Completed
Push — master ( 38c000...b1c7db )
by WEBEWEB
01:24
created

OcrProvider::downloadFiles()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 9.44
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
/*
4
 * This file is part of the core-library package.
5
 *
6
 * (c) 2020 WEBEWEB
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace WBW\Library\Core\ThirdParty\OcrLad\Provider;
13
14
use Closure;
15
use Psr\Log\LoggerAwareTrait;
16
use Psr\Log\LoggerInterface;
17
use WBW\Library\Core\Model\Attribute\StringHostnameTrait;
18
use WBW\Library\Core\Model\Attribute\StringPasswordTrait;
19
use WBW\Library\Core\Model\Attribute\StringUsernameTrait;
20
use WBW\Library\Core\Network\FTP\Client\FtpClient;
21
use WBW\Library\Core\Network\FTP\Exception\FtpException;
22
use WBW\Library\Core\Security\Authenticator;
23
use WBW\Library\Core\Security\PasswordAuthentication;
24
use WBW\Library\Core\ThirdParty\OcrLad\Model\IOFile;
25
26
/**
27
 * OCR provider.
28
 *
29
 * @author webeweb <https://github.com/webeweb>
30
 * @package WBW\Library\Core\ThirdParty\OcrLad\Provider
31
 */
32
class OcrProvider {
33
34
    use LoggerAwareTrait;
35
    use StringHostnameTrait;
36
    use StringPasswordTrait;
37
    use StringUsernameTrait;
38
39
    /**
40
     * FTP client.
41
     *
42
     * @var FtpClient
43
     */
44
    private $ftpClient;
45
46
    /**
47
     * Local directory "after".
48
     *
49
     * @var string
50
     */
51
    private $localDirectoryAfter;
52
53
    /**
54
     * Local directory "before".
55
     *
56
     * @var string
57
     */
58
    private $localDirectoryBefore;
59
60
    /**
61
     * Local directory "error".
62
     *
63
     * @var string
64
     */
65
    private $localDirectoryError;
66
67
    /**
68
     * Remote directory "after".
69
     *
70
     * @var string
71
     */
72
    private $remoteDirectoryAfter;
73
74
    /**
75
     * Remote directory "before".
76
     *
77
     * @var string
78
     */
79
    private $remoteDirectoryBefore;
80
81
    /**
82
     * Remote directory "error".
83
     *
84
     * @var string
85
     */
86
    private $remoteDirectoryError;
87
88
    /**
89
     * Constructor.
90
     *
91
     * @param LoggerInterface $logger The logger.
92
     */
93
    public function __construct(LoggerInterface $logger) {
94
        $this->setLogger($logger);
95
        $this->setRemoteDirectoryAfter("/Apres");
96
        $this->setRemoteDirectoryBefore("/Avant");
97
        $this->setRemoteDirectoryError("/Erreur");
98
    }
99
100
    /**
101
     * Destructor.
102
     *
103
     * @throws FtpException Throws a FTP exception if an error occurs.
104
     */
105
    public function __destruct() {
106
107
        if (null !== $this->ftpClient) {
108
109
            $this->getLogger()->info("OCR provider closes the FTP connection", ["_hostname" => $this->getHostname()]);
110
            $this->ftpClient->close();
111
            $this->ftpClient = null;
112
        }
113
    }
114
115
    /**
116
     * Build the file paths.
117
     *
118
     * @param IOFile $file The file.
119
     * @return array Returns the file paths.
120
     */
121
    protected function buildFilePaths(IOFile $file) {
122
        return [
123
            "upload" => implode("/", [$this->getRemoteDirectoryBefore(), $file->getUniqFilenamePdf()]),
124
            "remote" => [
125
                implode("/", [$this->getRemoteDirectoryAfter(), $file->getUniqFilenameDer()]),
126
                implode("/", [$this->getRemoteDirectoryAfter(), $file->getUniqFilenamePdf()]),
127
                implode("/", [$this->getRemoteDirectoryAfter(), $file->getUniqFilenameXml()]),
128
            ],
129
            "local"  => [
130
                implode("/", [$this->getLocalDirectoryAfter(), $file->getUniqFilenameDer()]),
131
                implode("/", [$this->getLocalDirectoryAfter(), $file->getUniqFilenamePdf()]),
132
                implode("/", [$this->getLocalDirectoryAfter(), $file->getUniqFilenameXml()]),
133
            ],
134
        ];
135
    }
136
137
    /**
138
     * Delete the files.
139
     *
140
     * @param IOFile $file The I/O file.
141
     * @return void
142
     * @throws FtpException Throws an FTP exception if an error occurs.
143
     */
144
    public function deleteFiles(IOFile $file) {
145
146
        $provider = $this;
147
148
        /**
149
         * Delete the remote files.
150
         *
151
         * @param string $directory The directory.
152
         * @return void
153
         * @var Closure
154
         */
155
        $deleteClosure = function($directory) use ($provider, $file) {
156
157
            $paths = $provider->buildFilePaths($file);
158
159
            $provider->getLogger()->info("OCR provider list files in a given directory", ["_directory" => $directory]);
160
            $files = $provider->getFtpClient()->nlist($directory);
161
            foreach ($files as $current) {
162
163
                if (false === in_array($current, $paths["remote"])) {
164
                    continue;
165
                }
166
167
                $provider->getLogger()->info("OCR provider deletes a file on the FTP server", ["_remote" => $current]);
168
                $provider->getFtpClient()->delete($current);
169
            }
170
        };
171
172
        $deleteClosure($this->getRemoteDirectoryBefore());
173
        $deleteClosure($this->getRemoteDirectoryAfter());
174
        $deleteClosure($this->getRemoteDirectoryError());
175
    }
176
177
    /**
178
     * Download the files.
179
     *
180
     * @param IOFile $file The I/O file.
181
     * @return bool Returns true in case of success, false otherwise.
182
     * @throws FtpException Throws an FTP exception if an error occurs.
183
     */
184
    public function downloadFiles(IOFile $file) {
185
186
        $paths = $this->buildFilePaths($file);
187
188
        $files = $this->getFtpClient()->nlist($this->getRemoteDirectoryAfter());
189
        if (false === in_array($paths["remote"][0], $files)) {
190
            return false;
191
        }
192
193
        $provider = $this;
194
195
        /**
196
         * Download a remote file.
197
         *
198
         * @param string $local The local file.
199
         * @param string $remote The remote file.
200
         * @return void
201
         * @var Closure
202
         */
203
        $downloadClosure = function($local, $remote) use ($provider) {
204
            $provider->getLogger()->info("OCR provider downloads a file  from the FTP server", ["_local" => $local, "_remote" => $remote]);
205
            $provider->getFtpClient()->get($local, $remote);
206
        };
207
208
        $downloadClosure($paths["local"][0], $paths["remote"][0]);
209
        $downloadClosure($paths["local"][1], $paths["remote"][1]);
210
        $downloadClosure($paths["local"][2], $paths["remote"][2]);
211
212
        return true;
213
    }
214
215
    /**
216
     * Get the FTP client.
217
     *
218
     * @return FtpClient Returns the FTP client.
219
     * @throws FtpException Throws an FTP exception if an error occurs.
220
     */
221
    public function getFtpClient() {
222
223
        if (null === $this->ftpClient) {
224
225
            $authentication = new PasswordAuthentication($this->getUsername(), $this->getPassword());
226
            $authenticator  = new Authenticator($this->getHostname(), $authentication);
227
228
            $this->ftpClient = new FtpClient($authenticator);
229
230
            $this->getLogger()->info("OCR provider opens an FTP connection to FTP", ["_hostname" => $this->getHostname()]);
231
            $this->ftpClient->connect();
232
233
            $this->getLogger()->info("OCR provider logs in to the FTP connection", ["_username" => $this->getUsername()]);
234
            $this->ftpClient->login();
235
236
            $this->getLogger()->info("OCR provider turns passive mode on");
237
            $this->ftpClient->pasv(true);
238
        }
239
240
        return $this->ftpClient;
241
    }
242
243
    /**
244
     * Get the local directory "after".
245
     *
246
     * @return string Returns the local directory "after".
247
     */
248
    public function getLocalDirectoryAfter() {
249
        return $this->localDirectoryAfter;
250
    }
251
252
    /**
253
     * Get the local directory "before".
254
     *
255
     * @return string Returns the local directory "before"
256
     */
257
    public function getLocalDirectoryBefore() {
258
        return $this->localDirectoryBefore;
259
    }
260
261
    /**
262
     * Get the local directory "error".
263
     *
264
     * @return string Returns the local directory "error".
265
     */
266
    public function getLocalDirectoryError() {
267
        return $this->localDirectoryError;
268
    }
269
270
    /**
271
     * Get the logger.
272
     *
273
     * @return LoggerInterface Returns the logger.
274
     */
275
    public function getLogger() {
276
        return $this->logger;
277
    }
278
279
    /**
280
     * Ge the remote directory "after".
281
     *
282
     * @return string Returns the remote directory "after".
283
     */
284
    public function getRemoteDirectoryAfter() {
285
        return $this->remoteDirectoryAfter;
286
    }
287
288
    /**
289
     * Get the remote directory "before".
290
     *
291
     * @return string Returns the remote directory "before".
292
     */
293
    public function getRemoteDirectoryBefore() {
294
        return $this->remoteDirectoryBefore;
295
    }
296
297
    /**
298
     * Get the remote directory "error".
299
     *
300
     * @return string Returns the remote directory "error".
301
     */
302
    public function getRemoteDirectoryError() {
303
        return $this->remoteDirectoryError;
304
    }
305
306
    /**
307
     * Scan a file.
308
     *
309
     * @param IOFile $file The I/O file.
310
     * @param int $retry The retry count.
311
     * @param int $wait The waiting time (in seconds) between retries.
312
     * @return bool Returns true in case of success, false otherwise.
313
     * @throws FtpException Throws an FTP exception in case of success, false otherwise.
314
     */
315
    public function scanFile(IOFile $file, $retry = 30, $wait = 5) {
316
317
        $paths = $this->buildFilePaths($file);
318
319
        $this->uploadFile($file);
320
321
        $result = false;
322
323
        for ($i = 0; $i < $retry; ++$i) {
324
325
            if (true === $this->downloadFiles($file)) {
326
                $result = true;
327
                break;
328
            }
329
330
            $this->getLogger()->info("OCR provider is waiting for...", ["_remote" => $paths["remote"][0]]);
331
            sleep($wait);
332
        }
333
334
        if (false === $result) {
335
            $this->getLogger()->info("OCR provider fail to download a file from the FTP server", ["_local" => $paths["local"][0], "_remote" => $paths["remote"][0]]);
336
            $this->getLogger()->info("OCR provider fail to download a file from the FTP server", ["_local" => $paths["local"][1], "_remote" => $paths["remote"][1]]);
337
            $this->getLogger()->info("OCR provider fail to download a file from the FTP server", ["_local" => $paths["local"][2], "_remote" => $paths["remote"][2]]);
338
        }
339
340
        return $result;
341
    }
342
343
    /**
344
     * Set the local directory "after".
345
     *
346
     * @param string $localDirectoryAfter The local directory "after".
347
     * @return OcrProvider Returns this OCR provider.
348
     */
349
    public function setLocalDirectoryAfter($localDirectoryAfter) {
350
        $this->localDirectoryAfter = $localDirectoryAfter;
351
        return $this;
352
    }
353
354
    /**
355
     * Set the local directory "before".
356
     *
357
     * @param string $localDirectoryBefore The local directory "before"
358
     * @return OcrProvider Returns this OCR provider.
359
     */
360
    public function setLocalDirectoryBefore($localDirectoryBefore) {
361
        $this->localDirectoryBefore = $localDirectoryBefore;
362
        return $this;
363
    }
364
365
    /**
366
     * Set the local directory "error".
367
     *
368
     * @param string $localDirectoryError The local directory "error".
369
     * @return OcrProvider Returns this OCR provider.
370
     */
371
    public function setLocalDirectoryError($localDirectoryError) {
372
        $this->localDirectoryError = $localDirectoryError;
373
        return $this;
374
    }
375
376
    /**
377
     * Set the remote directory "after".
378
     *
379
     * @param string $remoteDirectoryAfter The remote directory "after".
380
     * @return OcrProvider Returns this OCR provider.
381
     */
382
    public function setRemoteDirectoryAfter($remoteDirectoryAfter) {
383
        $this->remoteDirectoryAfter = $remoteDirectoryAfter;
384
        return $this;
385
    }
386
387
    /**
388
     * Set the remote directory "before".
389
     *
390
     * @param string $remoteDirectoryBefore The remote directory "before".
391
     * @return OcrProvider Returns this OCR provider.
392
     */
393
    public function setRemoteDirectoryBefore($remoteDirectoryBefore) {
394
        $this->remoteDirectoryBefore = $remoteDirectoryBefore;
395
        return $this;
396
    }
397
398
    /**
399
     * Set the remote directory "error".
400
     *
401
     * @param string $remoteDirectoryError The remote directory "error".
402
     * @return OcrProvider Returns this OCR provider.
403
     */
404
    public function setRemoteDirectoryError($remoteDirectoryError) {
405
        $this->remoteDirectoryError = $remoteDirectoryError;
406
        return $this;
407
    }
408
409
    /**
410
     * Upload a file.
411
     *
412
     * @param IOFile $file The I/O file.
413
     * @return void
414
     * @throws FtpException Throws an FTP exception if an error occurs.
415
     */
416
    public function uploadFile(IOFile $file) {
417
418
        $paths = $this->buildFilePaths($file);
419
420
        $this->getLogger()->info("OCR provider upload a file to the FTP server", ["_local" => $file->getPathname(), "_remote" => $paths["upload"]]);
421
        $this->getFtpClient()->put($file->getPathname(), $paths["upload"]);
422
    }
423
}