Passed
Branch dev3 (d976d5)
by Dispositif
02:50
created

OuvrageCompleteWorker::printTitle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
c 0
b 0
f 0
dl 0
loc 11
rs 10
cc 1
nc 1
nop 1
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 DateTime;
30
use DomainException;
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
    protected $notCosmetic = false;
61
    protected $major = false;
62
    /**
63
     * @var OuvrageTemplate
64
     */
65
    protected $ouvrage;
66
    /**
67
     * @var LoggerInterface
68
     */
69
    protected $logger;
70
    /**
71
     * @var WikidataAdapterInterface
72
     */
73
    protected $wikidataAdapter;
74
75
    public function __construct(
76
        DbAdapterInterface       $queueAdapter,
77
        WikidataAdapterInterface $wikidataAdapter,
78
        MemoryInterface          $memory,
79
        ?LoggerInterface         $logger = null
80
    )
81
    {
82
        $this->queueAdapter = $queueAdapter;
83
        $this->logger = $logger ?? new NullLogger();
84
        $this->wikidataAdapter = $wikidataAdapter;
85
        $this->memory = $memory;
86
    }
87
88
    public function run(?int $limit = 10000): bool
89
    {
90
        while ($limit > 0) {
91
            $limit--;
92
            sleep(1);
93
            $this->pageOuvrage = $this->getNewRow2CompleteOrException();
94
            $this->page = $this->pageOuvrage->getPage();
95
96
            $this->printTitle($this->pageOuvrage);
97
98
            // initialise variables
99
            $this->resetSummaryLog();
100
            $this->ouvrage = null;
101
            $this->notCosmetic = false;
102
            $this->major = false;
103
104
105
            // TODO WIP
106
            $handler = new ParseTemplateHandler($this->pageOuvrage, $this->queueAdapter, $this->logger);
107
            $origin = $handler->handle();
108
109
110
            // Final optimizing (with online predictions)
111
            $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

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

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