Passed
Push — master ( 9e3ea7...ee24dc )
by Dispositif
02:33
created

OuvrageCompleteWorker::run()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 53
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 29
c 0
b 0
f 0
dl 0
loc 53
rs 8.5226
cc 7
nc 6
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * This file is part of dispositif/wikibot application (@github)
4
 * 2019-2023 © Philippe M./Irønie  <[email protected]>
5
 * For the full copyright and MIT license information, view the license file.
6
 */
7
8
declare(strict_types=1);
9
10
namespace App\Application\OuvrageComplete;
11
12
use App\Application\InfrastructurePorts\DbAdapterInterface;
13
use App\Application\InfrastructurePorts\MemoryInterface;
14
use App\Application\OuvrageComplete\Handlers\BnfFromIsbnHandler;
15
use App\Application\OuvrageComplete\Handlers\GoogleBooksHandler;
16
use App\Application\OuvrageComplete\Handlers\OpenLibraryHandler;
17
use App\Application\OuvrageComplete\Handlers\ParseTemplateHandler;
18
use App\Application\OuvrageComplete\Handlers\WikidataSearchHandler;
19
use App\Application\OuvrageComplete\Validators\GoogleRequestValidator;
20
use App\Application\OuvrageComplete\Validators\IsbnBanValidator;
21
use App\Application\OuvrageComplete\Validators\NewPageOuvrageToCompleteValidator;
22
use App\Application\WikiBotConfig;
23
use App\Domain\InfrastructurePorts\WikidataAdapterInterface;
24
use App\Domain\Models\PageOuvrageDTO;
25
use App\Domain\Models\Wiki\OuvrageTemplate;
26
use App\Domain\OptimizerFactory;
27
use App\Domain\OuvrageComplete;
28
use App\Domain\SummaryLogTrait;
29
use App\Domain\WikiOptimizer\OuvrageOptimize;
30
use DateTime;
31
use Exception;
32
use Normalizer;
33
use Psr\Log\LoggerInterface;
34
use Psr\Log\NullLogger;
35
36
/**
37
 * TODO Legacy class, to be refactored. To big, too many responsibilities.
38
 * TODO use DTO from DbAdapter.
39
 */
