Completed
Push — 7.0-syntax-fixes ( ccbc92 )
by
unknown
535:45 queued 529:05
created

ariadne_object::save()   F

Complexity

Conditions 28
Paths > 20000

Size

Total Lines 194
Code Lines 123

Duplication

Lines 4
Ratio 2.06 %

Code Coverage

Tests 112
CRAP Score 38.5826

Importance

Changes 0
Metric Value
cc 28
eloc 123
nc 36904
nop 2
dl 4
loc 194
ccs 112
cts 147
cp 0.7619
crap 38.5826
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 38 and the first side effect is on line 36.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
    /******************************************************************
3
     pobject.phtml                                         Muze Ariadne
4
     ------------------------------------------------------------------
5
     Author: Muze ([email protected])
6
     Date: 31 october 2002
7
8
     Copyright 2002 Muze
9
10
     This file is part of Ariadne.
11
12
     Ariadne is free software; you can redistribute it and/or modify
13
     it under the terms of the GNU General Public License as published
14
     by the Free Software Foundation; either version 2 of the License,
15
     or (at your option) any later version.
16
17
     Ariadne is distributed in the hope that it will be useful,
18
     but WITHOUT ANY WARRANTY; without even the implied warranty of
19
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
     GNU General Public License for more details.
21
22
     You should have received a copy of the GNU General Public License
23
     along with Ariadne; if not, write to the Free Software
24
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25
     02111-1307  USA
26
27
    -------------------------------------------------------------------
28
29
     Class inheritance: 	pobject
30
     Description:
31
32
       This is the class definition file of the pobject class.
33
34
    ******************************************************************/
35
36
debug("pobject: Load","object");
37
38
abstract class ariadne_object extends object { // ariadne_object class definition
39
40
	public $store;
41
	public $path;
42
	public $data;
43
44 105
	public function init($store, $path, $data) {
45 105
		$this->store=$store;
46 105
		$this->path=$path;
47 105
		$this->data=$data;
48 105
		if ( !isset($this->data->config) ) {
49 21
			$this->data->config = new object();
50 21
		}
51 105
	}
52
53 105
	public function call($arCallFunction="view.html", $arCallArgs=array()) {
54
	/***********************************************************************
55
	  call tries to find the template ($arCallFunction) for the current
56
	  object. If it is not defined there, call will search the superclasses
57
	  until either it or the template 'default.phtml' is found.
58
59
	  $arCallFunction must be the name of a class or object template.
60
	    it can be prepended with "{classname}::". classname must be either
61
	    a valid ariadne class (derived from pobject). call()
62
	    will then try to find the template starting at the given classname.
63
		e.g.:
64
		call("pobject::view.html") will show the view.html template of
65
	      pobject, with the data of the current object.
66
67
	  variables available to templates:
68
	  local: arCallFunction, arCallArgs, arCallTemplate, data
69
	  global: AR, ARConfig, ARCurrent, ARBeenHere, ARnls
70
	***********************************************************************/
71 105
	global $AR, $ARConfig, $ARCurrent, $ARBeenHere, $ARnls;
72
73 105
		if ( $arCallFunction instanceof \Closure ) {
74 3
			$arCallFunctionName = 'Closure';
75 9
		} else {
76 105
			$arCallFunctionName = (string) $arCallFunction;
77
		}
78 105
		debug("pobject: ".$this->path.": call($arCallFunctionName, ".debug_serialize($arCallArgs).")","object","all","IN");
79
80
		// default to view.html
81 105
		if (!$arCallFunction) {
82 15
			$arCallFunction="view.html";
83
		}
84
		// clear previous results
85 105
		unset($ARCurrent->arResult);
86
87
		// callstack is needed for getvar()
88 105
		$ARCurrent->arCallStack[]=&$arCallArgs;
89
		// keep track of the context (php or pinp) in which the called template runs. call always sets it php, CheckConfig sets it to pinp if necessary.
90 105
		$this->pushContext( array(
91 105
			"arSuperContext" => array(),
92 105
			"arCurrentObject" => $this,
93 105
			"scope" => "php",
94
			"arCallFunction" => $arCallFunction
95 105
		) );
96
97
		// convert the deprecated urlencoded arguments to an array
98 105
		if (isset($arCallArgs) && is_string($arCallArgs)) {
99 45
			$ARCurrent->arTemp=$arCallArgs;
100 45
			$arCallArgs=array();
101 45
			parse_str($ARCurrent->arTemp, $arCallArgs);
102 45
		}
103
		// import the arguments in the current scope, but don't overwrite existing
104
		// variables.
105 105
		if (isset($arCallArgs) && is_array($arCallArgs)) {
106 45
			extract($arCallArgs,EXTR_SKIP);
107 45
		}
108
		// now find the initial nls selection (CheckConfig is needed for per
109
		// tree selected defaults)
110 105
		if ($ARCurrent->nls) {
111
			$this->reqnls=$ARCurrent->nls;
0 ignored issues
show
Bug introduced by
The property reqnls does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
112 105
		} else if (isset($ARConfig->cache[$this->path]) && $ARConfig->cache[$this->path]->nls->default) {
113 75
			$this->reqnls = $ARConfig->cache[$this->path]->nls->default;
114 75
		} else {
115 54
			$this->reqnls=$AR->nls->default;
116
		}
117 105
		if (isset($this->data->nls->list[$this->reqnls]) || !isset($this->data->nls)) {
118
			// the requested language is available
119 105
			$this->nls=$this->reqnls;
0 ignored issues
show
Bug introduced by
The property nls does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
120 105
			$nls=&$this->nls;
121 105
		} else {
122
			// the requested language is not available, use default of the
123
			// current object instead.
124
			$this->nls=$this->data->nls->default;
125 3
			$nls=&$this->nls;
126
		}
127 105
		if ($nls && isset($this->data->$nls)) {
128
			// now set the data and nlsdata pointers
129 99
			$this->nlsdata=$this->data->$nls;
0 ignored issues
show
Bug introduced by
The property nlsdata does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
130 99
			$nlsdata=&$this->nlsdata;
131 99
			$data=&$this->data;
132 99
		} else {
133
			// this object doesn't support nls data
134 27
			$this->nlsdata=$this->data;
135 27
			$nlsdata=&$this->data;
136 27
			$data=&$this->data;
137 3
		}
138 105
		if (isset($this->data->custom['none'])) {
139 6
			$customdata=$this->data->custom['none'];
140 6
		}
141 105
		if (isset($this->data->custom[$nls])) {
142
			$customnlsdata=$this->data->custom[$nls];
143
		}
144
145 105
		$arCallFunctionOrig = $arCallFunction;
146 105
		if (strpos($arCallFunctionName,"::")!==false) {
147
			// template of a specific class defined via call("class::template");
148 18
			list($arType, $arCallFunction)=explode("::",$arCallFunctionName);
149 18
			$temp = explode(":", $arType );
150 18
			if( count($temp) > 1 ) {
151
				$libname = $temp[0];
152
				$arType = $temp[1];
153
				$arCallFunction = $libname.":".$arCallFunction;
154
			}
155 18
		} else {
156 105
			$arType=$this->type;
0 ignored issues
show
Bug introduced by
The property type does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
157
		}
158
159 105
		if ( $arCallFunction instanceof \Closure ) {
160 3
			$context = $this->getContext(ARCALLINGCONTEXT);
161 3
			if ( $context["scope"] != "pinp" ) {
162
				$arResult = $arCallFunction($this );
163
			} else {
164 3
				if ( $this->CheckSilent('read') ) {
165 3
					$arResult = $arCallFunction($this);
166 3
				}
167
			}
168 3
		} else {
169 105
			if ($arCallFunction[0] === "#") {
170 15
				$ARCurrent->arCallClassTemplate = true;
171
				$arCallFunction = substr($arCallFunction, 1);
172
			} else {
173 105
				$ARCurrent->arCallClassTemplate = false;
174
			}
175
176 105
			if( $arCallFunction == "system.get.phtml" && ( $context = $this->getContext(ARCALLINGCONTEXT) ) && $context["scope"] != "pinp" ) {
177 27
				$arResult = $this;
178 24
			} else {
179 105
				$libtemplate = strpos($arCallFunction,":");
180 105
				$codedir = $this->store->get_config("code");
181
182
				// if it is a subtype object, disk templates do not exists,
183 105
				$subcpos = strpos($arType, '.');
184 105
				if ($subcpos !== false ) {
185
					// subtype, skip looking for templates
186 18
					$arSuper = substr($arType, 0, $subcpos);
187 18
					if(!isset($AR->superClass[$arType])){
188 3
						$AR->superClass[$arType]=$arSuper;
189 3
					}
190 18
					$arType=$arSuper;
191 18
				}
192
193 105
				while ($arType !== "ariadne_object") {
194
195
					// search for the template, stop at the root class ('ariadne_object')
196
					// (this should not happen, as pobject must have a 'default.phtml')
197 105
					$arCallTemplate=$codedir."templates/".$arType."/".$arCallFunction;
198 105
					if ($libtemplate === false && file_exists($arCallTemplate)) {
199
						//debug('found '.$arCallTemplate, 'all');
200
						// template found
201 99
						$arCallFunction = $arCallFunctionOrig;
202 99
						include($arCallTemplate);
203 99
						break;
204 102
					} else if (file_exists($codedir."templates/".$arType."/default.phtml")) {
205
						//debug('found default.phtml', 'all');
206
						// template not found, but we did find a 'default.phtml'
207 6
						include($this->store->get_config("code")."templates/".$arType."/default.phtml");
208 9
						break;
209 18
					} else {
210 102
						if (!($arSuper=$AR->superClass[$arType])) {
211
							// no template found, no default.phtml found, try superclass.
212
213 6
							if (!class_exists($arType, false)) {
214
								// the given class was not yet loaded, so do that now
215
								$this->store->newobject('','',$arType,new object);
216
							}
217 9
							$arSuper=get_parent_class($arType);
218
219 24
							$AR->superClass[$arType]=$arSuper;
220 6
						}
221 102
						$arType=$arSuper;
222 3
					}
223 102
				}
224
			}
225 3
		}
226 105
		array_pop($ARCurrent->arCallStack);
227 105
		$this->popContext();
228 105
		debug("pobject: call: end","all","all","OUT");
229 105
		if (isset($ARCurrent->arResult)) {
230
			// pinp templates can return results via putvar("arResult",$result);
231 15
			$arResult=$ARCurrent->arResult;
232 15
			unset($ARCurrent->arResult);
233 15
		}
234 105
		if (isset($arResult)) {
235
			// only do a return if we really have something to return
236 105
			return $arResult;
237
		}
238 18
	}
239
240 3
	public function ls($path="", $function="list.html", $args="") {
241 3
		$path=$this->store->make_path($this->path, $path);
242 3
		return $this->store->call($function, $args, $this->store->ls($path));
243 3
	}
244
245 42
	public function get($path, $function="view.html", $args="") {
246 42
		$path=$this->store->make_path($this->path, $path);
247 42
		return $this->store->call($function, $args, $this->store->get($path));
248 3
	}
249
250 6
	public function parents($path, $function="list.html", $args="", $top="") {
251
		/* FIXME: $this->store->parents is too slow when a lot of objects are in ariadne (2million+) */
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "$this->store->parents is too slow when a lot of objects are in ariadne (2million+) */"
Loading history...
252
		/* but this fix should be done in the store, not here */
253 3
		if (!$top) {
254 6
			$top = $this->currentsection();
255 3
		} else {
256 6
			$top = $this->store->make_path($this->path, $top);
257
		}
258
259 3
		$path=$this->store->make_path($this->path, $path);
260
261 3
		if ($path != $this->path ) {
262 3
			$target = current($this->get($path,"system.get.phtml"));
263 3
		} else {
264 3
			$target = $this;
265
		}
266
267 3
		$parents = array();
268 3
		if (strpos($target->path, $top) === 0) {
269 3
			$parents[] = $target;
270 3
			while ($target && $target->path != $top) {
271 3
				$target = current($target->get($target->parent, "system.get.phtml"));
272 3
				$parents[] = $target;
273 6
			}
274 3
		}
275 3
		$parents = array_reverse($parents);
276 3
		$result = array();
277 6
		foreach ($parents as $parent) {
278 3
			if ( $parent ) { // might not have read access to this object
279 3
				$result[] = $parent->call($function, $args);
280 3
			}
281 3
		}
282
283 3
		return $result;
284
	}
285
286 3
	public function find($path, $criteria, $function="list.html", $args="", $limit=100, $offset=0) {
287 3
		$path = $this->store->make_path($this->path, $path);
288 3
		$objects = $this->store->find($path, $criteria, $limit, $offset);
289 3
		if (!$this->store->error) {
290 3
			$result = $this->store->call($function, $args, $objects);
291 3 View Code Duplication
		} else {
292
			$this->error = ar::error( ''.$this->store->error, 1110, $this->store->error );
0 ignored issues
show
Bug introduced by
The property error does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
293
			$result = false;
294 3
		}
295 3
		return $result;
296
	}
297
298
	public function count_find($path='', $query='') {
299
		$path=$this->store->make_path($this->path, $path);
300
		if (method_exists($this->store, 'count_find')) {
301
			$result = $this->store->count_find($path, $query, 0);
302
		} else {
303
			$result = $this->store->count($this->store->find($path, $query, 0));
304
		}
305
		return $result;
306
	}
307
308
	public function count_ls($path) {
309
		return $this->store->count($this->store->ls($path));
310
	}
311
312 18
	private function saveMergeWorkflowResult($properties, $wf_result) {
313
		foreach ($wf_result as $wf_prop_name => $wf_prop) {
314
			foreach ($wf_prop as $wf_prop_index => $wf_prop_record) {
315
				if (!isset($wf_prop_record)) {
316
					unset($properties[$wf_prop_name][$wf_prop_index]);
317
				} else {
318
					$record = array();
319 View Code Duplication
					foreach ($wf_prop_record as $wf_prop_field => $wf_prop_value) {
320
						switch (gettype($wf_prop_value)) {
321 3
							case "integer":
322
							case "boolean":
323
							case "double":
324
								$value = $wf_prop_value;
325
								break;
326
							default:
327
								$value = $wf_prop_value;
328
								// backwards compatibility, store will do the escaping from now on
329
								// will be removed in the future
330
								if (substr($wf_prop_value, 0, 1) === "'" && substr($wf_prop_value, -1) === "'"
331
										&& "'".AddSlashes(StripSlashes(substr($wf_prop_value, 1, -1)))."'" == $wf_prop_value) {
332
									$value = stripSlashes(substr($wf_prop_value,1,-1));
333
									// todo add deprecated warning
334
								}
335
336 3
						}
337
						$record[$wf_prop_field] = $value;
338
					}
339
					$properties[$wf_prop_name][] = $record;
340
				}
341
			}
342
		}
343
344 18
		return $properties;
345
	}
346
347
	/*
348
		saves custom data
349
		returns properties for custom data
350
	*/
351 37
	private function saveCustomData($configcache, $properties) {
352 37
		$custom = $this->getdata("custom", "none");
353 36
		@parse_str($custom);
354 36
		if (isset($custom) && is_array($custom)) {
355
			foreach($custom as $nls=>$entries){
356
				if (isset($entries) && is_array($entries)) {
357
					foreach ( $entries as $customkey => $customval ){
358
						$this->data->custom[$nls][$customkey] = $customval;
359
					}
360
				}
361
			}
362
		}
363
		// the above works because either $custom comes from the form entry, and parse_str returns an
364
		// array with the name $custom, or $custom comes from the object and is an array and as such
365
		// parse_str fails miserably thus keeping the array $custom intact.
366
367 36
		if (isset($this->data->custom) && is_array($this->data->custom)) {
368
			foreach($this->data->custom as $nls => $cdata) {
369
				foreach($cdata as $name => $value){
370
					// one index, this order (name, value, nls) ?
371
					if ($configcache->custom[$name]['containsHTML']) {
372
						$this->_load('mod_url.php');
373
						$value = URL::RAWtoAR($value, $nls);
374
						$this->data->custom[$nls][$name] = $value;
375
					}
376
					if ($configcache->custom[$name]['property']) {
377
						if (isset($value) && is_array($value)) {
378
							foreach($value as $valkey => $valvalue ) {
379
								$properties["custom"][] = [
380
									"name"  => $name,
381
									"value" => $valvalue,
382
									"nls"   => $nls,
383
								];
384
							}
385
						} else {
386
							$properties["custom"][] = [
387
								"name"  => $name,
388
								"value" => $value,
389
								"nls"   => $nls,
390
							];
391
392
						}
393
					}
394
				}
395
			}
396
		}
397 36
		return $properties;
398
	}
399
400 38
	public function save($properties="", $vtype="") {
401
	/***********************************************************************
402
	  save the current object.
403
	  if this is a new object ($this->arIsNewObject) the path is checked and
404
	  the object is saved under the new path.
405
	***********************************************************************/
406 36
	global $AR, $ARnls, $ARCurrent;
407 36
		debug("pobject: save([properties], $vtype)","object");
408 36
		debug("pobject: save: path=".$this->path,"object");
409 36
		$configcache=$this->loadConfig();
410 37
		$needsUnlock = false;
411 36
		$arIsNewObject = false;
412 36
		$result = false;
413 36
		$this->error = '';
414 36
		if ($this->arIsNewObject) { // save a new object
0 ignored issues
show
Bug introduced by
The property arIsNewObject does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
415 18
			debug("pobject: save: new object","all");
416 18
			$this->path = $this->make_path();
417 18
			$arNewParent=$this->make_path("..");
418 18
			$arNewFilename=basename($this->path);
419 18
			$arIsNewObject = true;
420 18
			if (preg_match("|^[a-z0-9_\{\}\.\:-]+$|i",$arNewFilename)) { // no "/" allowed, these will void the 'add' grant check.
421 18
				if (!$this->exists($this->path)) { //arNewFilename)) {
422 18
					if ($this->exists($arNewParent)) {
423 18
						if (!$config = $this->data->config) {
424
							$config=new object();
425
						}
426 18
					} else {
427
						$this->error = ar::error( sprintf($ARnls["err:noparent"],$arNewParent), 1102);
428
					}
429 18
				} else {
430
					$this->error = ar::error( sprintf($ARnls["err:alreadyexists"],$arNewFilename), 1103);
431
				}
432 18
			} else {
433
				$this->error = ar::error( sprintf($ARnls["err:fileillegalchars"],$arNewFilename), 1104);
434
			}
435 18
		} else { // existing object
436 36
			debug("pobject: save: existing object","all");
437 36
			if ($this->exists($this->path)) { // prevent 'funny stuff'
438 36
				if (!$this->lock()) {
439
					$this->error = ar::error( $ARnls["err:objectalreadylocked"], 1105);
440
				} else {
441 36
					$needsUnlock = true;
442 36
					$config = $this->data->config;
443
				}
444 36
			} else {
445
				$this->error = ar::error($ARnls["err:corruptpathnosave"], 1106);
446
			}
447
		}
448
		// pre checks done
449
		// return now on error
450 36
		if ($this->error) {
451
			return $result;;
452
		}
453
454
455 36
		if ($ARCurrent->arCallStack) {
456 36
			$arCallArgs = end($ARCurrent->arCallStack);
457 36
		} else {
458 15
			$arCallArgs = array();
459
		}
460
461 36
		$context = $this->getContext();
462
463 36
		$wf_object = $this->store->newobject($this->path, $this->parent, $this->type, $this->data, $this->id, $this->lastchanged, $this->vtype, 0, $this->priority);
0 ignored issues
show
Bug introduced by
The property parent does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The property id does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The property lastchanged does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The property vtype does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The property priority does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
464 36
		if ( $arIsNewObject) {
465 18
			$wf_object->arIsNewObject=$arIsNewObject;
466 18
		}
467
468
		/* save custom data */
469 36
		$properties = $this->saveCustomData($configcache, $properties);
470
471
		// this makes sure the event handlers are run on $wf_object, so that $this->data changes don't change the data of the object to be saved
472 36
		$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $wf_object));
