Completed
Push — master ( d5b8a7...cdd9b5 )
by Dispositif
02:37
created

GoogleLivresTemplate::parseGoogleDomain()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 8
rs 10
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\Models\Wiki;
11
12
use DomainException;
13
use Exception;
14
15
/**
16
 * https://fr.wikipedia.org/wiki/Mod%C3%A8le:Google_Livres
17
 * Le premier paramètre (ou id) est obligatoire. L
18
 * Le deuxième (ou titre) est requis si on ne veut pas fabriquer le lien brut (inclusion {{ouvrage}} 'Lire en ligne')
19
 * Class GoogleLivresTemplate.
20
 */
21
class GoogleLivresTemplate extends AbstractWikiTemplate
22
{
23
    const DEFAULT_GOOGLEBOOK_URL = 'https://books.google.com/books';
24
25
    const ALLOW_USER_ORDER = false;
26
27
    const MODEL_NAME = 'Google Livres';
28
29
    const REQUIRED_PARAMETERS = ['id' => ''];
30
31
    const PARAM_ALIAS
32
        = [
33
            '1' => 'id',
34
            '2' => 'titre',
35
            'surligné' => 'surligne',
36
            'BuchID' => 'id',
37
        ];
38
39
    protected $parametersByOrder
40
        = ['id', 'titre', 'couv', 'page', 'romain', 'page autre', 'surligne'];
41
42
    /**
43
     * Serialize the wiki-template.
44
     * Improvement : force param order : id/titre/...
45
     *
46
     * @param bool|null $cleanOrder
47
     *
48
     * @return string
49
     */
50
    public function serialize(?bool $cleanOrder = true): string
51
    {
52
        $text = parent::serialize();
53
54
        // Documentation suggère non affichage de ces 2 paramètres
55
        return str_replace(['id=', 'titre='], '', $text);
56
    }
57
58
    /**
59
     * Create {Google Book} from URL.
60
     * See also https://fr.wikipedia.org/wiki/Utilisateur:Jack_ma/GB
61
     * https://stackoverflow.com/questions/11584551/need-information-on-query-parameters-for-google-books-e-g-difference-between-d.
62
     *
63
     * @param string $url
64
     *
65
     * @return GoogleLivresTemplate|null
66
     * @throws Exception
67
     */
68
    public static function createFromURL(string $url): ?self
69
    {
70
        if (!self::isGoogleBookURL($url)) {
71
            throw new DomainException('not a Google Book URL');
72
        }
73
        $gooDat = self::parseGoogleBookQuery($url);
74
75
        if (empty($gooDat['id'])) {
76
            throw new DomainException("no GoogleBook 'id' in URL");
77
        }
78
79
        $data = self::mapGooData($gooDat);
80
81
        $templ = new self();
82
        $templ->hydrate($data);
83
84
        return $templ;
85
    }
86
87
    /**
88
     * Mapping Google URL data to {Google Livres} data.
89
     *
90
     * @param array $gooData
91
     *
92
     * @return array
93
     */
94
    private static function mapGooData(array $gooData): array
95
    {
96
        $data = [];
97
        $data['id'] = $gooData['id'];
98
99
        // show cover ?
100
        if (isset($gooData['printsec']) && 'frontcover' === $gooData['printsec']) {
101
            $data['couv'] = '1';
102
        }
103
104
        // page number
105
        if (!empty($gooData['pg'])) {
106
            $data['page autre'] = $gooData['pg'];
107
108
            //  pg=PAx => "page=x"
109
            if (preg_match('/^PA([0-9]+)$/', $gooData['pg'], $matches) > 0) {
110
                $data['page'] = $matches[1];
111
                unset($data['page autre']);
112
            }
113
            //  pg=PRx => "page=x|romain=1"
114
            if (preg_match('/^PR([0-9]+)$/', $gooData['pg'], $matches) > 0) {
115
                $data['page'] = $matches[1];
116
                $data['romain'] = '1';
117
                unset($data['page autre']);
118
            }
119
        }
120
121
        if (!empty($gooData['dq']) || !empty($gooData['q'])) {
122
            $data['surligne'] = $gooData['dq'] ?? $gooData['q'];
123
            $data['surligne'] = urlencode($data['surligne']);
124
        }
125
126
        return $data;
127
    }
128
129
    /**
130
     * Clean the google book URL from optional&tracking data.
131
     *
132
     * @param string $url
133
     *
134
     * @return string URL
135
     */
136
    public static function simplifyGoogleUrl(string $url): string
137
    {
138
        if (!self::isGoogleBookURL($url)) {
139
            throw new DomainException('not a Google Book URL');
140
        }
141
142
        $gooDat = self::parseGoogleBookQuery($url);
143
        if (empty($gooDat['id'])) {
144
            throw new DomainException("no GoogleBook 'id' in URL");
145
        }
146
147
        $dat = [];
148
        // keep only a few parameters (+'q' ?)
149
        $keeps = ['id', 'pg', 'printsec', 'dq'];
150
        foreach ($keeps as $keep) {
151
            if (!empty($gooDat[$keep])) {
152
                $dat[$keep] = $gooDat[$keep];
153
            }
154
        }
155
156
        $googleURL = self::DEFAULT_GOOGLEBOOK_URL;
157
158
        // domain .com .fr
159
        $gooDomain = self::parseGoogleDomain($url);
160
        if ($gooDomain) {
161
            $googleURL = str_replace('.com', $gooDomain, $googleURL);
162
        }
163
164
        return $googleURL.'?'.http_build_query($dat);
165
    }
166
167
    /**
168
     * Parse URL argument from ?query and #fragment.
169
     *
170
     * @param string $url
171
     *
172
     * @return array
173
     */
174
    private static function parseGoogleBookQuery(string $url): array
175
    {
176
        // Note : Also datas in URL after the '#' !!! (URL fragment)
177
        $queryData = parse_url($url, PHP_URL_QUERY); // after ?
178
        $fragmentData = parse_url($url, PHP_URL_FRAGMENT); // after #
179
        // queryData precedence over fragmentData
180
        parse_str(implode('&', [$fragmentData, $queryData]), $val);
181
182
        return $val;
183
    }
184
185
    /**
186
     * return '.fr' or '.com'.
187
     *
188
     * @param string $url
189
     *
190
     * @return string|null
191
     */
192
    private static function parseGoogleDomain(string $url): ?string
193
    {
194
        $host = parse_url($url, PHP_URL_HOST);
195
        if (!empty($host) && preg_match('#\.[a-z]{2,3}$#', $host, $matches) > 0) {
196
            return $matches[0]; // .fr
197
        }
198
199
        return null;
200
    }
201
202
    /**
203
     * Check google URL pattern.
204
     *
205
     * @param string $text
206
     *
207
     * @return bool
208
     */
209
    public static function isGoogleBookURL(string $text): bool
210
    {
211
        if (preg_match('#^https?://(books|play)\.google\.[a-z]{2,3}/books(/reader)?\?id=#i', $text) > 0) {
212
            return true;
213
        }
214
215
        return false;
216
    }
217
218
    /**
219
     * Check if Google URL or wiki {Google Books} template.
220
     *
221
     * @param string $text
222
     *
223
     * @return bool
224
     */
225
    public static function isGoogleBookValue(string $text): bool
226
    {
227
        if (true === self::isGoogleBookURL($text)) {
228
            return true;
229
        }
230
        if (preg_match('#^{{[ \n]*Google (Livres|Books)[^}]+}}$#i', $text) > 0) {
231
            return true;
232
        }
233
234
        return false;
235
    }
236
}
237