Completed
Push — php7.2-travis ( be5e72...caaf61 )
by
unknown
09:45
created

ar::error()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 3
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
	if ( !defined('ARBaseDir') ) {
3
		define('ARBaseDir', dirname( __FILE__ ) . '/ar/');
4
	}
5
	require_once(ARBaseDir.'pinp.php');
6
	require_once(ARBaseDir.'core/exception.php');
7
8
	ar_pinp::allow('ar');
9
	ar_pinp::allow('ar_error');
10
11
	class ar implements arKeyValueStoreInterface {
12
		protected static $instances;
13
		protected static $ar;
14
		protected static $context = null;
15
16
		public static function __callStatic($name, $arguments) {
17
			return self::load($name);
18
		}
19
20
		public function __call($name, $arguments) {
21
			return $this->load($name);
22
		}
23
24
		public function __get($name) {
25
			return $this->load($name);
26
		}
27
28
		private static function _parseClassName($className) {
29
			$fileName = '';
30
			if (strpos($className, 'ar_')===0) {
31
				$fileName = substr($className, 3);
32
				$fileName = preg_replace('/[^a-z0-9_\.\\\\\/]/i', '', $fileName);
33
				$fileName = str_replace(array('_','\\'), '/', $fileName);
34
				$fileName = str_replace('../', '', $fileName);
35
			}
36
			return $fileName;
37
		}
38
39
		private static function _compileClassName($className) {
40
			if (strpos($className, 'ar_')!==0) {
41
				$className = 'ar_'.$className;
42
			}
43
			$className = str_replace(array('/','\\'), '_', $className);
44
			$className = preg_replace('/[^a-z0-9_]/i', '', $className);
45
			return $className;
46
		}
47
48
		public static function load($name=null) {
49
			if (!$name) {
50
				if (!self::$ar) {
51
					self::$ar = new ar();
52
				}
53
				return self::$ar;
54
			} else {
55
				$fullName = self::_compileClassName($name);
56
				if (!class_exists($fullName)) {
57
					$fileName = self::_parseClassName($fullName);
58 View Code Duplication
					if (!file_exists(ARBaseDir.$fileName.'.php')) {
59
						error( $name . ' not found' );
60
					} else {
61
						require_once(ARBaseDir.$fileName.'.php');
62
					}
63
				}
64
				if (!self::$instances[$name]) {
65
					self::$instances[$name] = new $fullName();
66
				}
67
				return self::$instances[$name];
68
			}
69
		}
70
71
		public static function autoload($className) {
72
			if (strpos($className, 'pinp_ar_')===0) {
73
				$className = substr($className, 5);
74
			}
75
			if (strpos($className, 'ar_')===0) {
76
				$fileName = self::_parseClassName($className);
77
				if (file_exists(ARBaseDir.$fileName.'.php')) {
78
					require_once(ARBaseDir.$fileName.'.php');
79
				} else {
80
					$subFileName = preg_replace( '/[A-Z].*$/', '', $fileName );
81 View Code Duplication
					if ( $subFileName != $fileName && file_exists( ARBaseDir.$subFileName.'.php' ) ) {
82
						require_once( ARBaseDir.$subFileName.'.php' );
83
					}
84
				}
85
			}
86
		}
87
88
		public static function ls() {
89
			return ar_store::ls();
90
		}
91
92
		public static function find($query="") {
93
			return ar_store::find($query);
94
		}
95
96
		public static function get($path="") {
97
			return ar_store::get($path);
98
		}
99
100
		public static function parents($path = ".") {
101
			return ar_store::parents($path);
0 ignored issues
show
Unused Code introduced by
The call to ar_store::parents() has too many arguments starting with $path.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
102
		}
103
104
		public static function exists($path = '.') {
105
			return ar_store::exists($path);
106
		}
107
108
		public static function error($message, $code, $previous = null) {
109
			return ar_error::raiseError($message, $code, $previous);
110
		}
111
112 View Code Duplication
		public static function call( $template, $params = null ) {
113
			$context = self::context();
114
			$me = $context->getObject();
115
			if ($me) {
116
				return $me->call( $template, $params );
117
			}
118
		}
119
120 View Code Duplication
		public static function callSuper( $params = null ) {
121
			$context = self::context();
122
			$me = $context->getObject();
123
			if ($me) {
124
				return $me->_call_super( $params );
125
			}
126
		}
127
128
		public static function taint(&$value) {
129
			if ( is_numeric($value) ) {
130
				return $value;
131
			} else if ( is_array($value) ) {
132
				array_walk_recursive( $value, array( 'self', 'taint' ) );
133
			} else if ( is_string($value) && $value ) { // empty strings don't need tainting
134
				$value = new arTainted($value);
135
			}
136
			return $value;
137
		}
138
139
		public static function untaint(&$value, $filter = FILTER_SANITIZE_SPECIAL_CHARS, $flags = null) {
140
			if ( $value instanceof arTainted ) {
141
				$value = filter_var($value->value, $filter, $flags);
142
			} else if ( is_array($value) ) {
143
				array_walk_recursive( $value, array( 'self', 'untaintArrayItem'), array(
144
					'filter' => $filter,
145
					'flags' => $flags
146
				) );
147
			}
148
			return $value;
149
		}
150
151
		protected static function untaintArrayItem(&$value, $key, $options) {
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
152
			self::untaint( $value, $options['filter'], $options['flags'] );
153
		}
154
155
		public function getvar( $name ) {
156
			global $ARCurrent, $ARConfig;
157
158
			if ($ARCurrent->arCallStack) {
159
				$arCallArgs=end($ARCurrent->arCallStack);
160
				if ( $name == 'arCallArgs' ) {
161
					return $arCallArgs;
162
				}
163
				if ( isset($arCallArgs[$name]) ) {
164
					return $arCallArgs[$name];
165
				}
166
			} else if ( $name == 'arCallArgs' ) {
167
				return ar_loader::getvar();
168
			}
169
			if ( isset($ARCurrent->$name) ) {
170
				return $ARCurrent->$name;
171
			}
172
			return ar_loader::getvar( $name );
173
		}
174
175
		public function putvar( $name, $value ) {
176
			global $ARCurrent;
177
			$ARCurrent->$name = $value;
178
		}
179
180
		public static function listExpression( $list ) {
181
			return new ar_listExpression( $list );
182
		}
183
184
		public static function listPattern() {
185
			self::autoload('ar_listExpression');
186
			$params = func_get_args();
187
			return new ar_listExpression_Pattern( $params );
188
		}
189
190
		public static function url( $url ) {
191
			return new ar_url( $url );
192
		}
193
194
		public static function context() {
195
			if (!isset(self::$context)) {
196
				self::setContext( new ar_ariadneContext() );
197
			}
198
			return self::$context;
199
		}
200
201
		public static function setContext( $context ) {
202
			if ( !isset( self::$context ) ) {
203
				self::$context = $context;
204
			} else {
205
				return self::error( 'Context can only be set once.', ar_exceptions::ACCESS_DENIED );
206
			}
207
		}
208
209
		public static function acquire( $varname, $options = array() ) {
210
			$context = self::context();
211
			return $context->acquire( $varname, $options);
212
		}
213
214
	}
