Completed
Push — master ( c61dd9...791f1f )
by Thierry
01:36
created

Manager::setConfirm()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Manager.php - Jaxon plugin manager
5
 *
6
 * Register Jaxon plugins, generate corresponding code, handle request
7
 * and redirect them to the right plugin.
8
 *
9
 * @package jaxon-core
10
 * @author Jared White
11
 * @author J. Max Wilson
12
 * @author Joseph Woolley
13
 * @author Steffen Konerow
14
 * @author Thierry Feuzeu <[email protected]>
15
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
16
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
17
 * @copyright 2016 Thierry Feuzeu <[email protected]>
18
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
19
 * @link https://github.com/jaxon-php/jaxon-core
20
 */
21
22
namespace Jaxon\Plugin;
23
24
use Jaxon\Jaxon;
25
use Jaxon\Plugin\Package;
26
use RecursiveDirectoryIterator;
27
use RecursiveIteratorIterator;
28
use RegexIterator;
29
use RecursiveRegexIterator;
30
use Closure;
31
32
class Manager
33
{
34
    use \Jaxon\Utils\Traits\Manager;
35
    use \Jaxon\Utils\Traits\Config;
36
    use \Jaxon\Utils\Traits\Cache;
37
    use \Jaxon\Utils\Traits\Event;
38
    use \Jaxon\Utils\Traits\Minifier;
39
    use \Jaxon\Utils\Traits\Template;
40
    use \Jaxon\Utils\Traits\Translator;
41
42
    /**
43
     * The response type.
44
     *
45
     * @var string
46
     */
47
    const RESPONSE_TYPE = 'JSON';
48
49
    /**
50
     * All plugins, indexed by priority
51
     *
52
     * @var array
53
     */
54
    private $aPlugins = [];
55
56
    /**
57
     * Request plugins, indexed by name
58
     *
59
     * @var array
60
     */
61
    private $aRequestPlugins = [];
62
63
    /**
64
     * Response plugins, indexed by name
65
     *
66
     * @var array
67
     */
68
    private $aResponsePlugins = [];
69
70
    /**
71
     * Directories where Jaxon classes to be registered are found
72
     *
73
     * @var array
74
     */
75
    private $aClassDirs = [];
76
77
    /**
78
     * An array of package names
79
     *
80
     * @var array
81
     */
82
    private $aPackages = [];
83
84
    /**
85
     * True if the Composer autoload is enabled
86
     *
87
     * @var boolean
88
     */
89
    private $bAutoloadEnabled;
90
91
    /**
92
     * The Composer autoloader
93
     *
94
     * @var Autoloader
95
     */
96
    private $xAutoloader;
97
98
    /**
99
     * Javascript confirm function
100
     *
101
     * @var \Jaxon\Request\Interfaces\Confirm
102
     */
103
    private $xConfirm;
104
105
    /**
106
     * Default javascript confirm function
107
     *
108
     * @var \Jaxon\Request\Support\Confirm
109
     */
110
    private $xDefaultConfirm;
111
112
    /**
113
     * Javascript alert function
114
     *
115
     * @var \Jaxon\Request\Interfaces\Alert
116
     */
117
    private $xAlert;
118
119
    /**
120
     * Default javascript alert function
121
     *
122
     * @var \Jaxon\Request\Support\Alert
123
     */
124
    private $xDefaultAlert;
125
126
    /**
127
     * Initialize the Jaxon Plugin Manager
128
     */
129
    public function __construct()
130
    {
131
        $this->bAutoloadEnabled = true;
132
        $this->xAutoloader = null;
133
134
        // Javascript confirm function
135
        $this->xConfirm = null;
136
        $this->xDefaultConfirm = new \Jaxon\Request\Support\Confirm();
137
138
        // Javascript alert function
139
        $this->xAlert = null;
140
        $this->xDefaultAlert = new \Jaxon\Request\Support\Alert();
141
    }
142
143
    /**
144
     * Use the Composer autoloader
145
     *
146
     * @return void
147
     */
148
    public function useComposerAutoloader()
149
    {
150
        $this->bAutoloadEnabled = true;
151
        $this->xAutoloader = require(__DIR__ . '/../../../../autoload.php');
152
    }
153
154
    /**
155
     * Disable the autoloader in the library
156
     *
157
     * The user shall provide an alternative autoload system.
158
     *
159
     * @return void
160
     */
161
    public function disableAutoload()
162
    {
163
        $this->bAutoloadEnabled = false;
164
        $this->xAutoloader = null;
165
    }
166
167
    /**
168
     * Set the javascript confirm function
169
     *
170
     * @param \Jaxon\Request\Interfaces\Confirm         $xConfirm     The javascript confirm function
171
     *
172
     * @return void
173
     */
174
    public function setConfirm(\Jaxon\Request\Interfaces\Confirm $xConfirm)
175
    {
176
        $this->xConfirm = $xConfirm;
177
    }
178
179
    /**
180
     * Get the javascript confirm function
181
     *
182
     * @return \Jaxon\Request\Interfaces\Confirm
183
     */
184
    public function getConfirm()
185
    {
186
        return (($this->xConfirm) ? $this->xConfirm : $this->xDefaultConfirm);
187
    }
188
189
    /**
190
     * Get the default javascript confirm function
191
     *
192
     * @return \Jaxon\Request\Support\Confirm
193
     */
194
    public function getDefaultConfirm()
195
    {
196
        return $this->xDefaultConfirm;
197
    }
198
199
    /**
200
     * Set the javascript alert function
201
     *
202
     * @param \Jaxon\Request\Interfaces\Alert           $xAlert       The javascript alert function
203
     *
204
     * @return void
205
     */
206
    public function setAlert(\Jaxon\Request\Interfaces\Alert $xAlert)
207
    {
208
        $this->xAlert = $xAlert;
209
    }
210
211
    /**
212
     * Get the javascript alert function
213
     *
214
     * @return \Jaxon\Request\Interfaces\Alert
215
     */
216
    public function getAlert()
217
    {
218
        return (($this->xAlert) ? $this->xAlert : $this->xDefaultAlert);
219
    }
220
221
    /**
222
     * Get the default javascript alert function
223
     *
224
     * @return \Jaxon\Request\Support\Alert
225
     */
226
    public function getDefaultAlert()
227
    {
228
        return $this->xDefaultAlert;
229
    }
230
231
    /**
232
     * Inserts an entry into an array given the specified priority number
233
     *
234
     * If a plugin already exists with the given priority, the priority is automatically incremented until a free spot is found.
235
     * The plugin is then inserted into the empty spot in the array.
236
     *
237
     * @param Plugin         $xPlugin               An instance of a plugin
238
     * @param integer        $nPriority             The desired priority, used to order the plugins
239
     *
240
     * @return void
241
     */
242
    private function setPluginPriority(Plugin $xPlugin, $nPriority)
243
    {
244
        while (isset($this->aPlugins[$nPriority]))
245
        {
246
            $nPriority++;
247
        }
248
        $this->aPlugins[$nPriority] = $xPlugin;
249
        // Sort the array by ascending keys
250
        ksort($this->aPlugins);
251
    }
252
253
    /**
254
     * Register a plugin
255
     *
256
     * Below is a table for priorities and their description:
257
     * - 0 thru 999: Plugins that are part of or extensions to the jaxon core
258
     * - 1000 thru 8999: User created plugins, typically, these plugins don't care about order
259
     * - 9000 thru 9999: Plugins that generally need to be last or near the end of the plugin list
260
     *
261
     * @param Plugin         $xPlugin               An instance of a plugin
262
     * @param integer        $nPriority             The plugin priority, used to order the plugins
263
     *
264
     * @return void
265
     */
266
    public function registerPlugin(Plugin $xPlugin, $nPriority = 1000)
267
    {
268
        $bIsAlert = ($xPlugin instanceof \Jaxon\Request\Interfaces\Alert);
269
        $bIsConfirm = ($xPlugin instanceof \Jaxon\Request\Interfaces\Confirm);
270
        if($xPlugin instanceof Request)
271
        {
272
            // The name of a request plugin is used as key in the plugin table
273
            $this->aRequestPlugins[$xPlugin->getName()] = $xPlugin;
274
        }
275
        elseif($xPlugin instanceof Response)
276
        {
277
            // The name of a response plugin is used as key in the plugin table
278
            $this->aResponsePlugins[$xPlugin->getName()] = $xPlugin;
279
        }
280
        elseif(!$bIsConfirm && !$bIsAlert)
281
        {
282
            throw new \Jaxon\Exception\Error($this->trans('errors.register.invalid', array('name' => get_class($xPlugin))));
283
        }
284
        // This plugin implements the Alert interface
285
        if($bIsAlert)
286
        {
287
            $this->setAlert($xPlugin);
288
        }
289
        // This plugin implements the Confirm interface
290
        if($bIsConfirm)
291
        {
292
            $this->setConfirm($xPlugin);
293
        }
294
        // Register the plugin as an event listener
295
        if($xPlugin instanceof \Jaxon\Utils\Interfaces\EventListener)
296
        {
297
            $this->addEventListener($xPlugin);
298
        }
299
300
        $this->setPluginPriority($xPlugin, $nPriority);
301
    }
302
303
    /**
304
     * Register a package
305
     *
306
     * @param string         $sPackageClass         The package class name
307
     * @param Closure        $xClosure              A closure to create package instance
308
     *
309
     * @return void
310
     */
311
    public function registerPackage(string $sPackageClass, Closure $xClosure)
312
    {
313
        $this->aPackages[] = $sPackageClass;
314
        jaxon()->di()->set($sPackageClass, $xClosure);
315
    }
316
317
    /**
318
     * Generate a hash for all the javascript code generated by the library
319
     *
320
     * @return string
321
     */
322
    private function generateHash()
323
    {
324
        $sHash = $this->getVersion();
325
        foreach($this->aPlugins as $xPlugin)
326
        {
327
            $sHash .= $xPlugin->generateHash();
328
        }
329
        return md5($sHash);
330
    }
331
332
    /**
333
     * Check if the current request can be processed
334
     *
335
     * Calls each of the request plugins and determines if the current request can be processed by one of them.
336
     * If no processor identifies the current request, then the request must be for the initial page load.
337
     *
338
     * @return boolean
339
     */
340
    public function canProcessRequest()
341
    {
342
        foreach($this->aRequestPlugins as $xPlugin)
343
        {
344
            if($xPlugin->getName() != Jaxon::FILE_UPLOAD && $xPlugin->canProcessRequest())
345
            {
346
                return true;
347
            }
348
        }
349
        return false;
350
    }
351
352
    /**
353
     * Process the current request
354
     *
355
     * Calls each of the request plugins to request that they process the current request.
356
     * If any plugin processes the request, it will return true.
357
     *
358
     * @return boolean
359
     */
360
    public function processRequest()
361
    {
362
        $xUploadPlugin = $this->getRequestPlugin(Jaxon::FILE_UPLOAD);
363
        foreach($this->aRequestPlugins as $xPlugin)
364
        {
365
            if($xPlugin->getName() != Jaxon::FILE_UPLOAD && $xPlugin->canProcessRequest())
366
            {
367
                // Process uploaded files
368
                if($xUploadPlugin != null)
369
                {
370
                    $xUploadPlugin->processRequest();
371
                }
372
                // Process the request
373
                return $xPlugin->processRequest();
374
            }
375
        }
376
        // Todo: throw an exception
377
        return false;
378
    }
379
380
    /**
381
     * Register a function, event or callable object
382
     *
383
     * Call each of the request plugins and give them the opportunity to handle the
384
     * registration of the specified function, event or callable object.
385
     *
386
     * @param array         $aArgs                The registration data
387
     *
388
     * @return mixed
389
     */
390
    public function register($aArgs)
391
    {
392
        foreach($this->aRequestPlugins as $xPlugin)
393
        {
394
            $mResult = $xPlugin->register($aArgs);
395
            if($mResult instanceof \Jaxon\Request\Request || is_array($mResult) || $mResult === true)
396
            {
397
                return $mResult;
398
            }
399
        }
400
        throw new \Jaxon\Exception\Error($this->trans('errors.register.method', array('args' => print_r($aArgs, true))));
401
    }
402
403
    /**
404
     * Add a path to the class directories
405
     *
406
     * @param string            $sDirectory             The path to the directory
407
     * @param string|null       $sNamespace             The associated namespace
408
     * @param string            $sSeparator             The character to use as separator in javascript class names
409
     * @param array             $aProtected             The functions that are not to be exported
410
     *
411
     * @return boolean
412
     */
413
    public function addClassDir($sDirectory, $sNamespace = '', $sSeparator = '.', array $aProtected = [])
414
    {
415
        if(!is_dir(($sDirectory = trim($sDirectory))))
416
        {
417
            return false;
418
        }
419
        // Only '.' and '_' are allowed to be used as separator. Any other value is ignored and '.' is used instead.
420
        if(($sSeparator = trim($sSeparator)) != '_')
421
        {
422
            $sSeparator = '.';
423
        }
424
        if(!($sNamespace = trim($sNamespace, ' \\')))
425
        {
426
            $sNamespace = '';
427
        }
428
        if(($sNamespace))
429
        {
430
            // If there is an autoloader, register the dir with PSR4 autoloading
431
            if(($this->xAutoloader))
432
            {
433
                $this->xAutoloader->setPsr4($sNamespace . '\\', $sDirectory);
434
            }
435
        }
436
        elseif(($this->xAutoloader))
437
        {
438
            // If there is an autoloader, register the dir with classmap autoloading
439
            $itDir = new RecursiveDirectoryIterator($sDirectory);
440
            $itFile = new RecursiveIteratorIterator($itDir);
441
            // Iterate on dir content
442
            foreach($itFile as $xFile)
443
            {
444
                // skip everything except PHP files
445
                if(!$xFile->isFile() || $xFile->getExtension() != 'php')
446
                {
447
                    continue;
448
                }
449
                $this->xAutoloader->addClassMap(array($xFile->getBasename('.php') => $xFile->getPathname()));
450
            }
451
        }
452
        $this->aClassDirs[] = array(
453
            'directory' => rtrim($sDirectory, DIRECTORY_SEPARATOR),
454
            'namespace' => $sNamespace,
455
            'separator' => $sSeparator,
456
            'protected' => $aProtected
457
        );
458
        return true;
459
    }
460
461
    /**
462
     * Register an instance of a given class from a file
463
     *
464
     * @param object            $xFile                  The PHP file containing the class
465
     * @param string            $sDirectory             The path to the directory
466
     * @param string|''         $sNamespace             The associated namespace
0 ignored issues
show
Documentation introduced by
The doc-type string|'' could not be parsed: Unknown type name "''" at position 7. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
467
     * @param string            $sSeparator             The character to use as separator in javascript class names
468
     * @param array             $aProtected             The functions that are not to be exported
469
     * @param array             $aOptions               The options to register the class with
470
     *
471
     * @return void
472
     */
473
    protected function registerClassFromFile($xFile, $sDirectory, $sNamespace = '', $sSeparator = '.',
474
        array $aProtected = [], array $aOptions = [])
475
    {
476
        $sDS = DIRECTORY_SEPARATOR;
477
        // Get the corresponding class path and name
478
        $sClassPath = substr($xFile->getPath(), strlen($sDirectory));
479
        $sClassPath = str_replace($sDS, '\\', trim($sClassPath, $sDS));
480
        $sClassName = $xFile->getBasename('.php');
481
        if(($sNamespace))
482
        {
483
            $sClassPath = ($sClassPath) ? $sNamespace . '\\' . $sClassPath : $sNamespace;
484
            $sClassName = '\\' . $sClassPath . '\\' . $sClassName;
485
        }
486
        // Require the file only if autoload is enabled but there is no autoloader
487
        if(($this->bAutoloadEnabled) && !($this->xAutoloader))
488
        {
489
            require_once($xFile->getPathname());
490
        }
491
        // Create and register an instance of the class
492
        if(!array_key_exists('*', $aOptions) || !is_array($aOptions['*']))
493
        {
494
            $aOptions['*'] = [];
495
        }
496
        $aOptions['*']['separator'] = $sSeparator;
497
        if(($sNamespace))
498
        {
499
            $aOptions['*']['namespace'] = $sNamespace;
500
        }
501
        if(($sClassPath))
502
        {
503
            $aOptions['*']['classpath'] = $sClassPath;
504
        }
505
        // Filter excluded methods
506
        $aProtected = array_filter($aProtected, function ($sName) {return is_string($sName);});
507
        if(count($aProtected) > 0)
508
        {
509
            $aOptions['*']['protected'] = $aProtected;
510
        }
511
        $this->register(array(Jaxon::CALLABLE_OBJECT, $sClassName, $aOptions));
512
    }
513
514
    /**
515
     * Register callable objects from all class directories
516
     *
517
     * @param array             $aOptions               The options to register the classes with
518
     *
519
     * @return void
520
     */
521
    public function registerClasses(array $aOptions = [])
522
    {
523
        $sDS = DIRECTORY_SEPARATOR;
524
        // Change the keys in $aOptions to have "\" as separator
525
        $aNewOptions = [];
526
        foreach($aOptions as $key => $aOption)
527
        {
528
            $key = trim(str_replace(['.', '_'], ['\\', '\\'], $key), ' \\');
529
            $aNewOptions[$key] = $aOption;
530
        }
531
532
        foreach($this->aClassDirs as $aClassDir)
533
        {
534
            // Get the directory
535
            $sDirectory = $aClassDir['directory'];
536
            // Get the namespace
537
            $sNamespace = $aClassDir['namespace'];
538
539
            $itDir = new RecursiveDirectoryIterator($sDirectory);
540
            $itFile = new RecursiveIteratorIterator($itDir);
541
            // Iterate on dir content
542
            foreach($itFile as $xFile)
543
            {
544
                // skip everything except PHP files
545
                if(!$xFile->isFile() || $xFile->getExtension() != 'php')
546
                {
547
                    continue;
548
                }
549
550
                // Get the class name
551
                $sClassPath = substr($xFile->getPath(), strlen($sDirectory));
552
                $sClassPath = trim(str_replace($sDS, '\\', $sClassPath), '\\');
553
                $sClassName = $xFile->getBasename('.php');
554
                if(($sClassPath))
555
                {
556
                    $sClassName = $sClassPath . '\\' . $sClassName;
557
                }
558
                if(($sNamespace))
559
                {
560
                    $sClassName = $sNamespace . '\\' . $sClassName;
561
                }
562
                // Get the class options
563
                $aClassOptions = [];
564
                if(array_key_exists($sClassName, $aNewOptions))
565
                {
566
                    $aClassOptions = $aNewOptions[$sClassName];
567
                }
568
569
                $this->registerClassFromFile($xFile, $sDirectory, $sNamespace,
570
                    $aClassDir['separator'], $aClassDir['protected'], $aClassOptions);
571
            }
572
        }
573
    }
574
575
    /**
576
     * Register an instance of a given class
577
     *
578
     * @param string            $sClassName             The name of the class to be registered
579
     * @param array             $aOptions               The options to register the class with
580
     *
581
     * @return bool
582
     */
583
    public function registerClass($sClassName, array $aOptions = [])
584
    {
585
        if(!($sClassName = trim($sClassName, ' \\._')))
586
        {
587
            return false;
588
        }
589
        $sDS = DIRECTORY_SEPARATOR;
590
591
        // Replace "." and "_" with antislashes, and set the class path.
592
        $sClassName = str_replace(['.', '_'], ['\\', '\\'], $sClassName);
593
        $sClassPath = '';
594
        if(($nLastSlashPosition = strrpos($sClassName, '\\')) !== false)
595
        {
596
            $sClassPath = substr($sClassName, 0, $nLastSlashPosition);
597
            $sClassName = substr($sClassName, $nLastSlashPosition + 1);
598
        }
599
        // Path to the file, relative to a registered directory.
600
        $sPartPath = str_replace('\\', $sDS, $sClassPath) . $sDS . $sClassName . '.php';
601
602
        // Search for the class file in all directories.
603
        foreach($this->aClassDirs as $aClassDir)
604
        {
605
            // Get the separator
606
            $sSeparator = $aClassDir['separator'];
607
            // Get the namespace
608
            $sNamespace = $aClassDir['namespace'];
609
            $nLen = strlen($sNamespace);
610
            $sFullPath = '';
611
            // Check if the class belongs to the namespace
612
            if(($sNamespace) && substr($sClassPath, 0, $nLen) == $sNamespace)
613
            {
614
                $sFullPath = $aClassDir['directory'] . $sDS . substr($sPartPath, $nLen + 1);
615
            }
616
            elseif(!($sNamespace))
617
            {
618
                $sFullPath = $aClassDir['directory'] . $sDS . $sPartPath;
619
            }
620
            if(($sFullPath) && is_file($sFullPath))
621
            {
622
                // Found the file in this directory
623
                $xFileInfo = new \SplFileInfo($sFullPath);
624
                $sDirectory = $aClassDir['directory'];
625
                $aProtected = $aClassDir['protected'];
626
                $this->registerClassFromFile($xFileInfo, $sDirectory, $sNamespace, $sSeparator, $aProtected, $aOptions);
627
                return true;
628
            }
629
        }
630
        return false;
631
    }
632
633
    /**
634
     * Find a user registered callable object by class name
635
     *
636
     * @param string        $sClassName            The class name of the callable object
637
     *
638
     * @return object
639
     */
640
    public function getRegisteredObject($sClassName)
641
    {
642
        $xObject = null; // The user registered object
643
        $xPlugin = $this->getRequestPlugin('CallableObject'); // The CallableObject plugin
644
        if(($xPlugin))
645
        {
646
            $xObject = $xPlugin->getRegisteredObject($sClassName);
647
        }
648
        return $xObject;
649
    }
650
651
    /**
652
     * Get the base URI of the Jaxon library javascript files
653
     *
654
     * @return string
655
     */
656
    private function getJsLibUri()
657
    {
658
        if(!$this->hasOption('js.lib.uri'))
659
        {
660
            // return 'https://cdn.jsdelivr.net/jaxon/1.2.0/';
661
            return 'https://cdn.jsdelivr.net/gh/jaxon-php/[email protected]/dist/';
662
        }
663
        // Todo: check the validity of the URI
664
        return rtrim($this->getOption('js.lib.uri'), '/') . '/';
665
    }
666
667
    /**
668
     * Get the extension of the Jaxon library javascript files
669
     *
670
     * The returned string is '.min.js' if the files are minified.
671
     *
672
     * @return string
673
     */
674
    private function getJsLibExt()
675
    {
676
        // $jsDelivrUri = 'https://cdn.jsdelivr.net';
677
        // $nLen = strlen($jsDelivrUri);
678
        // The jsDelivr CDN only hosts minified files
679
        // if(($this->getOption('js.app.minify')) || substr($this->getJsLibUri(), 0, $nLen) == $jsDelivrUri)
680
        // Starting from version 2.0.0 of the js lib, the jsDelivr CDN also hosts non minified files.
681
        if(($this->getOption('js.app.minify')))
682
        {
683
            return '.min.js';
684
        }
685
        return '.js';
686
    }
687
688
    /**
689
     * Check if the javascript code generated by Jaxon can be exported to an external file
690
     *
691
     * @return boolean
692
     */
693
    public function canExportJavascript()
694
    {
695
        // Check config options
696
        // - The js.app.extern option must be set to true
697
        // - The js.app.uri and js.app.dir options must be set to non null values
698
        if(!$this->getOption('js.app.extern') ||
699
            !$this->getOption('js.app.uri') ||
700
            !$this->getOption('js.app.dir'))
701
        {
702
            return false;
703
        }
704
        // Check dir access
705
        // - The js.app.dir must be writable
706
        $sJsAppDir = $this->getOption('js.app.dir');
707
        if(!is_dir($sJsAppDir) || !is_writable($sJsAppDir))
708
        {
709
            return false;
710
        }
711
        return true;
712
    }
713
714
    /**
715
     * Set the cache directory for the template engine
716
     *
717
     * @return void
718
     */
719
    private function setTemplateCacheDir()
720
    {
721
        if($this->hasOption('core.template.cache_dir'))
722
        {
723
            $this->setCacheDir($this->getOption('core.template.cache_dir'));
724
        }
725
    }
726
727
    /**
728
     * Get the HTML tags to include Jaxon javascript files into the page
729
     *
730
     * @return string
731
     */
732
    public function getJs()
733
    {
734
        $sJsLibUri = $this->getJsLibUri();
735
        $sJsLibExt = $this->getJsLibExt();
736
        $sJsCoreUrl = $sJsLibUri . 'jaxon.core' . $sJsLibExt;
737
        $sJsDebugUrl = $sJsLibUri . 'jaxon.debug' . $sJsLibExt;
738
        // $sJsVerboseUrl = $sJsLibUri . 'jaxon.verbose' . $sJsLibExt;
739
        $sJsLanguageUrl = $sJsLibUri . 'lang/jaxon.' . $this->getOption('core.language') . $sJsLibExt;
740
741
        // Add component files to the javascript file array;
742
        $aJsFiles = array($sJsCoreUrl);
743
        if($this->getOption('core.debug.on'))
744
        {
745
            $aJsFiles[] = $sJsDebugUrl;
746
            $aJsFiles[] = $sJsLanguageUrl;
747
            /*if($this->getOption('core.debug.verbose'))
748
            {
749
                $aJsFiles[] = $sJsVerboseUrl;
750
            }*/
751
        }
752
753
        // Set the template engine cache dir
754
        $this->setTemplateCacheDir();
755
        $sCode = $this->render('jaxon::plugins/includes.js', array(
756
            'sJsOptions' => $this->getOption('js.app.options'),
757
            'aUrls' => $aJsFiles,
758
        ));
759
        foreach($this->aResponsePlugins as $xPlugin)
760
        {
761
            if(($str = trim($xPlugin->getJs())))
762
            {
763
                $sCode .= rtrim($str, " \n") . "\n";
764
            }
765
        }
766
        foreach($this->aPackages as $sClass)
767
        {
768
            $xPackage = jaxon()->di()->get($sClass);
769
            if(($str = trim($xPackage->js())))
770
            {
771
                $sCode .= rtrim($str, " \n") . "\n";
772
            }
773
        }
774
        return $sCode;
775
    }
776
777
    /**
778
     * Get the HTML tags to include Jaxon CSS code and files into the page
779
     *
780
     * @return string
781
     */
782 View Code Duplication
    public function getCss()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
783
    {
784
        // Set the template engine cache dir
785
        $this->setTemplateCacheDir();
786
787
        $sCode = '';
788
        foreach($this->aResponsePlugins as $xPlugin)
789
        {
790
            if(($str = trim($xPlugin->getCss())))
791
            {
792
                $sCode .= rtrim($str, " \n") . "\n";
793
            }
794
        }
795
        foreach($this->aPackages as $sClass)
796
        {
797
            $xPackage = jaxon()->di()->get($sClass);
798
            if(($str = trim($xPackage->css())))
799
            {
800
                $sCode .= rtrim($str, " \n") . "\n";
801
            }
802
        }
803
        return $sCode;
804
    }
805
806
    /**
807
     * Get the correspondances between previous and current config options
808
     *
809
     * They are used to keep the deprecated config options working.
810
     * They will be removed when the deprecated options will lot be supported anymore.
811
     *
812
     * @return array
813
     */
814
    private function getOptionVars()
815
    {
816
        return array(
817
            'sResponseType'             => self::RESPONSE_TYPE,
818
            'sVersion'                  => $this->getOption('core.version'),
819
            'sLanguage'                 => $this->getOption('core.language'),
820
            'bLanguage'                 => $this->hasOption('core.language') ? true : false,
821
            'sRequestURI'               => $this->getOption('core.request.uri'),
822
            'sDefaultMode'              => $this->getOption('core.request.mode'),
823
            'sDefaultMethod'            => $this->getOption('core.request.method'),
824
            'sCsrfMetaName'             => $this->getOption('core.request.csrf_meta'),
825
            'bDebug'                    => $this->getOption('core.debug.on'),
826
            'bVerboseDebug'             => $this->getOption('core.debug.verbose'),
827
            'sDebugOutputID'            => $this->getOption('core.debug.output_id'),
828
            'nResponseQueueSize'        => $this->getOption('js.lib.queue_size'),
829
            'sStatusMessages'           => $this->getOption('js.lib.show_status') ? 'true' : 'false',
830
            'sWaitCursor'               => $this->getOption('js.lib.show_cursor') ? 'true' : 'false',
831
            'sDefer'                    => $this->getOption('js.app.options'),
832
        );
833
    }
834
835
    /**
836
     * Get the javascript code for Jaxon client side configuration
837
     *
838
     * @return string
839
     */
840
    private function getConfigScript()
841
    {
842
        $aVars = $this->getOptionVars();
843
        $sYesScript = 'jaxon.ajax.response.process(command.response)';
844
        $sNoScript = 'jaxon.confirm.skip(command);jaxon.ajax.response.process(command.response)';
845
        $sConfirmScript = $this->getConfirm()->confirm('msg', $sYesScript, $sNoScript);
846
        $aVars['sConfirmScript'] = $this->render('jaxon::plugins/confirm.js', array('sConfirmScript' => $sConfirmScript));
847
848
        return $this->render('jaxon::plugins/config.js', $aVars);
849
    }
850
851
    /**
852
     * Get the javascript code to be run after page load
853
     *
854
     * Also call each of the response plugins giving them the opportunity
855
     * to output some javascript to the page being generated.
856
     *
857
     * @return string
858
     */
859 View Code Duplication
    private function getReadyScript()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
860
    {
861
        $sPluginScript = '';
862
        foreach($this->aResponsePlugins as $xPlugin)
863
        {
864
            if(($str = trim($xPlugin->getScript())))
865
            {
866
                $sPluginScript .= "\n" . trim($str, " \n");
867
            }
868
        }
869
        foreach($this->aPackages as $sClass)
870
        {
871
            $xPackage = jaxon()->di()->get($sClass);
872
            if(($str = trim($xPackage->ready())))
873
            {
874
                $sPluginScript .= "\n" . trim($str, " \n");
875
            }
876
        }
877
878
        return $this->render('jaxon::plugins/ready.js', ['sPluginScript' => $sPluginScript]);
879
    }
880
881
    /**
882
     * Get the javascript code to be sent to the browser
883
     *
884
     * Also call each of the request plugins giving them the opportunity
885
     * to output some javascript to the page being generated.
886
     * This is called only when the page is being loaded initially.
887
     * This is not called when processing a request.
888
     *
889
     * @return string
890
     */
891
    private function getAllScripts()
892
    {
893
        // Get the config and plugins scripts
894
        $sScript = $this->getConfigScript() . "\n" . $this->getReadyScript() . "\n";
895
        foreach($this->aRequestPlugins as $xPlugin)
896
        {
897
            $sScript .= "\n" . trim($xPlugin->getScript(), " \n");
898
        }
899
        return $sScript;
900
    }
901
902
    /**
903
     * Get the javascript code to be sent to the browser
904
     *
905
     * Also call each of the request plugins giving them the opportunity
906
     * to output some javascript to the page being generated.
907
     * This is called only when the page is being loaded initially.
908
     * This is not called when processing a request.
909
     *
910
     * @return string
911
     */
912
    public function getScript()
913
    {
914
        // Set the template engine cache dir
915
        $this->setTemplateCacheDir();
916
917
        if($this->canExportJavascript())
918
        {
919
            $sJsAppURI = rtrim($this->getOption('js.app.uri'), '/') . '/';
920
            $sJsAppDir = rtrim($this->getOption('js.app.dir'), '/') . '/';
921
922
            // The plugins scripts are written into the javascript app dir
923
            $sHash = $this->generateHash();
924
            $sOutFile = $sHash . '.js';
925
            $sMinFile = $sHash . '.min.js';
926
            if(!is_file($sJsAppDir . $sOutFile))
927
            {
928
                file_put_contents($sJsAppDir . $sOutFile, $this->getAllScripts());
929
            }
930
            if(($this->getOption('js.app.minify')) && !is_file($sJsAppDir . $sMinFile))
931
            {
932
                if(($this->minify($sJsAppDir . $sOutFile, $sJsAppDir . $sMinFile)))
933
                {
934
                    $sOutFile = $sMinFile;
935
                }
936
            }
937
938
            // The returned code loads the generated javascript file
939
            $sScript = $this->render('jaxon::plugins/include.js', array(
940
                'sJsOptions' => $this->getOption('js.app.options'),
941
                'sUrl' => $sJsAppURI . $sOutFile,
942
            ));
943
        }
944
        else
945
        {
946
            // The plugins scripts are wrapped with javascript tags
947
            $sScript = $this->render('jaxon::plugins/wrapper.js', array(
948
                'sJsOptions' => $this->getOption('js.app.options'),
949
                'sScript' => $this->getAllScripts(),
950
            ));
951
        }
952
953
        return $sScript;
954
    }
955
956
    /**
957
     * Find the specified response plugin by name and return a reference to it if one exists
958
     *
959
     * @param string        $sName                The name of the plugin
960
     *
961
     * @return \Jaxon\Plugin\Response
962
     */
963
    public function getResponsePlugin($sName)
964
    {
965
        if(array_key_exists($sName, $this->aResponsePlugins))
966
        {
967
            return $this->aResponsePlugins[$sName];
968
        }
969
        return null;
970
    }
971
972
    /**
973
     * Find the specified request plugin by name and return a reference to it if one exists
974
     *
975
     * @param string        $sName                The name of the plugin
976
     *
977
     * @return \Jaxon\Plugin\Request
978
     */
979
    public function getRequestPlugin($sName)
980
    {
981
        if(array_key_exists($sName, $this->aRequestPlugins))
982
        {
983
            return $this->aRequestPlugins[$sName];
984
        }
985
        return null;
986
    }
987
}
988