1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Jaxon.php - Jaxon class |
5
|
|
|
* |
6
|
|
|
* The Jaxon class uses a modular plug-in system to facilitate the processing |
7
|
|
|
* of special Ajax requests made by a PHP page. |
8
|
|
|
* It generates Javascript that the page must include in order to make requests. |
9
|
|
|
* It handles the output of response commands (see <Jaxon\Response\Response>). |
10
|
|
|
* Many flags and settings can be adjusted to effect the behavior of the Jaxon class |
11
|
|
|
* as well as the client-side javascript. |
12
|
|
|
* |
13
|
|
|
* @package jaxon-core |
14
|
|
|
* @author Jared White |
15
|
|
|
* @author J. Max Wilson |
16
|
|
|
* @author Joseph Woolley |
17
|
|
|
* @author Steffen Konerow |
18
|
|
|
* @author Thierry Feuzeu <[email protected]> |
19
|
|
|
* @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson |
20
|
|
|
* @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson |
21
|
|
|
* @copyright 2016 Thierry Feuzeu <[email protected]> |
22
|
|
|
* @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License |
23
|
|
|
* @link https://github.com/jaxon-php/jaxon-core |
24
|
|
|
*/ |
25
|
|
|
|
26
|
|
|
namespace Jaxon; |
27
|
|
|
|
28
|
|
|
use Jaxon\Plugin\Manager as PluginManager; |
29
|
|
|
use Jaxon\Request\Manager as RequestManager; |
30
|
|
|
use Jaxon\Response\Manager as ResponseManager; |
31
|
|
|
|
32
|
|
|
use Jaxon\Utils\URI; |
33
|
|
|
use Exception; |
34
|
|
|
|
35
|
|
|
class Jaxon |
36
|
|
|
{ |
37
|
|
|
use \Jaxon\Utils\Traits\Config; |
38
|
|
|
use \Jaxon\Utils\Traits\Manager; |
39
|
|
|
use \Jaxon\Utils\Traits\Translator; |
40
|
|
|
use \Jaxon\Utils\Traits\Paginator; |
41
|
|
|
use \Jaxon\Utils\Traits\Template; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Package version number |
45
|
|
|
* |
46
|
|
|
* @var string |
47
|
|
|
*/ |
48
|
|
|
private $sVersion = 'Jaxon 2.0.4'; |
49
|
|
|
|
50
|
|
|
/* |
51
|
|
|
* Processing events |
52
|
|
|
*/ |
53
|
|
|
const PROCESSING_EVENT = 'ProcessingEvent'; |
54
|
|
|
const PROCESSING_EVENT_BEFORE = 'BeforeProcessing'; |
55
|
|
|
const PROCESSING_EVENT_AFTER = 'AfterProcessing'; |
56
|
|
|
const PROCESSING_EVENT_INVALID = 'InvalidRequest'; |
57
|
|
|
const PROCESSING_EVENT_ERROR = 'ProcessingError'; |
58
|
|
|
|
59
|
|
|
/* |
60
|
|
|
* Request methods |
61
|
|
|
*/ |
62
|
|
|
const METHOD_UNKNOWN = 0; |
63
|
|
|
const METHOD_GET = 1; |
64
|
|
|
const METHOD_POST = 2; |
65
|
|
|
|
66
|
|
|
/* |
67
|
|
|
* Request plugins |
68
|
|
|
*/ |
69
|
|
|
// For objects who's methods will be callable from the browser. |
70
|
|
|
const CALLABLE_OBJECT = 'CallableObject'; |
71
|
|
|
// For functions available at global scope, or from an instance of an object. |
72
|
|
|
const USER_FUNCTION = 'UserFunction'; |
73
|
|
|
// For browser events. |
74
|
|
|
const BROWSER_EVENT = 'BrowserEvent'; |
75
|
|
|
// For event handlers. |
76
|
|
|
const EVENT_HANDLER = 'EventHandler'; |
77
|
|
|
// For uploaded files. |
78
|
|
|
const FILE_UPLOAD = 'FileUpload'; |
79
|
|
|
|
80
|
|
|
/* |
81
|
|
|
* Request parameters |
82
|
|
|
*/ |
83
|
|
|
// Specifies that the parameter will consist of an array of form values. |
84
|
|
|
const FORM_VALUES = 'FormValues'; |
85
|
|
|
// Specifies that the parameter will contain the value of an input control. |
86
|
|
|
const INPUT_VALUE = 'InputValue'; |
87
|
|
|
// Specifies that the parameter will consist of a boolean value of a checkbox. |
88
|
|
|
const CHECKED_VALUE = 'CheckedValue'; |
89
|
|
|
// Specifies that the parameter value will be the innerHTML value of the element. |
90
|
|
|
const ELEMENT_INNERHTML = 'ElementInnerHTML'; |
91
|
|
|
// Specifies that the parameter will be a quoted value (string). |
92
|
|
|
const QUOTED_VALUE = 'QuotedValue'; |
93
|
|
|
// Specifies that the parameter will be a boolean value (true or false). |
94
|
|
|
const BOOL_VALUE = 'BoolValue'; |
95
|
|
|
// Specifies that the parameter will be a numeric, non-quoted value. |
96
|
|
|
const NUMERIC_VALUE = 'NumericValue'; |
97
|
|
|
// Specifies that the parameter will be a non-quoted value |
98
|
|
|
// (evaluated by the browsers javascript engine at run time). |
99
|
|
|
const JS_VALUE = 'UnquotedValue'; |
100
|
|
|
// Specifies that the parameter will be an integer used to generate pagination links. |
101
|
|
|
const PAGE_NUMBER = 'PageNumber'; |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Processing event handlers that have been assigned during this run of the script |
105
|
|
|
* |
106
|
|
|
* @var array |
107
|
|
|
*/ |
108
|
|
|
private $aProcessingEvents; |
109
|
|
|
|
110
|
|
|
public function __construct() |
111
|
|
|
{ |
112
|
|
|
$this->aProcessingEvents = array(); |
113
|
|
|
$this->setDefaultOptions(); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Set the default options of all components of the library |
118
|
|
|
* |
119
|
|
|
* @return void |
120
|
|
|
*/ |
121
|
|
|
private function setDefaultOptions() |
122
|
|
|
{ |
123
|
|
|
// The default configuration settings. |
124
|
|
|
$this->setOptions(array( |
125
|
|
|
'core.version' => $this->getVersion(), |
126
|
|
|
'core.language' => 'en', |
127
|
|
|
'core.encoding' => 'utf-8', |
128
|
|
|
'core.decode_utf8' => false, |
129
|
|
|
'core.prefix.function' => 'jaxon_', |
130
|
|
|
'core.prefix.class' => 'Jaxon', |
131
|
|
|
'core.prefix.event' => 'jaxon_event_', |
132
|
|
|
// 'core.request.uri' => '', |
133
|
|
|
'core.request.mode' => 'asynchronous', |
134
|
|
|
'core.request.method' => 'POST', // W3C: Method is case sensitive |
135
|
|
|
'core.debug.on' => false, |
136
|
|
|
'core.debug.verbose' => false, |
137
|
|
|
'core.process.exit' => true, |
138
|
|
|
'core.process.clean' => false, |
139
|
|
|
'core.process.timeout' => 6000, |
140
|
|
|
'core.error.handle' => false, |
141
|
|
|
'core.error.log_file' => '', |
142
|
|
|
'js.lib.output_id' => 0, |
143
|
|
|
'js.lib.queue_size' => 0, |
144
|
|
|
'js.lib.load_timeout' => 2000, |
145
|
|
|
'js.lib.show_status' => false, |
146
|
|
|
'js.lib.show_cursor' => true, |
147
|
|
|
'js.app.dir' => '', |
148
|
|
|
'js.app.minify' => true, |
149
|
|
|
'js.app.options' => '', |
150
|
|
|
)); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Set Jaxon to use the Composer autoloader |
155
|
|
|
* |
156
|
|
|
* @return void |
157
|
|
|
*/ |
158
|
|
|
public function useComposerAutoloader() |
159
|
|
|
{ |
160
|
|
|
$this->getPluginManager()->useComposerAutoloader(); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Disable Jaxon classes autoloading |
165
|
|
|
* |
166
|
|
|
* @return void |
167
|
|
|
*/ |
168
|
|
|
public function disableAutoload() |
169
|
|
|
{ |
170
|
|
|
$this->getPluginManager()->disableAutoload(); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* The current Jaxon version |
175
|
|
|
* |
176
|
|
|
* @return string |
177
|
|
|
*/ |
178
|
|
|
public function getVersion() |
179
|
|
|
{ |
180
|
|
|
return $this->sVersion; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Register request handlers, including functions, callable objects and events. |
185
|
|
|
* |
186
|
|
|
* New plugins can be added that support additional registration methods and request processors. |
187
|
|
|
* |
188
|
|
|
* @param string $sType The type of request handler being registered |
189
|
|
|
* Options include: |
190
|
|
|
* - Jaxon::USER_FUNCTION: a function declared at global scope |
191
|
|
|
* - Jaxon::CALLABLE_OBJECT: an object who's methods are to be registered |
192
|
|
|
* - Jaxon::BROWSER_EVENT: an event which will cause zero or more event handlers to be called |
193
|
|
|
* - Jaxon::EVENT_HANDLER: register an event handler function. |
194
|
|
|
* @param mixed $sFunction | $objObject | $sEvent |
195
|
|
|
* When registering a function, this is the name of the function |
196
|
|
|
* When registering a callable object, this is the object being registered |
197
|
|
|
* When registering an event or event handler, this is the name of the event |
198
|
|
|
* @param mixed $sIncludeFile | $aCallOptions | $sEventHandler |
199
|
|
|
* When registering a function, this is the (optional) include file |
200
|
|
|
* When registering a callable object, this is an (optional) array |
201
|
|
|
* of call options for the functions being registered |
202
|
|
|
* When registering an event handler, this is the name of the function |
203
|
|
|
* |
204
|
|
|
* @return mixed |
205
|
|
|
*/ |
206
|
|
|
public function register($sType, $xArgs) |
207
|
|
|
{ |
208
|
|
|
$aArgs = func_get_args(); |
209
|
|
|
$nArgs = func_num_args(); |
210
|
|
|
|
211
|
|
|
if(self::PROCESSING_EVENT == $sType) |
212
|
|
|
{ |
213
|
|
|
if($nArgs > 2) |
214
|
|
|
{ |
215
|
|
|
$sEvent = $xArgs; |
216
|
|
|
$xUserFunction = $aArgs[2]; |
217
|
|
|
if(!is_a($xUserFunction, 'Request\\Support\\UserFunction')) |
218
|
|
|
$xUserFunction = new Request\Support\UserFunction($xUserFunction); |
219
|
|
|
$this->aProcessingEvents[$sEvent] = $xUserFunction; |
220
|
|
|
} |
221
|
|
|
/*else |
222
|
|
|
{ |
223
|
|
|
// Todo: return error |
224
|
|
|
}*/ |
225
|
|
|
return true; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
return $this->getPluginManager()->register($aArgs); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* Add a path to the class directories |
233
|
|
|
* |
234
|
|
|
* @param string $sDirectory The path to the directory |
235
|
|
|
* @param string|null $sNamespace The associated namespace |
236
|
|
|
* @param string $sSeparator The character to use as separator in javascript class names |
237
|
|
|
* @param array $aProtected The functions that are not to be exported |
238
|
|
|
* |
239
|
|
|
* @return boolean |
240
|
|
|
*/ |
241
|
|
|
public function addClassDir($sDirectory, $sNamespace = null, $sSeparator = '.', array $aProtected = array()) |
242
|
|
|
{ |
243
|
|
|
return $this->getPluginManager()->addClassDir($sDirectory, $sNamespace, $sSeparator, $aProtected); |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* Register callable objects from all class directories |
248
|
|
|
* |
249
|
|
|
* @param array $aOptions The options to register the classes with |
250
|
|
|
* |
251
|
|
|
* @return void |
252
|
|
|
*/ |
253
|
|
|
public function registerClasses(array $aOptions = array()) |
254
|
|
|
{ |
255
|
|
|
return $this->getPluginManager()->registerClasses($aOptions); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Register a callable object from one of the class directories |
260
|
|
|
* |
261
|
|
|
* The class name can be dot, slash or anti-slash separated. |
262
|
|
|
* If the $bGetObject parameter is set to true, the registered instance of the class is returned. |
263
|
|
|
* |
264
|
|
|
* @param string $sClassName The name of the class to register |
265
|
|
|
* @param array $aOptions The options to register the class with |
266
|
|
|
* @param boolean $bGetObject Return the registered instance of the class |
267
|
|
|
* |
268
|
|
|
* @return void |
269
|
|
|
*/ |
270
|
|
|
public function registerClass($sClassName, array $aOptions = array(), $bGetObject = false) |
271
|
|
|
{ |
272
|
|
|
$this->getPluginManager()->registerClass($sClassName, $aOptions); |
273
|
|
|
return (($bGetObject) ? $this->getPluginManager()->getRegisteredObject($sClassName) : null); |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* Determine if a call is a jaxon request or a page load request |
278
|
|
|
* |
279
|
|
|
* @return boolean |
280
|
|
|
*/ |
281
|
|
|
public function canProcessRequest() |
282
|
|
|
{ |
283
|
|
|
return $this->getPluginManager()->canProcessRequest(); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* If this is a jaxon request, call the requested PHP function, build the response and send it back to the browser |
288
|
|
|
* |
289
|
|
|
* This is the main server side engine for Jaxon. |
290
|
|
|
* It handles all the incoming requests, including the firing of events and handling of the response. |
291
|
|
|
* If your RequestURI is the same as your web page, then this function should be called before ANY |
292
|
|
|
* headers or HTML is output from your script. |
293
|
|
|
* |
294
|
|
|
* This function may exit after the request is processed, if the 'core.process.exit' option is set to true. |
295
|
|
|
* |
296
|
|
|
* @return void |
297
|
|
|
* |
298
|
|
|
* @see <Jaxon\Jaxon->canProcessRequest> |
299
|
|
|
*/ |
300
|
|
|
public function processRequest() |
301
|
|
|
{ |
302
|
|
|
// Check to see if headers have already been sent out, in which case we can't do our job |
303
|
|
|
if(headers_sent($filename, $linenumber)) |
304
|
|
|
{ |
305
|
|
|
echo $this->trans('errors.output.already-sent', array( |
306
|
|
|
'location' => $filename . ':' . $linenumber |
307
|
|
|
)), "\n", $this->trans('errors.output.advice'); |
308
|
|
|
exit(); |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
// Check if there is a plugin to process this request |
312
|
|
|
if(!$this->canProcessRequest()) |
313
|
|
|
{ |
314
|
|
|
return; |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
$bEndRequest = false; |
318
|
|
|
$mResult = true; |
319
|
|
|
|
320
|
|
|
// Handle before processing event |
321
|
|
View Code Duplication |
if(isset($this->aProcessingEvents[self::PROCESSING_EVENT_BEFORE])) |
322
|
|
|
{ |
323
|
|
|
$this->aProcessingEvents[self::PROCESSING_EVENT_BEFORE]->call(array(&$bEndRequest)); |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
if(!$bEndRequest) |
327
|
|
|
{ |
328
|
|
|
try |
329
|
|
|
{ |
330
|
|
|
$mResult = $this->getPluginManager()->processRequest(); |
331
|
|
|
} |
332
|
|
|
catch(Exception $e) |
333
|
|
|
{ |
334
|
|
|
// An exception was thrown while processing the request. |
335
|
|
|
// The request missed the corresponding handler function, |
336
|
|
|
// or an error occurred while attempting to execute the handler. |
337
|
|
|
// Replace the response, if one has been started and send a debug message. |
338
|
|
|
|
339
|
|
|
$xResponseManager = $this->getResponseManager(); |
340
|
|
|
$xResponseManager->clear(); |
341
|
|
|
$xResponseManager->append(new Response\Response()); |
342
|
|
|
$xResponseManager->debug($e->getMessage()); |
343
|
|
|
$mResult = false; |
344
|
|
|
|
345
|
|
|
if($e instanceof \Jaxon\Exception\Error) |
346
|
|
|
{ |
347
|
|
|
$sEvent = self::PROCESSING_EVENT_INVALID; |
348
|
|
|
$aParams = array($e->getMessage()); |
349
|
|
|
} |
350
|
|
|
else |
351
|
|
|
{ |
352
|
|
|
$sEvent = self::PROCESSING_EVENT_ERROR; |
353
|
|
|
$aParams = array($e); |
354
|
|
|
} |
355
|
|
|
|
356
|
|
|
if(isset($this->aProcessingEvents[$sEvent])) |
357
|
|
|
{ |
358
|
|
|
// Call the processing event |
359
|
|
|
$this->aProcessingEvents[$sEvent]->call($aParams); |
360
|
|
|
} |
361
|
|
|
else |
362
|
|
|
{ |
363
|
|
|
// The exception is not to be processed here. |
364
|
|
|
throw $e; |
365
|
|
|
} |
366
|
|
|
} |
367
|
|
|
} |
368
|
|
|
// Clean the processing buffer |
369
|
|
|
if(($this->getOption('core.process.clean'))) |
370
|
|
|
{ |
371
|
|
|
$er = error_reporting(0); |
372
|
|
|
while (ob_get_level() > 0) |
373
|
|
|
{ |
374
|
|
|
ob_end_clean(); |
375
|
|
|
} |
376
|
|
|
error_reporting($er); |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
if($mResult === true) |
380
|
|
|
{ |
381
|
|
|
// Handle after processing event |
382
|
|
View Code Duplication |
if(isset($this->aProcessingEvents[self::PROCESSING_EVENT_AFTER])) |
383
|
|
|
{ |
384
|
|
|
$bEndRequest = false; |
385
|
|
|
$this->aProcessingEvents[self::PROCESSING_EVENT_AFTER]->call(array($bEndRequest)); |
386
|
|
|
} |
387
|
|
|
} |
388
|
|
|
|
389
|
|
|
$this->getResponseManager()->printDebug(); |
390
|
|
|
|
391
|
|
|
if(($this->getOption('core.process.exit'))) |
392
|
|
|
{ |
393
|
|
|
$this->getResponseManager()->sendOutput(); |
394
|
|
|
exit(); |
395
|
|
|
} |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
/** |
399
|
|
|
* Send the response output back to the browser |
400
|
|
|
* |
401
|
|
|
* @return void |
402
|
|
|
*/ |
403
|
|
|
public function sendResponse() |
404
|
|
|
{ |
405
|
|
|
$this->getResponseManager()->sendOutput(); |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
/** |
409
|
|
|
* Send the HTTP headers back to the browser |
410
|
|
|
* |
411
|
|
|
* @return void |
412
|
|
|
*/ |
413
|
|
|
public function sendHeaders() |
414
|
|
|
{ |
415
|
|
|
$this->getResponseManager()->sendHeaders(); |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
/** |
419
|
|
|
* Get the response output |
420
|
|
|
* |
421
|
|
|
* @return string |
422
|
|
|
*/ |
423
|
|
|
public function getOutput() |
424
|
|
|
{ |
425
|
|
|
$this->getResponseManager()->getOutput(); |
426
|
|
|
} |
427
|
|
|
|
428
|
|
|
/** |
429
|
|
|
* Returns the Jaxon Javascript header and wrapper code to be printed into the page |
430
|
|
|
* |
431
|
|
|
* The javascript code returned by this function is dependent on the plugins |
432
|
|
|
* that are included and the functions and classes that are registered. |
433
|
|
|
* |
434
|
|
|
* @param boolean $bIncludeJs Also get the JS files |
435
|
|
|
* @param boolean $bIncludeCss Also get the CSS files |
436
|
|
|
* |
437
|
|
|
* @return string |
438
|
|
|
*/ |
439
|
|
|
public function getScript($bIncludeJs = false, $bIncludeCss = false) |
440
|
|
|
{ |
441
|
|
|
if(!$this->getOption('core.request.uri')) |
442
|
|
|
{ |
443
|
|
|
$this->setOption('core.request.uri', URI::detect()); |
444
|
|
|
} |
445
|
|
|
$sCode = ''; |
446
|
|
|
if(($bIncludeCss)) |
447
|
|
|
{ |
448
|
|
|
$sCode .= $this->getPluginManager()->getCss() . "\n"; |
449
|
|
|
} |
450
|
|
|
if(($bIncludeJs)) |
451
|
|
|
{ |
452
|
|
|
$sCode .= $this->getPluginManager()->getJs() . "\n"; |
453
|
|
|
} |
454
|
|
|
$sCode .= $this->getPluginManager()->getScript(); |
455
|
|
|
return $sCode; |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
/** |
459
|
|
|
* Print the jaxon Javascript header and wrapper code into your page |
460
|
|
|
* |
461
|
|
|
* The javascript code returned by this function is dependent on the plugins |
462
|
|
|
* that are included and the functions and classes that are registered. |
463
|
|
|
* |
464
|
|
|
* @param boolean $bIncludeJs Also print the JS files |
465
|
|
|
* @param boolean $bIncludeCss Also print the CSS files |
466
|
|
|
* |
467
|
|
|
* @return void |
468
|
|
|
*/ |
469
|
|
|
public function printScript($bIncludeJs = false, $bIncludeCss = false) |
470
|
|
|
{ |
471
|
|
|
print $this->getScript($bIncludeJs, $bIncludeCss); |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
/** |
475
|
|
|
* Return the javascript header code and file includes |
476
|
|
|
* |
477
|
|
|
* @return string |
478
|
|
|
*/ |
479
|
|
|
public function getJs() |
480
|
|
|
{ |
481
|
|
|
return $this->getPluginManager()->getJs(); |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
/** |
485
|
|
|
* Return the CSS header code and file includes |
486
|
|
|
* |
487
|
|
|
* @return string |
488
|
|
|
*/ |
489
|
|
|
public function getCss() |
490
|
|
|
{ |
491
|
|
|
return $this->getPluginManager()->getCss(); |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
/** |
495
|
|
|
* Read and set Jaxon options from a PHP config file |
496
|
|
|
* |
497
|
|
|
* @param string $sConfigFile The full path to the config file |
498
|
|
|
* @param string $sLibKey The key of the library options in the file |
499
|
|
|
* @param string|null $sAppKey The key of the application options in the file |
500
|
|
|
* |
501
|
|
|
* @return array |
502
|
|
|
*/ |
503
|
|
|
public function readPhpConfigFile($sConfigFile, $sLibKey = '', $sAppKey = null) |
504
|
|
|
{ |
505
|
|
|
return Utils\Config\Php::read($sConfigFile, $sLibKey, $sAppKey); |
506
|
|
|
} |
507
|
|
|
|
508
|
|
|
/** |
509
|
|
|
* Read and set Jaxon options from a YAML config file |
510
|
|
|
* |
511
|
|
|
* @param string $sConfigFile The full path to the config file |
512
|
|
|
* @param string $sLibKey The key of the library options in the file |
513
|
|
|
* @param string|null $sAppKey The key of the application options in the file |
514
|
|
|
* |
515
|
|
|
* @return array |
516
|
|
|
*/ |
517
|
|
|
public function readYamlConfigFile($sConfigFile, $sLibKey = '', $sAppKey = null) |
518
|
|
|
{ |
519
|
|
|
return Utils\Config\Yaml::read($sConfigFile, $sLibKey, $sAppKey); |
520
|
|
|
} |
521
|
|
|
|
522
|
|
|
/** |
523
|
|
|
* Read and set Jaxon options from a JSON config file |
524
|
|
|
* |
525
|
|
|
* @param string $sConfigFile The full path to the config file |
526
|
|
|
* @param string $sLibKey The key of the library options in the file |
527
|
|
|
* @param string|null $sAppKey The key of the application options in the file |
528
|
|
|
* |
529
|
|
|
* @return array |
530
|
|
|
*/ |
531
|
|
|
public function readJsonConfigFile($sConfigFile, $sLibKey = '', $sAppKey = null) |
532
|
|
|
{ |
533
|
|
|
return Utils\Config\Json::read($sConfigFile, $sLibKey, $sAppKey); |
534
|
|
|
} |
535
|
|
|
|
536
|
|
|
/** |
537
|
|
|
* Read and set Jaxon options from a config file |
538
|
|
|
* |
539
|
|
|
* @param string $sConfigFile The full path to the config file |
540
|
|
|
* @param string $sLibKey The key of the library options in the file |
541
|
|
|
* @param string|null $sAppKey The key of the application options in the file |
542
|
|
|
* |
543
|
|
|
* @return array |
544
|
|
|
*/ |
545
|
|
|
public function readConfigFile($sConfigFile, $sLibKey = '', $sAppKey = null) |
546
|
|
|
{ |
547
|
|
|
$sExt = pathinfo($sConfigFile, PATHINFO_EXTENSION); |
548
|
|
|
switch($sExt) |
549
|
|
|
{ |
550
|
|
|
case 'php': |
551
|
|
|
return $this->readPhpConfigFile($sConfigFile, $sLibKey, $sAppKey); |
552
|
|
|
case 'yaml': |
553
|
|
|
case 'yml': |
554
|
|
|
return $this->readYamlConfigFile($sConfigFile, $sLibKey, $sAppKey); |
555
|
|
|
case 'json': |
556
|
|
|
return $this->readJsonConfigFile($sConfigFile, $sLibKey, $sAppKey); |
557
|
|
|
default: |
558
|
|
|
$sErrorMsg = jaxon_trans('config.errors.file.extension', array('path' => $sConfigFile)); |
559
|
|
|
throw new \Jaxon\Exception\Config\File($sErrorMsg); |
560
|
|
|
} |
561
|
|
|
} |
562
|
|
|
|
563
|
|
|
/** |
564
|
|
|
* Register a plugin |
565
|
|
|
* |
566
|
|
|
* Below is a table for priorities and their description: |
567
|
|
|
* - 0 thru 999: Plugins that are part of or extensions to the jaxon core |
568
|
|
|
* - 1000 thru 8999: User created plugins, typically, these plugins don't care about order |
569
|
|
|
* - 9000 thru 9999: Plugins that generally need to be last or near the end of the plugin list |
570
|
|
|
* |
571
|
|
|
* @param Plugin $xPlugin An instance of a plugin |
572
|
|
|
* @param integer $nPriority The plugin priority, used to order the plugins |
573
|
|
|
* |
574
|
|
|
* @return void |
575
|
|
|
*/ |
576
|
|
|
public function registerPlugin(\Jaxon\Plugin\Plugin $xPlugin, $nPriority = 1000) |
577
|
|
|
{ |
578
|
|
|
$this->getPluginManager()->registerPlugin($xPlugin, $nPriority); |
579
|
|
|
} |
580
|
|
|
|
581
|
|
|
/** |
582
|
|
|
* Register the Jaxon request plugins |
583
|
|
|
* |
584
|
|
|
* @return void |
585
|
|
|
*/ |
586
|
|
|
public function registerRequestPlugins() |
587
|
|
|
{ |
588
|
|
|
$this->registerPlugin(new \Jaxon\Request\Plugin\CallableObject(), 101); |
589
|
|
|
$this->registerPlugin(new \Jaxon\Request\Plugin\UserFunction(), 102); |
590
|
|
|
$this->registerPlugin(new \Jaxon\Request\Plugin\BrowserEvent(), 103); |
591
|
|
|
$this->registerPlugin(new \Jaxon\Request\Plugin\FileUpload(), 104); |
592
|
|
|
} |
593
|
|
|
|
594
|
|
|
/** |
595
|
|
|
* Register the Jaxon response plugins |
596
|
|
|
* |
597
|
|
|
* @return void |
598
|
|
|
*/ |
599
|
|
|
public function registerResponsePlugins() |
600
|
|
|
{ |
601
|
|
|
// Register an instance of the JQuery plugin |
602
|
|
|
$this->registerPlugin(new \Jaxon\JQuery\Plugin(), 700); |
603
|
|
|
} |
604
|
|
|
|
605
|
|
|
/** |
606
|
|
|
* Set a new directory for pagination templates |
607
|
|
|
* |
608
|
|
|
* @param string $sDirectory The directory path |
609
|
|
|
* |
610
|
|
|
* @return void |
611
|
|
|
*/ |
612
|
|
|
public function setPaginationDir($sDirectory) |
613
|
|
|
{ |
614
|
|
|
$this->addViewNamespace('pagination', $sDirectory, '.php'); |
615
|
|
|
} |
616
|
|
|
|
617
|
|
|
/** |
618
|
|
|
* Check if uploaded files are available |
619
|
|
|
* |
620
|
|
|
* @return boolean |
621
|
|
|
*/ |
622
|
|
|
public function hasUploadedFiles() |
623
|
|
|
{ |
624
|
|
|
if(($xUploadPlugin = $this->getPluginManager()->getRequestPlugin(self::FILE_UPLOAD)) == null) |
625
|
|
|
{ |
626
|
|
|
return false; |
627
|
|
|
} |
628
|
|
|
return $xUploadPlugin->canProcessRequest(); |
629
|
|
|
} |
630
|
|
|
|
631
|
|
|
/** |
632
|
|
|
* Check uploaded files validity and move them to the user dir |
633
|
|
|
* |
634
|
|
|
* @return boolean |
635
|
|
|
*/ |
636
|
|
|
public function saveUploadedFiles() |
637
|
|
|
{ |
638
|
|
|
try |
639
|
|
|
{ |
640
|
|
|
if(($xUploadPlugin = $this->getPluginManager()->getRequestPlugin(self::FILE_UPLOAD)) == null) |
641
|
|
|
{ |
642
|
|
|
throw new Exception($this->trans('errors.upload.plugin')); |
643
|
|
|
} |
644
|
|
|
else if(!$xUploadPlugin->canProcessRequest()) |
645
|
|
|
{ |
646
|
|
|
throw new Exception($this->trans('errors.upload.request')); |
647
|
|
|
} |
648
|
|
|
// Save uploaded files |
649
|
|
|
$sKey = $xUploadPlugin->saveUploadedFiles(); |
650
|
|
|
$sResponse = '{"code": "success", "upl": "' . $sKey . '"}'; |
651
|
|
|
$return = true; |
652
|
|
|
} |
653
|
|
|
catch(Exception $e) |
654
|
|
|
{ |
655
|
|
|
$sResponse = '{"code": "error", "msg": "' . addslashes($e->getMessage()) . '"}'; |
656
|
|
|
$return = false; |
657
|
|
|
} |
658
|
|
|
// Send the response back to the browser |
659
|
|
|
echo '<script>var res = ', $sResponse, '; </script>'; |
660
|
|
|
if(($this->getOption('core.process.exit'))) |
661
|
|
|
{ |
662
|
|
|
exit(); |
|
|
|
|
663
|
|
|
} |
664
|
|
|
return $return; |
665
|
|
|
} |
666
|
|
|
|
667
|
|
|
/** |
668
|
|
|
* Get the uploaded files |
669
|
|
|
* |
670
|
|
|
* @return array |
671
|
|
|
*/ |
672
|
|
|
public function getUploadedFiles() |
673
|
|
|
{ |
674
|
|
|
if(($xUploadPlugin = $this->getPluginManager()->getRequestPlugin(self::FILE_UPLOAD)) == null) |
675
|
|
|
{ |
676
|
|
|
return []; |
677
|
|
|
} |
678
|
|
|
return $xUploadPlugin->getUploadedFiles(); |
679
|
|
|
} |
680
|
|
|
|
681
|
|
|
/** |
682
|
|
|
* Filter uploaded file name |
683
|
|
|
* |
684
|
|
|
* @param Closure $fFileFilter The closure which filters filenames |
685
|
|
|
* |
686
|
|
|
* @return void |
687
|
|
|
*/ |
688
|
|
|
public function setUploadFileFilter($fFileFilter) |
689
|
|
|
{ |
690
|
|
|
if(($xUploadPlugin = $this->getPluginManager()->getRequestPlugin(self::FILE_UPLOAD)) == null) |
691
|
|
|
{ |
692
|
|
|
return; |
693
|
|
|
} |
694
|
|
|
$xUploadPlugin->setFileFilter($fFileFilter); |
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
/** |
698
|
|
|
* Get the Sentry instance |
699
|
|
|
* |
700
|
|
|
* @return \Jaxon\Sentry\Sentry |
701
|
|
|
*/ |
702
|
|
|
public function sentry() |
703
|
|
|
{ |
704
|
|
|
return Utils\Container::getInstance()->getSentry(); |
705
|
|
|
} |
706
|
|
|
|
707
|
|
|
/** |
708
|
|
|
* Get the Armada instance |
709
|
|
|
* |
710
|
|
|
* @return \Jaxon\Sentry\Traits\Armada |
711
|
|
|
*/ |
712
|
|
|
public function armada() |
713
|
|
|
{ |
714
|
|
|
return Utils\Container::getInstance()->getArmada(); |
715
|
|
|
} |
716
|
|
|
} |
717
|
|
|
|
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.