473
474 36
		$eventData = new object();
475 36
		$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
Bug introduced by
The property arCallArgs does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
476 36
		$eventData->arCallFunction	= $context['arCallFunction'];
0 ignored issues
show
Bug introduced by
The property arCallFunction does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
477 36
		$eventData->arIsNewObject = $arIsNewObject;
0 ignored issues
show
Bug introduced by
The property arIsNewObject does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
478 36
		$eventData->arProperties = $properties;
0 ignored issues
show
Bug introduced by
The property arProperties does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
479 36
		$eventData = ar_events::fire( 'onbeforesave', $eventData );
480
481
		// pop the wf_object, not needed later, the extra scope might hinder other code
482 36
		$this->popContext();
483
484 36
		if ( !$eventData ) {
485
			return false; // prevent saving of the object.
486
		}
487
488
		// arguments can be altered by event handlers, only usefull when a workflow template is also defined
489 36
		$arCallArgs = $eventData->arCallArgs;
490
491
		// the properties from the eventData are the new property list
492
		// no need to merge them with $properties, just manipulate the properties array directly
493
		// in the event data. unlike the user.workflow.pre.html template
494 36
		if (isset( $eventData->arProperties ) && is_array( $eventData->arProperties ) ) {
495 37
			$properties = $eventData->arProperties;
496 36
		} else {
497 33
			$properties = array();
498
		}
499
500
		// pass the current properties list to the workflow template
501
		// for backwards compatibility and workflow templates that just
502
		// returned only their own properties, merge them afterwards
503
		// don't do this for the eventData arProperties!
504 36
		$arCallArgs['properties'] = $properties;
505 36
		$wf_result = $wf_object->call("user.workflow.pre.html", $arCallArgs);
506
		/* merge workflow properties */
507 36
		if (isset($wf_result) && is_array($wf_result) ){
508
			$properties = $this->saveMergeWorkflowResult($properties,$wf_result);
509
		}
510
511 36
		$this->error = $wf_object->error;
512 36
		$this->priority = $wf_object->priority;
513 36
		$this->data = $wf_object->data;
514 36
		$this->data->config = $config;
0 ignored issues
show
Bug introduced by
The variable $config does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
515 36
		$this->data->mtime=time();
516 36
		if($arIsNewObject) {
517 18
			$this->data->ctime=$this->data->mtime;
518 18
		}
519
520 36
		$this->data->muser=$AR->user->data->login;
521 36
		if( !$this->data->config->owner ) {
522 18
			if( !$this->data->config->owner_name) {
523 18
				$this->data->config->owner_name=$AR->user->data->name;
524 18
			}
525 18
			$this->data->config->owner=$AR->user->data->login;
526 18
			$properties["owner"][0]["value"]=$this->data->config->owner;
527 18
		}
528 36
		$properties["time"][0]["ctime"]=$this->data->ctime;
529 36
		$properties["time"][0]["mtime"]=$this->data->mtime;
530 36
		$properties["time"][0]["muser"]=$this->data->muser;
531
532
533 36
		if (!$this->error) {
534 36
			if ($this->path=$this->store->save($this->path, $this->type, $this->data, $properties, $vtype, $this->priority)) {
535 36
				unset($this->arIsNewObject);
536 36
				$this->id=$this->exists($this->path);
537 36
				$result=$this->path;
538
539 36
				$config=$this->data->config; // need to set it again, to copy owner config data
540
541 36
				$wf_object = $this->store->newobject($this->path, $this->parent, $this->type, $this->data, $this->id, $this->lastchanged, $this->vtype, 0, $this->priority);
542 36
				$arCallArgs = $eventData->arCallArgs; // returned from onbeforesave event
543 36
				$arCallArgs['properties'] = $properties;
544
545 36
				if ($arIsNewObject) {
546 18
					$wf_object->arIsNewObject = $arIsNewObject;
547 18
				}
548 36
				$wf_result = $wf_object->call("user.workflow.post.html", $arCallArgs);
549 36
				$this->error = $wf_object->error;
550 36
				$this->priority = $wf_object->priority;
551 36
				$this->data = $wf_object->data;
552 36
				$this->data->config = $config;
553
				/* merge workflow properties */
554
555 36
				if (isset($wf_result) && is_array($wf_result) ){
556
					$properties = $this->saveMergeWorkflowResult($properties,$wf_result);
557
558
					if (!$this->store->save($this->path, $this->type, $this->data, $properties, $this->vtype, $this->priority)) {
559
						$this->error = ar::error( ''.$this->store->error, 1108, $this->store->error);
560
						$result = false;
561
					}
562 1
				}
563
				// all save actions have been done, fire onsave.
564 36
				$this->data->config = $config;
565
566
				//$this->ClearCache($this->path, true, false);
567 36
				$eventData->arProperties = $properties;
568 36
				$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $this));
569 36
				ar_events::fire( 'onsave', $eventData ); // nothing to prevent here, so ignore return value
570 36
				$this->popContext();
571 36 View Code Duplication
			} else {
572
				$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
573
				$result = false;
574
			}
575 36
		}
576 36
		if( $needsUnlock == true ){
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
577 36
			$this->unlock();
578 36
		}
579
580 36
		if ($this->data->nls->list[$this->nls]) {
581 36
			$mynlsdata=$this->data->{$this->nls};
582 36
		} else if ($this->data->nls->default) {
583
			$mynlsdata=$this->data->{$this->data->nls->default};
584
		} else {
585
			$mynlsdata=$this->data;
586
		}
587
588 36
		unset($this->nlsdata);
589 36
		$this->nlsdata=$mynlsdata;
590
591 36
		debug("pobject: save: end","all");
592 36
		return $result;
593
	}
594
595
	public function link($to) {
596
		return $this->store->link($this->path, $this->make_path($to));
597
	}
598
599
	public function delete() {
600
	global $ARCurrent;
601
		$result	= false;
602
		$this->error = '';
603
		if ($ARCurrent->arCallStack) {
604
			$arCallArgs = end($ARCurrent->arCallStack);
605
		} else {
606
			$arCallArgs = array();
607
		}
608
		$context = $this->getContext();
609
610
		$eventData = new object();
611
		$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
Bug introduced by
The property arCallArgs does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
612
		$eventData->arCallFunction = $context['arCallFunction'];
0 ignored issues
show
Bug introduced by
The property arCallFunction does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
613
		$eventData = ar_events::fire( 'onbeforedelete', $eventData );
614
		if ( !$eventData ) {
615
			return false;
616
		}
617
		$this->call("user.workflow.delete.pre.html", $eventData->arCallArgs);
618
		if (!$this->error) {
619
			if ($this->store->delete($this->path)) {
620
				$result = true;
621
				$this->call("user.workflow.delete.post.html", $eventData->arCallArgs);
622
				ar_events::fire( 'ondelete', $eventData );
623
			} else {
624
				$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
625
			}
626
		}
627
		return $result;
628
	}
629
630 42
	public function exists($path) {
631 42
		$path=$this->make_path($path);
632 42
		return $this->store->exists($path);
633
	}
634
635 54
	public function make_path($path="") {
636
		switch($path){
637 54
			case '':
638 54
			case '.':
639 54
			case $this->path:
640 54
				return $this->path;
641
				break;
642 45
			case '..':
643 18
				return $this->parent;
644
				break;
645 45
			default:
646 45
				return self::sanitizePath($this->store->make_path($this->path, $path));
647 45
		}
648
	}
649
650
	public function make_ariadne_url($path="") {
651
		global $AR;
652
		$path = $this->make_path($path);
653
		return self::sanitizeUrl($AR->host . $AR->root . $this->store->get_config('rootoptions') . $path);
654
	}
655
656
657 39
	public function make_url($path="", $nls=false, $session=true, $https=null, $keephost=null) {
658 39
		global $ARConfig, $AR, $ARCurrent;
659
660 39
		$rootoptions=$this->store->get_config('rootoptions');
661 39
		if (!$session || ($nls !== false)) {
662 39
			$rootoptions = "";
663 39
			if ($session && isset($ARCurrent->session->id) && !$AR->hideSessionIDfromURL) {
664
				$rootoptions .= "/-".$ARCurrent->session->id."-";
665
			}
666 39
			if ($nls) {
667 36
				$rootoptions_nonls = $rootoptions;
668 36
				$rootoptions .= '/'.$nls;
669 36
			}
670 39
		}
671 39
		$path=$this->make_path($path);
672
673
		// now run CheckConfig and get the parentsite of the path found
674 39
		if (!$temp_config=$ARConfig->cache[$path]) {
675 3
			$temp_path = $path;
676 3
			while (!($temp_site = $this->currentsite($temp_path)) && $temp_path!='/') {
677
				$temp_path = $this->make_path($temp_path.'../');
678
			}
679 3
			$temp_config=$ARConfig->cache[$temp_site];
680 3
		}
681
682 39
		if ( !isset($keephost) && (
683 39
			(!$nls && $this->compare_hosts($AR->host, $temp_config->root["value"])) ||
684 39
			($nls && ($this->compare_hosts($AR->host, $temp_config->root['list']['nls'][$nls])))
685 39
		)) {
686
			$keephost = false;
687
		}
688
689 39
		if (!$keephost) {
690 39
			if ($nls) {
691 36
				$url=$temp_config->root["list"]["nls"][$nls];
692 36
				if (isset($url) && is_array($url)) {
693
					$url = current( $url );
694
				}
695 36
				if ($url) {
696 View Code Duplication
					if (substr($url, -1)=='/') {
697
						$url=substr($url, 0, -1);
698
					}
699
					$url .= $rootoptions_nonls;
0 ignored issues
show
Bug introduced by
The variable $rootoptions_nonls does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
700
				}
701 36
			}
702 39
			if (!$url) {
0 ignored issues
show
Bug introduced by
The variable $url does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
703 39
				$checkNLS = $nls;
704 39
				if (!$checkNLS) {
705 21
					$checkNLS = $this->nls;
706 21
				}
707 39
				$urlList = $temp_config->root['list']['nls'][$checkNLS];
708 39
				if (isset($urlList) && is_array($urlList)) {
709
					$url = reset($urlList) . $rootoptions;
710
				} else {
711 39
					$url = $temp_config->root["value"].$rootoptions;
712
				}
713 39
			}
714 39
			$url.=substr($path, strlen($temp_config->root["path"])-1);
715
716 39
			if (is_bool($https)) {
717
				if ($https) {
718
					if ($AR->https) {
719
						$url = preg_replace('/^http:/', 'https:', $url);
720
					}
721
				} else {
722
					$url = preg_replace('/^https:/', 'http:', $url);
723
				}
724
			}
725 39
		} else {
726 36
			$checkNLS = $nls;
727 36
			if (!$checkNLS) {
728
				$checkNLS = $this->nls;
729
			}
730 36
			$urlCheck = $temp_config->root['list']['nls'][$checkNLS];
731 36
			if (!is_array($urlCheck)) {
732 36
				$urlCheck = $temp_config->root["value"];
733 36
			}
734 36
			$requestedHost = ldGetRequestedHost();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $requestedHost is correct as ldGetRequestedHost() seems to always returns null.
Loading history...
735 36
			if ($this->compare_hosts($requestedHost, $urlCheck)) {
736
				$url = $requestedHost . $rootoptions;
737
				$url .= substr($path, strlen($temp_config->root["path"])-1);
738
			} else {
739
				//$url=$AR->host.$AR->root.$rootoptions.$path;
740 36
				$url = $protocol . $requestedHost . $AR->root . $rootoptions . $path;
0 ignored issues
show
Bug introduced by
The variable $protocol does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
741
			}
742
		}
743 39
		return self::sanitizeUrl($url);
744
	}
745
746 39
	protected function compare_hosts($url1, $url2) {
747
		// Check if hosts are equal, so that http://www.muze.nl and //www.muze.nl also match.
748
		// using preg_replace instead of parse_url() because the latter doesn't parse '//www.muze.nl' correctly.
749 39
		if (isset($url2) ) {
750 39
			if ( !is_array($url2) ){
751 39
				$url2 = array($url2);
752 39
			}
753 39
		} else {
754 36
			$url2 = array();
755
		}
756
757 39
		$prepurl1 = preg_replace('|^[a-z:]*//|i', '', $url1);
758
759 39
		foreach($url2 as $url) {
760
			if (
761 39
					$url == $url1 ||
762 39
					$prepurl1 == preg_replace('|^[a-z:]*//|i', '', $url2)
763 39
				) {
764
				return true;
765
			}
766 39
		}
767 39
		return false;
768
	}
769
770 36
	public function make_local_url($path="", $nls=false, $session=true, $https=null) {
771 36
		global $ARCurrent, $ARConfig;
772 36
		$site = false;
773 36
		$path = $this->make_path($path);
774 36
		$checkpath = $path;
775
776 36
		$redirects = $ARCurrent->shortcut_redirect;
777 36
		if (isset($redirects) && is_array($redirects)) {
778
			$newpath = $checkpath;
779
			$c_redirects = count($redirects);
780
			$c_redirects_done = 0;
781 View Code Duplication
			while (count($redirects) && ($redir = array_pop($redirects)) && $redir['keepurl'] && substr($newpath, 0, strlen($redir['dest'])) == $redir['dest']) {
782
				$c_redirects_done++;
783
				$newpath = $redir['src'].substr($newpath, strlen($redir['dest']));
784
			}
785
786
			if ($c_redirects_done == $c_redirects) {
787
				$checkpath = $redir['src'];
0 ignored issues
show
Bug introduced by
The variable $redir does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
788
			}
789
		}
790
791
		do {
792 36
			if (!$config=$ARConfig->cache[$checkpath]) {
793
				$config=($ARConfig->cache[$checkpath]) ? $ARConfig->cache[$checkpath] : $this->loadConfig($checkpath);
794
			}
795 36
			if ($config) {
796 36
				$checkNLS = $nls;
797 36
				if (!$checkNLS) {
798
					$checkNLS = $this->nls;
799
				}
800 36
				$urlCheck = $config->root['list']['nls'][$checkNLS];
801 36
				if (!is_array($urlCheck)) {
802 36
					$urlCheck = $config->root["value"];
803 36
				}
804 36
				$requestedHost = ldGetRequestedHost();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $requestedHost is correct as ldGetRequestedHost() seems to always returns null.
Loading history...
805
806 36
				if ($this->compare_hosts($requestedHost, $urlCheck)) {
807
					$site=$config->site;
808
				}
809 36
			}
810 36
			$prevpath=$checkpath;
811 36
			$checkpath=$this->make_path($checkpath."../");
812 36
		} while ($prevpath!=$checkpath && !$site);
813 36
		if (!$site) {
814 36
			$site='/';
815 36
		}
816 36
		$site_url=$this->make_url($site, $nls, $session, $https, true);
817 36
		if ($newpath) { // $newpath is the destination of a shortcut redirection, with keepurl on
818
			$rest=substr($newpath, strlen($site));
0 ignored issues
show
Bug introduced by
The variable $newpath does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
819
		} else {
820 36
			$rest=substr($path, strlen($site));
821
		}
822 36
		return self::sanitizeUrl($site_url.$rest);
823
	}
824 45
	public function sanitizeUrl($url) {
825
		// remove unexpected chars from the url;
826 45
		return preg_replace("/[^\/{}:.A-Za-z0-9_-]/", "", $url);
827
	}
828 45
	public function sanitizePath($path) {
829
		// remove unexpected chars from the path; same as url for now;
830 45
		return self::sanitizeUrl($path);
831
	}
832
833
	public function AR_implements($implements) {
834
		$type = current(explode(".",$this->type));
835
		return $this->store->AR_implements($type, $implements);
836
	}
837
838 View Code Duplication
	public function getlocks() {
839
		global $AR;
840
		if ($this->store->mod_lock) {
841
			$result=$this->store->mod_lock->getlocks($AR->user->data->login);
842
		} else {
843
			$result="";
844
		}
845
		return $result;
846
	}
847
848 36 View Code Duplication
	public function lock($mode="O", $time=0) {
849 36
	global $AR;
850 36
		if ($this->store->mod_lock) {
851 36
			$result=$this->store->mod_lock->lock($AR->user->data->login,$this->path,$mode,$time);
852 36
		} else {
853
			$result=true; // no lock module, so lock is 'set'
854
		}
855 36
		return $result;
856
	}
857
858 36 View Code Duplication
	public function unlock() {
859 36
	global $AR;
860 36
		if ($this->store->mod_lock) {
861 36
			$result=$this->store->mod_lock->unlock($AR->user->data->login,$this->path);
862 36
		} else {
863
			$result=true;
864
		}
865 36
		return $result;
866
	}
867
868
	public function touch($id=0, $timestamp=-1) {
869
		if (!$id) {
870
			$id = $this->id;
871
		}
872
		$result = $this->store->touch($id, $timestamp);
873 View Code Duplication
		if ($this->store->error) {
874
			$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
875
		}
876
		return $result;
877
	}
878
879
	public function mogrify($id=0, $type, $vtype=null) {
0 ignored issues
show
Coding Style introduced by
Parameters which have default values should be placed at the end.

If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway:

// $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
Loading history...
880
		if (!$id) {
881
			$id = $this->id;
882
		}
883
		if (!$vtype) {
884
			$vtype = $type;
885
		}
886
		if (strpos($vtype, '.')!==false) {
887
			$vtype = substr($vtype, 0, strpos($vtype, '.'));
888
		}
889
		$result = $this->store->mogrify($id, $type, $vtype);
890 View Code Duplication
		if ($this->store->error) {
891
			$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
892
		}
893
		return $result;
894
	}