215
216
	class arTainted {
217
		public $value = null;
218
219
		public function __construct($value) {
220
			$this->value = $value;
221
		}
222
223
		public function __toString() {
224
			return filter_var($this->value, FILTER_SANITIZE_SPECIAL_CHARS);
225
		}
226
	}
227
228
229
	class arObject {
230
		public function __construct( $vars = '' ) {
231
			if ( is_array($vars) ) {
232
				foreach ( $vars as $key => $var ) {
233
					if ( !is_numeric($key) ) {
234
						$this->{$key} = $var;
235
					}
236
				}
237
			}
238
		}
239
	}
240
241
	class arBase {
242
243 View Code Duplication
		public function __call($name, $arguments) {
244
			if (($name[0]==='_')) {
245
				$realName = substr($name, 1);
246
				if (ar_pinp::isAllowed($this, $realName)) {
247
					return call_user_func_array(array($this, $realName), $arguments);
248
				} else {
249
					trigger_error("Method $realName not found in class ".get_class($this), E_USER_WARNING);
250
				}
251
			} else {
252
				trigger_error("Method $name not found in class ".get_class($this), E_USER_WARNING);
253
			}
254
		}
255
	}
256
257
	class arWrapper {
258
259
		protected $wrapped = null;
260
		protected $__class = 'arWrapper';
261
262
		public function __construct( $wrapped ) {
263
			$this->wrapped = $wrapped;
264
		}
265
266
		public function __call($name, $arguments) {
267
			if ( $name[0] === '_' ) {
268
				if ( !method_exists( $this->wrapped, $name ) || !ar_pinp::isAllowed( $this, $name ) ) {
269
					$name = substr($name, 1);
270
				}
271
			}
272
			if (ar_pinp::isAllowed($this, $name)) {
273
				try {
274
					return $this->__wrap( call_user_func_array( array( $this->wrapped, $name), $arguments) );
275
				} catch( Exception $e ) {
276
					return ar::error( $e->getMessage(), $e->getCode() );
277
				}
278
			} else {
279
				trigger_error("Method $name not found in class ".get_class($this), E_USER_WARNING);
280
			}
281
		}
282
283
		public function __wrap( $result ) {
284
			if (is_object($result)) {
285
				$class = $this->__class;
286
				return new $class($result);
287
			} else {
288
				return $result;
289
			}
290
		}
291
292
		public function __get( $name ) {
293
			return $this->wrapped->$name;
294
		}
295
296
		public function __set( $name, $value ) {
297
			$this->wrapped->$name = $value;
298
		}
299
300
	}
