Completed
Push — master ( 71f3ca...10d1fd )
by Thierry
01:44
created

Manager::getRequestPlugins()   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 0
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 Jaxon\Config\Config;
27
28
use Closure;
29
30
class Manager
31
{
32
    use \Jaxon\Utils\Traits\Manager;
33
    use \Jaxon\Utils\Traits\Config;
34
    use \Jaxon\Utils\Traits\Cache;
35
    use \Jaxon\Utils\Traits\Event;
36
    use \Jaxon\Utils\Traits\Translator;
37
38
    /**
39
     * All plugins, indexed by priority
40
     *
41
     * @var array
42
     */
43
    private $aPlugins = [];
44
45
    /**
46
     * Request plugins, indexed by name
47
     *
48
     * @var array
49
     */
50
    private $aRequestPlugins = [];
51
52
    /**
53
     * Response plugins, indexed by name
54
     *
55
     * @var array
56
     */
57
    private $aResponsePlugins = [];
58
59
    /**
60
     * An array of package names
61
     *
62
     * @var array
63
     */
64
    private $aPackages = [];
65
66
    /**
67
     * Get the request plugins
68
     *
69
     * @return array
70
     */
71
    public function getRequestPlugins()
72
    {
73
        return $this->aRequestPlugins;
74
    }
75
76
    /**
77
     * Get the response plugins
78
     *
79
     * @return array
80
     */
81
    public function getResponsePlugins()
82
    {
83
        return $this->aResponsePlugins;
84
    }
85
86
    /**
87
     * Get the package plugins
88
     *
89
     * @return array
90
     */
91
    public function getPackages()
92
    {
93
        return $this->aPackages;
94
    }
95
96
    /**
97
     * Inserts an entry into an array given the specified priority number
98
     *
99
     * If a plugin already exists with the given priority, the priority is automatically incremented until a free spot is found.
100
     * The plugin is then inserted into the empty spot in the array.
101
     *
102
     * @param Plugin         $xPlugin               An instance of a plugin
103
     * @param integer        $nPriority             The desired priority, used to order the plugins
104
     *
105
     * @return void
106
     */
107
    private function setPluginPriority(Plugin $xPlugin, $nPriority)
108
    {
109
        while (isset($this->aPlugins[$nPriority]))
110
        {
111
            $nPriority++;
112
        }
113
        $this->aPlugins[$nPriority] = $xPlugin;
114
        // Sort the array by ascending keys
115
        ksort($this->aPlugins);
116
    }
117
118
    /**
119
     * Register a plugin
120
     *
121
     * Below is a table for priorities and their description:
122
     * - 0 thru 999: Plugins that are part of or extensions to the jaxon core
123
     * - 1000 thru 8999: User created plugins, typically, these plugins don't care about order
124
     * - 9000 thru 9999: Plugins that generally need to be last or near the end of the plugin list
125
     *
126
     * @param Plugin         $xPlugin               An instance of a plugin
127
     * @param integer        $nPriority             The plugin priority, used to order the plugins
128
     *
129
     * @return void
130
     */
131
    public function registerPlugin(Plugin $xPlugin, $nPriority = 1000)
132
    {
133
        $bIsAlert = ($xPlugin instanceof Dialogs\Interfaces\Alert);
0 ignored issues
show
Bug introduced by
The class Jaxon\Plugin\Dialogs\Interfaces\Alert does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
134
        $bIsConfirm = ($xPlugin instanceof Dialogs\Interfaces\Confirm);
0 ignored issues
show
Bug introduced by
The class Jaxon\Plugin\Dialogs\Interfaces\Confirm does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
135
        if($xPlugin instanceof Request)
136
        {
137
            // The name of a request plugin is used as key in the plugin table
138
            $this->aRequestPlugins[$xPlugin->getName()] = $xPlugin;
139
        }
140
        elseif($xPlugin instanceof Response)
141
        {
142
            // The name of a response plugin is used as key in the plugin table
143
            $this->aResponsePlugins[$xPlugin->getName()] = $xPlugin;
144
        }
145
        elseif(!$bIsConfirm && !$bIsAlert)
146
        {
147
            throw new \Jaxon\Exception\Error($this->trans('errors.register.invalid', array('name' => get_class($xPlugin))));
148
        }
149
        // This plugin implements the Alert interface
150
        if($bIsAlert)
151
        {
152
            $this->setAlert($xPlugin);
0 ignored issues
show
Bug introduced by
The method setAlert() does not seem to exist on object<Jaxon\Plugin\Manager>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
153
        }
154
        // This plugin implements the Confirm interface
155
        if($bIsConfirm)
156
        {
157
            $this->setConfirm($xPlugin);
0 ignored issues
show
Bug introduced by
The method setConfirm() does not seem to exist on object<Jaxon\Plugin\Manager>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
158
        }
159
        // Register the plugin as an event listener
160
        if($xPlugin instanceof \Jaxon\Utils\Interfaces\EventListener)
161
        {
162
            $this->addEventListener($xPlugin);
163
        }
164
165
        $this->setPluginPriority($xPlugin, $nPriority);
166
    }
167
168
    /**
169
     * Register a package
170
     *
171
     * @param string         $sPackageClass         The package class name
172
     * @param Closure        $xClosure              A closure to create package instance
173
     *
174
     * @return void
175
     */
176
    public function registerPackage(string $sPackageClass, Closure $xClosure)
177
    {
178
        $this->aPackages[] = $sPackageClass;
179
        jaxon()->di()->set($sPackageClass, $xClosure);
180
    }
181
182
    /**
183
     * Register a function, event or callable object
184
     *
185
     * Call the request plugin with the $sType defined as name.
186
     *
187
     * @param string        $sType          The type of request handler being registered
188
     * @param string        $sCallable      The callable entity being registered
189
     * @param array|string  $aOptions       The associated options
190
     *
191
     * @return mixed
192
     */
193
    public function register($sType, $sCallable, $aOptions = [])
194
    {
195
        if(!key_exists($sType, $this->aRequestPlugins))
196
        {
197
            throw new \Jaxon\Exception\Error($this->trans('errors.register.plugin', ['name' => $sType]));
198
        }
199
200
        $xPlugin = $this->aRequestPlugins[$sType];
201
        return $xPlugin->register($sType, $sCallable, $aOptions);
202
        // foreach($this->aRequestPlugins as $xPlugin)
203
        // {
204
        //     if($mResult instanceof \Jaxon\Request\Request || is_array($mResult) || $mResult === true)
205
        //     {
206
        //         return $mResult;
207
        //     }
208
        // }
209
        // throw new \Jaxon\Exception\Error($this->trans('errors.register.method', ['args' => print_r($aArgs, true)]));
210
    }
211
212
    /**
213
     * Read and set Jaxon options from a JSON config file
214
     *
215
     * @param Config        $xAppConfig        The config options
216
     *
217
     * @return void
218
     */
219
    public function registerFromConfig($xAppConfig)
220
    {
221
        // Register user functions
222
        $aFunctionsConfig = $xAppConfig->getOption('functions', []);
223
        foreach($aFunctionsConfig as $xKey => $xValue)
224
        {
225
            if(is_integer($xKey) && is_string($xValue))
226
            {
227
                $sFunction = $xValue;
228
                // Register a function without options
229
                $this->register(Jaxon::USER_FUNCTION, $sFunction);
230
            }
231 View Code Duplication
            elseif(is_string($xKey) && is_array($xValue))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
232
            {
233
                $sFunction = $xKey;
234
                $aOptions = $xValue;
235
                // Register a function with options
236
                $this->register(Jaxon::USER_FUNCTION, $sFunction, $aOptions);
237
            }
238
            else
239
            {
240
                continue;
241
                // Todo: throw an exception
242
            }
243
        }
244
245
        // Register classes and directories
246
        $aClassesConfig = $xAppConfig->getOption('classes', []);
247
        foreach($aClassesConfig as $xKey => $xValue)
248
        {
249
            if(is_integer($xKey) && is_string($xValue))
250
            {
251
                $sClass = $xValue;
252
                // Register a class without options
253
                $this->register(Jaxon::CALLABLE_CLASS, $sClass);
254
            }
255 View Code Duplication
            elseif(is_string($xKey) && is_array($xValue))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
256
            {
257
                $sClass = $xKey;
258
                $aOptions = $xValue;
259
                // Register a class with options
260
                $this->register(Jaxon::CALLABLE_CLASS, $sClass, $aOptions);
261
            }
262
            elseif(is_integer($xKey) && is_array($xValue))
263
            {
264
                // The directory path is required
265
                if(!key_exists('directory', $xValue))
266
                {
267
                    continue;
268
                    // Todo: throw an exception
269
                }
270
                // Registering a directory
271
                $sDirectory = $xValue['directory'];
272
                $aOptions = [];
273
                if(key_exists('options', $xValue) &&
274
                    is_array($xValue['options']) || is_string($xValue['options']))
275
                {
276
                    $aOptions = $xValue['options'];
277
                }
278
                // Setup directory options
279
                if(key_exists('namespace', $xValue))
280
                {
281
                    $aOptions['namespace'] = $xValue['namespace'];
282
                }
283
                if(key_exists('separator', $xValue))
284
                {
285
                    $aOptions['separator'] = $xValue['separator'];
286
                }
287
                // Register a class without options
288
                $this->register(Jaxon::CALLABLE_DIR, $sDirectory, $aOptions);
289
            }
290
            else
291
            {
292
                continue;
293
                // Todo: throw an exception
294
            }
295
        }
296
    }
297
298
299
    /**
300
     * Find the specified response plugin by name and return a reference to it if one exists
301
     *
302
     * @param string        $sName                The name of the plugin
303
     *
304
     * @return \Jaxon\Plugin\Response
305
     */
306
    public function getResponsePlugin($sName)
307
    {
308
        if(array_key_exists($sName, $this->aResponsePlugins))
309
        {
310
            return $this->aResponsePlugins[$sName];
311
        }
312
        return null;
313
    }
314
315
    /**
316
     * Find the specified request plugin by name and return a reference to it if one exists
317
     *
318
     * @param string        $sName                The name of the plugin
319
     *
320
     * @return \Jaxon\Plugin\Request
321
     */
322
    public function getRequestPlugin($sName)
323
    {
324
        if(array_key_exists($sName, $this->aRequestPlugins))
325
        {
326
            return $this->aRequestPlugins[$sName];
327
        }
328
        return null;
329
    }
330
}
331