895
896
	public function can_mogrify() {
897
		if ($this->path == "/system/users/admin/") {
898
			return false;
899
		}
900
		return true;
901
	}
902
903
	public function load_properties($scope='') {
904
		return $this->store->load_properties($this->id,'',$scope);
905
	}
906
907
	public function _load_properties($scope='') {
908
		return $this->store->load_properties($this->id,'',$scope);
909
	}
910
911
	public function load_property($property, $scope='') {
912
		return $this->store->load_property($this->id,$property,$scope);
913
	}
914
915
	public function _load_property($property, $scope='') {
916
		return $this->store->load_property($this->id,$property,$scope);
917
	}
918
919 3
	public function GetValidGrants($path="") {
920
	/********************************************************************
921
922
	  This function finds all grants in effect on this object for the
923
	  logged in user! $AR->user must already be set.
924
925
	  Grants are checked in the following way:
926
	  1) First all parents of this object are checked for grants for this
927
	     specific user. The 'nearest' grants are valid, and the path of
928
	     parent that set these grants will be the upper limit for the
929
	     checking of group grants.
930
	  2) Now all groups of which the user is a member are checked for
931
	     grants. Likewise, all parents are checked for group grants, upto
932
	     but not including the upperlimit as set in 1. All group grants
933
	     found are merged into one grants list.
934
	  3) If there are gropup grants, this means that there are group
935
	     grants set in a parent nearer to this object than the user grants
936
	     and therefore the groupgrants must be merged with the
937
	     usergrants.
938
939
	  this results in:
940
	  1	/		user: read edit		group: none
941
	  2	/dir/					group: read
942
	  3	/dir2/		user: none		group: read
943
	  4	/dir/dir3/				group2: edit
944
	  case 1: the user takes precedence over the group, grants are 'read edit'
945
	  case 2: groupgrants are merged with usergrants, as its grants are set
946
	          in a 'nearer' parent (itself). grants are 'read edit'.
947
	  case 3: user takes precedence again. grants are 'none'.
948
	  case 4: All group grants are merged with the usergrants.
949
	          Therefore the grants are 'none read edit'.
950
	********************************************************************/
951
952 3
	global $AR;
953
954 3
		if ($AR->user) { 	// login and retrieval of user object
955 3
			if (!$path) {
956 3
				$path=$this->path;
957 3
			}
958 3
			if (!$AR->user->grants[$path]) {
959 3
				$grants=array();
960 3
				$userpath=$AR->user->FindGrants($path, $grants);
961
				// if not already done, find all groups of which the user is a member
962 3
				if (!is_array($AR->user->externalgroupmemberships) || count($AR->user->externalgroupmemberships)==0) {
963 3
					$criteria["members"]["login"]["="]=$AR->user->data->login;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$criteria was never initialized. Although not strictly required by PHP, it is generally a good practice to add $criteria = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
964 3
				} else {
965
					// Use the group memberships of external databases (e.g. LDAP)
966
					$criteria="members.login='".AddSlashes($AR->user->data->login)."'";
967
					foreach (array_keys($AR->user->externalgroupmemberships) as $group) {
968
						$criteria.=" or login.value='".AddSlashes($group)."'";
969
					}
970
				}
971 3
				if (!$AR->user->groups) {
972 3
					$groups=$this->find("/system/groups/",$criteria, "system.get.phtml");
973 3
					if (isset($groups) && is_array($groups)) {
974 3
						foreach($groups as $group ){
975 3
							if (is_object($group)) {
976 3
								$AR->user->groups[$group->path] = $group;
977 3
							}
978 3
						}
979 3
					}
980 3
					if (isset($AR->user->data->config->groups) && is_array($AR->user->data->config->groups)) {
981 3
						foreach ($AR->user->data->config->groups as $groupPath => $groupId) {
982 3
							if (!$AR->user->groups[$groupPath]) {
983
								$AR->user->groups[$groupPath] = current($this->get($groupPath, "system.get.phtml"));
984
							}
985 3
						}
986 3
					}
987 3
					if (!$AR->user->groups["/system/groups/public/"]) {
988
						if ($public=current($this->get("/system/groups/public/", "system.get.phtml"))) {
989
							$AR->user->groups[$public->path] = $public;
990
						}
991
					}
992 3
				}
993 3
				if ($AR->user->groups) {
994
					/* check for owner grants (set by system.get.config.phtml) */
995 3
					if (isset($AR->user->ownergrants) && is_array($AR->user->ownergrants)) {
996
						if (!$AR->user->groups["owner"]) {
997
							$AR->user->groups["owner"] = @current($this->get("/system/groups/owner/", "system.get.phtml"));
998
						}
999
						$AR->user->groups["owner"]->data->config->usergrants = $AR->user->ownergrants;
1000
					}
1001 3 View Code Duplication
					foreach($AR->user->groups as $group){
1002 3
						$groupgrants=array();
1003 3
						if (is_object($group)) {
1004 3
							$group->FindGrants($path, $groupgrants, $userpath);
1005 3
							if (isset($grants) && is_array($grants)) {
1006 3
								foreach($groupgrants as $gkey => $gval ){
1007
									if (isset($grants[$gkey]) && is_array($grants[$gkey]) && is_array($gval)) {
1008
										$grants[$gkey]=array_merge($gval, $grants[$gkey]);
1009
									} else
1010
									if ($gval && !is_array($gval)) {
1011
										$grants[$gkey] = $gval;
1012
									} else
1013
									if ($gval && !$grants[$gkey]) {
1014
										$grants[$gkey] = $gval;
1015
									}
1016 3
								}
1017 3
							} else {
1018
								$grants = $groupgrants;
1019
							}
1020 3
						}
1021 3
					}
1022 3
				}
1023 3
				if(isset($AR->sgGrants) && is_array($AR->sgGrants) ) {
1024
					ksort($AR->sgGrants);
1025
					$ppath = $this->make_path($path);
1026 View Code Duplication
					foreach( $AR->sgGrants as $sgpath => $sggrants) {
1027
						$sgpath = $this->make_path($sgpath);
1028
						if( substr($ppath, 0, strlen($sgpath)) == $sgpath ) { // sgpath is parent of ppath or equal to ppath
1029
							if (isset($grants) && is_array($grants)) {
1030
								foreach($sggrants as $gkey => $gval ){
1031
									if (isset($grants[$gkey]) && is_array($grants[$gkey]) && is_array($gval)) {
1032
										$grants[$gkey]=array_merge($gval, $grants[$gkey]);
1033
									} else
1034
									if ($gval && !is_array($gval)) {
1035
										$grants[$gkey] = $gval;
1036
									} else
1037
									if ($gval && !$grants[$gkey]) {
1038
										$grants[$gkey] = $gval;
1039
									}
1040
								}
1041
							} else {
1042
								$grants = $sggrants;
1043
							}
1044
						}
1045
					}
1046
				}
1047 3
				$AR->user->grants[$path]=$grants;
1048 3
			}
1049 3
			$grants=$AR->user->grants[$path];
1050
1051 3
		}
1052 3
		debug("pobject: GetValidGrants(user:".$AR->user->data->login."): end ( ".debug_serialize($grants)." )","all");
0 ignored issues
show
Bug introduced by
The variable $grants does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1053 3
		return $grants;
1054
	}
1055
1056
1057 105
	public function pushContext($context) {
1058 105
	global $AR;
1059 105
		if(!empty($AR->context)) {
1060 54
			$context = array_merge(end($AR->context), $context);
1061 54
		}
1062 105
		array_push($AR->context, $context);
1063 105
	}
1064
1065
	public function setContext($context, $level=0) {
1066
	global $AR;
1067
		$AR->context[count($AR->context)-(1+$level)]=$context;
1068
	}
1069
1070 105
	public function popContext() {
1071 105
	global $AR;
1072 105
		return array_pop($AR->context);
1073
	}
1074
1075 105
	public static function getContext($level=0) {
1076 105
	global $AR;
1077 105
		return $AR->context[count($AR->context)-(1+$level)];
1078
	}
1079
1080 54
	public function CheckAdmin($user) {
1081 54
	if ($user->data->login == "admin") {
1082 51
			return true;
1083
		}
1084 3
		if ($user->data->groups['/system/groups/admin/']) {
1085
			return true;
1086
		}
1087 3
		return false;
1088
	}
1089
1090 45
	public function CheckLogin($grant, $modifier=ARTHISTYPE) {
1091 45
	global $AR,$ARnls,$ARConfig,$ARCurrent,$ARConfigChecked;
1092 45
		if (!$this->store->is_supported("grants")) {
1093
			debug("pobject: store doesn't support grants");
1094
			return true;
1095
		}
1096 45
		if ($modifier==ARTHISTYPE) {
1097 45
			$modifier=$this->type;
1098 45
		}
1099
1100
		/* load config cache */
1101 45
		if (!isset($ARConfig->cache[$this->path])) {
1102
			// since this is usually run before CheckConfig, make sure
1103
			// it doesn't set cache time
1104
			$realConfigChecked = $ARConfigChecked;
1105
			$ARConfigChecked = true;
1106
			$this->loadConfig();
1107
			$ARConfigChecked = $realConfigChecked;
1108
		}
1109
1110 45
		$isadmin = $this->CheckAdmin($AR->user);
1111
1112 45
		if (!$isadmin && !$AR->user->grants[$this->path]) {
1113
			$grants = $this->GetValidGrants();
1114
		} else {
1115 45
			$grants = $AR->user->grants[$this->path];
1116
		}
1117
1118 45
		if ($AR->user->data->login!="public") {
1119
			// Don't remove this or MSIE users won't get uptodate pages...
1120 45
			ldSetClientCache(false);
1121 45
		}
1122
1123 45
		if ( 	( !$grants[$grant]
1124 45
					|| ( $modifier && is_array($grants[$grant]) && !$grants[$grant][$modifier] )
1125 45
				) && !$isadmin ) {
1126
			// do login
1127
			$arLoginMessage = $ARnls["accessdenied"];
1128
			ldAccessDenied($this->path, $arLoginMessage);
1129
			$result=false;
1130
		} else {
1131 45
			$result=($grants || $isadmin);
1132
		}
1133
1134 45
		$ARCurrent->arLoginSilent=1;
1135 45
		return $result;
1136
	}
1137
1138
1139 3
	public function CheckPublic($grant, $modifier=ARTHISTYPE) {
1140 3
	global $AR;
1141
1142 3
		$result=false;
1143 3
		if (!$AR->public) {
1144 3
			$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $this));
1145 3
				$AR->public=current($this->get("/system/users/public/", "system.get.phtml"));
1146 3
			$this->popContext();
1147 3
		}
1148 3
		if ($AR->public) {
1149 3
			$AR->private=$AR->user;
1150 3
			$AR->user=$AR->public;
1151 3
			$result=$this->CheckSilent($grant, $modifier);
1152 3
			$AR->user=$AR->private;
1153 3
		}
1154 3
		return $result;
1155
	}
1156
1157 33
	public function CheckSilent($grant, $modifier=ARTHISTYPE, $path=".") {
1158 33
	global $AR, $ARConfig;
1159 33
		$path = $this->make_path($path);
1160 33
		if ($modifier==ARTHISTYPE) {
1161 33
			$modifier=$this->type;
1162 33
		}
1163
1164
		/* load config cache */
1165 33
		if (!$ARConfig->cache[$path]) {
1166 6
			$this->loadConfig($path);
1167 6
		}
1168 33
		if ($this->CheckAdmin($AR->user)) {
1169 30
			$result=1;
1170 33
		} else if ($grants=$AR->user->grants[$path]) {
1171
			$result=$grants[$grant];
1172
		} else {
1173 3
			$grants=$this->GetValidGrants();
1174 3
			$result=$grants[$grant];
1175
		}
1176 33
		if ($modifier && is_array($result)) {
1177
			$result=$result[$modifier];
1178
		}
1179 33
		return $result;
1180
	}
1181
1182
	public function CheckNewFile($newfilename) {
1183
	global $ARnls;
1184
	/**********************************************************************
1185
1186
	  This function performs all the necessary checks on a path to see
1187
	whether it's a valid path for a new object. This consists of:
1188
	1) checking for invalid characters, valid chars are "a-zA-Z0-9./_-"
1189
	2) checking whether the path starts and ends with a "/".
1190
	3) checking whether the path doesn't exist already.
1191
	4) checking whether the parent exists.
1192
1193
	if all this checks out, it returns 1. If not, $this->error is set to
1194
	the correct error message.
1195
1196
	**********************************************************************/
1197
1198
		$this->error="";
1199
		if (preg_match("|^/[a-z0-9\./_-]*/$|i",$newfilename)) {
1200
			if (!$this->store->exists($newfilename)) {
1201
				$parent=$this->store->make_path($newfilename, "..");
1202
				if ($this->store->exists($parent)) {
1203
					$result=1;
1204
				} else {
1205
					$this->error = ar::error( sprintf($ARnls["err:filenameinvalidnoparent"],$newfilename,$parent), 1102);
1206
				}
1207
			} else {
1208
				$this->error = ar::error( sprintf($ARnls["err:chooseotherfilename"],$newfilename), 1103);
1209
			}
1210
		} else {
1211
			$this->error = ar::error( sprintf($ARnls["err:fileillegalchars"],$newfilename)." ".$ARnls["err:startendslash"], 1104);
1212
		}
1213
		return $result;
0 ignored issues
show
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1214
	}
1215
1216 View Code Duplication
	public function resetConfig($path='') {
1217
	global $ARConfig;
1218
		$path = $this->make_path($path);
1219
		if ($ARConfig->cache[$path]) {
1220
			$path = preg_quote($path,'/');
1221
			$keys = preg_grep('/^'.$path.'/',array_keys($ARConfig->cache));
1222
			foreach ($keys as $cachepath) {
1223
				unset($ARConfig->cache[$cachepath]);
1224
				unset($ARConfig->pinpcache[$cachepath]);
1225
			}
1226
		}
1227
	}
1228
1229 27 View Code Duplication
	public function clearChildConfigs($path='') {
1230 27
	global $ARConfig;
1231 27
		$path = $this->make_path($path);
1232 27
		if ($ARConfig->cache[$path]) {
1233 27
			$path = preg_quote($path,'/');
1234 27
			$keys = preg_grep('/^'.$path.'./',array_keys($ARConfig->cache));
1235 27
			foreach($keys as $cachepath) {
1236 3
				unset($ARConfig->cache[$cachepath]);
1237 3
				unset($ARConfig->pinpcache[$cachepath]);
1238 3
				unset($ARConfig->libraries[$cachepath]);
1239 27
			}
1240 27
		}
1241 27
	}
1242
1243 27
	protected function getConfig() {
1244 27
	global $ARConfig, $ARCurrent, $ARConfigChecked;
1245 27
		$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $this));
1246
		// $context=$this->getContext(0);
1247
		// debug("getConfig(".$this->path.") context: ".$context['scope'] );
1248
		// debug(print_r($ARConfig->nls, true));
1249 27
		if( !$ARConfig->cache[$this->parent] && $this->parent!=".." ) {
1250 3
			$parent = current($this->get($this->parent, "system.get.phtml"));
1251 3
			if ($parent) {
1252 3
				$parent->getConfig();
1253 3
			}
1254 3
		}
1255
1256 27
		$this->getConfigData();
1257
1258 27
		$ARConfig->pinpcache[$this->path] = $ARConfig->pinpcache[$this->parent];
1259
		// backwards compatibility when calling templates from config.ini
1260 27
		$prevArConfig = $ARCurrent->arConfig;
1261 27
		$ARCurrent->arConfig = $ARConfig->pinpcache[$this->path];
1262
1263 27
		$arCallArgs['arConfig'] = $ARConfig->pinpcache[$this->path];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$arCallArgs was never initialized. Although not strictly required by PHP, it is generally a good practice to add $arCallArgs = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1264
1265
		/* calling config.ini directly for each system.get.config.phtml call */
1266 27
		$loginSilent = $ARCurrent->arLoginSilent;
1267 27
		$ARCurrent->arLoginSilent = true;
1268
		// debug("getConfig:checkconfig start");
1269
1270 27
		$initialNLS = $ARCurrent->nls;
1271 27
		$initialConfigChecked = $ARConfigChecked;
1272
1273 27
		$ARConfig->cache[$this->path]->inConfigIni = true;
1274 27
		if ($ARConfig->cache[$this->path]->hasConfigIni && !$this->CheckConfig('config.ini', $arCallArgs)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->CheckConfig('config.ini', $arCallArgs) of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
1275
			//debug("pobject::getConfig() loaded config.ini @ ".$this->path);
1276
			// debug("getConfig:checkconfig einde");
1277 3
			$arConfig = $ARCurrent->arResult;
1278 3
			if (!isset($arConfig)) {
1279
				$arConfig = $ARCurrent->arConfig;
1280
			}
1281 3
			unset($ARCurrent->arResult);
1282 3
			if (isset($arConfig['library']) && is_array($arConfig['library'])) {
1283
				if (!$ARConfig->libraries[$this->path]) {
1284
					$ARConfig->libraries[$this->path] = array();
1285
				}
1286
				foreach ($arConfig['library'] as $libName => $libPath) {
1287
					$this->loadLibrary($libName, $libPath);
1288
				}
1289
				unset($arConfig['library']);
1290
			}
1291 3
			$ARConfig->pinpcache[$this->path] = (array) $arConfig;
1292 3
		}
1293 27
		$ARConfig->cache[$this->path]->inConfigIni = false;
1294 27
		$this->clearChildConfigs( $this->path ); // remove any config data for child objects, since these are set before their parent config was set
1295 27
		$ARConfigChecked = $initialConfigChecked;
1296 27
		$ARCurrent->nls = $initialNLS;
1297
1298 27
		$arConfig = &$ARConfig->pinpcache[$this->path];
1299 27 View Code Duplication
		if (!is_array($arConfig['authentication']['userdirs'])) {
1300
			$arConfig['authentication']['userdirs'] = array('/system/users/');
1301
		} else {
1302 27
			if (reset($arConfig['authentication']['userdirs']) != '/system/users/') {
1303
				array_unshift($arConfig['authentication']['userdirs'], '/system/users/');
1304
			}
1305
		}
1306 27 View Code Duplication
		if (!is_array($arConfig['authentication']['groupdirs'])) {
1307
			$arConfig['authentication']['groupdirs'] = array('/system/groups/');
1308
		} else {
1309 27
			if (reset($arConfig['authentication']['groupdirs']) != '/system/groups/') {
1310
				array_unshift($arConfig['authentication']['groupdirs'], '/system/groups/');
1311
			}
1312
		}
1313
1314 27
		$ARCurrent->arLoginSilent = $loginSilent;
1315 27
		$ARCurrent->arConfig = $prevArConfig;
1316 27
		$this->popContext();
1317 27
	}
