Completed
Push — master ( 2927d0...968590 )
by zyt
08:18 queued 13s
created

GoogleFontsCollection::getOriginalLinks()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace ZWF;
4
5
use ZWF\GoogleFontsOptimizerUtils as Utils;
6
7
class GoogleFontsCollection
8
{
9
10
    protected $links = [];
11
12
    protected $texts = [];
13
14
    /**
15
     * @var array|ZWF\GoogleFont[]
16
     */
17
    protected $fonts = [];
18
19
    protected $subsetsMap = [];
20
21
    protected $namedSizes = [];
22
23 5
    public function __construct(array $urls = [])
24 5
    {
25 5
        if (! empty($urls)) {
26 5
            foreach ($urls as $url) {
27 5
                $this->add($url);
28
            }
29
        }
30 5
    }
31
32 5
    public function add($url)
33 5
    {
34 5
        $this->addLink($url);
35
36 5
        $params = [];
37 5
        parse_str(parse_url($url, PHP_URL_QUERY), $params);
38
39 5
        $bucket = isset($params['text']) ? 'text' : 'complete';
40
41 5
        $fontstrings = $this->buildFontStringsFromQueryParams($params);
42 5
        foreach ($fontstrings as $font) {
43 5
            $this->addFontFromString($font, $bucket);
44 5
            if ('text' === $bucket) {
45 3
                $font_family = explode(':', $font);
46 5
                $this->addTextFont($font_family[0], Utils::httpsify($url));
47
            }
48
        }
49 5
    }
50
51 5
    protected function addLink($url)
52 5
    {
53 5
        $this->links[] = $url;
54 5
    }
55
56 5
    protected function addFontFromString($fontstring, $bucket = 'complete')
57 5
    {
58 5
        $font    = GoogleFont::fromString($fontstring);
59 5
        $name    = $font->getName();
60 5
        $subsets = $font->getSubsetsString();
61
62
        // Add to bucket list
63 5
        $this->fonts[$bucket][] = $font;
64
65
        // Keeping a separate map of names => subsets for webfontloader purposes
66 5
        if (! array_key_exists($name, $this->subsetsMap)) {
67
            // Nothing found yet, create a new key
68 5
            $this->subsetsMap[$name] = $subsets;
69
        } else {
70
            // Something is in there already, merge
71 1
            $this->subsetsMap[$name] = array_merge($this->subsetsMap[$name], (array) $subsets);
72
        }
73
74
        // Deduplicate values and don't sort the subsets map
75 5
        $this->subsetsMap = Utils::dedupValues($this->subsetsMap, false); // no sort
76
77
        // Maintain the list/hash of name => sizes when adding a new one too
78 5
        $this->namedSizes = $this->buildNamedsizesMap();
79 5
    }
80
81 3
    protected function addTextFont($name, $url)
82 3
    {
83 3
        $this->texts['name'][] = $name;
84 3
        $this->texts['url'][]  = $url;
85 3
    }
86
87
    /**
88
     * Returns an array of data needed to generated webfontloader script markup.
89
     *
90
     * @return array
91
     */
92 2
    public function getScriptData()
93 2
    {
94
        return [
95 2
            $this->getNamedSizesMap(),
96 2
            $this->getSubsetsMap()
97
        ];
98
    }
99
100 5
    public function getNamedSizesMap()
101 5
    {
102 5
        return $this->namedSizes;
103
    }
104
105
    /**
106
     * @return array
107
     */
108 2
    protected function getSubsetsMap()
109 2
    {
110 2
        return $this->subsetsMap;
111
    }
112
113 4
    public function getOriginalLinks()
114 4
    {
115 4
        return $this->links;
116
    }
117
118 5
    public function hasText()
119 5
    {
120 5
        return (! empty($this->texts));
121
    }
122
123
    /**
124
     * @return array
125
     */
126 4
    public function getTextUrls()
127 4
    {
128 4
        $urls = [];
129
130 4
        if ($this->hasText()) {
131 3
            $urls = $this->texts['url'];
132
        }
133
134 4
        return $urls;
135
    }
136
137
    /**
138
     * @return array
139
     */
140 1
    public function getTextNames()
141 1
    {
142 1
        return $this->texts['name'];
143
    }
144
145
    /**
146
     * @return ZWF\GoogleFont[]
147
     */
148 5
    public function getFonts()
149 5
    {
150 5
        return $this->fonts['complete'];
151
    }
152
153
    /**
154
     * @return string
155
     */
156 3
    public function getCombinedUrl()
157 3
    {
158 3
        return Utils::buildGoogleFontsUrl(
159 3
            $this->getNamedSizesMap(),
160 3
            $this->getSubsets()
161
        );
162
    }
163
164
    /**
165
     * @return array
166
     */
167 3
    public function getSubsets()
168 3
    {
169 3
        $subsets = [];
170
171 3
        $fonts = $this->getFonts();
172 3
        foreach ($fonts as $font) {
173 3
            $subsets[] = $font->getSubsets();
174
        }
175
176 3
        $subsets = Utils::arrayFlattenIterative($subsets);
177
178 3
        return array_unique($subsets);
179
    }
180
181
    /**
182
     * @return array
183
     */
184 5
    protected function buildNamedsizesMap()
185 5
    {
186 5
        $fonts = [];
187
188 5
        foreach ($this->getFonts() as $font) {
189 5
            $name = $font->getName();
190 5
            if (! array_key_exists($name, $fonts)) {
191 5
                $fonts[$name] = $font->getSizes();
192
            } else {
193 5
                $fonts[$name] = array_merge($fonts[$name], $font->getSizes());
194
            }
195
        }
196
197
        // Sanitize and de-dup
198 5
        $fonts = Utils::dedupValues($fonts, SORT_REGULAR); // sorts values (sizes)
199
200
        // Sorts by font names alphabetically
201 5
        ksort($fonts);
202
203 5
        return $fonts;
204
    }
205
206
    /**
207
     * Looks for and parses the `family` key in `$params` array to get back
208
     * the list of fonts/sizes/subsets requested via a GoogleFonts url.
209
     *
210
     * @param array $params
211
     *
212
     * @return array
213
     */
214 5
    protected function buildFontStringsFromQueryParams(array $params)
215 5
    {
216 5
        $fonts = [];
217
218 5
        foreach (explode('|', $params['family']) as $family) {
219 5
            $font = $this->parseFontStringName($family, $params);
220 5
            if (! empty($font)) {
221 5
                $fonts[] = $font;
222
            }
223
        }
224
225 5
        return $fonts;
226
    }
227
228
    /**
229
     * @param string $family
230
     * @param array $params
231
     *
232
     * @return string
233
     */
234 5
    protected function parseFontStringName($family, array $params)
235 5
    {
236 5
        $subset = false;
237 5
        $family = explode(':', $family);
238
239 5
        if (isset($params['subset'])) {
240
            // Use the found subset query parameter
241 4
            $subset = $params['subset'];
242 4
        } elseif (isset($family[2])) {
243
            // Use the subset in the family string if present
244 1
            $subset = $family[2];
245
        }
246
247
        // $family can have a lot of thing specified with separators etc.
248 5
        $parts = $this->validateFontStringParts($family, $subset);
249 5
        $font  = implode(':', $parts);
250
251 5
        return $font;
252
    }
253
254
    /**
255
     * Validate and return desired font name/size/subset parts.
256
     *
257
     * @param array $family
258
     * @param bool $subset
259
     *
260
     * @return array
261
     */
262 5
    protected function validateFontStringParts(array $family, $subset = false)
263 5
    {
264 5
        $parts = [];
265
266
        // First part is the font name, which should always be present
267 5
        $parts[] = $family[0];
268
269
        // Check if sizes are specified
270 5
        if (isset($family[1]) && strlen($family[1]) > 0) {
271 4
            $parts[] = $family[1];
272
        }
273
274
        // Add the subset if specified
275 5
        if ($subset) {
276 4
            $parts[] = $subset;
277
        }
278
279 5
        return $parts;
280
    }
281
}
282