301
302
303
	class ar_error extends ar_exceptionDefault {
304
		protected static $throwExceptions = false;
305
306
		public function __construct( $message = '', $code = 0, $previous = null ) {
307
			if ( $previous && !($previous instanceof \Exception) ) {
308
				$previous = new ar_error( $previous );
309
			}
310
			parent::__construct( (string) $message, (int) $code, $previous );
311
			$this->code = $code;
312
		}
313
314
		public function __call($name, $arguments) {
315
			if (($name[0]==='_')) {
316
				$realName = substr($name, 1);
317
				if (ar_pinp::isAllowed($this, $realName)) {
318
					return call_user_func_array(array($this, $realName), $arguments);
319 View Code Duplication
				} else {
320
					$trace = debug_backtrace(0,2);
321
					trigger_error("Method $realName not found in class ".get_class($this)." Called from line ".$trace[1]['line']." in ".$trace[1]['file'], E_USER_WARNING);
322
				}
323 View Code Duplication
			} else {
324
				$trace = debug_backtrace(0,2);
325
				trigger_error("Method $name not found in class ".get_class($this)." Called from line ".$trace[1]['line']." in ".$trace[1]['file'], E_USER_WARNING);
326
			}
327
		}
328
329
		public static function isError($ob) {
330
			return ( is_object($ob)
331
				&& ( is_a($ob, 'ar_error') || is_a($ob, 'error') || is_a($ob, 'PEAR_Error') ) );
332
		}
333
334
		public static function raiseError($message, $code, $previous = null) {
335
			if (self::$throwExceptions) {
336
				throw new ar_error($message, $code, $previous);
337
			} else {
338
				return new ar_error($message, $code, $previous);
339
			}
340
		}
341
342
		public static function configure( $option, $value ) {
343
			switch ($option) {
344
				case 'throwExceptions' :
345
					self::$throwExceptions = $value;
346
				break;
347
			}
348
		}
349
350
		public function __toString() {
351
			$result = $this->code.": ".$this->message."\r\n";
352
			$e = $this;
353
			while ($e = $e->getPrevious()) {
354
				$result .= $e->getCode().": ".$e->getMessage()."\r\n";
355
			}
356
			return $result;
357
		}
358
	}
359
360
	// FIXME: remove pinp_ar after pinp compiler has no need for it anymore
361
	class pinp_ar extends ar {
362
		public static function __callStatic($name, $arguments) {
363
			return self::load(substr($name, 1), $arguments);
0 ignored issues
show
Unused Code introduced by
The call to pinp_ar::load() has too many arguments starting with $arguments.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
364
		}
365
		public function __call($name, $arguments) {
366
			return $this->load(substr($name, 1), $arguments);
0 ignored issues
show
Unused Code introduced by
The call to pinp_ar::load() has too many arguments starting with $arguments.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
367
		}
368
		public function __get($name) {
369
			return $this->load(substr($name, 1));
370
		}
371
		public static function _ls() {
372
			return ar_store::ls();
373
		}
374
375
		public static function _find($query="") {
376
			return ar_store::find($query);
377
		}
378
379
		public static function _get($path="") {
380
			return ar_store::get($path);
381
		}
382
383
		public static function _parents($path = ".") {
384
			return ar_store::parents($path);
0 ignored issues
show
Unused Code introduced by
The call to ar_store::parents() has too many arguments starting with $path.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
385
		}
386
387
		public static function _exists($path = '.') {
388
			return ar_store::exists($path);
389
		}
390
391
		public static function _error($message, $code) {
392
			return ar::error($message, $code);
393
		}
394
395
		public static function _call($template, $params = null) {
396
			return ar::call($template, $params);
397
		}
398
399
		public static function _callSuper() {
400
			return ar::callSuper();
401
		}
402
403
		public static function _taint(&$value) {
404
			ar::taint($value);
405
		}
406
407
		public static function _untaint(&$value, $filter = FILTER_SANITIZE_SPECIAL_CHARS, $flags = null) {
408
			ar::untaint($value, $filter, $flags);
409
		}
410
411
		public static function _getvar( $name ) {
412
			return ar::getvar( $name );
413
		}
414
415
		public static function _putvar( $name, $value ) {
416
			return ar::putvar( $name, $value );
417
		}
418
419
		public static function _listExpression( $list ) {
420
			return ar::listExpression( $list );
421
		}
422
423
		public static function _listPattern() {
424
			$params = func_get_args();
425
			return call_user_func_array( array( 'ar', 'listPattern'), $params);
426
		}
427
428
		public static function _url( $url ) {
429
			return ar::url( $url );
430
		}
431
432
		public static function _acquire( $varname, $options = array() ) {
433
			return ar::acquire( $varname, $options );
434
		}
435
	}