1318
1319 27
	protected function getConfigData() {
1320 27
	global $ARConfig, $AR;
1321 27
		$context = $this->getContext(0);
1322 27
		if (!$ARConfig->cache[$this->path] && $context["scope"] != "pinp") {
1323
			// first inherit parent configuration data
1324 27
			$configcache= clone $ARConfig->cache[$this->parent];
1325 27
			$configcache->localTemplates = [];
1326 27
			$configcache->pinpTemplates = [];
1327 27
			$configcache->id = $this->id;
1328
1329
			// cache default templates
1330 27
			if (isset($this->data->config->templates) && count($this->data->config->templates)) {
1331
				$configcache->pinpTemplates    = $this->data->config->pinp;
1332
				$configcache->privatetemplates = $this->data->config->privatetemplates;
1333
				$configcache->localTemplates   = $this->data->config->templates;
1334
1335
				if( !$configcache->hasDefaultConfigIni ) {
1336
					foreach($configcache->localTemplates as $type => $templates ) {
1337
						if( isset($templates["config.ini"]) ) {
1338
							$configcache->hasDefaultConfigIni = true;
1339
							$configcache->hasConfigIni = true;
1340
							break;
1341
						}
1342
					}
1343
				}
1344 27
			} else if (isset($this->data->config->pinp) && count($this->data->config->pinp)) {
1345 3
				$configcache->pinpTemplates    = $this->data->config->pinp;
1346 3
			}
1347
1348 27
			if( !$configcache->hasDefaultConfigIni ) {
1349 27
				$configcache->hasConfigIni = false;
1350 27
				if(isset($this->data->config->pinp) && is_array($this->data->config->pinp) ) {
1351 3
					foreach( $this->data->config->pinp as $type => $templates ) {
1352 3
						if( isset($templates["config.ini"]) ) {
1353 3
							$configcache->hasConfigIni = true;
1354 3
							break;
1355
						}
1356 3
					}
1357 3
				}
1358 27
			}
1359
1360 27
			$localcachesettings = $this->data->config->cacheSettings;
1361 27
			if (!is_array($localcachesettings) ){
1362 27
				$localcachesettings = array();
1363 27
			}
1364
1365 27
			if (!is_array($configcache->cacheSettings) ) {
1366
				$configcache->cacheSettings = array();
1367
			}
1368
1369 27
			if ($this->data->config->cacheconfig) { // When removing this part, also fix the setting below.
1370 3
				$configcache->cache=$this->data->config->cacheconfig;
1371 3
			}
1372
1373 27
			if (!isset($localcachesettings['serverCache']) && isset($this->data->config->cacheconfig)) {
1374 3
				$localcachesettings["serverCache"] = $this->data->config->cacheconfig;
1375 3
			}
1376
1377 27
			if ($localcachesettings['serverCache'] != 0 ) {
1378 3
				$localcachesettings['serverCacheDefault'] = $localcachesettings['serverCache'];
1379 3
			}
1380
1381 27
			$configcache->cacheSettings = $localcachesettings + $configcache->cacheSettings;
1382
1383
			// store the current object type
1384 27
			$configcache->type = $this->type;
1385
1386 27
			if ($this->data->config->typetree && ($this->data->config->typetree!="inherit")) {
1387
				$configcache->typetree=$this->data->config->typetree;
1388
			}
1389 27
			if (isset($this->data->config->nlsconfig->list)) {
1390 3
				$configcache->nls = clone $this->data->config->nlsconfig;
1391 3
			}
1392
1393 27
			if ($this->data->config->grants["pgroup"]["owner"]) {
1394
				$configcache->ownergrants = $this->data->config->grants["pgroup"]["owner"];
1395
			}
1396 27
			if (isset($configcache->ownergrants) && is_array($configcache->ownergrants)) {
1397
				if ($AR->user && $AR->user->data->login != 'public' && $AR->user->data->login === $this->data->config->owner) {
1398
					$ownergrants = $configcache->ownergrants;
1399
					if (isset($ownergrants) && is_array($ownergrants)) {
1400
						foreach( $ownergrants as $grant => $val ) {
1401
							$AR->user->ownergrants[$this->path][$grant] = $val;
1402
						}
1403
					}
1404
				}
1405
			}
1406
1407 27
			if (isset($this->data->config->customconfig) && is_array($this->data->config->customconfig)) {
1408
				$configcache->custom=array_merge(is_array($configcache->custom)?$configcache->custom:array(), $this->data->config->customconfig);
1409
			}
1410 27
			$ARConfig->cache[$this->path]=$configcache;
1411
1412 27
		}
1413 27
	}
1414
1415 48
	public function loadConfig($path='') {
1416 48
	global $ARConfig, $ARConfigChecked, $ARCurrent;
1417 48
		$path=$this->make_path($path);
1418
		// debug("loadConfig($path)");
1419 48
		if (!isset($ARConfig->cache[$path]) ) {
1420 27
			$allnls = $ARCurrent->allnls;
1421 27
			$ARCurrent->allnls = true;
1422 27
			$configChecked = $ARConfigChecked;
1423 27
			if (($this->path == $path && !$this->arIsNewObject) || $this->exists($path)) {
1424 27
				$this->pushContext(array("scope" => "php"));
1425 27
				if( $this->path == $path ) {
1426
					// debug("loadConfig: currentpath $path ");
1427 27
					$this->getConfig();
1428 27
				} else {
1429
					//debug("loadConfig: get path $path ");
1430 3
					$cur_obj = current($this->get($path, "system.get.phtml"));
1431 3
					$cur_obj->getConfig();
1432
				}
1433 27
				$this->popContext();
1434 27
				$result=$ARConfig->cache[$path];
1435 27
			} else if ($path === '/') {
1436
				// special case: / doesn't exists in the store
1437
				$result=$ARConfig->cache['..'];
1438
			} else {
1439
				$parent=$this->make_path($path.'../');
1440
				if (!$ARConfig->cache[$parent]) {
1441
					$this->pushContext(array("scope" => "php"));
1442
					// debug("loadConfig: parent $parent");
1443
					$cur_obj = current($this->get($parent, "system.get.phtml"));
1444
					if( $cur_obj ) {
1445
						$cur_obj->getConfig();
1446
					}
1447
					$this->popContext();
1448
				}
1449
				$result=$ARConfig->cache[$parent];
1450
				$ARConfig->cache[ $path ] = $result;
1451
				$ARConfig->pinpcache[ $path ] = $ARConfig->pinpcache[ $parent ];
1452
			}
1453
			// restore old ARConfigChecked state
1454 27
			$ARConfigChecked = $configChecked;
1455 27
			$ARCurrent->allnls = $allnls;
1456 27
		} else {
1457
			// debug("loadConfig: exists $path ");
1458 39
			$result=$ARConfig->cache[$path];
1459
		}
1460 48
		return $result;
1461
	}
1462
1463
1464
	// TODO: look for a way to merge loadConfig and loadUserConfig into one function
1465
1466 9
	public function loadUserConfig($path='') {
1467 9
	global $ARConfig;
1468 9
		$path = $this->make_path($path);
1469 9
		$parent = $this->make_path($path.'../');
1470
1471 9
		if (!$ARConfig->cache[$path]) {
1472
			$this->loadConfig($path);
1473
		}
1474 9
		if (!$ARConfig->pinpcache[$path]) {
1475
			$config = $ARConfig->pinpcache[$parent];
1476
		} else {
1477 9
			$config = $ARConfig->pinpcache[$path];
1478
		}
1479 9
		return (array)$config;
1480
	}
1481
1482 3
	public function loadLibrary($name, $path) {
1483 3
	global $ARConfig;
1484 3
		$path=$this->make_path($path);
1485 3
		debug("pobject::loadLibrary($name, $path);");
1486 3
		if ($name===ARUNNAMED) {
1487 3
			if (strstr($path, $this->path)===0) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of strstr($path, $this->path) (string) and 0 (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
1488
				return ar::error('You cannot load an unnamed library from a child object.', 1109);
1489
			} else {
1490 3
				if (!isset($ARConfig->libraries[$this->path])) {
1491 3
					$ARConfig->libraries[$this->path] = [ $path ];
1492 3
				} else {
1493
					array_unshift($ARConfig->libraries[$this->path],$path);
1494
				}
1495
			}
1496 3
		} else if ($name && is_string($name)) {
1497
			$ARConfig->libraries[$this->path][$name]=$path;
1498
		} else if (is_int($name)) {
1499
			$ARConfig->libraries[$this->path][$name]=$path;
1500
		} else {
1501
			return ar::error('Illegal library name: '.$name, 1110);
1502
		}
1503 3
	}
1504
1505
	// returns a list of libraries loaded on $path
1506
	public function getLibraries($path = '') {
1507
	global $ARConfig;
1508
		$path = $this->make_path($path);
1509
		return (array)$ARConfig->libraries[$path];
1510
	}
1511
1512
	public function mergeLibraryConfig( $defaultLibraryName, $defaults ) {
1513
		$libraryName = ar::getvar('arLibrary');
1514
		if ( is_numeric($libraryName) || $libraryName == 'current' ) { // library is loaded unnamed
1515
			$libraryName = $defaultLibraryName;
1516
		}
1517
		if ( $libraryName ) {
1518
			$userConfig = ar::acquire('defaults.'.$libraryName);
1519
			if (isset($userConfig) && is_array($userConfig) ) {
1520
				$defaults = array_merge( $defaults, $userConfig );
1521
			}
1522
		}
1523
		return array_merge( $defaults, $this->getvar('arCallArgs') );
1524
	}
1525
1526
	public function _mergeLibraryConfig( $defaultLibraryName, $defaults ) {
1527
		return $this->mergeLibraryConfig( $defaultLibraryName, $defaults );
1528
	}
1529
1530 45
	protected function findTemplateOnPath($path, $arCallFunction, $arType, $reqnls, &$arSuperContext){
1531
1532 45
		while ($arType!='ariadne_object' ) {
1533 45
			list($arMatchType,$arMatchSubType) = explode('.',$arType,2);
1534 45
			$local = ($path === $this->path);
1535 45
			$templates = ar('template')->ls($path);
1536 45
			if(isset($templates[$arCallFunction])) {
1537 9
				$template = null;
1538 9
				if (!isset($arSuperContext[$path.":".$arType.":".$arCallFunction])) {
1539
					$template = array_reduce($templates[$arCallFunction] , function($carry, $item) use ($arMatchType,$arMatchSubType, $reqnls, $local) {
1540 9
						if ( ( $item['local'] == true && $local == true ) || $item['local'] == false ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1541 9
							if ($item['type'] === $arMatchType && ($item['subtype'] == $arMatchSubType) ) {
1542 9
								if (isset($carry) && $carry['language'] !== 'any') {
1543
									return $carry;
1544 9
								} else if ($item['language'] === 'any' || $item['language'] === $reqnls ) {
1545 9
									return $item;
1546
								}
1547
							}
1548
						}
1549
						return $carry;
1550 9
					}, null);
1551 9
				}
1552 9
				if ( isset($template) && !isset($arSuperContext[$path.":".$arType.":".$arCallFunction])) {
1553 9
					return $template;
1554
				}
1555
			}
1556 36
			if (!isset($AR->superClass[$arType])) {
1557
				// no template found, no default.phtml found, try superclass.
1558 36
				if ($subcpos = strpos($arType, '.')) {
1559 18
					$arSuper = substr($arType, 0, $subcpos);
1560 18
				} else {
1561 36
					if (!class_exists($arType, false )) {
1562
						// the given class was not yet loaded, so do that now
1563
						$arTemp=$this->store->newobject('','',$arType,new object);
1564
					} else {
1565 36
						$arTemp=new $arType();
1566
					}
1567 36
					$arSuper=get_parent_class($arTemp);
1568
				}
1569 36
				$AR->superClass[$arType]=$arSuper;
0 ignored issues
show
Bug introduced by
The variable $AR does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1570 36
			} else {
1571
				$arSuper=$AR->superClass[$arType];
1572
			}
1573 36
			$arType=$arSuper;
1574 36
		}
1575
1576 36
		return null;
1577
	}
