Passed
Push — master ( 7c83a0...cd350b )
by Thierry
02:08
created

PluginManager   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 345
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 85
dl 0
loc 345
rs 9.76
c 0
b 0
f 0
wmc 33

13 Methods

Rating   Name   Duplication   Size   Complexity  
A registerCallable() 0 10 3
A _registerFromConfig() 0 17 2
B registerCallablesFromConfig() 0 18 7
A registerPlugins() 0 11 1
A __construct() 0 6 1
A registerFromConfig() 0 9 2
A getRequestPlugin() 0 7 2
B registerPlugin() 0 40 7
A registerPackage() 0 22 2
A getResponsePlugin() 0 12 3
A readPackageConfig() 0 7 1
A getPackage() 0 3 1
A getRequestPlugins() 0 3 1
1
<?php
2
3
/**
4
 * ResponseManager.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
0 ignored issues
show
Coding Style introduced by
Package name "jaxon-core" is not valid; consider "Jaxoncore" instead
Loading history...
10
 * @author Jared White
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
11
 * @author J. Max Wilson
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
12
 * @author Joseph Woolley
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
13
 * @author Steffen Konerow
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
14
 * @author Thierry Feuzeu <[email protected]>
15
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
16
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
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
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
21
22
namespace Jaxon\Plugin;
23
24
use Jaxon\Jaxon;
25
use Jaxon\Plugin\Code\CodeGenerator;
26
use Jaxon\Plugin\RequestPlugin;
27
use Jaxon\Plugin\ResponsePlugin;
28
use Jaxon\Request\Plugin\CallableClass\ClassPlugin;
29
use Jaxon\Request\Plugin\CallableClass\DirPlugin;
30
use Jaxon\Request\Plugin\CallableFunction\FunctionPlugin;
31
use Jaxon\Response\Plugin\DataBag\DataBagPlugin;
32
use Jaxon\Response\Plugin\JQuery\JQueryPlugin;
33
use Jaxon\Response\Response;
34
use Jaxon\Utils\Config\Config;
35
use Jaxon\Utils\Translation\Translator;
36
use Jaxon\Contracts\Dialogs\Message;
37
use Jaxon\Contracts\Dialogs\Question;
38
use Jaxon\Exception\SetupException;
39
40
use function is_array;
41
use function is_integer;
42
use function is_string;
43
use function is_subclass_of;
44
use function trim;
45
46
class PluginManager
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class PluginManager
Loading history...
47
{
48
    /**
49
     * @var Jaxon
50
     */
51
    private $jaxon;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line(s) before first member var; 0 found
Loading history...
52
53
    /**
54
     * @var Config
55
     */
56
    protected $xConfig;
57
58
    /**
59
     * @var Translator
60
     */
61
    protected $xTranslator;
62
63
    /**
64
     * Request plugins, indexed by name
65
     *
66
     * @var array
67
     */
68
    private $aRequestPlugins = [];
69
70
    /**
71
     * Response plugins, indexed by name
72
     *
73
     * @var array
74
     */
75
    private $aResponsePlugins = [];
76
77
    /**
78
     * The code generator
79
     *
80
     * @var CodeGenerator
81
     */
82
    private $xCodeGenerator;
83
84
    /**
85
     * The constructor
86
     *
87
     * @param Jaxon $jaxon
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 9 spaces after parameter type; 1 found
Loading history...
88
     * @param Config $xConfig
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
89
     * @param Translator $xTranslator
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
90
     * @param CodeGenerator $xCodeGenerator
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
91
     */
