Test Setup Failed
Push — master ( c5c2a9...00574e )
by Dispositif
02:16
created

RefGoogleBook::convertGBurl2OuvrageCitation()   C

Complexity

Conditions 13
Paths 24

Size

Total Lines 66
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 13
eloc 35
c 2
b 0
f 0
nc 24
nop 1
dl 0
loc 66
rs 6.6166

How to fix   Long Method    Complexity   

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
4
 * 2019 © Philippe M. <[email protected]>
5
 * For the full copyright and MIT license information, please view the LICENSE file.
6
 */
7
8
declare(strict_types=1);
9
10
namespace App\Domain;
11
12
use App\Domain\Models\Wiki\GoogleLivresTemplate;
13
use App\Domain\Models\Wiki\OuvrageTemplate;
14
use App\Domain\Publisher\GoogleBookMapper;
15
use App\Domain\Utils\NumberUtil;
16
use App\Infrastructure\GoogleBooksAdapter;
17
18
/**
19
 * Transform <ref>https://books.google...</ref> to <ref>{{Ouvrage|...}}.</ref>
20
 * in an article wikitext.
21
 * Class RefGoogleBook
22
 *
23
 * @package App\Domain
24
 */
25
class RefGoogleBook
26
{
27
    const SLEEP_GOOGLE_API_INTERVAL = 8;
28
29
    /**
30
     * @var array OuvrageTemplate[]
31
     */
32
    private $cacheOuvrageTemplate = [];
33
34
    /**
35
     * RefGoogleBook constructor.
36
     * todo dependency injection
37
     */
38
    public function __construct() { }
39
40
    /**
41
     * Process page wikitext. Return wikitext with the <ref> converted.
42
     *
43
     * @param string $text Page wikitext
44
     *
45
     * @return string New wikitext
46
     */
47
    public function process(string $text): string
48
    {
49
        $refsData = $this->extractAllGoogleRefs($text);
50
        if (empty($refsData)) {
51
            echo "Pas d'URL GB trouvée";
52
53
            return $text;
54
        }
55
56
        foreach ($refsData as $ref) {
57
            try {
58
                $citation = $this->convertGBurl2OuvrageCitation($this->stripFinalPoint($ref[1]));
59
            } catch (\Exception $e) {
60
                echo "Exception ".$e->getMessage();
61
                continue;
62
            }
63
64
            // ajout point final pour référence
65
            $citation .= '.';
66
67
            $newRef = str_replace($ref[1], $citation, $ref[0]);
68
            echo $newRef."\n";
69
70
            $text = str_replace($ref[0], $newRef, $text);
71
72
            echo "sleep ".self::SLEEP_GOOGLE_API_INTERVAL."\n";
73
            sleep(self::SLEEP_GOOGLE_API_INTERVAL);
74
        }
75
76
        return $text;
77
    }
78
79
    /**
80
     * Strip the final point (".") as in <ref> ending.
81
     * TODO move to WikiRef or TextUtil class
82
     *
83
     * @param string $str
84
     *
85
     * @return string
86
     */
87
    private function stripFinalPoint(string $str): string
88
    {
89
        if (substr($str, -1, 1) === '.') {
90
            return substr($str, 0, strlen($str) - 1);
91
        }
92
93
        return $str;
94
    }
95
96
    /**
97
     * Convert GoogleBooks URL to wiki-template {ouvrage} citation.
98
     *
99
     * @param string $url GoogleBooks URL
100
     *
101
     * @return string {{ouvrage}}
102
     * @throws \Exception
103
     * @throws \Throwable
104
     */
105
    private function convertGBurl2OuvrageCitation(string $url): string
106
    {
107
        if (!GoogleLivresTemplate::isGoogleBookURL($url)) {
108
            throw new \DomainException('Pas de URL Google Books');
109
        }
110
111
        $gooDat = GoogleLivresTemplate::parseGoogleBookQuery($url);
112
        if (empty($gooDat['id'])) {
113
            throw new \DomainException('Pas de ID Google Books');
114
        }
115
116
        try {
117
            $ouvrage = $this->generateOuvrageFromGoogleData($gooDat['id']);
118
        } catch (\Throwable $e) {
119
            // ID n'existe pas sur Google Books
120
            if (strpos($e->getMessage(), '404 Not Found')
121
                && strpos($e->getMessage(), '"message": "The volume ID could n')
122
            ) {
123
                return sprintf(
124
                    '{{lien brisé |url= %s |titre= %s |brisé le=%s |CodexBot=1}}',
125
                    $url,
126
                    'ID introuvable sur Google Books',
127
                    date('d-m-Y')
128
                );
129
            }
130
            throw $e;
131
        }
132
133
134
        $cleanUrl = GoogleLivresTemplate::simplifyGoogleUrl($url);
135
        $ouvrage->unsetParam('présentation en ligne');
136
        $ouvrage->setParam('lire en ligne', $cleanUrl);
137
        $ouvrage->userSeparator = ' |';
138
139
        // Si titre absent
140
        if (empty($ouvrage->getParam('titre'))) {
141
            throw new \DomainException("Ouvrage sans titre (data Google?)");
142
        }
143
144
        // Google page => 'passage'
145
        if (!empty($gooDat['pg'])) {
146
            if (preg_match('#(?:PA|PT)([0-9]+)$#', $gooDat['pg'], $matches)) {
147
                // Exclusion de page=1, page=2 (vue par défaut sur Google Book)
148
                if (intval($matches[1]) >= 3) {
149
                    $page = $matches[1];
150
                }
151
            }
152
            // conversion chiffres Romain pour PR
153
            if (preg_match('#PR([0-9]+)$#', $gooDat['pg'], $matches)) {
154
                // Exclusion de page=1, page=2 (vue par défaut sur Google Book)
155
                if (intval($matches[1]) >= 3) {
156
                    $page = NumberUtil::arab2roman(intval($matches[1]), true);
157
                }
158
            }
159
160
            if (!empty($page)) {
161
                $ouvrage->setParam('passage', $page);
162
                // ajout commentaire '<!-- utile? -->' ?
163
            }
164
        }
165
166
        $optimizer = new OuvrageOptimize($ouvrage);
167
        $optimizer->doTasks();
168
        $ouvrage2 = $optimizer->getOuvrage();
169
170
        return $ouvrage2->serialize();
171
    }
172
173
    /**
174
     * todo: move (injection) to other class.
175
     * Generate wiki-template {ouvrage} from GoogleBook ID.
176
     *
177
     * @param string $id GoogleBooks ID
178
     *
179
     * @return OuvrageTemplate
180
     * @throws \Exception
181
     */
182
    private function generateOuvrageFromGoogleData(string $id): OuvrageTemplate
183
    {
184
        // return cached OuvrageTemplate
185
        if (isset($this->cacheOuvrageTemplate[$id])) {
186
            return clone $this->cacheOuvrageTemplate[$id];
187
        }
188
189
        // Get Google data by ID ZvhBAAAAcAAJ
190
        $adapter = new GoogleBooksAdapter();
191
        $volume = $adapter->getDataByGoogleId($id);
192
193
        $mapper = new GoogleBookMapper();
194
        $mapper->mapLanguageData(true);
195
        $data = $mapper->process($volume);
196
197
        // Generate wiki-template {ouvrage}
198
        $ouvrage = new OuvrageTemplate();
199
        $ouvrage->hydrate($data);
200
201
        // cache
202
        $this->cacheOuvrageTemplate[$id] = clone $ouvrage;
203
204
        return $ouvrage;
205
    }
206
207
    /**
208
     * Extract all <ref>/{ref} with only GoogleBooks URL.
209
     * Todo : supprimer point final URL
210
     *
211
     * @param string $text Page wikitext
212
     *
213
     * @return array [0 => ['<ref>http...</ref>', 'http://'], 1 => ...]
214
     */
215
    private function extractAllGoogleRefs(string $text): array
216
    {
217
        // <ref>...</ref> or {{ref|...}}
218
        if (preg_match_all(
219
            '#(?:<ref[^>]*>|{{ref\|) ?(https?://(?:books|play)\.google\.[a-z]{2,3}/(?:books)?(?:/reader)?\?id=[^>\]} \n]+) ?(?:</ref>|}})#i',
220
            $text,
221
            $matches,
222
            PREG_SET_ORDER
223
        )
224
        ) {
225
            return $matches;
226
        }
227
228
        return [];
229
    }
230
}
231