1578
1579 45
	public function getPinpTemplate($arCallFunction='view.html', $path=".", $top="", $inLibrary = false, $librariesSeen = null, $arSuperContext=array()) {
1580 45
	global $ARCurrent, $ARConfig, $AR, $ARConfigChecked;
1581 45
		debug("getPinpTemplate: function: $arCallFunction; path: $path; top: $top; inLib: $inLibrary","class");
1582 45
		$result = array();
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1583 45
		if (!$top) {
1584 45
			$top = '/';
1585 45
		}
1586 45
		$path = $this->make_path($path);
1587 45
		if (!is_array($arSuperContext)) {
1588
			$arSuperContext = array();
1589
		}
1590
1591 45
		$matches = [];
1592 45
		preg_match('/^
1593
		    ( (?<libname> [^:]+) :  )?
1594
		    ( (?<calltype>[^:]+) :: )?
1595
		      (?<template>[^:]+)
1596 45
		    $/x', $arCallFunction, $matches);
1597
1598 45
		$arCallFunction = $matches['template'];
1599
1600 45
		if($matches['calltype'] != '') {
1601
			$arCallType = $matches['calltype'];
1602
		} else {
1603 45
			$arCallType = $this->type;
1604
		}
1605
1606 45
		if ( $matches['libname'] != '' ) {
1607
			$arLibrary      = $matches['libname'];
1608
1609
			if ($arLibrary == 'current') {
1610
				// load the current arLibrary
1611
				$context       = $this->getContext(1);
1612
				$arLibrary     = $context['arLibrary'];
1613
				$arLibraryPath = $context['arLibraryPath'];
1614
			} else {
1615
				$libpath = $path;
1616
				while (!isset($arLibraryPath) && $libpath!=$lastlibpath) {
0 ignored issues
show
Bug introduced by
The variable $lastlibpath does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1617
					$lastlibpath = $libpath;
1618
					if (isset($ARConfig->libraries[$libpath][$arLibrary])) {
1619
						$arLibraryPath = $ARConfig->libraries[$libpath][$arLibrary];
1620
					} else {
1621
						if ($libpath == $top) {
1622
							break;
1623
						}
1624
						$libpath=$this->store->make_path($libpath, "..");
1625
					}
1626
				}
1627
			}
1628
			if ($arLibraryPath) {
1629
				debug("getPinpTemplate: found library '$arLibrary'. Searching for [".$arCallType."] $arCallFunction on '".$arLibraryPath."' up to '$top'");
0 ignored issues
show
Bug introduced by
The variable $arLibraryPath does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1630
				$librariesSeen[$arLibraryPath] = true;
1631
				$inLibrary = true;
1632
				$path = $arLibraryPath;
1633
			} else {
1634
				debug("getPinpTemplate: Failed to find library $arLibrary");
1635
			}
1636
			$path = $this->make_path($path);
1637
		}
1638
1639 45
		$checkpath           = $path;
1640 45
		$lastcheckedpath     = "";
1641 45
		$arCallClassTemplate = $ARCurrent->arCallClassTemplate;
1642 45
		$reqnls              = $this->reqnls;
1643 45
		$template            = null;
1644 45
		while (!$arCallClassTemplate && !isset($template) && $checkpath!=$lastcheckedpath) {
1645 45
			$lastcheckedpath = $checkpath;
1646
1647 45
			$template = $this->findTemplateOnPath( $checkpath, $arCallFunction, $arCallType, $reqnls, $arSuperContext);
1648
1649 45
			if (isset($template)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
1650
				// haal info uit template
1651
				// debug("getPinpTemplate: found ".$arCallFunction." on ".$checkpath);
1652 45
			} else if ($inLibrary) {
1653
1654
				// faster matching on psection, prefix doesn't have to be a valid type
1655
				$prefix = substr($ARConfig->cache[$checkpath]->type,0,8);
1656
1657
				if ($prefix === 'psection') {
1658
					 // debug("BREAKING; $arTemplateId");
1659
					// break search operation when we have found a
1660
					// psection object
1661
					break;
1662
				}
1663
			} else {
1664 36
				if (isset($ARConfig->libraries[$checkpath])) {
1665
					// need to check for unnamed libraries
1666 36
					$libraries = array_filter($ARConfig->libraries[$checkpath],'is_int',ARRAY_FILTER_USE_KEY);
1667 36
					foreach( $libraries as $key => $libpath ) {
1668 36
						$arLibraryPath = $libpath;
1669 36
						$arLibrary     = $key;
1670
1671 36
						$libprevpath = null;
1672 36
						while($libpath != $libprevpath ) {
1673 36
							$libprevpath = $libpath;
1674
1675 36
							$template = $this->findTemplateOnPath( $libpath, $arCallFunction, $arCallType, $reqnls, $arSuperContext);
1676 36
							if (isset($template)) {
1677
								break 2;
1678
							}
1679
1680 36
							$prefix = substr($ARConfig->cache[$libpath]->type,0,8);
1681 36
							if ($prefix === 'psection' || $top == $libpath) {
1682 36
								break;
1683
							}
1684
1685 36
							$libpath = $this->store->make_path($libpath, "..");
1686 36
						}
1687 36
					}
1688 36
					debug("getPinpTemplate: found ".$arCallFunction." on ".$template['path']);
1689 36
				}
1690
1691
			}
1692
1693 45
			if ($checkpath == $top) {
1694 36
				break;
1695
			}
1696
1697 45
			debug("getPinpTemplate: DONE checking for ".$arCallFunction." on ".$checkpath);
1698 45
			$checkpath=$this->store->make_path($checkpath, "..");
1699
			
1700 45
		}
1701 45
		$result = null;
1702 45
		if(isset($template)) {
1703 9
			$result = [];
1704
			//debug("getPinpTemplate END; ".$template['id'] .' '.$template['path']);
1705 9
			$type = $template['type'];
1706 9
			if(isset($template['subtype'])) {
1707
				$type .= '.' . $template['subtype'];
1708
			}
1709 9
			$result["arTemplateId"]       = $template['id'];
1710 9
			$result["arCallTemplate"]     = $template['filename'];
1711 9
			$result["arCallType"]         = $arCallType;
1712 9
			$result["arCallTemplateName"] = $arCallFunction;
1713 9
			$result["arCallTemplateNLS"]  = $template['language'];
1714 9
			$result["arCallTemplateType"] = $type;
1715 9
			$result["arCallTemplatePath"] = $template['path'];
1716 9
			$result["arLibrary"]          = $arLibrary;
0 ignored issues
show
Bug introduced by
The variable $arLibrary does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1717 9
			$result["arLibraryPath"]      = $arLibraryPath;
1718 9
			$result["arLibrariesSeen"]    = $librariesSeen;
1719 9
			$result["arPrivateTemplate"]  = $template['private'];
1720 9
		}
1721 45
		return $result;
1722
	}
1723
1724 48
	public function CheckConfig($arCallFunction="", $arCallArgs="") {
1725
	// returns true when cache isn't up to date and no other template is
1726
	// defined for $path/$function. Else it takes care of output to the
1727
	// browser.
1728
	// All these templates must exist under a fixed directory, $AR->dir->templates
1729 48
	global $nocache, $AR, $ARConfig, $ARCurrent, $ARBeenHere, $ARnls, $ARConfigChecked;
1730 48
		$MAX_LOOP_COUNT=10;
1731
1732
1733
		// system templates (.phtml) have $arCallFunction=='', so the first check in the next line is to
1734
		// make sure that loopcounts don't apply to those templates.
1735 48
		if (0 && $arCallFunction && $ARBeenHere[$this->path][$arCallFunction]>$MAX_LOOP_COUNT) { // protect against infinite loops
1736
			error(sprintf($ARnls["err:maxloopexceed"],$this->path,$arCallFunction,$arCallArgs));
1737
			$this->store->close();
1738
			exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method CheckConfig() contains an exit expression.

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.

Loading history...
1739
		} else {
1740 48
			$ARBeenHere[$this->path][$arCallFunction]+=1;
1741
1742
			// this will prevent the parents from setting the cache time
1743 48
			$initialConfigChecked = $ARConfigChecked;
1744 48
			$ARConfigChecked = true;
1745 48
			$config = ($ARConfig->cache[$this->path]) ? $ARConfig->cache[$this->path] : $this->loadConfig();
1746 48
			$ARConfigChecked = $initialConfigChecked;
1747 48
			$ARConfig->nls=$config->nls;
1748
1749
1750
			// if a default language is entered in a parent and no language is
1751
			// explicitly selected in the url, use that default.
1752
			// The root starts with the system default (ariadne.phtml config file)
1753 48
			if ( !$ARCurrent->nls ) {
1754 48
				if ( $config->root['nls'] ) {
1755
					$this->reqnls = $config->root['nls'];
1756
					if ( !$ARConfigChecked ) {
1757
						$ARCurrent->nls = $this->reqnls;
1758
					}
1759 48
				} else if ( $config->nls->default ) {
1760 48
					$this->reqnls = $config->nls->default;
1761 48
					$this->nls = $this->reqnls;
1762 48
					if ( !$ARConfigChecked ) {
1763
						$ARCurrent->nls = $this->nls;
1764
					}
1765 48
				}
1766 48
			} else {
1767
				$this->reqnls = $ARCurrent->nls;
1768
			}
1769 48
			$nls = &$this->nls;
1770 48
			$reqnls = &$this->reqnls;
1771
1772 48
			if (!$ARConfigChecked && is_object($ARnls)) {
1773
				$ARnls->setLanguage($ARCurrent->nls);
1774
			}
1775
1776
1777 48
			if (!$ARCurrent->arContentTypeSent) {
1778
				ldHeader("Content-Type: text/html; charset=UTF-8");
1779
				$ARCurrent->arContentTypeSent = true;
1780
			}
1781
1782
/*			// FIXME: the acceptlang code works a bit too well.. it overrides psite configuration settings.
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "the acceptlang code works a bit too well.. it overrides psite configuration settings"
Loading history...
1783
1784
			if ($ARCurrent->acceptlang && !$ARCurrent->nls) {
1785
				if ($ARCurrent->acceptlang && is_array($this->data->nls->list)) {
1786
					$validlangs = array_intersect(array_keys($ARCurrent->acceptlang), array_keys($this->data->nls->list));
1787
				}
1788
				if ($validlangs) {
1789
					$reqnls=array_shift($validlangs);
1790
					$ARCurrent->nls = $reqnls;
1791
				}
1792
			}
1793
*/
1794 48 View Code Duplication
			if (isset($this->data->custom) && is_array($this->data->custom) && $this->data->custom['none']) {
1795 3
				$this->customdata=$this->data->custom['none'];
0 ignored issues
show
Bug introduced by
The property customdata does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
1796 3
			}
1797 48 View Code Duplication
			if (isset($this->data->custom) && is_array($this->data->custom) && $this->data->custom[$nls]) {
1798
				$this->customnlsdata=$this->data->custom[$nls];
0 ignored issues
show
Bug introduced by
The property customnlsdata does not seem to exist. Did you mean nlsdata?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1799
			}
1800
1801 48
			if (!$ARConfigChecked) {
1802
				// this template is the first template called in this request.
1803
				$eventData = new object();
1804
				$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
Bug introduced by
The property arCallArgs does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1805
				$eventData->arCallFunction = $arCallFunction;
0 ignored issues
show
Bug introduced by
The property arCallFunction does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1806
1807
				$ARConfigChecked = true;
1808
				$result = ar_events::fire( 'onbeforeview', $eventData );
1809
				$ARConfigChecked = $initialConfigChecked;
1810
				if ( !$result ) { //prevent default action: view
1811
					return false;
1812
				}
1813
			}
1814
1815 48
			if (!$ARConfigChecked) {
1816
				// if this object isn't available in the requested language, show
1817
				// a language select dialog with all available languages for this object.
1818
				if (isset($this->data->nls) && !$this->data->name) {
1819
					if (!$ARCurrent->forcenls && (!isset($this->data->nls->list[$reqnls]) || !$config->nls->list[$reqnls])) {
1820
						if (!$ARCurrent->nolangcheck && $arCallFunction != 'config.ini') {
1821
							$ARCurrent->nolangcheck=1;
1822
							$eventData = new object();
1823
							$eventData->arCallFunction = $arCallFunction;
1824
							$eventData->arCallArgs = $arCallArgs;
1825
							$eventData->arRequestedNLS = $reqnls;
0 ignored issues
show
Bug introduced by
The property arRequestedNLS does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1826
							$result = ar_events::fire( 'onlanguagenotfound', $eventData );
1827
							if ( $result ) { // continue with default action: langaugeselect
1828
								$result->arCallArgs["arOriginalFunction"] = $result->arCallFunction;
1829
								$this->call("user.languageselect.html", $result->arCallArgs);
1830
								return false;
1831
							}
1832
						} else {
1833
							$this->nlsdata=$this->data->$nls;
1834
						}
1835
					} else {
1836
						$this->nlsdata=$this->data->$reqnls;
1837
					}
1838
				}
1839
				$ARCurrent->nolangcheck=1;
1840
			}
1841
1842
			/*
1843
				Set ARConfigChecked to true to indicate that we have been here
1844
				earlier.
1845
			*/
1846 48
			$ARConfigChecked = true;
1847 48
			if ($arCallFunction) { // don't search for templates named ''
1848
				// FIXME: Redirect code has to move to getPinpTemplate()
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "Redirect code has to move to getPinpTemplate"
Loading history...
1849 45
				$redirects	= $ARCurrent->shortcut_redirect;
1850 45
				if (isset($redirects) && is_array($redirects)) {
1851
					$redirpath = $this->path;
1852
					while (!$template['arTemplateId'] &&
0 ignored issues
show
Bug introduced by
The variable $template does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1853
							($redir = array_pop($redirects)) &&
1854
							$redir["keepurl"] &&
1855
							(substr($redirpath, 0, strlen($redir["dest"])) == $redir["dest"])
1856
					) {
1857
						$template = $this->getPinpTemplate($arCallFunction, $redirpath, $redir["dest"]);
1858
						$redirpath = $redir['src'];
1859
					}
1860
1861
					if (!$template["arTemplateId"] && $redirpath) {
1862
						$template = $this->getPinpTemplate($arCallFunction, $redirpath);
1863
					}
1864
				}
1865 45
				if (!$template["arTemplateId"]) {
1866 45
					$template = $this->getPinpTemplate($arCallFunction);
1867 45
				}
1868
1869 45
				if ($template["arCallTemplate"] && $template["arTemplateId"]) {
1870 9
					if (!isset($ARCurrent->cacheTemplateChain)) {
1871
						$ARCurrent->cacheTemplateChain = array();
1872
					}
1873 9
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]])) {
1874 6
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]] = array();
1875 6
					}
1876 9
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']])) {
1877 9
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']] = array();
1878 9
					}
1879 9
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']])) {
1880 9
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']] = 0;
1881 9
					}
1882 9
					$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']]++;
1883
1884
1885 9
					debug("CheckConfig: arCallTemplate=".$template["arCallTemplate"].", arTemplateId=".$template["arTemplateId"],"object");
1886
					// $arCallTemplate=$this->store->get_config("files")."templates".$arCallTemplate;
1887
					// check if template exists, if it doesn't exist, then continue the original template that called CheckConfig
1888 9
					$arTemplates=$this->store->get_filestore("templates");
0 ignored issues
show
Unused Code introduced by
$arTemplates is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1889 9
					$exists = ar('template')->exists($template['arCallTemplatePath'],$template["arCallTemplate"]);
1890 9
					if ( $exists ) {
1891
						// check if the requested language exists, if not do not display anything,
1892
						// unless otherwise indicated by $ARCurrent->allnls
1893
						// This triggers only for pinp templates called by other templates,
1894
						// as the first template (in the url) will first trigger the language
1895
						// choice dialogue instead.
1896 9
						$arLibrary = $template['arLibrary'];
1897 9
						if (is_int($arLibrary)) {
1898
							// set the library name for unnamed libraries to 'current'
1899
							// so that calls using getvar('arLibrary') will keep on working
1900
							$arLibrary = "current";
1901
						}
1902
1903 9 View Code Duplication
						if (!is_string($arCallArgs)) {
1904 9
							$arCallArgs['arCallFunction'] = $arCallFunction;
1905 9
							$arCallArgs['arLibrary']      = $arLibrary;
1906 9
							$arCallArgs['arLibraryPath']  = $template["arLibraryPath"];
1907 9
						}
1908
1909 9
						$ARCurrent->arCallStack[]=$arCallArgs;
1910
						// start running a pinp template
1911
1912 9
						$this->pushContext(
1913
							array(
1914 9
								"scope"              => "pinp",
1915 9
								"arLibrary"          => $arLibrary,
1916 9
								"arLibraryPath"      => $template['arLibraryPath'],
1917 9
								"arCallFunction"     => $arCallFunction,
1918 9
								"arCurrentObject"    => $this,
1919 9
								"arCallType"         => $template['arCallType'],
1920 9
								"arCallTemplateName" => $template['arCallTemplateName'],
1921 9
								"arCallTemplateNLS"  => $template['arCallTemplateNLS'],
1922 9
								"arCallTemplateType" => $template['arCallTemplateType'],
1923 9
								"arCallTemplatePath" => $template['arCallTemplatePath'],
1924 9
								"arLibrariesSeen"    => $template['arLibrariesSeen']
1925 9
							)
1926 9
						);
1927
1928
						// FIXME: is 2 het correcte getal? Kan dit minder magisch?
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "is 2 het correcte getal? Kan dit minder magisch?"
Loading history...
1929 9
						if (count($ARCurrent->arCallStack) == 2 && true === $template['arPrivateTemplate']) {
1930
							// Do not allow private templates to be called first in the stack.
1931
							// echo "Bad request";
1932
1933
							// FIXME: Echte header sturen? Of gewoon niet uitvoeren? Wat is het correcte gedrag?
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "Echte header sturen? Of gewoon niet uitvoeren? Wat is het correcte gedrag?"
Loading history...
1934
							// Return true zorgt er voor dat de default 404 handler het oppikt alsof het template niet bestaat.
1935
							$this->popContext();
1936
							array_pop($ARCurrent->arCallStack);
1937
							return true;
1938 9
						} else if ($ARCurrent->forcenls || isset($this->data->nls->list[$reqnls])) {
1939
							// the requested language is available.
1940 9
							$this->nlsdata=$this->data->$reqnls;
1941 9
							$this->nls=$reqnls;
1942 9
							$continue=true;
1943 9
						} else if (!isset($this->data->nls)) {
1944
							// the object has no language support
1945
							$this->nlsdata=$this->data;
1946
							$continue=true;
1947
						} else if (($ARCurrent->allnls) || (!$initialConfigChecked && $ARCurrent->nolangcheck)) {
1948
							// all objects must be displayed
1949
							// $this->reqnls=$this->nls; // set requested nls, for checks
1950
							$this->nls = isset($this->data->nls->default) ? $this->data->nls->default : $this->reqnls;
1951
							$this->nlsdata = $this->data->$nls ?: $this->data->{$this->nls} ?: $this->data;
1952
							$continue=true;
1953
						} else {
1954
							debug("CheckConfig: requested language not available, allnls not set","object");
1955
							// -> skip this object (do not run template but do return false)
1956
							$continue=false;
1957
						}
1958 9
						if ($continue) {
1959 9
							$eventData = new object();
1960 9 View Code Duplication
							if ( !$AR->contextCallHandler ) { /* prevent onbeforecall from re-entering here */
1961 9
								$AR->contextCallHandler = true;
1962 9
								$eventData->arCallArgs = $arCallArgs;
1963 9
								$eventData->arCallFunction = $arCallFunction;
1964 9
								$eventData->arContext = $this->getContext();
0 ignored issues
show
Bug introduced by
The property arContext does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1965 9
								$eventData = ar_events::fire('onbeforecall', $eventData);
1966 9
								$ARCurrent->arResult = $eventData->arResult;
1967 9
								$AR->contextCallHandler = false;
1968 9
								$continue = ($eventData!=false);
1969 9
							}
1970 9
							if ( $continue ) {
1971 9
								if (!isset($ARCurrent->cacheCallChainSettings)) {
1972
									$ARCurrent->cacheCallChainSettings = array();
1973
								}
1974 9
								if ($ARConfig->cache[$this->path]->inConfigIni == false) {
1975 6
									$ARCurrent->cacheCallChainSettings[$this->id] = $config->cacheSettings;
1976 6
								}
1977
1978 9
								if ($ARCurrent->ARShowTemplateBorders) {
1979
									echo "<!-- arTemplateStart\nData: ".$this->type." ".$this->path." \nTemplate: ".$template["arCallTemplatePath"]." ".$template["arCallTemplate"]." \nLibrary:".$template["arLibrary"]." -->";
1980
								}
1981 9
								set_error_handler(array('pobject','pinpErrorHandler'),error_reporting());
1982 9
								$func = ar('template')->get($template['arCallTemplatePath'],$template['arCallTemplate']);
1983 9
								if(is_callable($func)){
1984 9
									$arResult = $func($this);
1985 9
								}
1986 9
								restore_error_handler();
1987 9
								if (isset($arResult)) {
1988 9
									$ARCurrent->arResult=$arResult;
1989 9
								}
1990 9
								if ($ARCurrent->ARShowTemplateBorders) {
1991
									echo "<!-- arTemplateEnd -->";
1992
								}
1993 9 View Code Duplication
								if ( !$AR->contextCallHandler ) { /* prevent oncall from re-entering here */
1994 9
									$AR->contextCallHandler = true;
1995 9
									$temp = $ARCurrent->arResult; /* event listeners will change ARCurrent->arResult */
1996 9
									$eventData->arResult = $temp;
1997 9
									ar_events::fire('oncall', $eventData );
1998 9
									$ARCurrent->arResult = $temp; /* restore correct result */
1999 9
									$AR->contextCallHandler = false;
2000 9
								}
2001 9
							}
2002 9
						}
2003 9
						array_pop($ARCurrent->arCallStack);
2004 9
						$this->popContext();
2005
2006 9
						if ( !$initialConfigChecked && $arCallFunction != 'config.ini' ) {
2007
							// this template was the first template called in this request.
2008
							$eventData = new object();
2009
							$eventData->arCallArgs = $arCallArgs;
2010
							$eventData->arCallFunction = $arCallFunction;
2011
							ar_events::fire( 'onview', $eventData ); // no default action to prevent, so ignore return value.
2012
						}
2013 9
						return false;
2014
					} else {
2015 3
						debug("pobject: CheckConfig: no such file: ".$template["arTemplateId"].$template["arCallTemplate"]."","all");
2016
					}
2017 3
				} else {
2018 36
					debug("CheckConfig: no arCallTemplate ($arCallFunction from '$this->path')","object");
2019
				}
2020
2021 39
			}
2022
		}
2023 42
		return true;
2024
	}
2025
2026 18
	public function ClearCache($path="", $private=true, $recurse=false) {
2027 18
	global $AR;
2028 18
		$norealnode = false;
2029 18
		if (!$path) {
2030
			$path=$this->path;
2031
		} else {
2032 18
			$realpath = current($this->get($path, "system.get.path.phtml"));
2033 18
			if($realpath != false) {
2034 18
				$path = $realpath;
2035 18
			} else {
2036
				$norealnode = true;
2037
			}
2038
		}
2039
2040 18
		if($norealnode !== true) {
2041
			/*
2042
				we don't want to recurse to the currentsite, because the path
2043
				doesn't exists in the database, so it doesn't have a currentsite
2044
2045
				the privatecache should be emptied by delete, or by the cleanup
2046
				cronjob. The current path doesn't exists in the database, so a
2047
				object id which is needed to find the node in the cache, isn't
2048
				available
2049
			*/
2050
2051 18
			if ($private ) {
2052
				// now remove any private cache entries.
2053
				// FIXME: this doesn't scale very well.
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "this doesn't scale very well"
Loading history...
2054
				//        only scalable solution is storage in a database
2055
				//        but it will need the original path info to
2056
				//        remove recursively fast enough.
2057
				//        this means a change in the filestore api. -> 2.5
2058
2059
				// Use chunks of max 5000 objects at a time to be more memory-efficient;
2060 18
				$pcache=$this->store->get_filestore("privatecache");
2061 18
				if ($recurse) {
2062
					$offset = 0;
2063
					$limit = 5000;
2064
					$ids=$this->store->info($this->store->find($path, "" , $limit, $offset));
2065
					while (is_array($ids) && count($ids)) {
2066
						foreach($ids as $value) {
2067
							$eventData = new object();
2068
							$eventData = ar_events::fire( 'onbeforeclearprivatecache', $eventData, $value['type'], $value['path'] );
2069
							if ( !$eventData ) {
2070
								continue;
2071
							}
2072
2073
							$pcache->purge($value["id"]);
2074
							ar_events::fire( 'onclearprivatecache', $eventData, $value['type'], $value['path'] );
2075
						}
2076
2077
						$offset += $limit;
2078
						$ids = $this->store->info($this->store->find($path, "", $limit, $offset));
2079
					}
2080
				} else {
2081 18
					$eventData = new object();
2082 18
					$eventData = ar_events::fire( 'onbeforeclearprivatecache', $eventData, $this->type, $this->path );
2083 18
					if ( $eventData ) {
2084 18
						$pcache->purge($this->id);
2085 18
						ar_events::fire( 'onclearprivatecache', $eventData, $this->type, $this->path );
2086 18
					}
2087
				}
2088 18
			}
2089
2090
			// now clear all parents untill the current site
2091 18
			$site=$this->currentsite($path);
2092 18
			$project=$this->currentproject($path);
2093 18
			if ($path!=$site && $path != $project && $path!='/') {
2094 18
				$parent=$this->make_path($path.'../');
2095 18
				$this->ClearCache($parent, $private, false);
2096 18
			}
2097 18
		}
2098 18
		$recursed = array();
2099
2100
		// filesystem cache image filenames are always lower case, so
2101
		// use special path for that. Remember 'real' path name for
2102
		// recursion and stuff
2103 18
		$fs_path=strtolower($path);
2104 18
		$nlslist=$AR->nls->list;
2105 18
		$nlslist["."]="default";
2106 18
		$cache_types[] = "normal";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$cache_types was never initialized. Although not strictly required by PHP, it is generally a good practice to add $cache_types = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2107 18
		$cache_types[] = "compressed";
2108 18
		$cache_types[] = "session";
2109
2110 18
		global $cache_config,$store_config;
2111 18
		$cachestore=new cache($cache_config);
2112
2113
2114 18
		$filestore = $this->store->get_config("files");
2115 18
		foreach($cache_types as $type){
2116 18
			foreach($nlslist as $nls => $language){
2117
				// break away if nls doesn't exists
2118
				// is dir is cached, so it should not cost more that it add's in speed
2119 18
				if(!is_dir($filestore."cache/$type/$nls")){
2120 18
					continue;
2121
				}
2122
2123
				$fpath=$filestore."cache/$type/$nls".$fs_path;
2124
				$hpath=$filestore."cacheheaders/$type/$nls".$fs_path;
2125
				if ($dir=@dir($fpath)) {
2126
					while (false !== ($entry = $dir->read())) {
2127
						if ($entry!="." && $entry!="..") {
2128
							if (is_file($fpath.$entry)) {
2129
								@unlink($fpath.$entry);
2130
								@unlink($hpath.$entry);
2131
								$cachestore->delete("/".$type."/".$nls.$fs_path.$entry);
2132
							} else if ( $recurse && !$recursed[$entry]) {
2133
								$this->ClearCache($path.$entry."/", false, true);
2134
								$recursed[$entry]=true;
2135
							}
2136
						}
2137
					}
2138
					$dir->close();
2139
					// remove empty directory entry's, hide errors about directory entry's with content
2140
					@rmdir($fpath);
2141
					@rmdir($hpath);
2142
				} else if (file_exists(substr($fpath,0,-1)."=")) {
2143
					@unlink(substr($fpath,0,-1)."=");
2144
					@unlink(substr($hpath,0,-1)."=");
2145
					$cachestore->delete("/".$type."/".$nls.substr($fs_path,0,-1)."=");
2146
				}
2147 18
			}
2148 18
		}
2149 18
	}