92
    public function __construct(Jaxon $jaxon, Config $xConfig, Translator $xTranslator, CodeGenerator $xCodeGenerator)
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
93
    {
94
        $this->jaxon = $jaxon;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 10 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
95
        $this->xConfig = $xConfig;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 8 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
96
        $this->xTranslator = $xTranslator;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
97
        $this->xCodeGenerator = $xCodeGenerator;
98
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
99
100
    /**
101
     * Get the request plugins
102
     *
103
     * @return array
104
     */
105
    public function getRequestPlugins(): array
106
    {
107
        return $this->aRequestPlugins;
108
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
109
110
    /**
111
     * Get a package instance
112
     *
113
     * @param string $sClassName    The package class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
114
     *
115
     * @return Package|null
116
     */
117
    public function getPackage(string $sClassName): ?Package
118
    {
119
        return $this->jaxon->di()->get(trim($sClassName, '\\ '));
120
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
121
122
    /**
123
     * Register a plugin
124
     *
125
     * Below is a table for priorities and their description:
126
     * - 0 to 999: Plugins that are part of or extensions to the jaxon core
127
     * - 1000 to 8999: User created plugins, typically, these plugins don't care about order
128
     * - 9000 to 9999: Plugins that generally need to be last or near the end of the plugin list
129
     *
130
     * @param string $sClassName    The plugin class
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
131
     * @param string $sPluginName    The plugin name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
132
     * @param integer $nPriority    The plugin priority, used to order the plugins
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 4 found
Loading history...
133
     *
134
     * @return void
135
     * @throws SetupException
136
     */
137
    public function registerPlugin(string $sClassName, string $sPluginName, int $nPriority = 1000)
138
    {
139
        $bIsUsed = false;
140
        if(is_subclass_of($sClassName, RequestPlugin::class))
141
        {
142
            $this->aRequestPlugins[$sPluginName] = $sClassName;
143
            $this->xCodeGenerator->addGenerator($sClassName, $nPriority);
144
            $bIsUsed = true;
145
        }
146
        elseif(is_subclass_of($sClassName, ResponsePlugin::class))
147
        {
148
            $this->aResponsePlugins[$sPluginName] = $sClassName;
149
            $this->xCodeGenerator->addGenerator($sClassName, $nPriority);
150
            $bIsUsed = true;
151
        }
152
153
        // This plugin implements the Message interface
154
        if(is_subclass_of($sClassName, Message::class))
155
        {
156
            $this->jaxon->dialog()->setMessage($sClassName);
157
            $bIsUsed = true;
158
        }
159
        // This plugin implements the Question interface
160
        if(is_subclass_of($sClassName, Question::class))
161
        {
162
            $this->jaxon->dialog()->setQuestion($sClassName);
163
            $bIsUsed = true;
164
        }
165
166
        if(!$bIsUsed)
167
        {
168
            // The class is invalid.
169
            $sMessage = $this->xTranslator->trans('errors.register.invalid', ['name' => $sClassName]);
170
            throw new SetupException($sMessage);
171
        }
172
173
        // Register the plugin in the DI container, if necessary
174
        if(!$this->jaxon->di()->has($sClassName))
175
        {
176
            $this->jaxon->di()->auto($sClassName);
177
        }
178
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
179
180
    /**
181
     * Register a package
182
     *
183
     * @param string $sClassName    The package class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
184
     *
185
     * @return Config
186
     * @throws SetupException
187
     */
188
    private function readPackageConfig(string $sClassName): Config
189
    {
190
        $sConfigFile = $sClassName::getConfigFile();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
191
        $aPackageConfig = $this->jaxon->readConfig($sConfigFile);
192
        // Add the package name to the config
193
        $aPackageConfig['package'] = $sClassName;
194
        return $this->jaxon->di()->newConfig($aPackageConfig);
195
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
196
197
    /**
198
     * Register a package
199
     *
200
     * @param string $sClassName    The package class name
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
201
     * @param array $aAppOptions    The package options defined in the app section of the config file
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
202
     *
203
     * @return void
204
     * @throws SetupException
205
     */
206
    public function registerPackage(string $sClassName, array $aAppOptions)
207
    {
208
        $sClassName = trim($sClassName, '\\ ');
209
        if(!is_subclass_of($sClassName, Package::class))
210
        {
211
            $sMessage = $this->xTranslator->trans('errors.register.invalid', ['name' => $sClassName]);
212
            throw new SetupException($sMessage);
213
        }
214
        $di = $this->jaxon->di();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 9 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
215
        $xAppConfig = $di->registerPackage($sClassName, $aAppOptions);
216
217
        // Read the package config.
218
        $xPackageConfig = $this->readPackageConfig($sClassName);
219
220
        // Register the declarations in the package config.
221
        $this->_registerFromConfig($xPackageConfig);
222
223
        // Register the view namespaces
224
        $di->getViewManager()->addNamespaces($xPackageConfig, $xAppConfig);
225
226
        // Register the package as a code generator.
227
        $this->xCodeGenerator->addGenerator($sClassName, 500);
228
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
229
230
    /**
231
     * Register a function or callable class
232
     *
233
     * Call the request plugin with the $sType defined as name.
234
     *
235
     * @param string $sType    The type of request handler being registered
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
236
     * @param string $sCallable    The callable entity being registered
0 ignored issues
show
Coding Style introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
237
     * @param array|string $xOptions    The associated options
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
238
     *
239
     * @return void
240
     * @throws SetupException
241
     */
242
    public function registerCallable(string $sType, string $sCallable, $xOptions = [])
243
    {
244
        if(isset($this->aRequestPlugins[$sType]) &&
245
            ($xPlugin = $this->jaxon->di()->g($this->aRequestPlugins[$sType])))
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
246
        {
247
            $xPlugin->register($sType, $sCallable, $xPlugin->checkOptions($sCallable, $xOptions));
248
            return;
249
        }
250
        throw new SetupException($this->xTranslator->trans('errors.register.plugin',
251
            ['name' => $sType, 'callable' => $sCallable]));
252
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
253
254
    /**
255
     * Register callables from a section of the config
256
     *
257
     * @param Config $xAppConfig    The config options
258
     * @param string $sSection    The config section name
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter name; 4 found
Loading history...
259
     * @param string $sCallableType    The type of callable to register
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
260
     *
261
     * @return void
262
     * @throws SetupException
263
     */
264
    private function registerCallablesFromConfig(Config $xAppConfig, string $sSection, string $sCallableType)
265
    {
266
        $aConfig = $xAppConfig->getOption($sSection, []);
267
        foreach($aConfig as $xKey => $xValue)
268
        {
269
            if(is_integer($xKey) && is_string($xValue))
270
            {
271
                // Register a function without options
272
                $this->registerCallable($sCallableType, $xValue);
273
            }
274
            elseif(is_string($xKey) && (is_array($xValue) || is_string($xValue)))
275
            {
276
                // Register a function with options
277
                $this->registerCallable($sCallableType, $xKey, $xValue);
278
            }
279
            else
280
            {
281
                continue;
282
                // Todo: throw an exception
283
            }
284
        }
285
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
286
287
    /**
288
     * Read and set Jaxon options from a JSON config file
289
     *
290
     * @param Config $xAppConfig    The config options
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
291
     *
292
     * @return void
293
     * @throws SetupException
294
     */
295
    private function _registerFromConfig(Config $xAppConfig)
296
    {
297
        // Register functions
298
        $this->registerCallablesFromConfig($xAppConfig, 'functions', Jaxon::CALLABLE_FUNCTION);
299
300
        // Register classes
301
        $this->registerCallablesFromConfig($xAppConfig, 'classes', Jaxon::CALLABLE_CLASS);
302
303
        // Register directories
304
        $this->registerCallablesFromConfig($xAppConfig, 'directories', Jaxon::CALLABLE_DIR);
305
306
        // Register classes in DI container
307
        $di = $this->jaxon->di();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 15 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
308
        $aContainerConfig = $xAppConfig->getOption('container', []);
309
        foreach($aContainerConfig as $sClassName => $xClosure)
310
        {
311
            $di->set($sClassName, $xClosure);
312
        }
313
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
314
315
    /**
316
     * Read and set Jaxon options from a JSON config file
317
     *
318
     * @param Config $xAppConfig    The config options
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
319
     *
320
     * @return void
321
     * @throws SetupException
322
     */
323
    public function registerFromConfig(Config $xAppConfig)
324
    {
325
        $this->_registerFromConfig($xAppConfig);
326
327
        // Register packages
328
        $aPackageConfig = $xAppConfig->getOption('packages', []);
329
        foreach($aPackageConfig as $sClassName => $aOptions)
330
        {
331
            $this->registerPackage($sClassName, $aOptions);
332
        }
333
    }
334
335
336
    /**
337
     * Find the specified response plugin by name and return a reference to it if one exists
338
     *
339
     * @param string $sName    The name of the plugin
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
340
     * @param Response|null $xResponse    The response to attach the plugin to
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
341
     *
342
     * @return ResponsePlugin|null
343
     */
344
    public function getResponsePlugin(string $sName, ?Response $xResponse = null): ?ResponsePlugin
345
    {
346
        if(!isset($this->aResponsePlugins[$sName]))
347
        {
348
            return null;
349
        }
350
        $xPlugin = $this->jaxon->di()->g($this->aResponsePlugins[$sName]);
351
        if(($xResponse))
352
        {
353
            $xPlugin->setResponse($xResponse);
354
        }
355
        return $xPlugin;
356
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
357
358
    /**
359
     * Find the specified request plugin by name and return a reference to it if one exists
360
     *
361
     * @param string $sName    The name of the plugin
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
362
     *
363
     * @return RequestPlugin|null
364
     */
365
    public function getRequestPlugin(string $sName): ?RequestPlugin
366
    {
367
        if(!isset($this->aRequestPlugins[$sName]))
368
        {
369
            return null;
370
        }
371
        return $this->jaxon->di()->g($this->aRequestPlugins[$sName]);
372
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
373
374
    /**
375
     * Register the Jaxon request plugins
376
     *
377
     * @return void
378
     * @throws SetupException
379
     */
380
    public function registerPlugins()
381
    {
382
        // Request plugins
383
        $this->registerPlugin(ClassPlugin::class, Jaxon::CALLABLE_CLASS, 101);
384
        $this->registerPlugin(FunctionPlugin::class, Jaxon::CALLABLE_FUNCTION, 102);
385
        $this->registerPlugin(DirPlugin::class, Jaxon::CALLABLE_DIR, 103);
386
387
        // Register the JQuery response plugin
388
        $this->registerPlugin(JQueryPlugin::class, 'jquery', 700);
389
        // Register the DataBag response plugin
390
        $this->registerPlugin(DataBagPlugin::class, 'bags', 700);
391
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
392
}
393