436
437
	function ar($name=null) {
438
		// this function works as an alternative to statically calling the namespaced class
439
		// this is a fallback untill namespaces work in php 5.3
440
		return ar::load($name);
441
	}
442
443
	interface ar_contextInterface {
444
		public static function getPath( $options = array() );
445
446
		public static function getObject( $options = array() );
447
448
		public static function getLoader( $options = array() );
449
	}
450
451
	class ar_ariadneContext implements ar_contextInterface {
452
453
		public static function makePath( $cwd, $path ) { //FIXME: move this method to a better place
454
			$result = '/';
455
			if ( $path[0] === '/' ) {
456
				$path = substr( $path, 1);
457
			} else {
458
				$path = substr( $cwd, 1 ) . '/' . $path;
459
			}
460
			if ( $path ) {
461
				$splitpath = explode( '/', $path );
462
				foreach ( $splitpath as $pathticle ) {
463
					switch( $pathticle ) {
464
						case ".." :
465
							$result = dirname( $result );
466
							// if second char of $result is not set, then current result is the rootNode
467
							if ( isset($result[1]) ) {
468
								$result .= "/";
469
							}
470
							$result[0] = "/"; // make sure that even under windows, slashes are always forward slashes.
471
						break;
472
						case "." : break;
473
						case ""	 : break;
474
						default:
475
							$result .= $pathticle . '/';
476
						break;
477
					}
478
				}
479
			}
480
			return $result;
481
		}
482
483
		public static function getPath( $options = array() ) {
484
			$me = self::getObject( $options );
485
			if ($me) {
486
				$path = $me->make_path( $options['path'] );
487
				if ($options['skipShortcuts']) {
488
					$me->_load('mod_keepurl.php');
489
					$realpath = pinp_keepurl::_make_real_path( $path );
490
					if ($realpath) {
491
						$path = $realpath;
492
					}
493
				} else if ($options['rememberShortcuts']) {
494
					$me->_load('mod_keepurl.php');
495
					$path = pinp_keepurl::_make_path( $path );
496
				} else if ( $options['searchObject'] ) {
497
					if (isset($me->data->path)) {
498
						$path = $me->data->path;
499
					}
500
				}
501
			} else {
502
				$path = self::makePath( '/', $options['path'] );
503
			}
504
			return $path;
505
		}
506
507
		public static function getObject( $options = array() ) {
508
			if ( class_exists( 'pobject' ) ) {
509
				$context = pobject::getContext();
510
				$me = $context["arCurrentObject"];
511
			} else {
512
				$me = null;
513
			}
514
			return $me;
515
		}
516
517
		public static function getQuery( $query, $options = array() ) {
518
			$me = self::getObject( $options );
519
			if ($me) {
520
				if (isset($me->data->query)) {
521
					if ( $query ) {
522
						$query = "(" . $me->data->query . ") and $query";
523
					} else {
524
						 $query = $me->data->query;
525
					}
526
					return $query;
527
				}
528
			}
529
			return $query;
530
		}
531
532
		public static function getLoader( $options = array() ) { //FIXME: move code from ar_loader to here
533
			return ar_loader::getLoader();
534
		}
535
536
		public static function acquire( $varname, $options = array() ) {
537
			$me = self::getObject( $options );
538
			if ($me) {
539
				$data = $me->loadUserConfig();
540
				$vars = explode('.', $varname);
541
				foreach( $vars as $var ) {
542
					$data = $data[$var];
543
				}
544
				return $data;
545
			}
546
		}
547
548
		public static function callAtPath( $path, $callback ) {
549
			$ob = current( ar_store::get($path)->call('system.get.phtml'));
550
			pobject::pushContext( array(
551
					"arCurrentObject" => $ob,
552
					"scope" => "php"
553
					) );
554
			call_user_func( $callback );
555
			pobject::popContext();
556
		}
557
558
	}
559
560
	interface arKeyValueStoreInterface {
561
562
		public function getvar( $name );
563
564
		public function putvar( $name, $value );
565
566
	}
567
568
	spl_autoload_register('ar::autoload',true,true);
569