2150
2151
	public function getcache($name, $nls="") {
2152
		global $ARCurrent, $ARnls;
2153
		$result=false;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2154
		$this->error = '';
2155
		if ($name) {
2156
			$result=false;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2157
			if (!$nls) {
2158
				$nls=$this->nls;
2159
			}
2160
			$file=$nls.".".$name;
2161
2162
			$minfresh = time();
2163
			if (isset($ARCurrent->RequestCacheControl["min-fresh"])) {
2164
				$minfresh += $ARCurrent->RequestCacheControl["min-fresh"];
2165
			}
2166
2167
			$pcache=$this->store->get_filestore("privatecache");
2168
			if ( $pcache->exists($this->id, $file) &&
2169
			     ($pcache->mtime($this->id, $file) > ($minfresh) )  ) {
2170
2171
				$result = $pcache->read($this->id, $file);
2172
2173
				$contentType = $ARCurrent->ldHeaders['content-type'];
2174
				if (preg_match('|^content-type:[ ]*([^ /]+)/|i', $contentType, $matches)) {
2175
					$contentType = $matches[1];
2176
				} else {
2177
					$contentType = '';
2178
				}
2179
2180 View Code Duplication
				if (!$contentType || strtolower($contentType) == 'text') {
2181
					require_once($this->store->get_config('code')."modules/mod_url.php");
2182
					$temp = explode('.', $file);
2183
					$imageNLS = $temp[0];
2184
					$result = URL::ARtoRAW($result, $imageNLS);
0 ignored issues
show
Unused Code introduced by
The call to URL::ARtoRAW() has too many arguments starting with $imageNLS.

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...
2185
				}
2186
			} else {
2187
				$result=false;
2188
				$ARCurrent->cache[]=$file;
2189
				ob_start();
2190
				/* output buffering is recursive, so this won't interfere with
2191
				   normal page caching, unless you forget to call savecache()...
2192
				   so normal pagecache needs to check $ARCurrent->cache, if it's
2193
				   not empty, issue a warning and don't cache the outputbuffer...
2194
				   savecache() must then pop the stack.
2195
				*/
2196
			}
2197
		} else {
2198
			$this->error = ar::error($ARnls["err:nonamecache"], 1111);
2199
			$result = false;
2200
		}
2201
		return $result;
2202
	}
2203
2204
	public function cached($name, $nls="") {
2205
		if ($image=$this->getcache($name, $nls)) {
2206
			echo $image;
2207
			$result=true;
2208
		} else {
2209
			$result=false;
2210
		}
2211
		return $result;
2212
	}
2213
2214
	public function savecache($time="") {
2215
		global $ARCurrent, $ARnls, $DB;
2216
		$result = false;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2217
		$this->error = '';
2218
		if (!$time) {
2219
			$time=2; // 'freshness' in hours.
2220
		}
2221
		if ($file=array_pop($ARCurrent->cache)) {
2222
			$image=ob_get_contents();
2223
			if ($image !== false) {
2224
				$result = true;
2225
				$origimage = $image;
2226
2227
				$contentType = $ARCurrent->ldHeaders['content-type'];
2228
				if (preg_match('|^content-type:[ ]*([^ /]+)/|i', $contentType, $matches)) {
2229
					$contentType = $matches[1];
2230
				} else {
2231
					$contentType = '';
2232
				}
2233
2234 View Code Duplication
				if (!$contentType || strtolower($contentType) == 'text') {
2235
					require_once($this->store->get_config('code')."modules/mod_url.php");
2236
					$temp = explode('.', $file);
2237
					$imageNLS = $temp[0];
2238
					$image = URL::RAWtoAR($image, $imageNLS);
2239
				}
2240
2241
				if( $time > 0  && $DB["wasUsed"] == 0) {
2242
					$pcache=$this->store->get_filestore("privatecache");
2243
					$pcache->write($image, $this->id, $file);
2244
					$time=time()+($time*3600);
2245 View Code Duplication
					if (!$pcache->touch($this->id, $file, $time)) {
2246
						$this->error = ar::error("savecache: ERROR: couldn't touch $file", 1113);
2247
						$result = false;
2248
					}
2249
				}
2250
				ob_end_clean();
2251
				echo $origimage;
2252
			} else {
2253
				debug("skipped saving cache - ob_get_contents returned false so output buffering was not active", "all");
2254
				$result = false;
2255
			}
2256
		} else {
2257
			$this->error = ar::error($ARnls["err:savecachenofile"], 1112);
2258
			$result = false;
2259
		}
2260
		return $result;
2261
	}
2262
2263
	public function getdatacache($name) {
2264
		global $ARCurrent, $ARnls;
2265
		$result=false;
2266
		$this->error = '';
2267
		if ($name) {
2268
2269
			$minfresh = time();
2270
			if (isset($ARCurrent->RequestCacheControl["min-fresh"])) {
2271
				$minfresh += $ARCurrent->RequestCacheControl["min-fresh"];
2272
			}
2273
2274
			$pcache=$this->store->get_filestore("privatecache");
2275
			if ( $pcache->exists($this->id, $name) &&
2276
			     ($pcache->mtime($this->id, $name) > $minfresh) ) {
2277
				$result = unserialize($pcache->read($this->id, $name));
2278
			} else {
2279
				debug("getdatacache: $name doesn't exists, returning false.","all");
2280
			}
2281
		} else {
2282
			$this->error = ar::error($ARnls["err:nonamecache"], 1111);
2283
		}
2284
		return $result;
2285
	}
2286
2287
	public function savedatacache($name,$data,$time="") {
2288
		global $DB;
2289
		$this->error = '';
2290
		if (!$time) {
2291
			$time=2; // 'freshness' in hours.
2292
		}
2293
		$pcache=$this->store->get_filestore("privatecache");
2294
		if( $time > 0  && $DB["wasUsed"] == 0) {
2295
			$pcache->write(serialize($data), $this->id, $name);
2296
			$time=time()+($time*3600);
2297 View Code Duplication
			if (!$pcache->touch($this->id, $name, $time)) {
2298
				$this->error = ar::error('Could not touch '.$name, 1113);
2299
				return false;
2300
			}
2301
		}
2302
		return true;
2303
	}
2304
2305 39
	public function getdata($varname, $nls="none", $emptyResult=false) {
0 ignored issues
show
Coding Style introduced by
getdata uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
getdata uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
2306
	// function to retrieve variables from $this->data, with the correct
2307
	// language version.
2308 39
	global $ARCurrent;
2309
2310 39
		$result = false;
2311 39
		if ($nls!="none") {
2312 36 View Code Duplication
			if ($ARCurrent->arCallStack) {
2313 36
				$arCallArgs=end($ARCurrent->arCallStack);
2314 36
				if (isset($arCallArgs) && is_array($arCallArgs)) {
2315 36
					extract($arCallArgs);
2316 36
				} else if (is_string($arCallArgs)) {
2317
					Parse_Str($arCallArgs);
2318
				}
2319 36
			}
2320 36
			if (isset(${$nls}[$varname])) {
2321 21
				$result=${$nls}[$varname];
2322 36
			} else if (isset($ARCurrent->$nls) && isset($ARCurrent->$nls->$varname)) {
2323
				$result=$ARCurrent->$nls->$varname;
2324 36
			} else if (($values=$_POST[$nls]) && isset($values[$varname])) {
2325
				$result=$values[$varname];
2326 36
			} else if (($values=$_GET[$nls]) && isset($values[$varname])) {
2327
				$result=$values[$varname];
2328 36
			} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$nls][$varname])) {
2329
				$result=$arStoreVars[$nls][$varname];
2330 36
			} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$nls][$varname])) {
2331
				$result=$arStoreVars[$nls][$varname];
2332
			}
2333 36
			if ($result===false) {
2334 36
				if (isset($this->data->${nls}) && isset($this->data->${nls}->${varname})) {
2335 18
					$result=$this->data->${nls}->${varname};
2336 18
				}
2337 36
			}
2338 36
		} else { // language independant variable.
2339 39 View Code Duplication
			if ($ARCurrent->arCallStack) {
2340 39
				$arCallArgs=end($ARCurrent->arCallStack);
2341 39
				if (isset($arCallArgs) && is_array($arCallArgs)) {
2342 36
					extract($arCallArgs);
2343 39
				} else if (is_string($arCallArgs)) {
2344
					Parse_Str($arCallArgs);
2345
				}
2346 39
			}
2347 39
			if (isset($$varname)) {
2348 18
				$result=$$varname;
2349 39
			} else if (isset($ARCurrent->$varname)) {
2350
				$result=$ARCurrent->$varname;
2351 39 View Code Duplication
			} else if (isset($_POST[$varname])) {
2352
				$result=$_POST[$varname];
2353 39
			} else if (isset($_GET[$varname])) {
2354
				$result=$_GET[$varname];
2355 39
			} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$varname])) {
2356
				$result=$arStoreVars[$varname];
2357 39
			} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$varname])) {
2358
				$result=$arStoreVars[$varname];
2359
			}
2360 39
			if ($result===false) {
2361 39
				if (isset($this->data->$varname)) {
2362 18
					$result=$this->data->$varname;
2363 18
				}
2364 39
			}
2365
		}
2366 39
		if ( $result === false ) {
2367 39
			$result = $emptyResult;
2368 39
		}
2369 39
		return $result;
2370
	}
2371
2372
	public function showdata($varname, $nls="none", $emptyResult=false) {
2373
		echo htmlspecialchars($this->getdata($varname, $nls, $emptyResult), ENT_QUOTES, 'UTF-8');
2374
	}
2375
2376
	public function setnls($nls) {
2377
		ldSetNls($nls);
2378
	}
2379
2380
	public function getcharset() {
2381
		return "UTF-8";
2382
	}
2383
2384
	public function HTTPRequest($method, $url, $postdata = "", $port=80 ) {
2385
		$maxtries = 5;
2386
		$tries = 0;
2387
		$redirecting = true;
2388
2389
		if(isset($postdata) && is_array($postdata)) {
2390
			foreach($postdata as $key=>$val) {
2391
				if(!is_integer($key)) {
2392
					$data .= "$key=".urlencode($val)."&";
0 ignored issues
show
Bug introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2393
				}
2394
			}
2395
		} else {
2396
			$data = $postdata;
2397
		}
2398
2399
		while ($redirecting && $tries < $maxtries) {
2400
			$tries++;
2401
			// get host name and URI from URL, URI not needed though
2402
			preg_match("/^([htps]*:\/\/)?([^\/]+)(.*)/i", $url, $matches);
2403
			$host = $matches[2];
2404
			$uri = $matches[3];
2405
			if (!$matches[1]) {
2406
				$url="http://".$url;
2407
			}
2408
			$connection = @fsockopen( $host, $port, $errno, $errstr, 120);
2409
			if( $connection ) {
2410
				if( strtoupper($method) == "GET" ) {
2411
					if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
2412
						$uri .= "?" . $data;
2413
					}
2414
					fputs( $connection, "GET $uri HTTP/1.0\r\n");
2415
				} else if( strtoupper($method) == "POST" ) {
2416
					fputs( $connection, "POST $uri HTTP/1.0\r\n");
2417
				} else {
2418
					fputs( $connection, "$method $uri HTTP/1.0\r\n");
2419
				}
2420
2421
				fputs( $connection, "Host: $host\r\n");
2422
				fputs( $connection, "Accept: */*\r\n");
2423
				fputs( $connection, "Accept: image/gif\r\n");
2424
				fputs( $connection, "Accept: image/x-xbitmap\r\n");
2425
				fputs( $connection, "Accept: image/jpeg\r\n");
2426
2427
				if( strtoupper($method) == "POST" ) {
2428
					$strlength = strlen( $data);
2429
					fputs( $connection, "Content-type: application/x-www-form-urlencoded\r\n" );
2430
					fputs( $connection, "Content-length: ".$strlength."\r\n\r\n");
2431
					fputs( $connection, $data."\r\n");
2432
				}
2433
2434
				fputs( $connection, "\r\n" , 2);
2435
2436
				$headerContents = '';
2437
				$headerStart = 0;
2438
				$headerEnd = 0;
2439
				$redirecting = false;
2440
2441
				while (!feof($connection)) {
2442
					$currentLine = fgets ($connection, 1024);
2443
					if ($headerEnd && $redirecting) {
2444
						break;
2445
					} else if ($headerEnd && !$redirecting) {
2446
						//this is the html from the page
2447
						$contents = $contents . $currentLine;
0 ignored issues
show
Bug introduced by
The variable $contents does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2448
					} else if ( preg_match("/^HTTP/", $currentLine) ) {
2449
						//came to the start of the header
2450
						$headerStart = 1;
2451
						$headerContents = $currentLine;
2452
					} else if ( $headerStart && preg_match('/^[\n\r\t ]*$/', $currentLine) ) {
2453
						//came to the end of the header
2454
						$headerEnd = 1;
2455
					} else {
2456
						//this is the header, if you want it...
2457
						if (preg_match("/^Location: (.+?)\n/is",$currentLine,$matches) ) {
2458
							$headerContents .= $currentLine;
2459
							//redirects are sometimes relative
2460
							$newurl = $matches[1];
2461
							if (!preg_match("/http:\/\//i", $newurl, $matches) ) {
2462
								$url .= $newurl;
2463
							} else {
2464
								$url = $newurl;
2465
							}
2466
							//extra \r's get picked up sometimes
2467
							//i think only with relative redirects
2468
							//this is a quick fix.
2469
							$url = preg_replace("/\r/s","",$url);
2470
							$redirecting = true;
2471
						} else {
2472
							$headerContents.=$currentLine;
2473
						}
2474
					}
2475
				}
2476
			} else {
2477
				$this->error="$errstr ($errno)";
2478
				$contents=false;
2479
				$url = "";
2480
			}
2481
			@fclose($connection);
2482
		}
2483
		if (($method!="GET") && ($method!="POST")) {
2484
			$contents=$headerContents."\n".$contents;
0 ignored issues
show
Bug introduced by
The variable $headerContents does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2485
		}
2486
		return $contents;
2487
	}
2488
2489
	public function make_filesize( $size="" ,$precision=0) {
2490
		$suffixes = array('B','KB','MB','GB','TB','PB','EB','ZB','YB');
2491
2492
		if( $size === "" ) {
2493
			$size = $this->size;
0 ignored issues
show
Bug introduced by
The property size does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
2494
		}
2495
		while ( (count($suffixes) > 1) && ($size > 1024) ){
2496
			$size = $size / 1024;
2497
			array_shift($suffixes);
2498
		}
2499
		$size = round($size,$precision);
2500
		if($precision==0){ // compatible with the old make_filesize
2501
			$size = intval($size);
2502
		}
2503
		$result = $size." ".array_shift($suffixes);
2504
		return $result;
2505
	}
2506
2507
	public function convertToUTF8($data, $charset = "CP1252") {
2508
2509
		include_once($this->store->get_config("code")."modules/mod_unicode.php");
2510
2511
		if (isset($data) && is_array($data)) {
2512
			foreach($data as $key => $val){
2513
				$data[$key] = $this->convertToUTF8($val, $charset);
2514
			}
2515
		} else
2516
		if (is_object($data)) {
2517
			foreach($data as $key => $val){
2518
				$data->$key = $this->convertToUTF8($val, $charset);
2519
			}
2520
		} else {
2521
			$data = unicode::convertToUTF8($charset, $data);
2522
		}
2523
		return $data;
2524
	}
2525
2526 21
	public function resetloopcheck() {
2527 21
		global $ARBeenHere;
2528 21
		$ARBeenHere=array();
2529 21
	}
2530
2531
/********************************************************************
2532
2533
  "safe" functions.
2534
2535
  The following functions are safe versions of existing functions
2536
  above.
2537
  - They don't change anything in the database.
2538
    This means that to save/delete something, a user will need to call
2539
    "system.save.data.phtml" or "system.delete.phtml" which check grants.
2540
  - All functions except _get and _exists don't take a path as
2541
    argument, they use the current objects path instead.
2542
2543
  These are meant to be used by 'pinp' versions of templates,
2544
  meaning user defined templates. 'pinp' rewrites call to functions
2545
  to the form '$this->_function'.
2546
2547
  All pinp files automatically first call CheckLogin('read').
2548
2549
********************************************************************/
2550
2551
	public function _call($function, $args="") {
2552
		// remove possible path information (greedy match)
2553
		if ( !( $function instanceof \Closure ) ) {
2554
			$function = basename( (string) $function );
2555
		}
2556
		return $this->call($function, $args);
0 ignored issues
show
Bug introduced by
It seems like $function can also be of type object<Closure>; however, ariadne_object::call() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
2557
	}
