These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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 \Jaxon\Dialog\Interfaces\Alert); |
||
134 | $bIsConfirm = ($xPlugin instanceof \Jaxon\Dialog\Interfaces\Confirm); |
||
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', ['name' => get_class($xPlugin)])); |
||
148 | } |
||
149 | // This plugin implements the Alert interface |
||
150 | if($bIsAlert) |
||
151 | { |
||
152 | jaxon()->dialog()->setAlert($xPlugin); |
||
153 | } |
||
154 | // This plugin implements the Confirm interface |
||
155 | if($bIsConfirm) |
||
156 | { |
||
157 | jaxon()->dialog()->setConfirm($xPlugin); |
||
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
|
|||
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
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 |
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.