Passed
Push — master ( 2345e6...3849ed )
by
unknown
13:07
created

FontawesomeIconProvider   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 951
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 23
eloc 860
dl 0
loc 951
rs 9.74
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A generateMarkup() 0 3 1
A __construct() 0 3 1
A getName() 0 14 4
A escape() 0 7 1
A getSvgIcons() 0 8 2
A getSvgContents() 0 25 6
A generateInlineMarkup() 0 4 1
A prepareIconMarkup() 0 4 1
A createSvgIcons() 0 44 5
A getCacheIdentifier() 0 3 1
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Core\Imaging\IconProvider;
17
18
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
19
use TYPO3\CMS\Core\Core\Environment;
20
use TYPO3\CMS\Core\Imaging\Icon;
21
use TYPO3\CMS\Core\Imaging\IconProviderInterface;
22
use TYPO3\CMS\Core\Information\Typo3Version;
23
use TYPO3\CMS\Core\Utility\GeneralUtility;
24
25
/**
26
 * Class FontawesomeIconProvider
27
 */
28
class FontawesomeIconProvider implements IconProviderInterface
29
{
30
    public const MARKUP_IDENTIFIER_INLINE = 'inline';
31
32
    private FrontendInterface $cache;
33
34
    /**
35
     * Map of font-awesome names to unicode numbers
36
     *
37
     * Generated with:
38
     *  sed -n "s/@fa-var-\(.*\): \"\\\\f\(.*\)\";/        '\1' => 0xf\2,/p" \
39
     *    Build/node_modules/font-awesome/less/variables.less
40
     */
41
    private array $unicodeMap = [
42
        '500px' => 0xf26e,
43
        'address-book' => 0xf2b9,
44
        'address-book-o' => 0xf2ba,
45
        'address-card' => 0xf2bb,
46
        'address-card-o' => 0xf2bc,
47
        'adjust' => 0xf042,
48
        'adn' => 0xf170,
49
        'align-center' => 0xf037,
50
        'align-justify' => 0xf039,
51
        'align-left' => 0xf036,
52
        'align-right' => 0xf038,
53
        'amazon' => 0xf270,
54
        'ambulance' => 0xf0f9,
55
        'american-sign-language-interpreting' => 0xf2a3,
56
        'anchor' => 0xf13d,
57
        'android' => 0xf17b,
58
        'angellist' => 0xf209,
59
        'angle-double-down' => 0xf103,
60
        'angle-double-left' => 0xf100,
61
        'angle-double-right' => 0xf101,
62
        'angle-double-up' => 0xf102,
63
        'angle-down' => 0xf107,
64
        'angle-left' => 0xf104,
65
        'angle-right' => 0xf105,
66
        'angle-up' => 0xf106,
67
        'apple' => 0xf179,
68
        'archive' => 0xf187,
69
        'area-chart' => 0xf1fe,
70
        'arrow-circle-down' => 0xf0ab,
71
        'arrow-circle-left' => 0xf0a8,
72
        'arrow-circle-o-down' => 0xf01a,
73
        'arrow-circle-o-left' => 0xf190,
74
        'arrow-circle-o-right' => 0xf18e,
75
        'arrow-circle-o-up' => 0xf01b,
76
        'arrow-circle-right' => 0xf0a9,
77
        'arrow-circle-up' => 0xf0aa,
78
        'arrow-down' => 0xf063,
79
        'arrow-left' => 0xf060,
80
        'arrow-right' => 0xf061,
81
        'arrow-up' => 0xf062,
82
        'arrows' => 0xf047,
83
        'arrows-alt' => 0xf0b2,
84
        'arrows-h' => 0xf07e,
85
        'arrows-v' => 0xf07d,
86
        'asl-interpreting' => 0xf2a3,
87
        'assistive-listening-systems' => 0xf2a2,
88
        'asterisk' => 0xf069,
89
        'at' => 0xf1fa,
90
        'audio-description' => 0xf29e,
91
        'automobile' => 0xf1b9,
92
        'backward' => 0xf04a,
93
        'balance-scale' => 0xf24e,
94
        'ban' => 0xf05e,
95
        'bandcamp' => 0xf2d5,
96
        'bank' => 0xf19c,
97
        'bar-chart' => 0xf080,
98
        'bar-chart-o' => 0xf080,
99
        'barcode' => 0xf02a,
100
        'bars' => 0xf0c9,
101
        'bath' => 0xf2cd,
102
        'bathtub' => 0xf2cd,
103
        'battery' => 0xf240,
104
        'battery-0' => 0xf244,
105
        'battery-1' => 0xf243,
106
        'battery-2' => 0xf242,
107
        'battery-3' => 0xf241,
108
        'battery-4' => 0xf240,
109
        'battery-empty' => 0xf244,
110
        'battery-full' => 0xf240,
111
        'battery-half' => 0xf242,
112
        'battery-quarter' => 0xf243,
113
        'battery-three-quarters' => 0xf241,
114
        'bed' => 0xf236,
115
        'beer' => 0xf0fc,
116
        'behance' => 0xf1b4,
117
        'behance-square' => 0xf1b5,
118
        'bell' => 0xf0f3,
119
        'bell-o' => 0xf0a2,
120
        'bell-slash' => 0xf1f6,
121
        'bell-slash-o' => 0xf1f7,
122
        'bicycle' => 0xf206,
123
        'binoculars' => 0xf1e5,
124
        'birthday-cake' => 0xf1fd,
125
        'bitbucket' => 0xf171,
126
        'bitbucket-square' => 0xf172,
127
        'bitcoin' => 0xf15a,
128
        'black-tie' => 0xf27e,
129
        'blind' => 0xf29d,
130
        'bluetooth' => 0xf293,
131
        'bluetooth-b' => 0xf294,
132
        'bold' => 0xf032,
133
        'bolt' => 0xf0e7,
134
        'bomb' => 0xf1e2,
135
        'book' => 0xf02d,
136
        'bookmark' => 0xf02e,
137
        'bookmark-o' => 0xf097,
138
        'braille' => 0xf2a1,
139
        'briefcase' => 0xf0b1,
140
        'btc' => 0xf15a,
141
        'bug' => 0xf188,
142
        'building' => 0xf1ad,
143
        'building-o' => 0xf0f7,
144
        'bullhorn' => 0xf0a1,
145
        'bullseye' => 0xf140,
146
        'bus' => 0xf207,
147
        'buysellads' => 0xf20d,
148
        'cab' => 0xf1ba,
149
        'calculator' => 0xf1ec,
150
        'calendar' => 0xf073,
151
        'calendar-check-o' => 0xf274,
152
        'calendar-minus-o' => 0xf272,
153
        'calendar-o' => 0xf133,
154
        'calendar-plus-o' => 0xf271,
155
        'calendar-times-o' => 0xf273,
156
        'camera' => 0xf030,
157
        'camera-retro' => 0xf083,
158
        'car' => 0xf1b9,
159
        'caret-down' => 0xf0d7,
160
        'caret-left' => 0xf0d9,
161
        'caret-right' => 0xf0da,
162
        'caret-square-o-down' => 0xf150,
163
        'caret-square-o-left' => 0xf191,
164
        'caret-square-o-right' => 0xf152,
165
        'caret-square-o-up' => 0xf151,
166
        'caret-up' => 0xf0d8,
167
        'cart-arrow-down' => 0xf218,
168
        'cart-plus' => 0xf217,
169
        'cc' => 0xf20a,
170
        'cc-amex' => 0xf1f3,
171
        'cc-diners-club' => 0xf24c,
172
        'cc-discover' => 0xf1f2,
173
        'cc-jcb' => 0xf24b,
174
        'cc-mastercard' => 0xf1f1,
175
        'cc-paypal' => 0xf1f4,
176
        'cc-stripe' => 0xf1f5,
177
        'cc-visa' => 0xf1f0,
178
        'certificate' => 0xf0a3,
179
        'chain' => 0xf0c1,
180
        'chain-broken' => 0xf127,
181
        'check' => 0xf00c,
182
        'check-circle' => 0xf058,
183
        'check-circle-o' => 0xf05d,
184
        'check-square' => 0xf14a,
185
        'check-square-o' => 0xf046,
186
        'chevron-circle-down' => 0xf13a,
187
        'chevron-circle-left' => 0xf137,
188
        'chevron-circle-right' => 0xf138,
189
        'chevron-circle-up' => 0xf139,
190
        'chevron-down' => 0xf078,
191
        'chevron-left' => 0xf053,
192
        'chevron-right' => 0xf054,
193
        'chevron-up' => 0xf077,
194
        'child' => 0xf1ae,
195
        'chrome' => 0xf268,
196
        'circle' => 0xf111,
197
        'circle-o' => 0xf10c,
198
        'circle-o-notch' => 0xf1ce,
199
        'circle-thin' => 0xf1db,
200
        'clipboard' => 0xf0ea,
201
        'clock-o' => 0xf017,
202
        'clone' => 0xf24d,
203
        'close' => 0xf00d,
204
        'cloud' => 0xf0c2,
205
        'cloud-download' => 0xf0ed,
206
        'cloud-upload' => 0xf0ee,
207
        'cny' => 0xf157,
208
        'code' => 0xf121,
209
        'code-fork' => 0xf126,
210
        'codepen' => 0xf1cb,
211
        'codiepie' => 0xf284,
212
        'coffee' => 0xf0f4,
213
        'cog' => 0xf013,
214
        'cogs' => 0xf085,
215
        'columns' => 0xf0db,
216
        'comment' => 0xf075,
217
        'comment-o' => 0xf0e5,
218
        'commenting' => 0xf27a,
219
        'commenting-o' => 0xf27b,
220
        'comments' => 0xf086,
221
        'comments-o' => 0xf0e6,
222
        'compass' => 0xf14e,
223
        'compress' => 0xf066,
224
        'connectdevelop' => 0xf20e,
225
        'contao' => 0xf26d,
226
        'copy' => 0xf0c5,
227
        'copyright' => 0xf1f9,
228
        'creative-commons' => 0xf25e,
229
        'credit-card' => 0xf09d,
230
        'credit-card-alt' => 0xf283,
231
        'crop' => 0xf125,
232
        'crosshairs' => 0xf05b,
233
        'css3' => 0xf13c,
234
        'cube' => 0xf1b2,
235
        'cubes' => 0xf1b3,
236
        'cut' => 0xf0c4,
237
        'cutlery' => 0xf0f5,
238
        'dashboard' => 0xf0e4,
239
        'dashcube' => 0xf210,
240
        'database' => 0xf1c0,
241
        'deaf' => 0xf2a4,
242
        'deafness' => 0xf2a4,
243
        'dedent' => 0xf03b,
244
        'delicious' => 0xf1a5,
245
        'desktop' => 0xf108,
246
        'deviantart' => 0xf1bd,
247
        'diamond' => 0xf219,
248
        'digg' => 0xf1a6,
249
        'dollar' => 0xf155,
250
        'dot-circle-o' => 0xf192,
251
        'download' => 0xf019,
252
        'dribbble' => 0xf17d,
253
        'drivers-license' => 0xf2c2,
254
        'drivers-license-o' => 0xf2c3,
255
        'dropbox' => 0xf16b,
256
        'drupal' => 0xf1a9,
257
        'edge' => 0xf282,
258
        'edit' => 0xf044,
259
        'eercast' => 0xf2da,
260
        'eject' => 0xf052,
261
        'ellipsis-h' => 0xf141,
262
        'ellipsis-v' => 0xf142,
263
        'empire' => 0xf1d1,
264
        'envelope' => 0xf0e0,
265
        'envelope-o' => 0xf003,
266
        'envelope-open' => 0xf2b6,
267
        'envelope-open-o' => 0xf2b7,
268
        'envelope-square' => 0xf199,
269
        'envira' => 0xf299,
270
        'eraser' => 0xf12d,
271
        'etsy' => 0xf2d7,
272
        'eur' => 0xf153,
273
        'euro' => 0xf153,
274
        'exchange' => 0xf0ec,
275
        'exclamation' => 0xf12a,
276
        'exclamation-circle' => 0xf06a,
277
        'exclamation-triangle' => 0xf071,
278
        'expand' => 0xf065,
279
        'expeditedssl' => 0xf23e,
280
        'external-link' => 0xf08e,
281
        'external-link-square' => 0xf14c,
282
        'eye' => 0xf06e,
283
        'eye-slash' => 0xf070,
284
        'eyedropper' => 0xf1fb,
285
        'fa' => 0xf2b4,
286
        'facebook' => 0xf09a,
287
        'facebook-f' => 0xf09a,
288
        'facebook-official' => 0xf230,
289
        'facebook-square' => 0xf082,
290
        'fast-backward' => 0xf049,
291
        'fast-forward' => 0xf050,
292
        'fax' => 0xf1ac,
293
        'feed' => 0xf09e,
294
        'female' => 0xf182,
295
        'fighter-jet' => 0xf0fb,
296
        'file' => 0xf15b,
297
        'file-archive-o' => 0xf1c6,
298
        'file-audio-o' => 0xf1c7,
299
        'file-code-o' => 0xf1c9,
300
        'file-excel-o' => 0xf1c3,
301
        'file-image-o' => 0xf1c5,
302
        'file-movie-o' => 0xf1c8,
303
        'file-o' => 0xf016,
304
        'file-pdf-o' => 0xf1c1,
305
        'file-photo-o' => 0xf1c5,
306
        'file-picture-o' => 0xf1c5,
307
        'file-powerpoint-o' => 0xf1c4,
308
        'file-sound-o' => 0xf1c7,
309
        'file-text' => 0xf15c,
310
        'file-text-o' => 0xf0f6,
311
        'file-video-o' => 0xf1c8,
312
        'file-word-o' => 0xf1c2,
313
        'file-zip-o' => 0xf1c6,
314
        'files-o' => 0xf0c5,
315
        'film' => 0xf008,
316
        'filter' => 0xf0b0,
317
        'fire' => 0xf06d,
318
        'fire-extinguisher' => 0xf134,
319
        'firefox' => 0xf269,
320
        'first-order' => 0xf2b0,
321
        'flag' => 0xf024,
322
        'flag-checkered' => 0xf11e,
323
        'flag-o' => 0xf11d,
324
        'flash' => 0xf0e7,
325
        'flask' => 0xf0c3,
326
        'flickr' => 0xf16e,
327
        'floppy-o' => 0xf0c7,
328
        'folder' => 0xf07b,
329
        'folder-o' => 0xf114,
330
        'folder-open' => 0xf07c,
331
        'folder-open-o' => 0xf115,
332
        'font' => 0xf031,
333
        'font-awesome' => 0xf2b4,
334
        'fonticons' => 0xf280,
335
        'fort-awesome' => 0xf286,
336
        'forumbee' => 0xf211,
337
        'forward' => 0xf04e,
338
        'foursquare' => 0xf180,
339
        'free-code-camp' => 0xf2c5,
340
        'frown-o' => 0xf119,
341
        'futbol-o' => 0xf1e3,
342
        'gamepad' => 0xf11b,
343
        'gavel' => 0xf0e3,
344
        'gbp' => 0xf154,
345
        'ge' => 0xf1d1,
346
        'gear' => 0xf013,
347
        'gears' => 0xf085,
348
        'genderless' => 0xf22d,
349
        'get-pocket' => 0xf265,
350
        'gg' => 0xf260,
351
        'gg-circle' => 0xf261,
352
        'gift' => 0xf06b,
353
        'git' => 0xf1d3,
354
        'git-square' => 0xf1d2,
355
        'github' => 0xf09b,
356
        'github-alt' => 0xf113,
357
        'github-square' => 0xf092,
358
        'gitlab' => 0xf296,
359
        'gittip' => 0xf184,
360
        'glass' => 0xf000,
361
        'glide' => 0xf2a5,
362
        'glide-g' => 0xf2a6,
363
        'globe' => 0xf0ac,
364
        'google' => 0xf1a0,
365
        'google-plus' => 0xf0d5,
366
        'google-plus-circle' => 0xf2b3,
367
        'google-plus-official' => 0xf2b3,
368
        'google-plus-square' => 0xf0d4,
369
        'google-wallet' => 0xf1ee,
370
        'graduation-cap' => 0xf19d,
371
        'gratipay' => 0xf184,
372
        'grav' => 0xf2d6,
373
        'group' => 0xf0c0,
374
        'h-square' => 0xf0fd,
375
        'hacker-news' => 0xf1d4,
376
        'hand-grab-o' => 0xf255,
377
        'hand-lizard-o' => 0xf258,
378
        'hand-o-down' => 0xf0a7,
379
        'hand-o-left' => 0xf0a5,
380
        'hand-o-right' => 0xf0a4,
381
        'hand-o-up' => 0xf0a6,
382
        'hand-paper-o' => 0xf256,
383
        'hand-peace-o' => 0xf25b,
384
        'hand-pointer-o' => 0xf25a,
385
        'hand-rock-o' => 0xf255,
386
        'hand-scissors-o' => 0xf257,
387
        'hand-spock-o' => 0xf259,
388
        'hand-stop-o' => 0xf256,
389
        'handshake-o' => 0xf2b5,
390
        'hard-of-hearing' => 0xf2a4,
391
        'hashtag' => 0xf292,
392
        'hdd-o' => 0xf0a0,
393
        'header' => 0xf1dc,
394
        'headphones' => 0xf025,
395
        'heart' => 0xf004,
396
        'heart-o' => 0xf08a,
397
        'heartbeat' => 0xf21e,
398
        'history' => 0xf1da,
399
        'home' => 0xf015,
400
        'hospital-o' => 0xf0f8,
401
        'hotel' => 0xf236,
402
        'hourglass' => 0xf254,
403
        'hourglass-1' => 0xf251,
404
        'hourglass-2' => 0xf252,
405
        'hourglass-3' => 0xf253,
406
        'hourglass-end' => 0xf253,
407
        'hourglass-half' => 0xf252,
408
        'hourglass-o' => 0xf250,
409
        'hourglass-start' => 0xf251,
410
        'houzz' => 0xf27c,
411
        'html5' => 0xf13b,
412
        'i-cursor' => 0xf246,
413
        'id-badge' => 0xf2c1,
414
        'id-card' => 0xf2c2,
415
        'id-card-o' => 0xf2c3,
416
        'ils' => 0xf20b,
417
        'image' => 0xf03e,
418
        'imdb' => 0xf2d8,
419
        'inbox' => 0xf01c,
420
        'indent' => 0xf03c,
421
        'industry' => 0xf275,
422
        'info' => 0xf129,
423
        'info-circle' => 0xf05a,
424
        'inr' => 0xf156,
425
        'instagram' => 0xf16d,
426
        'institution' => 0xf19c,
427
        'internet-explorer' => 0xf26b,
428
        'intersex' => 0xf224,
429
        'ioxhost' => 0xf208,
430
        'italic' => 0xf033,
431
        'joomla' => 0xf1aa,
432
        'jpy' => 0xf157,
433
        'jsfiddle' => 0xf1cc,
434
        'key' => 0xf084,
435
        'keyboard-o' => 0xf11c,
436
        'krw' => 0xf159,
437
        'language' => 0xf1ab,
438
        'laptop' => 0xf109,
439
        'lastfm' => 0xf202,
440
        'lastfm-square' => 0xf203,
441
        'leaf' => 0xf06c,
442
        'leanpub' => 0xf212,
443
        'legal' => 0xf0e3,
444
        'lemon-o' => 0xf094,
445
        'level-down' => 0xf149,
446
        'level-up' => 0xf148,
447
        'life-bouy' => 0xf1cd,
448
        'life-buoy' => 0xf1cd,
449
        'life-ring' => 0xf1cd,
450
        'life-saver' => 0xf1cd,
451
        'lightbulb-o' => 0xf0eb,
452
        'line-chart' => 0xf201,
453
        'link' => 0xf0c1,
454
        'linkedin' => 0xf0e1,
455
        'linkedin-square' => 0xf08c,
456
        'linode' => 0xf2b8,
457
        'linux' => 0xf17c,
458
        'list' => 0xf03a,
459
        'list-alt' => 0xf022,
460
        'list-ol' => 0xf0cb,
461
        'list-ul' => 0xf0ca,
462
        'location-arrow' => 0xf124,
463
        'lock' => 0xf023,
464
        'long-arrow-down' => 0xf175,
465
        'long-arrow-left' => 0xf177,
466
        'long-arrow-right' => 0xf178,
467
        'long-arrow-up' => 0xf176,
468
        'low-vision' => 0xf2a8,
469
        'magic' => 0xf0d0,
470
        'magnet' => 0xf076,
471
        'mail-forward' => 0xf064,
472
        'mail-reply' => 0xf112,
473
        'mail-reply-all' => 0xf122,
474
        'male' => 0xf183,
475
        'map' => 0xf279,
476
        'map-marker' => 0xf041,
477
        'map-o' => 0xf278,
478
        'map-pin' => 0xf276,
479
        'map-signs' => 0xf277,
480
        'mars' => 0xf222,
481
        'mars-double' => 0xf227,
482
        'mars-stroke' => 0xf229,
483
        'mars-stroke-h' => 0xf22b,
484
        'mars-stroke-v' => 0xf22a,
485
        'maxcdn' => 0xf136,
486
        'meanpath' => 0xf20c,
487
        'medium' => 0xf23a,
488
        'medkit' => 0xf0fa,
489
        'meetup' => 0xf2e0,
490
        'meh-o' => 0xf11a,
491
        'mercury' => 0xf223,
492
        'microchip' => 0xf2db,
493
        'microphone' => 0xf130,
494
        'microphone-slash' => 0xf131,
495
        'minus' => 0xf068,
496
        'minus-circle' => 0xf056,
497
        'minus-square' => 0xf146,
498
        'minus-square-o' => 0xf147,
499
        'mixcloud' => 0xf289,
500
        'mobile' => 0xf10b,
501
        'mobile-phone' => 0xf10b,
502
        'modx' => 0xf285,
503
        'money' => 0xf0d6,
504
        'moon-o' => 0xf186,
505
        'mortar-board' => 0xf19d,
506
        'motorcycle' => 0xf21c,
507
        'mouse-pointer' => 0xf245,
508
        'music' => 0xf001,
509
        'navicon' => 0xf0c9,
510
        'neuter' => 0xf22c,
511
        'newspaper-o' => 0xf1ea,
512
        'object-group' => 0xf247,
513
        'object-ungroup' => 0xf248,
514
        'odnoklassniki' => 0xf263,
515
        'odnoklassniki-square' => 0xf264,
516
        'opencart' => 0xf23d,
517
        'openid' => 0xf19b,
518
        'opera' => 0xf26a,
519
        'optin-monster' => 0xf23c,
520
        'outdent' => 0xf03b,
521
        'pagelines' => 0xf18c,
522
        'paint-brush' => 0xf1fc,
523
        'paper-plane' => 0xf1d8,
524
        'paper-plane-o' => 0xf1d9,
525
        'paperclip' => 0xf0c6,
526
        'paragraph' => 0xf1dd,
527
        'paste' => 0xf0ea,
528
        'pause' => 0xf04c,
529
        'pause-circle' => 0xf28b,
530
        'pause-circle-o' => 0xf28c,
531
        'paw' => 0xf1b0,
532
        'paypal' => 0xf1ed,
533
        'pencil' => 0xf040,
534
        'pencil-square' => 0xf14b,
535
        'pencil-square-o' => 0xf044,
536
        'percent' => 0xf295,
537
        'phone' => 0xf095,
538
        'phone-square' => 0xf098,
539
        'photo' => 0xf03e,
540
        'picture-o' => 0xf03e,
541
        'pie-chart' => 0xf200,
542
        'pied-piper' => 0xf2ae,
543
        'pied-piper-alt' => 0xf1a8,
544
        'pied-piper-pp' => 0xf1a7,
545
        'pinterest' => 0xf0d2,
546
        'pinterest-p' => 0xf231,
547
        'pinterest-square' => 0xf0d3,
548
        'plane' => 0xf072,
549
        'play' => 0xf04b,
550
        'play-circle' => 0xf144,
551
        'play-circle-o' => 0xf01d,
552
        'plug' => 0xf1e6,
553
        'plus' => 0xf067,
554
        'plus-circle' => 0xf055,
555
        'plus-square' => 0xf0fe,
556
        'plus-square-o' => 0xf196,
557
        'podcast' => 0xf2ce,
558
        'power-off' => 0xf011,
559
        'print' => 0xf02f,
560
        'product-hunt' => 0xf288,
561
        'puzzle-piece' => 0xf12e,
562
        'qq' => 0xf1d6,
563
        'qrcode' => 0xf029,
564
        'question' => 0xf128,
565
        'question-circle' => 0xf059,
566
        'question-circle-o' => 0xf29c,
567
        'quora' => 0xf2c4,
568
        'quote-left' => 0xf10d,
569
        'quote-right' => 0xf10e,
570
        'ra' => 0xf1d0,
571
        'random' => 0xf074,
572
        'ravelry' => 0xf2d9,
573
        'rebel' => 0xf1d0,
574
        'recycle' => 0xf1b8,
575
        'reddit' => 0xf1a1,
576
        'reddit-alien' => 0xf281,
577
        'reddit-square' => 0xf1a2,
578
        'refresh' => 0xf021,
579
        'registered' => 0xf25d,
580
        'remove' => 0xf00d,
581
        'renren' => 0xf18b,
582
        'reorder' => 0xf0c9,
583
        'repeat' => 0xf01e,
584
        'reply' => 0xf112,
585
        'reply-all' => 0xf122,
586
        'resistance' => 0xf1d0,
587
        'retweet' => 0xf079,
588
        'rmb' => 0xf157,
589
        'road' => 0xf018,
590
        'rocket' => 0xf135,
591
        'rotate-left' => 0xf0e2,
592
        'rotate-right' => 0xf01e,
593
        'rouble' => 0xf158,
594
        'rss' => 0xf09e,
595
        'rss-square' => 0xf143,
596
        'rub' => 0xf158,
597
        'ruble' => 0xf158,
598
        'rupee' => 0xf156,
599
        's15' => 0xf2cd,
600
        'safari' => 0xf267,
601
        'save' => 0xf0c7,
602
        'scissors' => 0xf0c4,
603
        'scribd' => 0xf28a,
604
        'search' => 0xf002,
605
        'search-minus' => 0xf010,
606
        'search-plus' => 0xf00e,
607
        'sellsy' => 0xf213,
608
        'send' => 0xf1d8,
609
        'send-o' => 0xf1d9,
610
        'server' => 0xf233,
611
        'share' => 0xf064,
612
        'share-alt' => 0xf1e0,
613
        'share-alt-square' => 0xf1e1,
614
        'share-square' => 0xf14d,
615
        'share-square-o' => 0xf045,
616
        'shekel' => 0xf20b,
617
        'sheqel' => 0xf20b,
618
        'shield' => 0xf132,
619
        'ship' => 0xf21a,
620
        'shirtsinbulk' => 0xf214,
621
        'shopping-bag' => 0xf290,
622
        'shopping-basket' => 0xf291,
623
        'shopping-cart' => 0xf07a,
624
        'shower' => 0xf2cc,
625
        'sign-in' => 0xf090,
626
        'sign-language' => 0xf2a7,
627
        'sign-out' => 0xf08b,
628
        'signal' => 0xf012,
629
        'signing' => 0xf2a7,
630
        'simplybuilt' => 0xf215,
631
        'sitemap' => 0xf0e8,
632
        'skyatlas' => 0xf216,
633
        'skype' => 0xf17e,
634
        'slack' => 0xf198,
635
        'sliders' => 0xf1de,
636
        'slideshare' => 0xf1e7,
637
        'smile-o' => 0xf118,
638
        'snapchat' => 0xf2ab,
639
        'snapchat-ghost' => 0xf2ac,
640
        'snapchat-square' => 0xf2ad,
641
        'snowflake-o' => 0xf2dc,
642
        'soccer-ball-o' => 0xf1e3,
643
        'sort' => 0xf0dc,
644
        'sort-alpha-asc' => 0xf15d,
645
        'sort-alpha-desc' => 0xf15e,
646
        'sort-amount-asc' => 0xf160,
647
        'sort-amount-desc' => 0xf161,
648
        'sort-asc' => 0xf0de,
649
        'sort-desc' => 0xf0dd,
650
        'sort-down' => 0xf0dd,
651
        'sort-numeric-asc' => 0xf162,
652
        'sort-numeric-desc' => 0xf163,
653
        'sort-up' => 0xf0de,
654
        'soundcloud' => 0xf1be,
655
        'space-shuttle' => 0xf197,
656
        'spinner' => 0xf110,
657
        'spoon' => 0xf1b1,
658
        'spotify' => 0xf1bc,
659
        'square' => 0xf0c8,
660
        'square-o' => 0xf096,
661
        'stack-exchange' => 0xf18d,
662
        'stack-overflow' => 0xf16c,
663
        'star' => 0xf005,
664
        'star-half' => 0xf089,
665
        'star-half-empty' => 0xf123,
666
        'star-half-full' => 0xf123,
667
        'star-half-o' => 0xf123,
668
        'star-o' => 0xf006,
669
        'steam' => 0xf1b6,
670
        'steam-square' => 0xf1b7,
671
        'step-backward' => 0xf048,
672
        'step-forward' => 0xf051,
673
        'stethoscope' => 0xf0f1,
674
        'sticky-note' => 0xf249,
675
        'sticky-note-o' => 0xf24a,
676
        'stop' => 0xf04d,
677
        'stop-circle' => 0xf28d,
678
        'stop-circle-o' => 0xf28e,
679
        'street-view' => 0xf21d,
680
        'strikethrough' => 0xf0cc,
681
        'stumbleupon' => 0xf1a4,
682
        'stumbleupon-circle' => 0xf1a3,
683
        'subscript' => 0xf12c,
684
        'subway' => 0xf239,
685
        'suitcase' => 0xf0f2,
686
        'sun-o' => 0xf185,
687
        'superpowers' => 0xf2dd,
688
        'superscript' => 0xf12b,
689
        'support' => 0xf1cd,
690
        'table' => 0xf0ce,
691
        'tablet' => 0xf10a,
692
        'tachometer' => 0xf0e4,
693
        'tag' => 0xf02b,
694
        'tags' => 0xf02c,
695
        'tasks' => 0xf0ae,
696
        'taxi' => 0xf1ba,
697
        'telegram' => 0xf2c6,
698
        'television' => 0xf26c,
699
        'tencent-weibo' => 0xf1d5,
700
        'terminal' => 0xf120,
701
        'text-height' => 0xf034,
702
        'text-width' => 0xf035,
703
        'th' => 0xf00a,
704
        'th-large' => 0xf009,
705
        'th-list' => 0xf00b,
706
        'themeisle' => 0xf2b2,
707
        'thermometer' => 0xf2c7,
708
        'thermometer-0' => 0xf2cb,
709
        'thermometer-1' => 0xf2ca,
710
        'thermometer-2' => 0xf2c9,
711
        'thermometer-3' => 0xf2c8,
712
        'thermometer-4' => 0xf2c7,
713
        'thermometer-empty' => 0xf2cb,
714
        'thermometer-full' => 0xf2c7,
715
        'thermometer-half' => 0xf2c9,
716
        'thermometer-quarter' => 0xf2ca,
717
        'thermometer-three-quarters' => 0xf2c8,
718
        'thumb-tack' => 0xf08d,
719
        'thumbs-down' => 0xf165,
720
        'thumbs-o-down' => 0xf088,
721
        'thumbs-o-up' => 0xf087,
722
        'thumbs-up' => 0xf164,
723
        'ticket' => 0xf145,
724
        'times' => 0xf00d,
725
        'times-circle' => 0xf057,
726
        'times-circle-o' => 0xf05c,
727
        'times-rectangle' => 0xf2d3,
728
        'times-rectangle-o' => 0xf2d4,
729
        'tint' => 0xf043,
730
        'toggle-down' => 0xf150,
731
        'toggle-left' => 0xf191,
732
        'toggle-off' => 0xf204,
733
        'toggle-on' => 0xf205,
734
        'toggle-right' => 0xf152,
735
        'toggle-up' => 0xf151,
736
        'trademark' => 0xf25c,
737
        'train' => 0xf238,
738
        'transgender' => 0xf224,
739
        'transgender-alt' => 0xf225,
740
        'trash' => 0xf1f8,
741
        'trash-o' => 0xf014,
742
        'tree' => 0xf1bb,
743
        'trello' => 0xf181,
744
        'tripadvisor' => 0xf262,
745
        'trophy' => 0xf091,
746
        'truck' => 0xf0d1,
747
        'try' => 0xf195,
748
        'tty' => 0xf1e4,
749
        'tumblr' => 0xf173,
750
        'tumblr-square' => 0xf174,
751
        'turkish-lira' => 0xf195,
752
        'tv' => 0xf26c,
753
        'twitch' => 0xf1e8,
754
        'twitter' => 0xf099,
755
        'twitter-square' => 0xf081,
756
        'umbrella' => 0xf0e9,
757
        'underline' => 0xf0cd,
758
        'undo' => 0xf0e2,
759
        'universal-access' => 0xf29a,
760
        'university' => 0xf19c,
761
        'unlink' => 0xf127,
762
        'unlock' => 0xf09c,
763
        'unlock-alt' => 0xf13e,
764
        'unsorted' => 0xf0dc,
765
        'upload' => 0xf093,
766
        'usb' => 0xf287,
767
        'usd' => 0xf155,
768
        'user' => 0xf007,
769
        'user-circle' => 0xf2bd,
770
        'user-circle-o' => 0xf2be,
771
        'user-md' => 0xf0f0,
772
        'user-o' => 0xf2c0,
773
        'user-plus' => 0xf234,
774
        'user-secret' => 0xf21b,
775
        'user-times' => 0xf235,
776
        'users' => 0xf0c0,
777
        'vcard' => 0xf2bb,
778
        'vcard-o' => 0xf2bc,
779
        'venus' => 0xf221,
780
        'venus-double' => 0xf226,
781
        'venus-mars' => 0xf228,
782
        'viacoin' => 0xf237,
783
        'viadeo' => 0xf2a9,
784
        'viadeo-square' => 0xf2aa,
785
        'video-camera' => 0xf03d,
786
        'vimeo' => 0xf27d,
787
        'vimeo-square' => 0xf194,
788
        'vine' => 0xf1ca,
789
        'vk' => 0xf189,
790
        'volume-control-phone' => 0xf2a0,
791
        'volume-down' => 0xf027,
792
        'volume-off' => 0xf026,
793
        'volume-up' => 0xf028,
794
        'warning' => 0xf071,
795
        'wechat' => 0xf1d7,
796
        'weibo' => 0xf18a,
797
        'weixin' => 0xf1d7,
798
        'whatsapp' => 0xf232,
799
        'wheelchair' => 0xf193,
800
        'wheelchair-alt' => 0xf29b,
801
        'wifi' => 0xf1eb,
802
        'wikipedia-w' => 0xf266,
803
        'window-close' => 0xf2d3,
804
        'window-close-o' => 0xf2d4,
805
        'window-maximize' => 0xf2d0,
806
        'window-minimize' => 0xf2d1,
807
        'window-restore' => 0xf2d2,
808
        'windows' => 0xf17a,
809
        'won' => 0xf159,
810
        'wordpress' => 0xf19a,
811
        'wpbeginner' => 0xf297,
812
        'wpexplorer' => 0xf2de,
813
        'wpforms' => 0xf298,
814
        'wrench' => 0xf0ad,
815
        'xing' => 0xf168,
816
        'xing-square' => 0xf169,
817
        'y-combinator' => 0xf23b,
818
        'y-combinator-square' => 0xf1d4,
819
        'yahoo' => 0xf19e,
820
        'yc' => 0xf23b,
821
        'yc-square' => 0xf1d4,
822
        'yelp' => 0xf1e9,
823
        'yen' => 0xf157,
824
        'yoast' => 0xf2b1,
825
        'youtube' => 0xf167,
826
        'youtube-play' => 0xf16a,
827
        'youtube-square' => 0xf166,
828
    ];
829
830
    public function __construct(FrontendInterface $assetsCache)
831
    {
832
        $this->cache = $assetsCache;
833
    }
834
835
    /**
836
     * @param Icon $icon
837
     * @param array $options
838
     */
839
    public function prepareIconMarkup(Icon $icon, array $options = [])
840
    {
841
        $icon->setMarkup($this->generateMarkup($icon, $options));
842
        $icon->setAlternativeMarkup(self::MARKUP_IDENTIFIER_INLINE, $this->generateInlineMarkup($options));
843
    }
844
845
    protected function getName(array $options): string
846
    {
847
        $name = (string)($options['name'] ?? '');
848
        if (strlen($name) === 0) {
849
            throw new \InvalidArgumentException('The option "name" is required and must not be empty', 1440754978);
850
        }
851
        /* Not available in font-awesome, used as a (blank) placeholder icon */
852
        if ($name === 'empty-empty') {
853
            return $name;
854
        }
855
        if (!isset($this->unicodeMap[$name])) {
856
            throw new \InvalidArgumentException('The FontAwesome icon name "' . $name . '" is not defined', 1440754979);
857
        }
858
        return $name;
859
    }
860
861
    /**
862
     * @param Icon $icon
863
     * @param array $options
864
     *
865
     * @throws \InvalidArgumentException
866
     * @return string
867
     */
868
    protected function generateMarkup(Icon $icon, array $options)
869
    {
870
        return '<span class="icon-unify"><i class="fa fa-' . htmlspecialchars($this->getName($options), ENT_QUOTES, 'UTF-8') . '"></i></span>';
871
    }
872
873
    /**
874
     * @param array $options
875
     * @return string
876
     * @throws \InvalidArgumentException
877
     */
878
    protected function generateInlineMarkup(array $options): string
879
    {
880
        $icons = $this->getSvgIcons();
881
        return $icons[$this->getName($options)] ?? '';
882
    }
883
884
    protected function getCacheIdentifier(): string
885
    {
886
        return 'FontawesomeSvgIcons_' . sha1((string)(new Typo3Version()) . Environment::getProjectPath() . 'FontawesomeSvgIcons');
887
    }
888
889
    protected function getSvgIcons(): array
890
    {
891
        $icons = $this->cache->get($this->getCacheIdentifier());
892
        if ($icons !== false) {
893
            return $icons;
894
        }
895
896
        return $this->createSvgIcons();
897
    }
898
899
    protected function createSvgIcons(): array
900
    {
901
        $icons = [];
902
        $doc = $this->getSvgContents('EXT:backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.svg');
903
        if ($doc === null) {
904
            throw new \RuntimeException('Fontawsome SVG webfont could not be loaded.', 1612868955);
905
        }
906
        $defaultUnitsPerEm = 1000; // https://www.w3.org/TR/SVG11/fonts.html#FontFaceElementUnitsPerEmAttribute
907
        $defaultHeight = (int)($doc->xpath('//font-face')[0]['units-per-em'] ?? $defaultUnitsPerEm);
908
        $defaultWidth = (int)($doc->xpath('//font')[0]['horiz-adv-x']);
909
        $viewBoxXOffset = 0;
910
        $viewBoxYOffset = (int)($doc->xpath('//font-face')[0]['descent']);
911
912
        foreach ($this->unicodeMap as $name => $unicode) {
913
            $elements = $doc->xpath('//glyph[@unicode="' . html_entity_decode('&#x' . dechex($unicode) . ';', ENT_NOQUOTES, 'UTF-8') . '"]');
914
            if ($elements === false || count($elements) === 0) {
915
                throw new \RuntimeException('Fontawsome SVG glyph ' . $name . ' not found.', 1612868954);
916
            }
917
            $element = $elements[0];
918
919
            $path = (string)($element['d'] ?? '');
920
            $width = (int)($element['horiz-adv-x'] ?? $defaultWidth);
921
            $height = $defaultHeight;
922
            $transformOriginX = $width / 2 + $viewBoxXOffset;
923
            $transformOriginY = $height / 2 + $viewBoxYOffset;
924
925
            $svg = vsprintf(
926
                '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="%s %s %s %s" class="icon-unify"><path transform="scale(1 -1)" transform-origin="%s %s" class="icon-color" d="%s" /></svg>',
927
                $this->escape([
928
                    $viewBoxXOffset,
929
                    $viewBoxYOffset,
930
                    $width,
931
                    $height,
932
                    $transformOriginX,
933
                    $transformOriginY,
934
                    $path,
935
                ])
936
            );
937
938
            $icons[$name] = $svg;
939
        }
940
941
        $this->cache->set($this->getCacheIdentifier(), $icons);
942
        return $icons;
943
    }
944
945
    protected function getSvgContents(string $source): ?\SimpleXMLElement
946
    {
947
        $source = GeneralUtility::getFileAbsFileName($source);
948
        if (!file_exists($source)) {
949
            return null;
950
        }
951
952
        $svgContent = file_get_contents($source);
953
        if ($svgContent === false) {
954
            return null;
955
        }
956
        // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
957
        $previousValueOfEntityLoader = null;
958
        if (PHP_MAJOR_VERSION < 8) {
959
            $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
960
        }
961
        $svgElement = simplexml_load_string($svgContent);
962
        if (PHP_MAJOR_VERSION < 8) {
963
            libxml_disable_entity_loader($previousValueOfEntityLoader);
0 ignored issues
show
Bug introduced by
It seems like $previousValueOfEntityLoader can also be of type null; however, parameter $disable of libxml_disable_entity_loader() does only seem to accept boolean, 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

963
            libxml_disable_entity_loader(/** @scrutinizer ignore-type */ $previousValueOfEntityLoader);
Loading history...
964
        }
965
        if ($svgElement === false) {
966
            return null;
967
        }
968
969
        return $svgElement;
970
    }
971
972
    protected function escape(array $strings): array
973
    {
974
        return array_map(
975
            function (string $value): string {
976
                return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
977
            },
978
            $strings
979
        );
980
    }
981
}
982