2558
2559
	public function _call_super($arCallArgs="") {
2560
	global $ARCurrent, $AR;
2561
		$context = $this->getContext();
2562
		if (!$arCallArgs) {
2563
			$arCallArgs = end($ARCurrent->arCallStack);
2564
		}
2565
		$arSuperContext  = (array)$context['arSuperContext'];
2566
		$arLibrary       = $context['arLibrary'];
2567
		$arLibraryPath   = $context['arLibraryPath'];
2568
		$arCallType      = $context['arCallTemplateType'];
2569
		$arSuperPath     = $context['arCallTemplatePath'];
2570
		$arLibrariesSeen = $context['arLibrariesSeen'];
2571
		$arCallFunction  = $arSuperFunction = $context['arCallFunction'];
2572
		if ($arLibrary) {
2573
			$arSuperFunction = str_replace($arLibrary.':', '', $arCallFunction);
2574
		}
2575
		if (strpos($arSuperFunction, "::") !== false) {
2576
			// template of a specific class defined via call("class::template");
2577
			list($arBaseType, $arSuperFunction)=explode("::", $arSuperFunction);
0 ignored issues
show
Unused Code introduced by
The assignment to $arBaseType is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
2578
		}
2579
		// remove current library path from the arLibrariesSeen array so that
2580
		// Ariadne will be able to re-enter the library and toggle the arSuperContext boolean there.
2581
		unset($arLibrariesSeen[$arLibraryPath]);
2582
		$arSuperContext[$arSuperPath.":".$arCallType.":".$arSuperFunction] = true;
2583
2584
		debug("call_super: searching for the template following (path: $arSuperPath; type: $arCallType; function: $arCallFunction) from $this->path");
2585
		// FIXME: Redirect code has to move to getPinpTemplate()
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "Redirect code has to move to getPinpTemplate"
Loading history...
2586
		$redirects	= $ARCurrent->shortcut_redirect;
2587
		if (isset($redirects) && is_array($redirects)) {
2588
			$redirpath = $this->path;
2589
			while (!$template['arTemplateId'] &&
0 ignored issues
show
Bug introduced by
The variable $template does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2590
				($redir = array_pop($redirects)) &&
2591
				$redir["keepurl"] &&
2592
				(substr($redirpath, 0, strlen($redir["dest"])) == $redir["dest"])
2593
			) {
2594
				debug("call_super: following shortcut redirect: $redirpath; to ".$redir["dest"]);
2595
				$template = $this->getPinpTemplate($arCallFunction, $redirpath, $redir["dest"], false, $arLibrariesSeen, $arSuperContext);
2596
				$redirpath = $redir['src'];
2597
			}
2598 View Code Duplication
			if (!$template["arTemplateId"]) {
2599
				$template = $this->getPinpTemplate($arCallFunction, $redirpath, '', false, $arLibrariesSeen, $arSuperContext);
2600
			}
2601
		}
2602 View Code Duplication
		if (!$template["arTemplateId"]) {
2603
			$template = $this->getPinpTemplate($arCallFunction, $this->path, '', false, $arLibrariesSeen, $arSuperContext);
2604
		}
2605
		if ($template["arCallTemplate"] && $template["arTemplateId"]) {
2606
			$exists = ar('template')->exists($template['arCallTemplatePath'],$template["arCallTemplate"]);
2607
			if ( $exists ) {
2608
				debug("call_super: found template ".$template["arCallTemplate"]." on object with id ".$template["arTemplateId"]);
2609
				$arLibrary = $template['arLibrary'];
2610
				debug("call_super: found template on ".$template["arTemplateId"]);
2611
				if (is_int($arLibrary)) {
2612
					// set the library name for unnamed libraries to 'current'
2613
					// so that calls using getvar('arLibrary') will keep on working
2614
					$arLibrary = "current";
2615
				}
2616 View Code Duplication
				if (!is_string($arCallArgs)) {
2617
					$arCallArgs['arCallFunction'] = $arCallFunction;
2618
					$arCallArgs['arLibrary'] = $arLibrary;
2619
					$arCallArgs['arLibraryPath'] = $template["arLibraryPath"];
2620
				}
2621
				$ARCurrent->arCallStack[]=$arCallArgs;
2622
				$this->pushContext(
2623
					array(
2624
						"scope"              => "pinp",
2625
						"arSuperContext"     => $arSuperContext,
2626
						"arLibrary"          => $arLibrary,
2627
						"arLibraryPath"      => $template['arLibraryPath'],
2628
						"arCallFunction"     => $arCallFunction,
2629
						"arCurrentObject"    => $this,
2630
						"arCallType"         => $template['arCallType'],
2631
						"arCallTemplateName" => $template['arCallTemplateName'],
2632
						"arCallTemplateNLS"  => $template['arCallTemplateNLS'],
2633
						"arCallTemplateType" => $template['arCallTemplateType'],
2634
						"arCallTemplatePath" => $template['arCallTemplatePath']
2635
					)
2636
				);
2637
				$continue = true;
2638
				$eventData = new object();
2639 View Code Duplication
				if ( !$AR->contextCallHandler ) { /* prevent onbeforecall from re-entering here */
2640
					$AR->contextCallHandler = true;
2641
					$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
Bug introduced by
The property arCallArgs does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
2642
					$eventData->arCallFunction = $arCallFunction;
0 ignored issues
show
Bug introduced by
The property arCallFunction does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
2643
					$eventData->arContext = $this->getContext();
0 ignored issues
show
Bug introduced by
The property arContext does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
2644
					$eventData = ar_events::fire('onbeforecall', $eventData);
2645
					$ARCurrent->arResult = $eventData->arResult;
2646
					$AR->contextCallHandler = false;
2647
					$continue = ($eventData!=false);
2648
				}
2649
				if ( $continue ) {
2650
					set_error_handler(array('pobject','pinpErrorHandler'),error_reporting());
2651
					$func = ar('template')->get($template['arCallTemplatePath'],$template['arCallTemplate']);
2652
					if(is_callable($func)){
2653
						$arResult = $func($this);
2654
					}
2655
					restore_error_handler();
2656
2657 View Code Duplication
					if ( !$AR->contextCallHandler ) { /* prevent oncall from re-entering here */
2658
						$AR->contextCallHandler = true;
2659
						$temp = $ARCurrent->arResult; /* event listeners will change ARCurrent->arResult */
2660
						$eventData->arResult = $arResult;
0 ignored issues
show
Bug introduced by
The variable $arResult does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2661
						ar_events::fire('oncall', $eventData );
2662
						$ARCurrent->arResult = $temp; /* restore correct result */
2663
						$AR->contextCallHandler = false;
2664
					}
2665
				}
2666
				array_pop($ARCurrent->arCallStack);
2667
				$this->popContext();
2668
			}
2669
		}
2670
		return $arResult;
2671
	}
2672
2673
	public function _get($path, $function="view.html", $args="") {
2674
		// remove possible path information (greedy match)
2675
		if ( !($function instanceof \Closure) ) {
2676
			$function = basename( (string) $function);
2677
		}
2678
		return $this->store->call($function, $args,
2679
			$this->store->get(
2680
				$this->make_path($path)));
2681
	}
2682
2683
	public function _call_object($object, $function, $args="") {
2684
		return $object->call($function, $args);
2685
	}
2686
2687 View Code Duplication
	public function _ls($function="list.html", $args="") {
2688
		// remove possible path information (greedy match)
2689
		if ( ! ( $function instanceof \Closure ) ) {
2690
			$function = basename( (string) $function );
2691
		}
2692
		return $this->store->call($function, $args,
2693
			$this->store->ls($this->path));
2694
	}
2695
2696 View Code Duplication
	public function _parents($function="list.html", $args="", $top="") {
2697
		// remove possible path information (greedy match)
2698
		if ( !($function instanceof \Closure ) ) {
2699
			$function = basename( (string) $function);
2700
		}
2701
		return $this->parents($this->path, $function, $args, $top);
2702
	}
2703
2704
	public function _find($criteria, $function="list.html", $args="", $limit=100, $offset=0) {
2705
		$this->error = '';
2706
		// remove possible path information (greedy match)
2707
		if ( !($function instanceof \Closure ) ) {
2708
			$function = basename( (string) $function);
2709
		}
2710
		$result = $this->store->call($function, $args,
2711
			$this->store->find($this->path, $criteria, $limit, $offset));
2712 View Code Duplication
		if ($this->store->error) {
2713
			$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error );
2714
		}
2715
		return $result;
2716
	}
2717
2718
	public function _exists($path) {
2719
		return $this->store->exists($this->make_path($path));
2720
	}
2721
2722
	public function _implements($implements) {
2723
		return $this->AR_implements($implements);
2724
	}
2725
2726 39
	public function getvar($var) {
0 ignored issues
show
Coding Style introduced by
getvar uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
getvar uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
2727 39
	global $ARCurrent, $ARConfig; // Warning: if you add other variables here, make sure you cannot get at it through $$var.
2728
2729 39 View Code Duplication
		if ($ARCurrent->arCallStack) {
2730 36
			$arCallArgs=end($ARCurrent->arCallStack);
2731 36
			if (isset($arCallArgs) && is_array($arCallArgs)) {
2732 27
				extract($arCallArgs);
2733 36
			} else if (is_string($arCallArgs)) {
2734
				Parse_Str($arCallArgs);
2735
			}
2736 36
		}
2737 39
		if (isset($$var) && ($var!='ARConfig')) {
2738 12
			$result=$$var;
2739 39
		} else if (isset($ARCurrent->$var)) {
2740
			$result=$ARCurrent->$var;
2741 39
		} else if (isset($ARConfig->pinpcache[$this->path][$var])) {
2742
			$result=$ARConfig->pinpcache[$this->path][$var];
2743 39 View Code Duplication
		} else if (isset($_POST[$var])) {
2744
			$result=$_POST[$var];
2745 39
		} else if (isset($_GET[$var])) {
2746
			$result=$_GET[$var];
2747 39
		} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$var])) {
2748
			$result=$arStoreVars[$var];
2749 39
		} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$var])) {
2750
			$result=$arStoreVars[$var];
2751
		}
2752 39
		return $result;
2753
	}
2754
2755
	public function _getvar($var) {
2756
		return $this->getvar($var);
2757
	}
2758
2759
	public function putvar($var, $value) {
2760
		global $ARCurrent;
2761
2762
		$ARCurrent->$var=$value;
2763
	}
2764
2765
	public function _putvar($var, $value) {
2766
		return $this->putvar($var, $value);
2767
	}
2768
2769
	public function _setnls($nls) {
2770
		$this->setnls($nls);
2771
	}
2772
2773
	// not exposed to pinp for obvious reasons
2774
	public function sgKey($grants) {
2775
		global $AR;
2776
		if( !$AR->sgSalt || !$this->CheckSilent("config") ) {
2777
			return false;
2778
		}
2779
		// serialize the grants so the order does not matter, mod_grant takes care of the sorting for us
2780
		$this->_load("mod_grant.php");
2781
		$mg = new mod_grant();
2782
		$grantsarray = array();
2783
		$mg->compile($grants, $grantsarray);
2784
		$grants = serialize($grantsarray);
2785
		return sha1( $AR->sgSalt . $grants . $this->path);
2786
	}
2787
2788
	public function sgBegin($grants, $key = '', $path = '.') {
2789
		global $AR;
2790
		$result = false;
2791
		$context = $this->getContext();
2792
		$path    = $this->make_path($path);
2793
2794
		// serialize the grants so the order does not matter, mod_grant takes care of the sorting for us
2795
		$this->_load("mod_grant.php");
2796
		$mg = new mod_grant();
2797
		$grantsarray = array();
2798
		$mg->compile($grants, $grantsarray);
2799
2800
		if ($context['scope'] == 'pinp') {
2801
			$checkgrants = serialize($grantsarray);
2802
			$check = ( $AR->sgSalt ? sha1( $AR->sgSalt . $checkgrants . $path) : false ); // not using suKey because that checks for config grant
2803
		} else {
2804
			$check = true;
2805
			$key = true;
2806
		}
2807
		if( $check !== false && $check === $key ) {
2808
			$AR->user->grants = array(); // unset all grants for the current user, this makes sure GetValidGrants gets called again for this path and all childs
2809
			$grantsarray = (array)$AR->sgGrants[$path];
2810
			$mg->compile($grants, $grantsarray);
2811
			$AR->sgGrants[$path] = $grantsarray;
2812
			$result = true;
2813
		}
2814
		return $result;
2815
	}
2816
2817
	public function sgEnd($path = '.') {
2818
		global $AR;
2819
		$AR->user->grants = array(); // unset all grants for the current user, this makes sure GetValidGrants gets called again for this path and all childs
2820
		$path = $this->make_path( $path );
2821
		unset($AR->sgGrants[$path]);
2822
		return true; // temp return true;
2823
	}
2824
2825
	public function sgCall($grants, $key, $function="view.html", $args="") {
2826
		$result = false;
2827
		if( $this->sgBegin($grants, $key ) ) {
2828
			$result = $this->call($function, $args);
2829
			$this->sgEnd();
2830
		}
2831
		return $result;
2832
	}
2833
2834
	public function _sgBegin($grants, $key, $path = '.') {
2835
		return $this->sgBegin($grants, $key, $path);
2836
	}
2837
2838
	public function _sgEnd($path = '.') {
2839
		return $this->sgEnd($path);
2840
	}
2841
2842
	public function _sgCall($grants, $key, $function="view.html", $args="") {
2843
		return $this->sgCall($grants, $key, $function, $args);
2844
	}
2845
2846
	public function _widget($arWidgetName, $arWidgetTemplate, $arWidgetArgs="", $arWidgetType="lib") {
2847
	global $AR, $ARConfig, $ARCurrent, $ARnls;
2848
2849
		$arWidgetName=preg_replace("/[^a-zA-Z0-9\/]/","",$arWidgetName);
2850
		$arWidgetTemplate=preg_replace("/[^a-zA-Z0-9\.]/","",$arWidgetTemplate);
2851
		$wgResult=null;
2852
		if ($arWidgetType=="www") {
2853
			$coderoot=$AR->dir->root;
2854
		} else {
2855
			$coderoot=$this->store->get_config("code");
2856
		}
2857
		if (file_exists($coderoot."widgets/$arWidgetName")) {
2858
			if (file_exists($coderoot."widgets/$arWidgetName/$arWidgetTemplate")) {
2859
				if (isset($arWidgetArgs) && is_array($arWidgetArgs)) {
2860
					extract($arWidgetArgs);
2861
				} else if (is_string($arWidgetArgs)) {
2862
					Parse_str($arWidgetArgs);
2863
				}
2864
				include($coderoot."widgets/$arWidgetName/$arWidgetTemplate");
2865
			} else {
2866
				error("Template $arWidgetTemplate for widget $arWidgetName not found.");
2867
			}
2868
		} else {
2869
			error(sprintf($ARnls["err:widgetnotfound"],$arWidgetName));
2870
		}
2871
		if ($wgResult) {
2872
			return $wgResult;
2873
		}
2874
	}
2875
2876
	public function _getdata($varname, $nls="none", $emptyResult=false) {
2877
		return $this->getdata($varname, $nls, $emptyResult);
2878
	}
2879
2880
	public function _showdata($varname, $nls="none", $emptyResult=false) {
2881
		$this->showdata($varname, $nls, $emptyResult);
2882
	}
2883
2884
	public function _gettext($index=false) {
2885
	global $ARnls;
2886
		if (!$index) {
2887
			return $ARnls;
2888
		} else {
2889
			return $ARnls[$index];
2890
		}
2891
	}
2892
2893
	public function _loadtext($nls, $section="") {
2894
	global $ARnls, $ARCurrent;
2895
		if( is_object($ARnls) ) {
2896
			$ARnls->load($section, $nls);
2897
			$ARnls->setLanguage($nls);
2898
			$this->ARnls = $ARnls;
0 ignored issues
show
Bug introduced by
The property ARnls does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
2899
		} else { // older loaders and other shizzle
2900
2901
			$nls = preg_replace('/[^a-z]*/i','',$nls);
2902
			$section = preg_replace('/[^a-z0-9\._:-]*/i','',$section);
2903
			if (!$section) {
2904
				include($this->store->get_config("code")."nls/".$nls);
2905
				$this->ARnls = array_merge((array)$this->ARnls, $ARnls);
2906
			} else {
2907
				$nlsfile = $this->store->get_config("code")."nls/".$section.".".$nls;
2908
				if(strpos($nlsfile, ':') === false && file_exists($nlsfile)) {
2909
					include($nlsfile);
2910
					$this->ARnls = array_merge((array)$this->ARnls, $ARnls);
2911
				} else {
2912
					// current result;
2913
					$arResult = $ARCurrent->arResult;
2914
					$this->pushContext(array());
2915
						$oldnls = $this->reqnls;
2916
						$this->reqnls = $nls;
2917
						$this->CheckConfig($section, array('nls' => $nls));
2918
						$this->reqnls = $oldnls;
2919
					$this->popContext();
2920
					// reset current result (CheckConfig may have changed it when it should not have).
2921
					$ARCurrent->arResult = $arResult;
2922
				}
2923
			}
2924
		}
2925
	}
2926
2927
	public function _startsession() {
2928
	global $ARCurrent;
2929
		ldStartSession(0);
2930
		return $ARCurrent->session->id;
2931
	}
2932
2933
	public function _putsessionvar($varname, $varvalue) {
2934
	global $ARCurrent;
2935
2936
		if ($ARCurrent->session) {
2937
			return $ARCurrent->session->put($varname, $varvalue);
2938
		} else {
2939
			return false;
2940
		}
2941
	}
2942
2943
	public function _getsessionvar($varname) {
2944
	global $ARCurrent;
2945
2946
		if ($ARCurrent->session) {
2947
			return $ARCurrent->session->get($varname);
2948
		} else {
2949
			return false;
2950
		}
2951
	}
2952
2953
	public function _setsessiontimeout($timeout = 0) {
2954
	global $ARCurrent;
2955
		if ($ARCurrent->session) {
2956
			return $ARCurrent->session->setTimeout($timeout);
2957
		} else {
2958
			return false;
2959
		}
2960
	}
2961
2962
	public function _killsession() {
2963
	global $ARCurrent;
2964
2965
		if ($ARCurrent->session) {
2966
			$ARCurrent->session->kill();
2967
			unset($ARCurrent->session);
2968
		}
2969
	}
