Passed
Push — master ( 4a5f5f...d4ccbb )
by Sebastian
03:14
created

Localization::getSelectedKeyByNS()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 10
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 16
rs 9.9332
1
<?php
2
/**
3
 * File containing the {@link Localization} class.
4
 * @package Localization
5
 * @subpackage Core
6
 * @see Localization
7
 */
8
9
declare(strict_types=1);
10
11
namespace AppLocalize;
12
13
use HTML_QuickForm2_Container;
14
use HTML_QuickForm2_Element_Select;
15
16
/**
17
 * Localization handling collection for both the
18
 * application itself as well as its user contents.
19
 *
20
 * @package Localization
21
 * @subpackage Core
22
 * @author Sebastian Mordziol <[email protected]>
23
 */
24
class Localization
25
{
26
    const ERROR_UNKNOWN_CONTENT_LOCALE = 39001;
27
    const ERROR_UNKNOWN_APPLICATION_LOCALE = 39002;
28
    const ERROR_NO_STORAGE_FILE_SET = 39003;
29
    const ERROR_CONFIGURE_NOT_CALLED = 39004;
30
    const ERROR_NO_SOURCES_ADDED = 39005;
31
    const ERROR_NO_LOCALE_SELECTED_IN_NS = 39006;
32
    const ERROR_NO_LOCALES_IN_NAMESPACE = 39007;
33
    const ERROR_UNKNOWN_NAMESPACE = 39008;
34
    const ERROR_UNKNOWN_LOCALE_IN_NS = 39009;
35
    const ERROR_UNKNOWN_EVENT_NAME = 39010;
36
    
37
    /**
38
     * The name of the default application locale, i.e. the
39
     * locale in which application textual content is written.
40
     *
41
     * @var string
42
     */
43
    const BUILTIN_LOCALE_NAME = 'en_UK';
44
45
    const NAMESPACE_APPLICATION = '__application';
46
    
47
    const NAMESPACE_CONTENT = '__content';
48
    const EVENT_LOCALE_CHANGED = 'LocaleChanged';
49
50
    /**
51
    * Collection of all locales by namespace (application, content, custom...). 
52
    *
53
    * @var array<string,array<string,Localization_Locale>>
54
    * @see Localization::addLocale()
55
    */
56
    protected static $locales = array();
57
58
    /**
59
     * @var boolean
60
     * @see Localization::init()
61
     */
62
    private static $initDone = false;
63
64
   /**
65
    * Path to the file in which the scanner results are stored.
66
    * @var string
67
    * @see Localization::configure()
68
    */
69
    protected static $storageFile = '';
70
    
71
   /**
72
    * Path to the folder into which the client libraries are written.
73
    * @var string
74
    * @see Localization::setClientLibrariesFolder()
75
    */
76
    protected static $clientFolder = '';
77
    
78
   /**
79
    * If this key changes, client libraries are refreshed.
80
    * @var string
81
    * @see Localization::setClientLibrariesCacheKey()
82
    */
83
    protected static $clientCacheKey = '';
84
    
85
   /**
86
    * Whether the configuration has been made.
87
    * @var bool
88
    * @see Localization::configure()
89
    */
90
    protected static $configured = false;
91
    
92
   /**
93
    * Stores event listener instances.
94
    * @var array
95
    */
96
    protected static $listeners = array();
97
    
98
   /**
99
    * @var integer
100
    * @see Localization::addEventListener()
101
    */
102
    protected static $listenersCounter = 0;
103
    
104
   /**
105
    * @var Localization_Translator|NULL
106
    */
107
    protected static $translator;
108
    
109
   /**
110
    * Initializes the localization layer. This is done
111
    * automatically, and only once per request.
112
    * 
113
    * (Called at the end of this file)
114
    */
115
    public static function init() : void
116
    {
117
        if(self::$initDone) {
118
            return;
119
        }
120
121
        self::reset();
122
        
123
        $installFolder = realpath(__DIR__.'/../');
124
        
125
        // add the localization package's own sources,
126
        // so the bundled localized strings can
127
        // always be translated.
128
        \AppLocalize\Localization::addSourceFolder(
129
            'application-localization',
130
            'Application Localization Package',
131
            'Composer packages',
132
            $installFolder.'/localization',
133
            $installFolder.'/src'
134
        )
135
        ->excludeFiles(array('jtokenizer'))
136
        ->excludeFolder('css');
137
        
138
        self::$initDone = true;
139
    }
140
141
    /**
142
     * Retrieves all available application locales, as an indexed
143
     * array with locale objects sorted by locale label.
144
     *
145
     * @return Localization_Locale[]
146
     * @see getAppLocale()
147
     */
148
    public static function getAppLocales()
149
    {
150
        return self::getLocalesByNS(self::NAMESPACE_APPLICATION);
151
    }
152
    
153
   /**
154
    * Retrieves all locales in the specified namespace.
155
    * 
156
    * @param string $namespace
157
    * @return Localization_Locale[]
158
    */
159
    public static function getLocalesByNS(string $namespace)
160
    {
161
        if(isset(self::$locales[$namespace])) {
162
            return array_values(self::$locales[$namespace]);
163
        }
164
        
165
        throw new Localization_Exception(
166
            'No locales available in namespace',
167
            sprintf(
168
                'The namespace [%s] does not exist.',
169
                $namespace
170
            ),
171
            self::ERROR_NO_LOCALES_IN_NAMESPACE
172
        );
173
    }
174
    
175
   /**
176
    * Adds an application locale to use in the application.
177
    * 
178
    * @param string $localeName
179
    * @return Localization_Locale
180
    */
181
    public static function addAppLocale(string $localeName) : Localization_Locale
182
    {
183
        return self::addLocaleByNS($localeName, self::NAMESPACE_APPLICATION);
184
    }
185
    
186
   /**
187
    * Adds a content locale to use for content in the application.
188
    * 
189
    * @param string $localeName
190
    * @return Localization_Locale
191
    */
192
    public static function addContentLocale(string $localeName) : Localization_Locale
193
    {
194
        return self::addLocaleByNS($localeName, self::NAMESPACE_CONTENT);
195
    }
196
    
197
   /**
198
    * Adds a locale to the specified namespace.
199
    * 
200
    * @param string $localeName
201
    * @param string $namespace
202
    * @return Localization_Locale
203
    */
204
    public static function addLocaleByNS(string $localeName, string $namespace) : Localization_Locale
205
    {
206
        if(!isset(self::$locales[$namespace])) {
207
            self::$locales[$namespace] = array();
208
        }
209
        
210
        if(!isset(self::$locales[$namespace][$localeName])) 
211
        {
212
            self::$locales[$namespace][$localeName] = self::createLocale($localeName);
213
            
214
            // sort the locales on add: less resource intensive
215
            // than doing it on getting locales.
216
            uasort(self::$locales[$namespace], function(Localization_Locale $a, Localization_Locale $b) {
217
                return strnatcasecmp($a->getLabel(), $b->getLabel());
218
            });
219
        }
220
        
221
        return self::$locales[$namespace][$localeName];
222
    }
223
    
224
    /**
225
     * @param string $localeName
226
     * @return Localization_Locale
227
     */
228
    protected static function createLocale(string $localeName)
229
    {
230
        return new Localization_Locale($localeName);
231
    }
232
233
    /**
234
     * Creates a new country object for the specified country, e.g. "uk".
235
     *
236
     * @param string $id
237
     * @return Localization_Country
238
     */
239
    public static function createCountry(string $id)
240
    {
241
        $className = '\AppLocalize\Localization_Country_' . strtoupper($id);
242
        return new $className();
243
    }
244
    
245
   /**
246
    * Retrieves the currency of the selected app locale.
247
    * 
248
    * @return Localization_Currency
249
    */
250
    public static function getAppCurrency() : Localization_Currency
251
    {
252
        return self::getCurrencyNS(self::NAMESPACE_APPLICATION);
253
    }
254
255
    /**
256
     * Retrieves the currency of the selected content locale.
257
     *
258
     * @return Localization_Currency
259
     */
260
    public static function getContentCurrency() : Localization_Currency
261
    {
262
        return self::getCurrencyNS(self::NAMESPACE_CONTENT);
263
    }
264
    
265
    /**
266
     * Retrieves the currency of the selected locale in the specified namespace.
267
     *
268
     * @param string $namespace
269
     * @return Localization_Currency
270
     */
271
    public static function getCurrencyNS(string $namespace) : Localization_Currency
272
    {
273
        return self::getSelectedLocaleByNS($namespace)->getCurrency();
274
    }
275
    
276
    /**
277
     * Retrieves the selected application locale instance. 
278
     *
279
     * @return Localization_Locale
280
     */
281
    public static function getAppLocale() : Localization_Locale
282
    {
283
        return self::getSelectedLocaleByNS(self::NAMESPACE_APPLICATION);
284
    }
285
    
286
   /**
287
    * Retrieves the name of the selected application locale.
288
    * 
289
    * @return string
290
    */
291
    public static function getAppLocaleName() : string
292
    {
293
        return self::getLocaleNameByNS(self::NAMESPACE_APPLICATION);
294
    }
295
    
296
   /**
297
    * Retrieves the names of the available application locales.
298
    * @return string[]
299
    */
300
    public static function getAppLocaleNames() : array
301
    {
302
        return self::getLocaleNamesByNS(self::NAMESPACE_APPLICATION);
303
    }
304
    
305
   /**
306
    * Retrieves the selected locale name in the specified namespace.
307
    * 
308
    * @param string $namespace
309
    * @throws Localization_Exception
310
    * @return string
311
    */
312
    public static function getLocaleNameByNS(string $namespace) : string
313
    {
314
        return self::getSelectedLocaleByNS($namespace)->getName();
315
    }
316
    
317
   /**
318
    * Retrieves the selected locale instance for the specified namespace.
319
    * 
320
    * @param string $namespace
321
    * @return Localization_Locale
322
    * @throws Localization_Exception
323
    */
324
    public static function getSelectedLocaleByNS(string $namespace) : Localization_Locale
325
    {
326
        self::requireNamespace($namespace);
327
        
328
        if(isset(self::$selected[$namespace])) {
329
            return self::$selected[$namespace];
330
        }
331
        
332
        throw new Localization_Exception(
333
            'No selected locale in namespace.',
334
            sprintf(
335
                'Cannot retrieve selected locale: no locale has been selected in the namespace [%s].',
336
                $namespace
337
            ),
338
            self::ERROR_NO_LOCALE_SELECTED_IN_NS
339
        );
340
    }
341
    
342
   /**
343
    * Stores the selected locale names by namespace.
344
    * @var array<string,Localization_Locale>
345
    */
346
    protected static $selected = array();
347
348
   /**
349
    * Selects the active locale for the specified namespace.
350
    *
351
    * NOTE: Triggers the "LocaleChanged" event.
352
    * 
353
    * @param string $localeName
354
    * @param string $namespace
355
    * @return Localization_Locale
356
    * @throws Localization_Exception
357
    *
358
    * @see Localization_Event_LocaleChanged
359
    */
360
    public static function selectLocaleByNS(string $localeName, string $namespace) : Localization_Locale
361
    {
362
        self::requireNamespace($namespace);
363
        
364
        $locale = self::addLocaleByNS($localeName, $namespace);
365
        $previous = null;
366
        
367
        if(isset(self::$selected[$namespace])) 
368
        {
369
            if(self::$selected[$namespace]->getName() === $localeName) {
370
                return $locale;
371
            }
372
            
373
            $previous = self::$selected[$namespace];
374
        }
375
        
376
        self::$translator = null;
377
378
        self::$selected[$namespace] = $locale;
379
        
380
        self::triggerEvent(
381
            self::EVENT_LOCALE_CHANGED,
382
            array(
383
                $namespace,
384
                $previous, 
385
                self::$selected[$namespace]
386
            )
387
        );
388
        
389
        return $locale;
390
    }
391
392
    /**
393
     * Triggers the specified event, with the provided arguments.
394
     *
395
     * @param string $name The event name.
396
     * @param array $argsList
397
     * @return Localization_Event
398
     * @see Localization_Event
399
     */
400
    protected static function triggerEvent(string $name, array $argsList) : Localization_Event
401
    {
402
        $class = Localization_Event::class.'_'.$name;
403
        $event = new $class($argsList);
404
        
405
        if(!isset(self::$listeners[$name])) {
406
            return $event;
407
        }
408
        
409
        foreach(self::$listeners[$name] as $listener) 
410
        {
411
            $callArgs = $listener['args'];
412
            array_unshift($callArgs, $event);
413
            
414
            call_user_func_array($listener['callback'], $callArgs);
415
        }
416
        
417
        return $event;
418
    }
419
420
    /**
421
     * Adds a listener to the specified event name.
422
     *
423
     * @param string $eventName
424
     * @param callable $callback
425
     * @param array $args Additional arguments to add to the event
426
     * @return int The listener number.
427
     *
428
     * @throws Localization_Exception
429
     * @see \AppLocalize\Localization::ERROR_UNKNOWN_EVENT_NAME
430
     */
431
    public static function addEventListener(string $eventName, $callback, array $args=array()) : int
432
    {
433
        if(!isset(self::$listeners[$eventName])) {
434
            self::$listeners[$eventName] = array();
435
        }
436
        
437
        $className = Localization_Event::class.'_'.$eventName;
438
        
439
        if(!class_exists($className)) 
440
        {
441
            throw new Localization_Exception(
442
                sprintf('Unknown localization event [%s].', $eventName),
443
                sprintf('The required event class [%s] is not present.', $className),
444
                self::ERROR_UNKNOWN_EVENT_NAME
445
            );
446
        }
447
        
448
        self::$listenersCounter++;
449
        
450
        self::$listeners[$eventName][] = array(
451
            'class' => $className,
452
            'callback' => $callback,
453
            'args' => $args,
454
            'id' => self::$listenersCounter
455
        );
456
        
457
        return self::$listenersCounter;
458
    }
459
460
    /**
461
     * Adds an event listener for the <code>LocaleChanged</code> event,
462
     * which is triggered every time a locale is changed in any of the
463
     * available namespaces.
464
     *
465
     * The first parameter of the callback is always the event instance.
466
     *
467
     * @param callable $callback The listener function to call.
468
     * @param array $args Optional indexed array with additional arguments to pass on to the callback function.
469
     * @return int
470
     * @throws Localization_Exception
471
     * @see Localization_Event_LocaleChanged
472
     */
473
    public static function onLocaleChanged($callback, array $args=array()) : int
474
    {
475
        return self::addEventListener(self::EVENT_LOCALE_CHANGED, $callback, $args);
476
    }
477
478
    /**
479
     * Selects the application locale to use.
480
     *
481
     * @param string $localeName
482
     * @return Localization_Locale
483
     * @throws Localization_Exception
484
     */
485
    public static function selectAppLocale(string $localeName) : Localization_Locale
486
    {
487
        return self::selectLocaleByNS($localeName, self::NAMESPACE_APPLICATION);
488
    }
489
490
   /**
491
    * Retrieves an application locale by its name. 
492
    * Note that the locale must have been added first.
493
    * 
494
    * @param string $localeName
495
    * @throws Localization_Exception
496
    * @return Localization_Locale
497
    * @see Localization::appLocaleExists()
498
    */
499
    public static function getAppLocaleByName(string $localeName) : Localization_Locale
500
    {
501
        return self::getLocaleByNameNS($localeName, self::NAMESPACE_APPLICATION);
502
    }
503
504
    /**
505
     * Checks by the locale name if the specified locale is
506
     * available as a locale for the application.
507
     *
508
     * @param string $localeName
509
     * @return boolean
510
     */
511
    public static function appLocaleExists(string $localeName) : bool
512
    {
513
        return self::localeExistsInNS($localeName, self::NAMESPACE_APPLICATION);
514
    }
515
   
516
    public static function localeExistsInNS(string $localeName, string $namespace) : bool
517
    {
518
        return isset(self::$locales[$namespace]) && isset(self::$locales[$namespace][$localeName]);
519
    }
520
521
    /**
522
     * Retrieves an indexed array with all available content locales,
523
     * sorted by locale label.
524
     *
525
     * @return Localization_Locale[];
526
     * @throws Localization_Exception
527
     */
528
    public static function getContentLocales()
529
    {
530
        return self::getLocalesByNS(self::NAMESPACE_CONTENT);
531
    }
532
    
533
   /**
534
    * Retrieves the names of all content locales that have been added.
535
    * @return string[]
536
    */
537
    public static function getContentLocaleNames()
538
    {
539
        return self::getLocaleNamesByNS(self::NAMESPACE_CONTENT);
540
    }
541
542
    /**
543
     * Retrieves all locale names available in the specified namespace.
544
     * The names are sorted alphabetically.
545
     *
546
     * @param string $namespace
547
     * @return string[]
548
     * @throws Localization_Exception
549
     */
550
    public static function getLocaleNamesByNS(string $namespace) : array
551
    {
552
        self::requireNamespace($namespace);
553
        
554
        $names = array_keys(self::$locales[$namespace]);
555
        
556
        sort($names);
557
        
558
        return $names;
559
     }
560
    
561
    /**
562
     * Checks by the locale name if the specified locale is
563
     * available as a locale for the user data.
564
     *
565
     * @param string $localeName
566
     * @return boolean
567
     */
568
    public static function contentLocaleExists(string $localeName) : bool
569
    {
570
        return self::localeExistsInNS($localeName, self::NAMESPACE_CONTENT);
571
    }
572
573
    /**
574
     * Retrieves a specific content locale object by the locale name.
575
     * Note that you should check if it exists first to avoid triggering
576
     * an Exception if it does not.
577
     *
578
     * @param string $localeName
579
     * @throws Localization_Exception
580
     * @return Localization_Locale
581
     * @see Localization::contentLocaleExists()
582
     */
583
    public static function getContentLocaleByName($localeName) : Localization_Locale
584
    {
585
        return self::getLocaleByNameNS($localeName, self::NAMESPACE_CONTENT);
586
    }
587
    
588
   /**
589
    * Retrieves a locale by its name in the specified namespace.
590
    * 
591
    * @param string $localeName
592
    * @param string $namespace
593
    * @throws Localization_Exception
594
    * @return Localization_Locale
595
    */
596
    public static function getLocaleByNameNS(string $localeName, string $namespace) : Localization_Locale
597
    {
598
        self::requireNamespace($namespace);
599
        
600
        if(isset(self::$locales[$namespace]) && isset(self::$locales[$namespace][$localeName])) {
601
            return self::$locales[$namespace][$localeName];
602
        }
603
        
604
        throw new Localization_Exception(
605
            'Unknown locale in namespace',
606
            sprintf(
607
                'The locale [%s] has not been added to the namespace [%s].',
608
                $localeName,
609
                $namespace
610
            ),
611
            self::ERROR_UNKNOWN_LOCALE_IN_NS
612
        );
613
    }
614
615
    /**
616
     * Retrieves the currently selected content locale.
617
     *
618
     * @return Localization_Locale
619
     * @throws Localization_Exception
620
     */
621
    public static function getContentLocale() : Localization_Locale
622
    {
623
        return self::getSelectedLocaleByNS(self::NAMESPACE_CONTENT);
624
    }
625
626
    /**
627
     * @return string
628
     * @throws Localization_Exception
629
     */
630
    public static function getContentLocaleName() : string
631
    {
632
        return self::getSelectedLocaleByNS(self::NAMESPACE_CONTENT)->getName();
633
    }
634
635
    /**
636
     * @param Localization_Locale $locale
637
     * @return bool
638
     */
639
    public static function isActiveAppLocale(Localization_Locale $locale) : bool
640
    {
641
        return $locale->getName() === self::getAppLocaleName();
642
    }
643
644
    /**
645
     * Checks whether the specified locale is the current content locale.
646
     * @param Localization_Locale $locale
647
     * @return boolean
648
     * @throws Localization_Exception
649
     */
650
    public static function isActiveContentLocale(Localization_Locale $locale) : bool
651
    {
652
        return $locale->getName() === self::getContentLocaleName();
653
    }
654
655
    /**
656
     * Selects a specific content locale
657
     * @param string $localeName
658
     * @return Localization_Locale
659
     * @throws Localization_Exception
660
     */
661
    public static function selectContentLocale(string $localeName) : Localization_Locale
662
    {
663
        return self::selectLocaleByNS($localeName, self::NAMESPACE_CONTENT);
664
    }
665
    
666
   /**
667
    * Checks whether the localization has been configured entirely.
668
    * @return bool
669
    */
670
    public static function isConfigured() : bool
671
    {
672
        return self::$configured;
673
    }
674
675
    /**
676
     * @param Localization_Locale|null $locale
677
     * @return Localization_Translator
678
     */
679
    public static function getTranslator(?Localization_Locale $locale=null) : Localization_Translator
680
    {
681
        if($locale !== null)
682
        {
683
            $obj = new Localization_Translator();
684
            $obj->addSources(self::getSources());
685
            $obj->setTargetLocale($locale);
686
            return $obj;
687
        }
688
            
689
        if(!isset(self::$translator)) 
690
        {
691
            $obj = new Localization_Translator();
692
            $obj->addSources(self::getSources());
693
            $obj->setTargetLocale(self::getAppLocale());
694
            self::$translator = $obj;
695
        }
696
697
        return self::$translator;
698
    }
699
700
    public static function countContentLocales() : int
701
    {
702
        return self::countLocalesByNS(self::NAMESPACE_CONTENT);
703
    }
704
705
    public static function countAppLocales() : int
706
    {
707
        return self::countLocalesByNS(self::NAMESPACE_APPLICATION);
708
    }
709
    
710
    public static function countLocalesByNS(string $namespace) : int
711
    {
712
        self::requireNamespace($namespace);
713
        
714
        if(isset(self::$locales[$namespace])) {
715
            return count(self::$locales[$namespace]);
716
        }
717
        
718
        return 0;
719
    }
720
721
    /**
722
     * @param string $namespace
723
     * @throws Localization_Exception
724
     */
725
    protected static function requireNamespace(string $namespace) : void
726
    {
727
        if(isset(self::$locales[$namespace])) {
728
            return;
729
        }
730
        
731
        throw new Localization_Exception(
732
            'Cannot count locales in unknown namespace',
733
            sprintf(
734
                'The namespace [%s] does not exist.',
735
                $namespace
736
            ),
737
            self::ERROR_UNKNOWN_NAMESPACE
738
        );
739
    }
740
    
741
   /**
742
    * Injects a content locales selector element into the specified
743
    * HTML QuickForm2 container.
744
    * 
745
    * @param string $elementName
746
    * @param HTML_QuickForm2_Container $container
747
    * @param string $label
748
    * @return HTML_QuickForm2_Element_Select
749
    */
750
    public static function injectContentLocalesSelector(string $elementName, HTML_QuickForm2_Container $container, string $label='') : HTML_QuickForm2_Element_Select
751
    {
752
        return self::injectLocalesSelectorNS($elementName, self::NAMESPACE_CONTENT, $container, $label);
753
    }
754
    
755
   /**
756
    * Injects an app locales selector element into the specified
757
     * HTML QuickForm2 container.
758
     * 
759
    * @param string $elementName
760
    * @param HTML_QuickForm2_Container $container
761
    * @param string $label
762
    * @return HTML_QuickForm2_Element_Select
763
    */
764
    public static function injectAppLocalesSelector(string $elementName, HTML_QuickForm2_Container $container, string $label='') : HTML_QuickForm2_Element_Select
765
    {
766
        return self::injectLocalesSelectorNS($elementName, self::NAMESPACE_APPLICATION, $container, $label);
767
    }
768
769
    /**
770
     * Injects a locales selector element into the specified
771
     * HTML QuickForm2 container, for the specified locales
772
     * namespace.
773
     *
774
     * @param string $elementName
775
     * @param string $namespace
776
     * @param HTML_QuickForm2_Container $container
777
     * @param string $label
778
     * @return HTML_QuickForm2_Element_Select
779
     * @throws Localization_Exception
780
     */
781
    public static function injectLocalesSelectorNS(string $elementName, string $namespace, HTML_QuickForm2_Container $container, string $label='') : HTML_QuickForm2_Element_Select
782
    {
783
        if(empty($label)) {
784
            $label = t('Language');
785
        }
786
787
        $select = $container->addSelect($elementName);
788
        $select->setLabel($label);
789
790
        $locales = self::getLocalesByNS($namespace);
791
        
792
        foreach($locales as $locale) {
793
            $select->addOption($locale->getLabel(), $locale->getName());
794
        }
795
796
        return $select;
797
    }
798
799
   /**
800
    * @var Localization_Source[]
801
    */
802
    protected static $sources = array();
803
    
804
   /**
805
    * @var string[]
806
    */
807
    protected static $excludeFolders = array();
808
    
809
   /**
810
    * @var string[]
811
    */
812
    protected static $excludeFiles = array();
813
    
814
   /**
815
    * Retrieves all currently available sources.
816
    * 
817
    * @return Localization_Source[]
818
    */
819
    public static function getSources() : array
820
    {
821
        return self::$sources;
822
    }
823
    
824
    public static function addExcludeFolder(string $folderName) : void
825
    { 
826
        if(!in_array($folderName, self::$excludeFolders)) {
827
            self::$excludeFolders[] = $folderName;
828
        }
829
    }
830
    
831
    public static function addExcludeFile(string $fileName) : void
832
    {
833
        if(!in_array($fileName, self::$excludeFiles)) {
834
            self::$excludeFiles[] = $fileName;
835
        }
836
    }
837
    
838
    public static function addSourceFolder(string $alias, string $label, string $group, string $storageFolder, string $path) : Localization_Source_Folder
839
    {
840
        $source = new Localization_Source_Folder($alias, $label, $group, $storageFolder, $path);
841
        self::$sources[] = $source;
842
843
        usort(self::$sources, function(Localization_Source $a, Localization_Source $b) {
844
            return strnatcasecmp($a->getLabel(), $b->getLabel());
845
        });
846
        
847
        return $source;
848
    }
849
    
850
   /**
851
    * Retrieves all sources grouped by their group name.
852
    * @return array
853
    */
854
    public static function getSourcesGrouped()
855
    {
856
        $sources = self::getSources();
857
        
858
        $grouped = array();
859
        
860
        foreach($sources as $source) 
861
        {
862
            $group = $source->getGroup();
863
            
864
            if(!isset($grouped[$group])) {
865
                $grouped[$group] = array();
866
            }
867
            
868
            $grouped[$group][] = $source;
869
        }
870
        
871
        return $grouped;
872
    }
873
    
874
   /**
875
    * Checks whether a specific source exists by its ID.
876
    * @param string $sourceID
877
    * @return boolean
878
    */
879
    public static function sourceExists(string $sourceID) : bool
880
    {
881
        $sources = self::getSources();
882
        foreach($sources as $source) {
883
            if($source->getID() == $sourceID) {
884
                return true;
885
            }
886
        }
887
        
888
        return false;
889
    }
890
    
891
   /**
892
    * Checks whether a specific source exists by its alias.
893
    * @param string $sourceAlias
894
    * @return boolean
895
    */
896
    public static function sourceAliasExists(string $sourceAlias) : bool
897
    {
898
        $sources = self::getSources();
899
        foreach($sources as $source) {
900
            if($source->getAlias() == $sourceAlias) {
901
                return true;
902
            }
903
        }
904
        
905
        return false;
906
    }
907
908
   /**
909
    * Retrieves a localization source by its ID.
910
    * 
911
    * @param string $sourceID
912
    * @throws Localization_Exception
913
    * @return Localization_Source
914
    */
915
    public static function getSourceByID(string $sourceID) : Localization_Source
916
    {
917
        $sources = self::getSources();
918
        foreach($sources as $source) {
919
            if($source->getID() == $sourceID) {
920
                return $source;
921
            }
922
        }
923
        
924
        throw new Localization_Exception(
925
            'Unknown localization source',
926
            sprintf(
927
                'The source [%s] has not been added. Available soources are: [%s].',
928
                $sourceID,
929
                implode(', ', self::getSourceIDs())
930
            )
931
        );
932
    }
933
    
934
    /**
935
     * Retrieves a localization source by its ID.
936
     *
937
     * @param string $sourceAlias
938
     * @throws Localization_Exception
939
     * @return Localization_Source
940
     */
941
    public static function getSourceByAlias(string $sourceAlias) : Localization_Source
942
    {
943
        $sources = self::getSources();
944
        foreach($sources as $source) {
945
            if($source->getAlias() == $sourceAlias) {
946
                return $source;
947
            }
948
        }
949
        
950
        throw new Localization_Exception(
951
            'Unknown localization source',
952
            sprintf(
953
                'The source [%s] has not been added. Available soources are: [%s].',
954
                $sourceAlias,
955
                implode(', ', self::getSourceAliases())
956
            )
957
        );
958
    }
959
960
    /**
961
     * Creates the scanner instance that is used to find
962
     * all translatable strings in the application.
963
     *
964
     * @return Localization_Scanner
965
     * @throws Localization_Exception
966
     */
967
    public static function createScanner() : Localization_Scanner
968
    {
969
        self::requireConfiguration();
970
        
971
        return new Localization_Scanner(self::$storageFile);
972
    }
973
    
974
    public static function log(string $message) : void
0 ignored issues
show
Unused Code introduced by
The parameter $message is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

974
    public static function log(/** @scrutinizer ignore-unused */ string $message) : void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
975
    {
976
        // FIXME: TODO: Add this
977
    }
978
    
979
   /**
980
    * Configures the localization for the application:
981
    * sets the location of the required files and folders.
982
    * Also updated the client library files as needed.
983
    * 
984
    * @param string $storageFile Where to store the file analysis storage file.
985
    * @param string $clientLibrariesFolder Where to put the client libraries and translation files. Will be created if it does not exist. Optional: if not set, client libraries will not be created.
986
    */
987
    public static function configure(string $storageFile, string $clientLibrariesFolder='') : void
988
    {
989
        self::$configured = true;
990
        
991
        self::$storageFile = $storageFile;
992
        self::$clientFolder = $clientLibrariesFolder;
993
994
        // only write the client libraries to disk if the folder
995
        // has been specified.
996
        if(!empty($clientLibrariesFolder)) 
997
        {
998
            self::writeClientFiles();
999
        }
1000
    }
1001
    
1002
   /**
1003
    * Sets a key that is used to verify whether the client
1004
    * libraries have to be refreshed. A common use is to set
1005
    * this to the application's version number to guarantee
1006
    * new texts are automatically used with each release.
1007
    * 
1008
    * NOTE: Otherwise files are refreshed only when saving 
1009
    * them in the editor UI.
1010
    *  
1011
    * @param string $key
1012
    */
1013
    public static function setClientLibrariesCacheKey(string $key) : void
1014
    {
1015
        self::$clientCacheKey = $key;
1016
    }
1017
    
1018
    public static function getClientLibrariesCacheKey() : string
1019
    {
1020
        return self::$clientCacheKey;
1021
    }
1022
    
1023
   /**
1024
    * Sets the folder where client libraries are to be stored.
1025
    * @param string $folder
1026
    */
1027
    public static function setClientLibrariesFolder(string $folder) : void
1028
    {
1029
        self::$clientFolder = $folder;
1030
    }
1031
    
1032
   /**
1033
    * Retrieves the path to the folder in which the client
1034
    * libraries should be stored.
1035
    * 
1036
    * NOTE: Can return an empty string, when this is disabled.
1037
    * 
1038
    * @return string
1039
    */
1040
    public static function getClientLibrariesFolder() : string
1041
    {
1042
        return self::$clientFolder;
1043
    }
1044
1045
    /**
1046
     * Writes / updates the client library files on disk,
1047
     * at the location specified in the {@link Localization::configure()}
1048
     * method.
1049
     *
1050
     * @param bool $force Whether to refresh the files, even if they exist.
1051
     * @throws Localization_Exception
1052
     * @see Localization_ClientGenerator
1053
     */
1054
    public static function writeClientFiles(bool $force=false) : void
1055
    {
1056
        self::createGenerator()->writeFiles($force);
1057
    }
1058
    
1059
   /**
1060
    * Creates a new instance of the client generator class
1061
    * that is used to write the localization files into the
1062
    * target folder on disk.
1063
    * 
1064
    * @return Localization_ClientGenerator
1065
    */
1066
    public static function createGenerator() : Localization_ClientGenerator
1067
    {
1068
        return new Localization_ClientGenerator();
1069
    }
1070
1071
    /**
1072
     * @return string
1073
     * @throws Localization_Exception
1074
     */
1075
    public static function getClientFolder() : string
1076
    {
1077
        self::requireConfiguration();
1078
        
1079
        return self::$clientFolder;
1080
    }
1081
1082
    /**
1083
     * @throws Localization_Exception
1084
     */
1085
    protected static function requireConfiguration() : void
1086
    {
1087
        if(!self::$configured) 
1088
        {
1089
            throw new Localization_Exception(
1090
                'The localization configuration is incomplete.',
1091
                'The configure method has not been called.',
1092
                self::ERROR_CONFIGURE_NOT_CALLED
1093
            );
1094
        }
1095
1096
        if(empty(self::$storageFile))
1097
        {
1098
            throw new Localization_Exception(
1099
                'No localization storage file set',
1100
                'To use the scanner, the storage file has to be set using the setStorageFile method.',
1101
                self::ERROR_NO_STORAGE_FILE_SET
1102
            );
1103
        }
1104
        
1105
        if(empty(self::$sources)) 
1106
        {
1107
            throw new Localization_Exception(
1108
                'No source folders have been defined.',
1109
                'At least one source folder has to be configured using the addSourceFolder method.',
1110
                self::ERROR_NO_SOURCES_ADDED
1111
            );
1112
        }
1113
    }
1114
1115
    /**
1116
     * Creates the editor instance that can be used to
1117
     * display the localization UI to edit translatable
1118
     * strings in the browser.
1119
     *
1120
     * @return Localization_Editor
1121
     * @throws Localization_Exception
1122
     */
1123
    public static function createEditor() : Localization_Editor
1124
    {
1125
        self::requireConfiguration();
1126
        
1127
        return new Localization_Editor();
1128
    }
1129
    
1130
   /**
1131
    * Retrieves a list of all available source IDs.
1132
    * @return string[]
1133
    */
1134
    public static function getSourceIDs() : array
1135
    {
1136
        $ids = array();
1137
        
1138
        foreach(self::$sources as $source) {
1139
            $ids[] = $source->getID();
1140
        }
1141
        
1142
        return $ids;
1143
    }
1144
    
1145
    /**
1146
     * Retrieves a list of all available source aliases.
1147
     * @return string[]
1148
     */
1149
    public static function getSourceAliases() : array
1150
    {
1151
        $aliases = array();
1152
        
1153
        foreach(self::$sources as $source) {
1154
            $aliases[] = $source->getAlias();
1155
        }
1156
        
1157
        return $aliases;
1158
    }
1159
    
1160
   /**
1161
    * Resets all locales to the built-in locale.
1162
    */
1163
    public static function reset() : void
1164
    {
1165
        self::$locales = array();
1166
        self::$selected = array();
1167
        self::$listeners = array();
1168
        self::$listenersCounter = 0;
1169
        
1170
        self::addAppLocale(self::BUILTIN_LOCALE_NAME);
1171
        self::addContentLocale(self::BUILTIN_LOCALE_NAME);
1172
        
1173
        self::selectAppLocale(self::BUILTIN_LOCALE_NAME);
1174
        self::selectContentLocale(self::BUILTIN_LOCALE_NAME);
1175
    }
1176
    
1177
    /**
1178
     * Indxed array with locale names supported by the application
1179
     * @var string[]
1180
     */
1181
    protected static $supportedLocales = array(
1182
        'de_DE',
1183
        'en_US',
1184
        'en_CA',
1185
        'en_UK',
1186
        'es_ES',
1187
        'fr_FR',
1188
        'pl_PL',
1189
        'it_IT',
1190
        'de_AT',
1191
        'de_CH'
1192
    );
1193
    
1194
   /**
1195
    * Retrieves a list of all supported locales.
1196
    * 
1197
    * @return string[]
1198
    */
1199
    public static function getSupportedLocaleNames() : array
1200
    {
1201
        return self::$supportedLocales;
1202
    }
1203
    
1204
   /**
1205
    * Checks whether the specified locale is supported.
1206
    * 
1207
    * @param string $localeName
1208
    * @return bool
1209
    */
1210
    public static function isLocaleSupported(string $localeName) : bool
1211
    {
1212
        return in_array($localeName, self::$supportedLocales);
1213
    }
1214
}
1215
1216
Localization::init();
1217