40
class OuvrageCompleteWorker
41
{
42
    use SummaryLogTrait;
43
44
45
    /**
46
     * @var MemoryInterface
47
     */
48
    protected $memory;
49
    /**
50
     * @var PageOuvrageDTO
51
     */
52
    protected $pageOuvrage;
53
    /**
54
     * @var DbAdapterInterface
55
     */
56
    protected $queueAdapter;
57
58
    protected $page; // article title
59
    /**
60
     * @var OuvrageTemplate
61
     */
62
    protected $ouvrage;
63
    /**
64
     * @var LoggerInterface
65
     */
66
    protected $logger;
67
    /**
68
     * @var WikidataAdapterInterface
69
     */
70
    protected $wikidataAdapter;
71
    /**
72
     * @var CitationWorkStatus
73
     */
74
    protected $citationWorkStatus;
75
76
    public function __construct(
77
        DbAdapterInterface       $queueAdapter,
78
        WikidataAdapterInterface $wikidataAdapter,
79
        MemoryInterface          $memory,
80
        ?LoggerInterface         $logger = null
81
    )
82
    {
83
        $this->queueAdapter = $queueAdapter;
84
        $this->logger = $logger ?? new NullLogger();
85
        $this->wikidataAdapter = $wikidataAdapter;
86
        $this->memory = $memory;
87
    }
88
89
    public function run(?int $limit = 10000): bool
90
    {
91
        while ($limit > 0) {
92
            $limit--;
93
            sleep(1);
94
            $this->pageOuvrage = $this->getNewRow2CompleteOrException();
95
            if ($this->pageOuvrage === null) {
96
                throw new Exception('no more queue to process');
97
            }
98
            $this->page = $this->pageOuvrage->getPage();
99
100
            $this->printTitle($this->pageOuvrage);
101
102
            // initialise variables
103
            $this->citationWorkStatus = new CitationWorkStatus($this->page);
104
105
            $this->resetSummaryLog();
106
            $this->ouvrage = null;
107
108
109
            // TODO WIP
110
            $handler = new ParseTemplateHandler($this->pageOuvrage, $this->queueAdapter, $this->logger);
111
            $origin = $handler->handle();
112
113
114
            // Final optimizing (with online predictions)
115
            $optimizer = OptimizerFactory::fromTemplate($origin, $this->page, $this->logger);
0 ignored issues
show
Bug introduced by
It seems like $origin can also be of type null; however, parameter $template of App\Domain\OptimizerFactory::fromTemplate() does only seem to accept App\Domain\Models\Wiki\WikiTemplateInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

115
            $optimizer = OptimizerFactory::fromTemplate(/** @scrutinizer ignore-type */ $origin, $this->page, $this->logger);
Loading history...
116
            /** @var OuvrageOptimize $optimizer */
117
            $optimizer->doTasks();
118
            $this->ouvrage = $optimizer->getOptiTemplate();
119
            $this->summaryLog = array_merge($this->getSummaryLog(), $optimizer->getSummaryLog());
120
            $this->citationWorkStatus->notCosmetic = ($optimizer->isNotCosmetic() || $this->citationWorkStatus->notCosmetic);
121
122
123
            /**
124
             * RECHERCHE ONLINE
125
             */
126
            $isbn = $origin->getParam('isbn') ?? null; // avant mise en forme EAN>ISBN
127
            $isbn10 = $origin->getParam('isbn2') ?? $origin->getParam('isbn10') ?? null;
128
            if (!empty($isbn)
129
                && !$origin->hasParamValue('isbn invalide')
130
                && !$origin->hasParamValue('isbn erroné')
131
            ) {
132
                $this->completeByIsbnSearch($isbn, $isbn10);
133
            }
134
135
            $this->sendCompleted();
136
            unset($optimizer);
137
            unset($parse);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $parse seems to be never defined.
Loading history...
138
            unset($origin);
139
        } // END WHILE
140
141
        return true;
142
    }
143
144
    /**
145
     * Get array (title+raw strings) to complete from AMQP queue, SQL Select or file reading.
146
     */
147
    protected function getNewRow2CompleteOrException(): ?PageOuvrageDTO
148
    {
149
        $pageOuvrageDTO = $this->queueAdapter->getNewRaw();
150
        if ((new NewPageOuvrageToCompleteValidator($pageOuvrageDTO))->validate()) {
151
            return $pageOuvrageDTO;
152
        }
153
        $this->logger->debug('no more raw');
154
155
        return null;
156
    }
157
158
    // todo extract class
159
160
    protected function printTitle(PageOuvrageDTO $pageOuvrage): void
161
    {
162
        echo sprintf(
163
            "-------------------------------\n%s [%s]\n%s\n%s\n",
164
            date("Y-m-d H:i:s"),
165
            WikiBotConfig::VERSION ?? '',
166
            $pageOuvrage->getPage(),
167
            $pageOuvrage->getRaw()
168
        );
169
170
        $this->logger->debug($this->memory->getMemory(true));
171
    }
172
173
    //    protected function onlineQuerySearch(string $query)
174
    //    {
175
    //        echo "sleep 40...";
176
    //        sleep(20);
177
    //        onlineQuerySearch:
178
    //
179
    //        try {
180
    //            dump('GOOGLE SEARCH...');
181
    //            //            $googleOuvrage = OuvrageFactory::GoogleFromIsbn($isbn);
182
    //            $adapter = new GoogleBooksAdapter();
183
    //            $data = $adapter->search('blabla');
184
    //            dump($data);
185
    //            //die;
186
    //            //            return $import->getOuvrage();
187
    //            //            $this->completeOuvrage($googleOuvrage);
188
    //        } catch (Throwable $e) {
189
    //            echo "*** ERREUR GOOGLE QuerySearch *** ".$e->getMessage()."\n";
190
    //            echo "sleep 30min";
191
    //            sleep(60 * 30);
192
    //            echo "Wake up\n";
193
    //            goto onlineQuerySearch;
194
    //        }
195
    //    }
196
197
    protected function completeByIsbnSearch(string $isbn, ?string $isbn10 = null)
198
    {
199
        if ((new IsbnBanValidator($isbn, $isbn10))->validate() === false) {
200
            echo "*** SKIP THAT ISBN ***\n";
201
            return;
202
        }
203
204
        $this->logger->info("sleep 10...\n"); // API throttle
205
        sleep(10);
206
207
        $bnfOuvrage = (new BnfFromIsbnHandler($isbn, $isbn10, $this->logger))->handle();
208
        $this->completeOuvrage($bnfOuvrage); // todo move to BnfFromIsbnHandler ?
209
210
        if ($bnfOuvrage instanceof OuvrageTemplate) {
211
            $wdOuvrage = (new WikidataSearchHandler($bnfOuvrage, $this->wikidataAdapter, $this->page))->handle();
212
            $this->completeOuvrage($wdOuvrage);
213
        }
214
215
        if ((new GoogleRequestValidator($this->ouvrage, $bnfOuvrage))->validate()) {
216
            $googleOuvrage = (new GoogleBooksHandler($isbn, $this->logger))->handle();
217
            $this->completeOuvrage($googleOuvrage);
218
        }
219
220
        if (!isset($bnfOuvrage) && !isset($googleOuvrage)) {
221
            $openLibraryOuvrage = (new OpenLibraryHandler($isbn, $this->logger))->handle();
222
            $this->completeOuvrage($openLibraryOuvrage);
223
        }
224
    }
225
226
    protected function completeOuvrage(?OuvrageTemplate $onlineOuvrage): void
227
    {
228
        if (!$onlineOuvrage instanceof OuvrageTemplate) {
229
            return;
230
        }
231
        $this->logger->info($onlineOuvrage->serialize(true));
232
        $optimizer = OptimizerFactory::fromTemplate($onlineOuvrage, $this->page, $this->logger);
233
        $onlineOptimized = ($optimizer)->doTasks()->getOptiTemplate();
234
235
        $completer = new OuvrageComplete($this->ouvrage, $onlineOptimized, $this->logger);
236
        $this->ouvrage = $completer->getResult();
237
238
        // todo move that optimizing in OuvrageComplete ?
239
        $optimizer = OptimizerFactory::fromTemplate($this->ouvrage, $this->page, $this->logger);
240
        $this->ouvrage = $optimizer->doTasks()->getOptiTemplate();
241
242
        $this->logger->info('Summary', $completer->getSummaryLog());
243
244
        if ($completer->major) {
245
            $this->citationWorkStatus->minorFlag = false;
246
        }
247
        $this->citationWorkStatus->notCosmetic = ($completer->notCosmetic || $this->citationWorkStatus->notCosmetic);
248
        $this->summaryLog = array_merge($this->getSummaryLog(), $completer->getSummaryLog());
249
        unset($optimizer);
250
        unset($completer);
251
    }
252
253
    protected function sendCompleted()
254
    {
255
        $this->pageOuvrage
256
            ->setOpti($this->serializeFinalOpti())
257
            ->setOptidate(new DateTime())
258
            ->setModifs(mb_substr(implode(',', $this->getSummaryLog()), 0, 250))
259
            ->setNotcosmetic(($this->citationWorkStatus->notCosmetic) ? 1 : 0)
260
            ->setMajor(($this->citationWorkStatus->minorFlag) ? 0 : 1)
261
            ->setIsbn(substr($this->ouvrage->getParam('isbn'), 0, 19))
0 ignored issues
show
Bug introduced by
It seems like $this->ouvrage->getParam('isbn') can also be of type null; however, parameter $string of substr() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

261
            ->setIsbn(substr(/** @scrutinizer ignore-type */ $this->ouvrage->getParam('isbn'), 0, 19))
Loading history...
262
            ->setVersion(WikiBotConfig::VERSION ?? null);
263
264
        $result = $this->queueAdapter->sendCompletedData($this->pageOuvrage);
265
        $this->logger->debug($result ? 'OK DB' : 'erreur sendCompletedData()');
266
    }
267
268
    /**
269
     * Final serialization of the completed OuvrageTemplate.
270
     */
271
    protected function serializeFinalOpti(): string
272
    {
273
        //        // Améliore style compact : plus espacé
274
        //        if ('|' === $this->ouvrage->userSeparator) {
275
        //            $this->ouvrage->userSeparator = ' |';
276
        //        }
277
        $finalOpti = $this->ouvrage->serialize(true);
278
        $finalOpti = Normalizer::normalize($finalOpti);
279
        if (empty($finalOpti) || !is_string($finalOpti)) {
280
            throw new Exception('normalized $finalOpti serialize in OuvrageComplete is not a string');
281
        }
282
283
        return $finalOpti;
284
    }
285
}
286