2970
2971
	public function _sessionid() {
2972
	global $ARCurrent;
2973
		if ($ARCurrent->session) {
2974
			return $ARCurrent->session->id;
2975
		} else {
2976
			return 0;
2977
		}
2978
	}
2979
2980
	public function _resetloopcheck() {
2981
		return $this->resetloopcheck();
2982
	}
2983
2984
	public function _make_path($path="") {
2985
		return $this->make_path($path);
2986
	}
2987
2988
	public function _make_ariadne_url($path="") {
2989
		return $this->make_ariadne_url($path);
2990
	}
2991
2992
	public function _make_url($path="", $nls=false, $session=true, $https=null, $keephost=null) {
2993
		return $this->make_url($path, $nls, $session, $https, $keephost);
2994
	}
2995
2996
	public function _make_local_url($path="", $nls=false, $session=true, $https=null) {
2997
		return $this->make_local_url($path, $nls, $session, $https);
2998
	}
2999
3000
	public function _getcache($name, $nls='') {
3001
		return $this->getcache($name, $nls);
3002
	}
3003
3004
	public function _cached($name, $nls='') {
3005
		return $this->cached($name, $nls);
3006
	}
3007
3008
	public function _savecache($time="") {
3009
		return $this->savecache($time);
3010
	}
3011
3012
	public function _getdatacache($name) {
3013
		return $this->getdatacache($name);
3014
	}
3015
3016
	public function _savedatacache($name,$data,$time="")
3017
	{
3018
		return $this->savedatacache($name,$data,$time);
3019
	}
3020
3021 42
	public function currentsite($path="", $skipRedirects = false) {
3022 42
		global $ARCurrent, $ARConfig;
3023 42
		if (!$path) {
3024 36
			$path=$this->path;
3025 36
		}
3026 42
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3027 42
		if (!$skipRedirects && @count($ARCurrent->shortcut_redirect)) {
3028
			$redir = end($ARCurrent->shortcut_redirect);
3029
			if ($redir["keepurl"] && substr($path, 0, strlen($redir["dest"])) == $redir["dest"]) {
3030
				if (substr($config->site, 0, strlen($redir["dest"]))!=$redir["dest"]) {
3031
					// search currentsite from the reference
3032
					$config = ($ARConfig->cache[$redir['src']]) ? $ARConfig->cache[$redir['src']] : $this->loadConfig($redir['src']);
3033
				}
3034
			}
3035
		}
3036 42
		return $config->site;
3037
	}
3038
3039
	public function parentsite($site) {
3040
	global $ARConfig;
3041
		$path=$this->store->make_path($site, "..");
3042
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3043
		return $config->site;
3044
	}
3045
3046 3 View Code Duplication
	public function currentsection($path="") {
3047 3
	global $ARConfig;
3048 3
		if (!$path) {
3049 3
			$path=$this->path;
3050 3
		}
3051 3
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3052 3
		return $config->section;
3053
	}
3054
3055 View Code Duplication
	public function parentsection($path) {
3056
	global $ARConfig;
3057
		$path=$this->store->make_path($path, "..");
3058
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3059
		return $config->section;
3060
	}
3061
3062 18 View Code Duplication
	public function currentproject($path="") {
3063 18
	global $ARConfig;
3064 18
		if (!$path) {
3065
			$path=$this->path;
3066
		}
3067 18
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3068 18
		return $config->project;
3069
	}
3070
3071
	public function parentproject($path) {
3072
	global $ARConfig;
3073
		$path=$this->store->make_path($path, "..");
3074
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3075
		return $config->project;
3076
	}
3077
3078
	public function validateFormSecret() {
3079
		global $ARCurrent;
3080
		if (!$ARCurrent->session) {
3081
			return true;
3082
		}
3083
3084
		if ($ARCurrent->session && $ARCurrent->session->data && $ARCurrent->session->data->formSecret) {
3085
			$formSecret = $this->getvar("formSecret");
3086
			return ($formSecret === $ARCurrent->session->data->formSecret);
3087
		}
3088
		return false;
3089
	}
3090
3091
	public function _validateFormSecret() {
3092
		return $this->validateFormSecret();
3093
	}
3094
3095
	public function getValue($name, $nls=false) {
3096
	global $ARCurrent;
3097
		switch ($nls) {
3098
			case "none":
3099
				$result = $this->data->$name;
3100
			break;
3101
			case false:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
3102
				$nls = $ARCurrent->nls;
3103
				if (!isset($this->data->$nls) || !isset($this->data->$nls->$name)) {
3104
					$result = $this->data->$name;
3105
					break;
3106
				}
3107
			default:
3108
				$result = $this->data->$nls->$name;
3109
		}
3110
		return $result;
3111
	}
3112
3113
	public function setValue($name, $value, $nls=false) {
3114
3115
	global $AR, $ARConfig;
3116
		if ($value === null) {
3117
			if ($nls && $nls!="none") {
3118
				unset($this->data->$nls->$name);
3119
				if (!count(get_object_vars($this->data->$nls))) {
3120
					unset($this->data->$nls);
3121
					unset($this->data->nls->list[$nls]);
3122
					if (!count($this->data->nls->list)) {
3123
						unset($this->data->nls->list);
3124
						unset($this->data->nls);
3125
					} else {
3126
						if ($this->data->nls->default == $nls) {
3127
							if ($this->data->nls->list[$ARConfig->nls->default]) {
3128
								$this->data->nls->default = $ARConfig->nls->default;
3129
							} else {
3130
								list($this->data->nls->default) = each($this->data->nls->list);
3131
							}
3132
						}
3133
					}
3134
				}
3135
			} else {
3136
				unset($this->data->$name);
3137
			}
3138
		} else
3139
		if (!$nls) {
3140
			$this->data->$name = $value;
3141
		} else {
3142
			if (!$this->data->$nls) {
3143
				$this->data->$nls = new object;
3144
				if (!$this->data->nls) {
3145
					$this->data->nls = new object;
3146
					$this->data->nls->default = $nls;
0 ignored issues
show
Bug introduced by
The property default does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
3147
				}
3148
				$this->data->nls->list[$nls] = $AR->nls->list[$nls];
0 ignored issues
show
Bug introduced by
The property list does not seem to exist in object.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
3149
			}
3150
			$this->data->$nls->$name = $value;
3151
		}
3152
	}
3153
3154
	public function showValue($name, $nls=false) {
3155
		$result = $this->getValue($name, $nls);
3156
		echo $result;
3157
		return $result;
3158
	}
3159
3160
	public function _getValue($name, $nls=false) {
3161
		return $this->getValue($name, $nls);
3162
	}
3163
3164
	public function _setValue($name, $value, $nls=false) {
3165
		return $this->setValue($name, $value, $nls);
3166
	}
3167
3168
	public function _showValue($name, $nls=false) {
3169
		return $this->showValue($name, $nls);
3170
	}
3171
3172
	public function _currentsite($path="", $skipRedirects = false) {
3173
		return $this->currentsite( $path, $skipRedirects );
3174
	}
3175
3176
	public function _parentsite($site) {
3177
		return $this->parentsite($site);
3178
	}
3179
3180
	public function _currentsection() {
3181
		return $this->currentsection();
3182
	}
3183
3184
	public function _parentsection($section) {
3185
		return $this->parentsection($section);
3186
	}
3187
3188
	public function _currentproject() {
3189
		return $this->currentproject();
3190
	}
3191
3192
	public function _parentproject($path) {
3193
		return $this->parentproject($path);
3194
	}
3195
3196
	public function _checkAdmin($user) {
3197
		return $this->CheckAdmin($user);
3198
	}
3199
3200
	public function _checkgrant($grant, $modifier=ARTHISTYPE, $path=".") {
3201
		// as this is called within a pinp template,
3202
		// all the grants are already loaded, so
3203
		// checksilent will fullfill our needs
3204
		$this->pushContext(array("scope" => "php"));
3205
			$result = $this->CheckSilent($grant, $modifier, $path);
3206
		$this->popContext();
3207
		return $result;
3208
	}
3209
3210
	public function _checkpublic($grant, $modifier=ARTHISTYPE) {
3211
3212
		return $this->CheckPublic($grant, $modifier);
3213
	}
3214
3215
	public function _getcharset() {
3216
		return $this->getcharset();
3217
	}
3218
3219
	public function _count_find($query='') {
3220
		return $this->count_find($this->path, $query);
3221
	}
3222
3223
	public function _count_ls() {
3224
		return $this->count_ls($this->path);
3225
	}
3226
3227
	public function _HTTPRequest($method, $url, $postdata = "", $port=80) {
3228
		return $this->HTTPRequest($method, $url, $postdata, $port);
3229
	}
3230
3231
	public function _make_filesize( $size="" ,$precision=0) {
3232
		return $this->make_filesize( $size ,$precision);
3233
	}
3234
3235
	public function _convertToUTF8($data, $charset = "CP1252") {
3236
		return $this->convertToUTF8($data,$charset);
3237
	}
3238
3239
	public function _getuser() {
3240
	global $AR;
3241
		if ($AR->pinp_user && $AR->pinp_user->data->login == $AR->user->data->login) {
3242
			$user = $AR->pinp_user;
3243
		} else {
3244
			$this->pushContext(array("scope" => "php"));
3245
				if ( $AR->user instanceof ariadne_object ) {
3246
					$user = current($AR->user->get(".", "system.get.phtml"));
3247
				} else {
3248
					$user = $AR->user;
3249
				}
3250
				$AR->pinp_user = $user;
3251
			$this->popContext();
3252
		}
3253
		return $user;
3254
	}
3255
3256
	public function ARinclude($file) {
3257
		include($file);
3258
	}
3259
3260 3
	public function _load($class) {
3261
		// only allow access to modules in the modules directory.
3262 3
		$class = preg_replace('/[^a-z0-9\._]/i','',$class);
3263 3
		include_once($this->store->get_config("code")."modules/".$class);
3264 3
	}
3265
3266
	public function _import($class) {
3267
		// deprecated
3268
		return $this->_load($class);
3269
	}
3270
3271 27
	public function html_to_text($text) {
3272 27
		$trans = array_flip(get_html_translation_table(HTML_ENTITIES));
3273 27
		$cb  = function($matches) use ($trans) {
3274
			return strtr($matches[1],$trans);
3275 27
		};
3276
		//strip nonbreaking space, strip script and style blocks, strip html tags, convert html entites, strip extra white space
3277 27
		$search_clean = array("%&nbsp;%i", "%<(script|style)[^>]*>.*?<\/(script|style)[^>]*>%si", "%<[\/]*[^<>]*>%Usi", "%\s+%");
3278 27
		$replace_clean = array(" ", " ", " ", " ");
3279
3280 27
		$text = preg_replace_callback(
3281 27
			"%(\&[a-zA-Z0-9\#]+;)%s",
3282 27
			$cb,
3283
			$text
3284 27
		);
3285 27
		$text = preg_replace($search_clean, $replace_clean, $text);
3286 27
		return $text;
3287
	}
3288
3289
	public function _html_to_text($text) {
3290
		return $this->html_to_text($text);
3291
	}
3292
3293
	public function _newobject($filename, $type) {
3294
		$newpath=$this->make_path($filename);
3295
		$newparent=$this->store->make_path($newpath, "..");
3296
		$data=new object;
3297
		$object=$this->store->newobject($newpath, $newparent, $type, $data);
3298
		$object->arIsNewObject=true;
3299
		return $object;
3300
	}
3301
3302
	public function _save($properties="", $vtype="") {
3303
		if (isset($properties) && is_array($properties)) {
3304
			// isn't this double work, the save function doesn this again
3305
			foreach ($properties as $prop_name => $prop) {
3306
				foreach ($prop as $prop_index => $prop_record) {
3307
					$record = array();
3308 View Code Duplication
					foreach ($prop_record as $prop_field => $prop_value) {
3309
						switch (gettype($prop_value)) {
3310
							case "integer":
3311
							case "boolean":
3312
							case "double":
3313
								$value = $prop_value;
3314
							break;
3315
							default:
3316
								$value = $prop_value;
3317
								if (substr($prop_value, 0, 1) === "'" && substr($prop_value, -1) === "'"
3318
										&& "'".AddSlashes(StripSlashes(substr($prop_value, 1, -1)))."'" == $prop_value) {
3319
									$value = stripSlashes(substr($prop_value,1,-1));
3320
									// todo add deprecated warning
3321
								}
3322
						}
3323
						$record[$prop_field] = $value;
3324
					}
3325
					$properties[$prop_name][$prop_index] = $record;
3326
				}
3327
			}
3328
		}
3329
3330
		if ($this->arIsNewObject && $this->CheckSilent('add', $this->type)) {
3331
			unset($this->data->config);
3332
			$result = $this->save($properties, $vtype);
0 ignored issues
show
Bug introduced by
It seems like $properties can also be of type array or null; however, ariadne_object::save() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
3333
		} else if (!$this->arIsNewObject && $this->CheckSilent('edit', $this->type)) {
3334
			$this->data->config = current($this->get('.', 'system.get.data.config.phtml'));
3335
			$result = $this->save($properties, $vtype);
0 ignored issues
show
Bug introduced by
It seems like $properties can also be of type array or null; however, ariadne_object::save() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
3336
		}
3337
		return $result;
0 ignored issues
show
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
3338
	}
3339
3340
	public function _is_supported($feature) {
3341
		return $this->store->is_supported($feature);
3342
	}
3343
3344
	/*
3345
		since the preg_replace() function is able to execute normal php code
3346
		we have to intercept all preg_replace() calls and parse the
3347
		php code with the pinp parser.
3348
	*/
3349
3350
3351
	/*	this is a private function used by the _preg_replace wrapper */
3352
	// FIXME: remove this function when the minimal php version for ariadne is raised to php 7.0
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "remove this function when the minimal php version for ariadne is raised to php 7.0"
Loading history...
3353
	protected function preg_replace_compile($pattern, $replacement) {
3354
	global $AR;
3355
		include_once($this->store->get_config("code")."modules/mod_pinp.phtml");
3356
		preg_match("/^\s*(.)/", $pattern, $regs);
3357
		$delim = $regs[1];
3358
		if (@eregi("\\${delim}[^$delim]*\\${delim}.*e.*".'$', $pattern)) {
3359
			$pinp = new pinp($AR->PINP_Functions, 'local->', '$AR_this->_');
3360
			return substr($pinp->compile("<pinp>$replacement</pinp>"), 5, -2);
3361
		} else {
3362
			return $replacement;
3363
		}
3364
	}
3365
3366
	public function _preg_replace($pattern, $replacement, $text, $limit = -1) {
3367
		if (version_compare(PHP_VERSION, '7.0.0', '<')) {
3368
			if (isset($pattern) && is_array($pattern)) {
3369
				$newrepl = array();
3370
				reset($replacement);
3371
				foreach ($pattern as $i_pattern) {
3372
					list(, $i_replacement) = each($replacement);
3373
					$newrepl[] = $this->preg_replace_compile($i_pattern, $i_replacement);
3374
				}
3375
			} else {
3376
				$newrepl = $this->preg_replace_compile($pattern, $replacement);
3377
			}
3378
		} else {
3379
			// php7 is safe, no more eval
3380
			$newrepl = $replacement;
3381
		}
3382
		return preg_replace($pattern, $newrepl, $text, $limit);
3383
	}
3384
3385
	/* ob_start accepts a callback but we don't want that
3386
	 * this wrapper removes the arguments from the ob_start call
3387
	 */
3388
	public function _ob_start() {
3389
		return ob_start();
3390
	}
3391
3392
	public function _loadConfig($path='') {
3393
		return clone $this->loadConfig($path);
3394
	}
3395
3396
	public function _loadUserConfig($path='') {
3397
		return $this->loadUserConfig($path);
3398
	}
3399
3400
	public function _loadLibrary($name, $path) {
3401 3
		return $this->loadLibrary($name, $path);
3402
	}
3403
3404
	public function _resetConfig($path='') {
3405
		return $this->resetConfig($path);
3406
	}
3407
3408
	public function _getLibraries($path = '') {
3409
		return $this->getLibraries($path);
3410
	}
3411
3412
3413
	public function _getSetting($setting) {
3414
	global $AR;
3415
3416
		switch ($setting) {
3417
			case 'www':
3418
			case 'dir:www':
3419
				return $AR->dir->www;
3420
			case 'images':
3421
			case 'dir:images':
3422
				return $AR->dir->images;
3423
			case 'ARSessionKeyCheck':
3424
				$result = null;
3425
				if (function_exists('ldGenerateSessionKeyCheck')) {
3426
					$result = ldGenerateSessionKeyCheck();
3427
				}
3428
				return $result;
3429
			break;
3430
			case 'nls:list':
3431
				return $AR->nls->list;
3432
			break;
3433
			case 'nls:default':
3434
				return $AR->nls->default;
3435
			break;
3436
			case 'svn':
3437
				return $AR->SVN->enabled;
3438
			break;
3439
		}
3440
	}
3441
3442
	public function __call($name,$arguments) {
3443
		if ( $name[0] == '_' ) {
3444
			$fname = substr($name, 1);
3445
			if ( isset($this->{$fname}) && $this->{$fname} instanceof \Closure ) {
3446
				\Closure::bind( $this->{$fname}, $this );
3447
				return call_user_func_array( $this->{$fname}, $arguments);
3448
			}
3449
		}
3450
		switch($name) {
3451
			case "implements":
3452
				return $this->AR_implements($arguments[0]);
3453
			break;
3454
			default:
3455
				trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $name), E_USER_ERROR);
3456
				return false;
3457
			break;
3458
		}
3459
	}
3460
3461
	static public function pinpErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) {
0 ignored issues
show
Unused Code introduced by
The parameter $errfile 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...
Unused Code introduced by
The parameter $errcontext 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...
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
3462 4
		global $nocache;
3463 4
		if (($errno & error_reporting()) == 0) {
3464 4
			return true;
3465
		}
3466
3467
		$nocache = true;
3468
		$context = pobject::getContext();
3469
		if ($context["arLibraryPath"]) { //  != null) {
3470
			$msg = "Error on line $errline in ".$context['arCallTemplateType'].'::'.$context['arCallFunction'] ." in library ".$context["arLibraryPath"] ."\n".$errstr."\n";
3471
		} else {
3472
			$msg = "Error on line $errline in ".$context['arCallTemplateType'].'::'.$context['arCallFunction'] ." on object ".$context['arCurrentObject']->path."\n".$errstr."\n";
3473
		}
3474
		$display = ini_get('display_errors');
3475
3476
		if($display) {
3477
			echo $msg;
3478
		}
3479
		error_log($msg);
3480
3481
		return false;
3482
	}
3483
3484
} // end of ariadne_object class definition
3485