Passed
Push — master ( 7a576b...99159c )
by zyt
04:01
created

GoogleFontsCollection::getScriptData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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