Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 12 |
CRAP | |
0.00% |
0 / 66 |
DedupGenerateSingleFile | |
0.00% |
0 / 1 |
|
0.00% |
0 / 12 |
306 | |
0.00% |
0 / 66 |
__construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
launch | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 7 |
|||
generatePaths | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 10 |
|||
createFile | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 9 |
|||
zip | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 8 |
|||
setFilename | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 6 |
|||
getZipPath | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 1 |
|||
getFilePath | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 1 |
|||
get | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 8 |
|||
chunk | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 6 |
|||
getHashs | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
eachHash | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
1 | <?php |
2 | |
3 | namespace Qmp\Laravel\Deduplication\Console\Commands; |
4 | |
5 | use Closure; |
6 | use Exception; |
7 | use Illuminate\Support\Facades\Storage; |
8 | use Illuminate\Support\Str; |
9 | use Qmp\Laravel\Deduplication\Exceptions\ZipErrorException; |
10 | use Qmp\Laravel\Deduplication\Models\Session; |
11 | use Qmp\Laravel\Deduplication\Models\SessionData; |
12 | use ZipArchive; |
13 | |
14 | class DedupGenerateSingleFile extends BaseCommand |
15 | { |
16 | /** |
17 | * The download folder |
18 | */ |
19 | const DOWNLOAD_DIRECTORY = 'download'; |
20 | |
21 | /** |
22 | * The created file extension |
23 | */ |
24 | const FILE_EXTENSION = '.txt'; |
25 | |
26 | /** |
27 | * The zip file extension |
28 | */ |
29 | const ZIP_EXTENSION = '.zip'; |
30 | |
31 | |
32 | /** |
33 | * The size of hash for the chunk method |
34 | */ |
35 | const HASHS_CHUNK_SIZE = 10000; |
36 | |
37 | /** |
38 | * The name and signature of the console command. |
39 | * |
40 | * @var string |
41 | */ |
42 | protected $signature = 'dedup:generate-single-files {sessionId} |
43 | {--site-id= : The site id} |
44 | {--throw-error : Throw errors if catch}'; |
45 | |
46 | /** |
47 | * The console command description. |
48 | * |
49 | * @var string |
50 | */ |
51 | protected $description = 'Generate file after deduplication'; |
52 | |
53 | /** The dedup disk |
54 | * |
55 | * @var \Illuminate\Contracts\Filesystem\Filesystem |
56 | */ |
57 | protected $disk; |
58 | |
59 | /** |
60 | * The current session model |
61 | */ |
62 | protected $sessionConfig; |
63 | |
64 | /** |
65 | * Undocumented variable |
66 | * |
67 | * @var integer |
68 | */ |
69 | protected $count = 0; |
70 | |
71 | /** |
72 | * Undocumented variable |
73 | * |
74 | * @var int |
75 | */ |
76 | protected $siteId = null; |
77 | |
78 | /** |
79 | * Undocumented variable |
80 | * |
81 | * @var resource|false |
82 | */ |
83 | protected $fileRessource = null; |
84 | |
85 | /** |
86 | * Undocumented variable |
87 | * |
88 | * @var string |
89 | */ |
90 | protected $filename = ""; |
91 | /** |
92 | * Create a new command instance. |
93 | * |
94 | * @return void |
95 | */ |
96 | public function __construct() |
97 | { |
98 | parent::__construct(); |
99 | $this->disk = Storage::disk('deduplication'); |
100 | } |
101 | |
102 | /** |
103 | * Undocumented function |
104 | * |
105 | * @return void |
106 | */ |
107 | protected function launch(): void |
108 | { |
109 | $this->siteId = (int) $this->option('site-id'); |
110 | $this->sessionConfig = Session::findOrFail($this->argument('sessionId')); |
111 | |
112 | $this->generatePaths() |
113 | ->createFile() |
114 | ->zip() |
115 | ->setFilename(); |
116 | } |
117 | |
118 | /** |
119 | * Generate all paths and filenames |
120 | * |
121 | * @return \Qmp\Laravel\Deduplication\Console\Commands\DedupGenerateSingleFile |
122 | */ |
123 | protected function generatePaths(): DedupGenerateSingleFile |
124 | { |
125 | $fileNameParts = collect([ |
126 | $this->sessionConfig->name, // Session name |
127 | collect($this->sessionConfig->sites)->recursive()->where('id', $this->siteId)->first()->get('name'), // Site name |
128 | $this->sessionConfig->id, // Session id |
129 | date('m-Y') // Month/year |
130 | ]); |
131 | |
132 | $filename = Str::slug($fileNameParts->implode('-')); |
133 | |
134 | $this->filename = $filename . self::FILE_EXTENSION; |
135 | $this->zipname = $filename . self::ZIP_EXTENSION; |
136 | $this->savePath = $this->sessionConfig->id . '/' . self::DOWNLOAD_DIRECTORY . '/' . $this->siteId . '/'; |
137 | |
138 | return $this; |
139 | } |
140 | |
141 | /** |
142 | * Create file for a single site |
143 | * |
144 | * @param string $siteId |
145 | * @return \Qmp\Laravel\Deduplication\Console\Commands\DedupGenerateSingleFile |
146 | */ |
147 | protected function createFile(): DedupGenerateSingleFile |
148 | { |
149 | |
150 | $this->info("Création du fichier : " . $this->getFilePath(true) . " ..."); |
151 | |
152 | $this->disk->put($this->getFilePath(), ''); |
153 | $this->fileRessource = fopen($this->disk->path($this->getFilePath()), "w"); |
154 | |
155 | $this->startTimer('chunk', 'total'); |
156 | $this->get(); |
157 | |
158 | fclose($this->fileRessource); |
159 | |
160 | $this->info("write done for $this->count entries in : " . $this->getTimer('total')); |
161 | $this->info("Fichier : " . $this->getFilePath(true) . " ok !"); |
162 | |
163 | return $this; |
164 | } |
165 | |
166 | /** |
167 | * Zip file |
168 | * |
169 | * @return \Qmp\Laravel\Deduplication\Console\Commands\DedupGenerateSingleFile |
170 | */ |
171 | protected function zip(): DedupGenerateSingleFile |
172 | { |
173 | $this->info("Création du zip : " . $this->getZipPath(true) . " ..."); |
174 | |
175 | $zip = new ZipArchive; |
176 | if ($zip->open($this->disk->path($this->getZipPath()), ZipArchive::CREATE) === TRUE) { |
177 | $zip->addFile($this->disk->path($this->getFilePath()), $this->getFilePath(true)); |
178 | $zip->close(); |
179 | $this->info('zip Ok !'); |
180 | } else { |
181 | throw new ZipErrorException("Erreur lors de la creation du zip " . $this->getZipPath(true)); |
182 | } |
183 | |
184 | return $this; |
185 | } |
186 | |
187 | /** |
188 | * Add download filename into DB |
189 | * |
190 | * @return void |
191 | */ |
192 | protected function setFilename(): void |
193 | { |
194 | $array = [ |
195 | 'zip' => $this->getZipPath(), |
196 | 'file' => $this->getFilePath(), |
197 | 'basename' => $this->getFilePath(true), |
198 | 'count' => $this->count |
199 | ]; |
200 | |
201 | $this->sessionConfig->setKeyFilter('sites.$id', 'output_file', $array, [$this->siteId]); |
202 | } |
203 | |
204 | /** |
205 | * Get zipfile or full zip path |
206 | * |
207 | * @param boolean $onlyFilename |
208 | * @return string |
209 | */ |
210 | protected function getZipPath($onlyFilename = false): string |
211 | { |
212 | return $onlyFilename ? $this->zipname : $this->savePath . $this->zipname; |
213 | } |
214 | |
215 | /** |
216 | * Get filename or full file path |
217 | * |
218 | * @param boolean $onlyFilename |
219 | * @return string |
220 | */ |
221 | protected function getFilePath($onlyFilename = false): string |
222 | { |
223 | return $onlyFilename ? $this->filename : $this->savePath . $this->filename; |
224 | } |
225 | |
226 | /** |
227 | * Get All hash at once |
228 | * |
229 | * @return void |
230 | */ |
231 | protected function get(): void |
232 | { |
233 | try { |
234 | $this->startTimer('hashsGet'); |
235 | $hashs = $this->getHashs()->get(); |
236 | $this->info('Get Hashs in ' . $this->getTimer('hashsGet')); |
237 | |
238 | $this->startTimer('hashEntry'); |
239 | $hashs->each(Closure::fromCallable([$this, 'eachHash'])); |
240 | } catch (Exception $e) { |
241 | $this->chunk(); |
242 | } |
243 | } |
244 | |
245 | /** |
246 | * Get hash by chunk |
247 | * |
248 | * @return void |
249 | */ |
250 | protected function chunk(): void |
251 | { |
252 | $this->getHashs()->chunk(self::HASHS_CHUNK_SIZE, function ($hashs) { |
253 | $this->info('chunk OK : ' . $this->getTimer('chunk', true)); |
254 | $this->info('write start'); |
255 | |
256 | $hashs->each(Closure::fromCallable([$this, 'eachHash'])); |
257 | }); |
258 | } |
259 | |
260 | /** |
261 | * Get all hashs for one site id and one session |
262 | * |
263 | */ |
264 | protected function getHashs() |
265 | { |
266 | return SessionData::where(['site_id' => $this->siteId, 'active' => false, "session_id" => $this->sessionConfig->id])->select('hash'); |
267 | } |
268 | |
269 | /** |
270 | * Closure to execute on each entry |
271 | * |
272 | * @param [type] $hash |
273 | * @return void |
274 | */ |
275 | protected function eachHash($hash): void |
276 | { |
277 | $this->count++; |
278 | $string = $hash->hash . "\r\n"; |
279 | fwrite($this->fileRessource, $string, strlen($string)); |
280 | |
281 | if ($this->count % 50000 === 0) { |
282 | $this->info("write $this->count entries in : " . $this->filename . " - " . $this->getTimer('hashEntry')); |
283 | } |
284 | } |
285 | } |