Completed
Push — master ( 33b38e...1faa07 )
by
unknown
465:40 queued 403:16
created

ariadne_object::sanitizeUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
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 3
	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
		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
	public function sanitizeUrl($url) {
825
		// remove unexpected chars from the url;
826
		return preg_replace("/[^\/{}:.A-Za-z0-9_-]/", "", $url);
827
	}
828
	public function sanitizePath($path) {
829
		// remove unexpected chars from the path; same as url for now;
830
		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 36
		if ($this->store->mod_lock) {
841 36
			$result=$this->store->mod_lock->getlocks($AR->user->data->login);
842 36
		} else {
843 36
			$result="";
844 36
		}
845
		return $result;
846
	}
847 36
848 View Code Duplication
	public function lock($mode="O", $time=0) {
849
	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 36
			$result=true; // no lock module, so lock is 'set'
854 36
		}
855
		return $result;
856
	}
857 36
858 View Code Duplication
	public function unlock() {
859
	global $AR;
860
		if ($this->store->mod_lock) {
861
			$result=$this->store->mod_lock->unlock($AR->user->data->login,$this->path);
862
		} else {
863
			$result=true;
864
		}
865
		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 3
	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
	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 3
	  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 3
	          in a 'nearer' parent (itself). grants are 'read edit'.
947 3
	  case 3: user takes precedence again. grants are 'none'.
948 3
	  case 4: All group grants are merged with the usergrants.
949 3
	          Therefore the grants are 'none read edit'.
950 3
	********************************************************************/
951 3
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
			}
958
			if (!$AR->user->grants[$path]) {
959
				$grants=array();
960
				$userpath=$AR->user->FindGrants($path, $grants);
961
				// if not already done, find all groups of which the user is a member
962
				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 3
					// Use the group memberships of external databases (e.g. LDAP)
966 3
					$criteria="members.login='".AddSlashes($AR->user->data->login)."'";
967 3
					foreach (array_keys($AR->user->externalgroupmemberships) as $group) {
968 3
						$criteria.=" or login.value='".AddSlashes($group)."'";
969 3
					}
970 3
				}
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
							if (is_object($group)) {
976
								$AR->user->groups[$group->path] = $group;
977 3
							}
978 3
						}
979 3
					}
980
					if (isset($AR->user->data->config->groups) && is_array($AR->user->data->config->groups)) {
981
						foreach ($AR->user->data->config->groups as $groupPath => $groupId) {
982
							if (!$AR->user->groups[$groupPath]) {
983
								$AR->user->groups[$groupPath] = current($this->get($groupPath, "system.get.phtml"));
984 3
							}
985 3
						}
986
					}
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
				}
993 3
				if ($AR->user->groups) {
994 3
					/* check for owner grants (set by system.get.config.phtml) */
995 3
					if (isset($AR->user->ownergrants) && is_array($AR->user->ownergrants)) {
996 3
						if (!$AR->user->groups["owner"]) {
997 3
							$AR->user->groups["owner"] = @current($this->get("/system/groups/owner/", "system.get.phtml"));
998 3
						}
999
						$AR->user->groups["owner"]->data->config->usergrants = $AR->user->ownergrants;
1000
					}
1001 View Code Duplication
					foreach($AR->user->groups as $group){
1002
						$groupgrants=array();
1003
						if (is_object($group)) {
1004
							$group->FindGrants($path, $groupgrants, $userpath);
1005
							if (isset($grants) && is_array($grants)) {
1006
								foreach($groupgrants as $gkey => $gval ){
1007
									if (isset($grants[$gkey]) && is_array($grants[$gkey]) && is_array($gval)) {
1008 3
										$grants[$gkey]=array_merge($gval, $grants[$gkey]);
1009 3
									} else
1010
									if ($gval && !is_array($gval)) {
1011
										$grants[$gkey] = $gval;
1012 3
									} else
1013 3
									if ($gval && !$grants[$gkey]) {
1014 3
										$grants[$gkey] = $gval;
1015 3
									}
1016
								}
1017
							} else {
1018
								$grants = $groupgrants;
1019
							}
1020
						}
1021
					}
1022
				}
1023
				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 3
									}
1040 3
								}
1041 3
							} else {
1042
								$grants = $sggrants;
1043 3
							}
1044 3
						}
1045 3
					}
1046
				}
1047
				$AR->user->grants[$path]=$grants;
1048
			}
1049 105
			$grants=$AR->user->grants[$path];
1050 105
1051 105
		}
1052 54
		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 54
		return $grants;
1054 105
	}
1055 105
1056
1057
	public function pushContext($context) {
1058
	global $AR;
1059
		if(!empty($AR->context)) {
1060
			$context = array_merge(end($AR->context), $context);
1061
		}
1062 105
		array_push($AR->context, $context);
1063 105
	}
1064 105
1065
	public function setContext($context, $level=0) {
1066
	global $AR;
1067 105
		$AR->context[count($AR->context)-(1+$level)]=$context;
1068 105
	}
1069 105
1070
	public function popContext() {
1071
	global $AR;
1072 54
		return array_pop($AR->context);
1073 54
	}
1074 51
1075
	public static function getContext($level=0) {
1076 3
	global $AR;
1077
		return $AR->context[count($AR->context)-(1+$level)];
1078
	}
1079 3
1080
	public function CheckAdmin($user) {
1081
	if ($user->data->login == "admin") {
1082 45
			return true;
1083 45
		}
1084 45
		if ($user->data->groups['/system/groups/admin/']) {
1085
			return true;
1086
		}
1087
		return false;
1088 45
	}
1089 45
1090 45
	public function CheckLogin($grant, $modifier=ARTHISTYPE) {
1091
	global $AR,$ARnls,$ARConfig,$ARCurrent,$ARConfigChecked;
1092
		if (!$this->store->is_supported("grants")) {
1093 45
			debug("pobject: store doesn't support grants");
1094
			return true;
1095
		}
1096
		if ($modifier==ARTHISTYPE) {
1097
			$modifier=$this->type;
1098
		}
1099
1100
		/* load config cache */
1101
		if (!isset($ARConfig->cache[$this->path])) {
1102 45
			// since this is usually run before CheckConfig, make sure
1103
			// it doesn't set cache time
1104 45
			$realConfigChecked = $ARConfigChecked;
1105
			$ARConfigChecked = true;
1106
			$this->loadConfig();
1107 45
			$ARConfigChecked = $realConfigChecked;
1108
		}
1109
1110 45
		$isadmin = $this->CheckAdmin($AR->user);
1111
1112 45
		if (!$isadmin && !$AR->user->grants[$this->path]) {
1113 45
			$grants = $this->GetValidGrants();
1114
		} else {
1115 45
			$grants = $AR->user->grants[$this->path];
1116 45
		}
1117 45
1118
		if ($AR->user->data->login!="public") {
1119
			// Don't remove this or MSIE users won't get uptodate pages...
1120
			ldSetClientCache(false);
1121
		}
1122
1123 45
		if ( 	( !$grants[$grant]
1124
					|| ( $modifier && is_array($grants[$grant]) && !$grants[$grant][$modifier] )
1125
				) && !$isadmin ) {
1126 45
			// do login
1127 45
			$arLoginMessage = $ARnls["accessdenied"];
1128
			ldAccessDenied($this->path, $arLoginMessage);
1129
			$result=false;
1130
		} else {
1131 3
			$result=($grants || $isadmin);
1132 3
		}
1133
1134 3
		$ARCurrent->arLoginSilent=1;
1135 3
		return $result;
1136 3
	}
1137 3
1138 3
1139 3
	public function CheckPublic($grant, $modifier=ARTHISTYPE) {
1140 3
	global $AR;
1141 3
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
		}
1148
		if ($AR->public) {
1149 33
			$AR->private=$AR->user;
1150 33
			$AR->user=$AR->public;
1151 33
			$result=$this->CheckSilent($grant, $modifier);
1152 33
			$AR->user=$AR->private;
1153 33
		}
1154 33
		return $result;
1155
	}
1156
1157 33
	public function CheckSilent($grant, $modifier=ARTHISTYPE, $path=".") {
1158 6
	global $AR, $ARConfig;
1159 6
		$path = $this->make_path($path);
1160 33
		if ($modifier==ARTHISTYPE) {
1161 30
			$modifier=$this->type;
1162 33
		}
1163
1164
		/* load config cache */
1165 3
		if (!$ARConfig->cache[$path]) {
1166 3
			$this->loadConfig($path);
1167
		}
1168 33
		if ($this->CheckAdmin($AR->user)) {
1169
			$result=1;
1170
		} else if ($grants=$AR->user->grants[$path]) {
1171 33
			$result=$grants[$grant];
1172
		} else {
1173
			$grants=$this->GetValidGrants();
1174
			$result=$grants[$grant];
1175
		}
1176
		if ($modifier && is_array($result)) {
1177
			$result=$result[$modifier];
1178
		}
1179
		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 27
			$keys = preg_grep('/^'.$path.'/',array_keys($ARConfig->cache));
1222 27
			foreach ($keys as $cachepath) {
1223 27
				unset($ARConfig->cache[$cachepath]);
1224 27
				unset($ARConfig->pinpcache[$cachepath]);
1225 27
			}
1226 27
		}
1227 27
	}
1228 3
1229 3 View Code Duplication
	public function clearChildConfigs($path='') {
1230 3
	global $ARConfig;
1231 27
		$path = $this->make_path($path);
1232 27
		if ($ARConfig->cache[$path]) {
1233 27
			$path = preg_quote($path,'/');
1234
			$keys = preg_grep('/^'.$path.'./',array_keys($ARConfig->cache));
1235 27
			foreach($keys as $cachepath) {
1236 27
				unset($ARConfig->cache[$cachepath]);
1237 27
				unset($ARConfig->pinpcache[$cachepath]);
1238
				unset($ARConfig->libraries[$cachepath]);
1239
			}
1240
		}
1241 27
	}
1242 3
1243 3
	protected function getConfig() {
1244 3
	global $ARConfig, $ARCurrent, $ARConfigChecked;
1245 3
		$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $this));
1246 3
		// $context=$this->getContext(0);
1247
		// debug("getConfig(".$this->path.") context: ".$context['scope'] );
1248 27
		// debug(print_r($ARConfig->nls, true));
1249
		if( !$ARConfig->cache[$this->parent] && $this->parent!=".." ) {
1250 27
			$parent = current($this->get($this->parent, "system.get.phtml"));
1251
			if ($parent) {
1252 27
				$parent->getConfig();
1253 27
			}
1254
		}
1255 27
1256
		$this->getConfigData();
1257
1258 27
		$ARConfig->pinpcache[$this->path] = $ARConfig->pinpcache[$this->parent];
1259 27
		// backwards compatibility when calling templates from config.ini
1260
		$prevArConfig = $ARCurrent->arConfig;
1261
		$ARCurrent->arConfig = $ARConfig->pinpcache[$this->path];
1262 27
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 27
		/* calling config.ini directly for each system.get.config.phtml call */
1266 27
		$loginSilent = $ARCurrent->arLoginSilent;
1267
		$ARCurrent->arLoginSilent = true;
1268
		// debug("getConfig:checkconfig start");
1269 3
1270 3
		$initialNLS = $ARCurrent->nls;
1271
		$initialConfigChecked = $ARConfigChecked;
1272
1273 3
		$ARConfig->cache[$this->path]->inConfigIni = true;
1274 3
		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
			$arConfig = $ARCurrent->arResult;
1278
			if (!isset($arConfig)) {
1279
				$arConfig = $ARCurrent->arConfig;
1280
			}
1281
			unset($ARCurrent->arResult);
1282
			if (isset($arConfig['library']) && is_array($arConfig['library'])) {
1283 3
				if (!$ARConfig->libraries[$this->path]) {
1284 3
					$ARConfig->libraries[$this->path] = array();
1285 27
				}
1286 27
				foreach ($arConfig['library'] as $libName => $libPath) {
1287 27
					$this->loadLibrary($libName, $libPath);
1288 27
				}
1289
				unset($arConfig['library']);
1290 27
			}
1291 27
			$ARConfig->pinpcache[$this->path] = (array) $arConfig;
1292
		}
1293
		$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
		$ARConfigChecked = $initialConfigChecked;
1296
		$ARCurrent->nls = $initialNLS;
1297
1298 27
		$arConfig = &$ARConfig->pinpcache[$this->path];
1299 View Code Duplication
		if (!is_array($arConfig['authentication']['userdirs'])) {
1300
			$arConfig['authentication']['userdirs'] = array('/system/users/');
1301 27
		} else {
1302
			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 27
			$arConfig['authentication']['groupdirs'] = array('/system/groups/');
1308 27
		} else {
1309 27
			if (reset($arConfig['authentication']['groupdirs']) != '/system/groups/') {
1310
				array_unshift($arConfig['authentication']['groupdirs'], '/system/groups/');
1311 27
			}
1312 27
		}
1313 27
1314 27
		$ARCurrent->arLoginSilent = $loginSilent;
1315
		$ARCurrent->arConfig = $prevArConfig;
1316 27
		$this->popContext();
1317 27
	}
1318 27
1319 27
	protected function getConfigData() {
1320
	global $ARConfig, $AR;
1321
		$context = $this->getContext(0);
1322 27
		if (!$ARConfig->cache[$this->path] && $context["scope"] != "pinp") {
1323
			// first inherit parent configuration data
1324
			$configcache= clone $ARConfig->cache[$this->parent];
1325
			$configcache->localTemplates = [];
1326
			$configcache->pinpTemplates = [];
1327
			$configcache->id = $this->id;
1328
1329
			// cache default templates
1330
			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 27
					foreach($configcache->localTemplates as $type => $templates ) {
1337 3
						if( isset($templates["config.ini"]) ) {
1338 3
							$configcache->hasDefaultConfigIni = true;
1339
							$configcache->hasConfigIni = true;
1340 27
							break;
1341 27
						}
1342 27
					}
1343 3
				}
1344 3
			} else if (isset($this->data->config->pinp) && count($this->data->config->pinp)) {
1345 3
				$configcache->pinpTemplates    = $this->data->config->pinp;
1346 3
			}
1347
1348 3
			if( !$configcache->hasDefaultConfigIni ) {
1349 3
				$configcache->hasConfigIni = false;
1350 27
				if(isset($this->data->config->pinp) && is_array($this->data->config->pinp) ) {
1351
					foreach( $this->data->config->pinp as $type => $templates ) {
1352 27
						if( isset($templates["config.ini"]) ) {
1353 27
							$configcache->hasConfigIni = true;
1354 27
							break;
1355 27
						}
1356
					}
1357 27
				}
1358
			}
1359
1360
			$localcachesettings = $this->data->config->cacheSettings;
1361 27
			if (!is_array($localcachesettings) ){
1362 3
				$localcachesettings = array();
1363 3
			}
1364
1365 27
			if (!is_array($configcache->cacheSettings) ) {
1366 3
				$configcache->cacheSettings = array();
1367 3
			}
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
				$localcachesettings["serverCache"] = $this->data->config->cacheconfig;
1375
			}
1376 27
1377
			if ($localcachesettings['serverCache'] != 0 ) {
1378 27
				$localcachesettings['serverCacheDefault'] = $localcachesettings['serverCache'];
1379
			}
1380
1381 27
			$configcache->cacheSettings = $localcachesettings + $configcache->cacheSettings;
1382 3
1383 3
			// store the current object type
1384
			$configcache->type = $this->type;
1385 27
1386
			if ($this->data->config->typetree && ($this->data->config->typetree!="inherit")) {
1387
				$configcache->typetree=$this->data->config->typetree;
1388 27
			}
1389
			if (isset($this->data->config->nlsconfig->list)) {
1390
				$configcache->nls = clone $this->data->config->nlsconfig;
1391
			}
1392
1393
			if ($this->data->config->grants["pgroup"]["owner"]) {
1394
				$configcache->ownergrants = $this->data->config->grants["pgroup"]["owner"];
1395
			}
1396
			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 27
					if (isset($ownergrants) && is_array($ownergrants)) {
1400
						foreach( $ownergrants as $grant => $val ) {
1401
							$AR->user->ownergrants[$this->path][$grant] = $val;
1402 27
						}
1403
					}
1404 27
				}
1405 27
			}
1406
1407 48
			if (isset($this->data->config->customconfig) && is_array($this->data->config->customconfig)) {
1408 48
				$configcache->custom=array_merge(is_array($configcache->custom)?$configcache->custom:array(), $this->data->config->customconfig);
1409 48
			}
1410
			$ARConfig->cache[$this->path]=$configcache;
1411 48
1412 27
		}
1413 27
	}
1414 27
1415 27
	public function loadConfig($path='') {
1416 27
	global $ARConfig, $ARConfigChecked, $ARCurrent;
1417 27
		$path=$this->make_path($path);
1418
		// debug("loadConfig($path)");
1419 27
		if (!isset($ARConfig->cache[$path]) ) {
1420 27
			$allnls = $ARCurrent->allnls;
1421
			$ARCurrent->allnls = true;
1422 3
			$configChecked = $ARConfigChecked;
1423 3
			if (($this->path == $path && !$this->arIsNewObject) || $this->exists($path)) {
1424
				$this->pushContext(array("scope" => "php"));
1425 27
				if( $this->path == $path ) {
1426 27
					// debug("loadConfig: currentpath $path ");
1427 27
					$this->getConfig();
1428
				} else {
1429
					//debug("loadConfig: get path $path ");
1430
					$cur_obj = current($this->get($path, "system.get.phtml"));
1431
					$cur_obj->getConfig();
1432
				}
1433
				$this->popContext();
1434
				$result=$ARConfig->cache[$path];
1435
			} 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 27
					}
1447 27
					$this->popContext();
1448 27
				}
1449
				$result=$ARConfig->cache[$parent];
1450 39
				$ARConfig->cache[ $path ] = $result;
1451
				$ARConfig->pinpcache[ $path ] = $ARConfig->pinpcache[ $parent ];
1452 48
			}
1453
			// restore old ARConfigChecked state
1454
			$ARConfigChecked = $configChecked;
1455
			$ARCurrent->allnls = $allnls;
1456
		} else {
1457
			// debug("loadConfig: exists $path ");
1458 9
			$result=$ARConfig->cache[$path];
1459 9
		}
1460 9
		return $result;
1461 9
	}
1462
1463 9
1464
	// TODO: look for a way to merge loadConfig and loadUserConfig into one function
1465
1466 9
	public function loadUserConfig($path='') {
1467
	global $ARConfig;
1468
		$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 3
		if (!$ARConfig->pinpcache[$path]) {
1475 3
			$config = $ARConfig->pinpcache[$parent];
1476 3
		} else {
1477 3
			$config = $ARConfig->pinpcache[$path];
1478 3
		}
1479 3
		return (array)$config;
1480
	}
1481
1482 3
	public function loadLibrary($name, $path) {
1483 3
	global $ARConfig;
1484 3
		$path=$this->make_path($path);
1485
		debug("pobject::loadLibrary($name, $path);");
1486
		if ($name===ARUNNAMED) {
1487
			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 3
				return ar::error('You cannot load an unnamed library from a child object.', 1109);
1489
			} else {
1490
				if (!isset($ARConfig->libraries[$this->path])) {
1491
					$ARConfig->libraries[$this->path] = [ $path ];
1492
				} else {
1493
					array_unshift($ARConfig->libraries[$this->path],$path);
1494
				}
1495 3
			}
1496
		} 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
	}
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 45
		}
1523
		return array_merge( $defaults, $this->getvar('arCallArgs') );
1524 45
	}
1525 45
1526 45
	public function _mergeLibraryConfig( $defaultLibraryName, $defaults ) {
1527 45
		return $this->mergeLibraryConfig( $defaultLibraryName, $defaults );
1528 45
	}
1529 9
1530 9
	protected function findTemplateOnPath($path, $arCallFunction, $arType, $reqnls, &$arSuperContext){
1531
1532 9
		while ($arType!='ariadne_object' ) {
1533 9
			list($arMatchType,$arMatchSubType) = explode('.',$arType,2);
1534 9
			$local = ($path === $this->path);
1535
			$templates = ar('template')->ls($path);
1536 9
			if(isset($templates[$arCallFunction])) {
1537 9
				$template = null;
1538
				if (!isset($arSuperContext[$path.":".$arType.":".$arCallFunction])) {
1539
					$template = array_reduce($templates[$arCallFunction] , function($carry, $item) use ($arMatchType,$arMatchSubType, $reqnls, $local) {
1540
						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
							if ($item['type'] === $arMatchType && ($item['subtype'] == $arMatchSubType) ) {
1542 9
								if (isset($carry) && $carry['language'] !== 'any') {
1543 9
									return $carry;
1544 9
								} else if ($item['language'] === 'any' || $item['language'] === $reqnls ) {
1545 9
									return $item;
1546
								}
1547
							}
1548 36
						}
1549
						return $carry;
1550 36
					}, null);
1551 18
				}
1552 18
				if ( isset($template) && !isset($arSuperContext[$path.":".$arType.":".$arCallFunction])) {
1553 36
					return $template;
1554
				}
1555
			}
1556
			if (!isset($AR->superClass[$arType])) {
1557 36
				// no template found, no default.phtml found, try superclass.
1558
				if ($subcpos = strpos($arType, '.')) {
1559 36
					$arSuper = substr($arType, 0, $subcpos);
1560
				} else {
1561 36
					if (!class_exists($arType, false )) {
1562 36
						// 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 36
					}
1567
					$arSuper=get_parent_class($arTemp);
1568 36
				}
1569
				$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
			} else {
1571 45
				$arSuper=$AR->superClass[$arType];
1572 45
			}
1573 45
			$arType=$arSuper;
1574 45
		}
1575 45
1576 45
		return null;
1577 45
	}
1578 45
1579 45
	public function getPinpTemplate($arCallFunction='view.html', $path=".", $top="", $inLibrary = false, $librariesSeen = null, $arSuperContext=array()) {
1580
	global $ARCurrent, $ARConfig, $AR, $ARConfigChecked;
1581
		debug("getPinpTemplate: function: $arCallFunction; path: $path; top: $top; inLib: $inLibrary","class");
1582
		$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
		}
1586
		$path = $this->make_path($path);
1587
		if (!is_array($arSuperContext)) {
1588 45
			$arSuperContext = array();
1589
		}
1590 45
1591
		$matches = [];
1592 45
		preg_match('/^
1593
		    ( (?<libname> [^:]+) :  )?
1594
		    ( (?<calltype>[^:]+) :: )?
1595 45
		      (?<template>[^:]+)
1596
		    $/x', $arCallFunction, $matches);
1597
1598 45
		$arCallFunction = $matches['template'];
1599
1600
		if($matches['calltype'] != '') {
1601
			$arCallType = $matches['calltype'];
1602
		} else {
1603
			$arCallType = $this->type;
1604
		}
1605
1606
		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 45
				$inLibrary = true;
1632 45
				$path = $arLibraryPath;
1633 45
			} else {
1634 45
				debug("getPinpTemplate: Failed to find library $arLibrary");
1635 45
			}
1636 45
			$path = $this->make_path($path);
1637 45
		}
1638
1639 45
		$checkpath           = $path;
1640
		$lastcheckedpath     = "";
1641 45
		$arCallClassTemplate = $ARCurrent->arCallClassTemplate;
1642
		$reqnls              = $this->reqnls;
1643
		$template            = null;
1644 45
		while (!$arCallClassTemplate && !isset($template) && $checkpath!=$lastcheckedpath) {
1645
			$lastcheckedpath = $checkpath;
1646
1647
			$template = $this->findTemplateOnPath( $checkpath, $arCallFunction, $arCallType, $reqnls, $arSuperContext);
1648
1649
			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
			} 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 36
1657
				if ($prefix === 'psection') {
1658 36
					 // debug("BREAKING; $arTemplateId");
1659 36
					// break search operation when we have found a
1660 36
					// psection object
1661 36
					break;
1662
				}
1663 36
			} else {
1664 36
				if (isset($ARConfig->libraries[$checkpath])) {
1665 36
					// need to check for unnamed libraries
1666
					$libraries = array_filter($ARConfig->libraries[$checkpath],'is_int',ARRAY_FILTER_USE_KEY);
1667 36
					foreach( $libraries as $key => $libpath ) {
1668 36
						$arLibraryPath = $libpath;
1669
						$arLibrary     = $key;
1670
1671
						$libprevpath = null;
1672 36
						while($libpath != $libprevpath ) {
1673 36
							$libprevpath = $libpath;
1674 36
1675
							$template = $this->findTemplateOnPath( $libpath, $arCallFunction, $arCallType, $reqnls, $arSuperContext);
1676
							if (isset($template)) {
1677 36
								break 2;
1678 36
							}
1679 36
1680 36
							$prefix = substr($ARConfig->cache[$libpath]->type,0,8);
1681 36
							if ($prefix === 'psection' || $top == $libpath) {
1682
								break;
1683
							}
1684
1685 45
							$libpath = $this->store->make_path($libpath, "..");
1686 36
						}
1687
					}
1688
					debug("getPinpTemplate: found ".$arCallFunction." on ".$template['path']);
1689 45
				}
1690 45
1691
			}
1692 45
1693 45
			if ($checkpath == $top) {
1694 45
				break;
1695 9
			}
1696
1697 9
			debug("getPinpTemplate: DONE checking for ".$arCallFunction." on ".$checkpath);
1698 9
			$checkpath=$this->store->make_path($checkpath, "..");
1699
			
1700
		}
1701 9
		$result = null;
1702 9
		if(isset($template)) {
1703 9
			$result = [];
1704 9
			//debug("getPinpTemplate END; ".$template['id'] .' '.$template['path']);
1705 9
			$type = $template['type'];
1706 9
			if(isset($template['subtype'])) {
1707 9
				$type .= '.' . $template['subtype'];
1708 9
			}
1709 9
			$result["arTemplateId"]       = $template['id'];
1710 9
			$result["arCallTemplate"]     = $template['filename'];
1711 9
			$result["arCallType"]         = $arCallType;
1712 9
			$result["arCallTemplateName"] = $arCallFunction;
1713 45
			$result["arCallTemplateNLS"]  = $template['language'];
1714
			$result["arCallTemplateType"] = $type;
1715
			$result["arCallTemplatePath"] = $template['path'];
1716 48
			$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
			$result["arLibraryPath"]      = $arLibraryPath;
1718
			$result["arLibrariesSeen"]    = $librariesSeen;
1719
			$result["arPrivateTemplate"]  = $template['private'];
1720
		}
1721 48
		return $result;
1722 48
	}
1723
1724
	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 48
	// browser.
1728
	// All these templates must exist under a fixed directory, $AR->dir->templates
1729
	global $nocache, $AR, $ARConfig, $ARCurrent, $ARBeenHere, $ARnls, $ARConfigChecked;
1730
		$MAX_LOOP_COUNT=10;
1731
1732 48
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 48
			error(sprintf($ARnls["err:maxloopexceed"],$this->path,$arCallFunction,$arCallArgs));
1737 48
			$this->store->close();
1738 48
			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 48
		} else {
1740
			$ARBeenHere[$this->path][$arCallFunction]+=1;
1741
1742
			// this will prevent the parents from setting the cache time
1743
			$initialConfigChecked = $ARConfigChecked;
1744
			$ARConfigChecked = true;
1745 48
			$config = ($ARConfig->cache[$this->path]) ? $ARConfig->cache[$this->path] : $this->loadConfig();
1746 48
			$ARConfigChecked = $initialConfigChecked;
1747
			$ARConfig->nls=$config->nls;
1748
1749
1750
			// if a default language is entered in a parent and no language is
1751 48
			// explicitly selected in the url, use that default.
1752 48
			// 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 48
						$ARCurrent->nls = $this->reqnls;
1758 48
					}
1759
				} else if ( $config->nls->default ) {
1760
					$this->reqnls = $config->nls->default;
1761 48
					$this->nls = $this->reqnls;
1762 48
					if ( !$ARConfigChecked ) {
1763
						$ARCurrent->nls = $this->nls;
1764 48
					}
1765
				}
1766
			} else {
1767
				$this->reqnls = $ARCurrent->nls;
1768
			}
1769 48
			$nls = &$this->nls;
1770
			$reqnls = &$this->reqnls;
1771
1772
			if (!$ARConfigChecked && is_object($ARnls)) {
1773
				$ARnls->setLanguage($ARCurrent->nls);
1774
			}
1775
1776
1777
			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 48
					$validlangs = array_intersect(array_keys($ARCurrent->acceptlang), array_keys($this->data->nls->list));
1787 3
				}
1788 3
				if ($validlangs) {
1789 48
					$reqnls=array_shift($validlangs);
1790
					$ARCurrent->nls = $reqnls;
1791
				}
1792
			}
1793 48
*/
1794 View Code Duplication
			if (isset($this->data->custom) && is_array($this->data->custom) && $this->data->custom['none']) {
1795
				$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
			}
1797 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
			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 48
				$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
			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 48
				}
1839 48
				$ARCurrent->nolangcheck=1;
1840
			}
1841 45
1842 45
			/*
1843
				Set ARConfigChecked to true to indicate that we have been here
1844
				earlier.
1845
			*/
1846
			$ARConfigChecked = true;
1847
			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
				$redirects	= $ARCurrent->shortcut_redirect;
1850
				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 45
						$template = $this->getPinpTemplate($arCallFunction, $redirpath, $redir["dest"]);
1858 45
						$redirpath = $redir['src'];
1859 45
					}
1860
1861 45
					if (!$template["arTemplateId"] && $redirpath) {
1862 9
						$template = $this->getPinpTemplate($arCallFunction, $redirpath);
1863
					}
1864
				}
1865 9
				if (!$template["arTemplateId"]) {
1866 6
					$template = $this->getPinpTemplate($arCallFunction);
1867 6
				}
1868 9
1869 9
				if ($template["arCallTemplate"] && $template["arTemplateId"]) {
1870 9
					if (!isset($ARCurrent->cacheTemplateChain)) {
1871 9
						$ARCurrent->cacheTemplateChain = array();
1872 9
					}
1873 9
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]])) {
1874 9
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]] = array();
1875
					}
1876
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']])) {
1877 9
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']] = array();
1878
					}
1879
					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
					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
					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 9
						// choice dialogue instead.
1896 9
						$arLibrary = $template['arLibrary'];
1897 9
						if (is_int($arLibrary)) {
1898 9
							// set the library name for unnamed libraries to 'current'
1899 9
							// so that calls using getvar('arLibrary') will keep on working
1900
							$arLibrary = "current";
1901 9
						}
1902
1903 View Code Duplication
						if (!is_string($arCallArgs)) {
1904 9
							$arCallArgs['arCallFunction'] = $arCallFunction;
1905
							$arCallArgs['arLibrary']      = $arLibrary;
1906 9
							$arCallArgs['arLibraryPath']  = $template["arLibraryPath"];
1907 9
						}
1908 9
1909 9
						$ARCurrent->arCallStack[]=$arCallArgs;
1910 9
						// start running a pinp template
1911 9
1912 9
						$this->pushContext(
1913 9
							array(
1914 9
								"scope"              => "pinp",
1915 9
								"arLibrary"          => $arLibrary,
1916 9
								"arLibraryPath"      => $template['arLibraryPath'],
1917 9
								"arCallFunction"     => $arCallFunction,
1918 9
								"arCurrentObject"    => $this,
1919
								"arCallType"         => $template['arCallType'],
1920
								"arCallTemplateName" => $template['arCallTemplateName'],
1921 9
								"arCallTemplateNLS"  => $template['arCallTemplateNLS'],
1922
								"arCallTemplateType" => $template['arCallTemplateType'],
1923
								"arCallTemplatePath" => $template['arCallTemplatePath'],
1924
								"arLibrariesSeen"    => $template['arLibrariesSeen']
1925
							)
1926
						);
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
						if (count($ARCurrent->arCallStack) == 2 && true === $template['arPrivateTemplate']) {
1930 9
							// Do not allow private templates to be called first in the stack.
1931
							// echo "Bad request";
1932 9
1933 9
							// 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 9
							// Return true zorgt er voor dat de default 404 handler het oppikt alsof het template niet bestaat.
1935 9
							$this->popContext();
1936
							array_pop($ARCurrent->arCallStack);
1937
							return true;
1938
						} else if ($ARCurrent->forcenls || isset($this->data->nls->list[$reqnls])) {
1939
							// the requested language is available.
1940
							$this->nlsdata=$this->data->$reqnls;
1941
							$this->nls=$reqnls;
1942
							$continue=true;
1943
						} 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 9
							$this->nls = isset($this->data->nls->default) ? $this->data->nls->default : $this->reqnls;
1951 9
							$this->nlsdata = $this->data->$nls ?: $this->data->{$this->nls} ?: $this->data;
1952 9
							$continue=true;
1953 9
						} else {
1954 9
							debug("CheckConfig: requested language not available, allnls not set","object");
1955 9
							// -> skip this object (do not run template but do return false)
1956 9
							$continue=false;
1957 9
						}
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
								$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
								$eventData = ar_events::fire('onbeforecall', $eventData);
1966 9
								$ARCurrent->arResult = $eventData->arResult;
1967 6
								$AR->contextCallHandler = false;
1968 6
								$continue = ($eventData!=false);
1969
							}
1970 9
							if ( $continue ) {
1971
								if (!isset($ARCurrent->cacheCallChainSettings)) {
1972
									$ARCurrent->cacheCallChainSettings = array();
1973 9
								}
1974 9
								if ($ARConfig->cache[$this->path]->inConfigIni == false) {
1975 9
									$ARCurrent->cacheCallChainSettings[$this->id] = $config->cacheSettings;
1976 9
								}
1977 9
1978 9
								if ($ARCurrent->ARShowTemplateBorders) {
1979 9
									echo "<!-- arTemplateStart\nData: ".$this->type." ".$this->path." \nTemplate: ".$template["arCallTemplatePath"]." ".$template["arCallTemplate"]." \nLibrary:".$template["arLibrary"]." -->";
1980 9
								}
1981 9
								set_error_handler(array('pobject','pinpErrorHandler'),error_reporting());
1982 9
								$func = ar('template')->get($template['arCallTemplatePath'],$template['arCallTemplate']);
1983
								if(is_callable($func)){
1984
									$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 9
									echo "<!-- arTemplateEnd -->";
1992 9
								}
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
									ar_events::fire('oncall', $eventData );
1998 9
									$ARCurrent->arResult = $temp; /* restore correct result */
1999
									$AR->contextCallHandler = false;
2000
								}
2001
							}
2002
						}
2003
						array_pop($ARCurrent->arCallStack);
2004
						$this->popContext();
2005 9
2006
						if ( !$initialConfigChecked && $arCallFunction != 'config.ini' ) {
2007 3
							// this template was the first template called in this request.
2008
							$eventData = new object();
2009 3
							$eventData->arCallArgs = $arCallArgs;
2010 36
							$eventData->arCallFunction = $arCallFunction;
2011
							ar_events::fire( 'onview', $eventData ); // no default action to prevent, so ignore return value.
2012
						}
2013 39
						return false;
2014
					} else {
2015 42
						debug("pobject: CheckConfig: no such file: ".$template["arTemplateId"].$template["arCallTemplate"]."","all");
2016
					}
2017
				} else {
2018 18
					debug("CheckConfig: no arCallTemplate ($arCallFunction from '$this->path')","object");
2019 18
				}
2020 18
2021 18
			}
2022
		}
2023
		return true;
2024 18
	}
2025 18
2026 18
	public function ClearCache($path="", $private=true, $recurse=false) {
2027 18
	global $AR;
2028
		$norealnode = false;
2029
		if (!$path) {
2030
			$path=$this->path;
2031
		} else {
2032 18
			$realpath = current($this->get($path, "system.get.path.phtml"));
2033
			if($realpath != false) {
2034
				$path = $realpath;
2035
			} else {
2036
				$norealnode = true;
2037
			}
2038
		}
2039
2040
		if($norealnode !== true) {
2041
			/*
2042
				we don't want to recurse to the currentsite, because the path
2043 18
				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
			if ($private ) {
2052 18
				// now remove any private cache entries.
2053 18
				// 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
				$pcache=$this->store->get_filestore("privatecache");
2061
				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 18
							$pcache->purge($value["id"]);
2074 18
							ar_events::fire( 'onclearprivatecache', $eventData, $value['type'], $value['path'] );
2075 18
						}
2076 18
2077 18
						$offset += $limit;
2078 18
						$ids = $this->store->info($this->store->find($path, "", $limit, $offset));
2079
					}
2080 18
				} else {
2081
					$eventData = new object();
2082
					$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 18
				}
2088 18
			}
2089 18
2090 18
			// now clear all parents untill the current site
2091
			$site=$this->currentsite($path);
2092
			$project=$this->currentproject($path);
2093
			if ($path!=$site && $path != $project && $path!='/') {
2094
				$parent=$this->make_path($path.'../');
2095 18
				$this->ClearCache($parent, $private, false);
2096 18
			}
2097 18
		}
2098 18
		$recursed = array();
2099 18
2100 18
		// filesystem cache image filenames are always lower case, so
2101
		// use special path for that. Remember 'real' path name for
2102 18
		// recursion and stuff
2103 18
		$fs_path=strtolower($path);
2104
		$nlslist=$AR->nls->list;
2105
		$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
		global $cache_config,$store_config;
2111 18
		$cachestore=new cache($cache_config);
2112 18
2113
2114
		$filestore = $this->store->get_config("files");
2115
		foreach($cache_types as $type){
2116
			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
				if(!is_dir($filestore."cache/$type/$nls")){
2120
					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 18
					// remove empty directory entry's, hide errors about directory entry's with content
2140 18
					@rmdir($fpath);
2141 18
					@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
			}
2148
		}
2149
	}
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 39 View Code Duplication
			if (!$pcache->touch($this->id, $name, $time)) {
2298
				$this->error = ar::error('Could not touch '.$name, 1113);
2299
				return false;
2300 39
			}
2301
		}
2302 39
		return true;
2303 39
	}
2304 36
2305 36
	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 36
	// function to retrieve variables from $this->data, with the correct
2307 36
	// language version.
2308 36
	global $ARCurrent;
2309
2310
		$result = false;
2311 36
		if ($nls!="none") {
2312 36 View Code Duplication
			if ($ARCurrent->arCallStack) {
2313 21
				$arCallArgs=end($ARCurrent->arCallStack);
2314 36
				if (isset($arCallArgs) && is_array($arCallArgs)) {
2315
					extract($arCallArgs);
2316 36
				} else if (is_string($arCallArgs)) {
2317
					Parse_Str($arCallArgs);
2318 36
				}
2319
			}
2320 36
			if (isset(${$nls}[$varname])) {
2321
				$result=${$nls}[$varname];
2322 36
			} else if (isset($ARCurrent->$nls) && isset($ARCurrent->$nls->$varname)) {
2323
				$result=$ARCurrent->$nls->$varname;
2324
			} else if (($values=$_POST[$nls]) && isset($values[$varname])) {
2325 36
				$result=$values[$varname];
2326 36
			} else if (($values=$_GET[$nls]) && isset($values[$varname])) {
2327 18
				$result=$values[$varname];
2328 18
			} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$nls][$varname])) {
2329 36
				$result=$arStoreVars[$nls][$varname];
2330 36
			} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$nls][$varname])) {
2331 39
				$result=$arStoreVars[$nls][$varname];
2332 39
			}
2333 39
			if ($result===false) {
2334 36
				if (isset($this->data->${nls}) && isset($this->data->${nls}->${varname})) {
2335 39
					$result=$this->data->${nls}->${varname};
2336
				}
2337
			}
2338 39
		} else { // language independant variable.
2339 39 View Code Duplication
			if ($ARCurrent->arCallStack) {
2340 18
				$arCallArgs=end($ARCurrent->arCallStack);
2341 39
				if (isset($arCallArgs) && is_array($arCallArgs)) {
2342
					extract($arCallArgs);
2343 39
				} else if (is_string($arCallArgs)) {
2344
					Parse_Str($arCallArgs);
2345 39
				}
2346
			}
2347 39
			if (isset($$varname)) {
2348
				$result=$$varname;
2349 39
			} else if (isset($ARCurrent->$varname)) {
2350
				$result=$ARCurrent->$varname;
2351 View Code Duplication
			} else if (isset($_POST[$varname])) {
2352 39
				$result=$_POST[$varname];
2353 39
			} else if (isset($_GET[$varname])) {
2354 18
				$result=$_GET[$varname];
2355 18
			} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$varname])) {
2356 39
				$result=$arStoreVars[$varname];
2357
			} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$varname])) {
2358 39
				$result=$arStoreVars[$varname];
2359 39
			}
2360 39
			if ($result===false) {
2361 39
				if (isset($this->data->$varname)) {
2362
					$result=$this->data->$varname;
2363
				}
2364
			}
2365
		}
2366
		if ( $result === false ) {
2367
			$result = $emptyResult;
2368
		}
2369
		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 21
				$data->$key = $this->convertToUTF8($val, $charset);
2519 21
			}
2520 21
		} else {
2521 21
			$data = unicode::convertToUTF8($charset, $data);
2522
		}
2523
		return $data;
2524
	}
2525
2526
	public function resetloopcheck() {
2527
		global $ARBeenHere;
2528
		$ARBeenHere=array();
2529
	}
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 39
	public function _exists($path) {
2719 39
		return $this->store->exists($this->make_path($path));
2720
	}
2721 39
2722 36
	public function _implements($implements) {
2723 36
		return $this->AR_implements($implements);
2724 27
	}
2725 36
2726
	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
	global $ARCurrent, $ARConfig; // Warning: if you add other variables here, make sure you cannot get at it through $$var.
2728 36
2729 39 View Code Duplication
		if ($ARCurrent->arCallStack) {
2730 12
			$arCallArgs=end($ARCurrent->arCallStack);
2731 39
			if (isset($arCallArgs) && is_array($arCallArgs)) {
2732
				extract($arCallArgs);
2733 39
			} else if (is_string($arCallArgs)) {
2734
				Parse_Str($arCallArgs);
2735 39
			}
2736
		}
2737 39
		if (isset($$var) && ($var!='ARConfig')) {
2738
			$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 View Code Duplication
		} else if (isset($_POST[$var])) {
2744 39
			$result=$_POST[$var];
2745
		} else if (isset($_GET[$var])) {
2746
			$result=$_GET[$var];
2747
		} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$var])) {
2748
			$result=$arStoreVars[$var];
2749
		} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$var])) {
2750
			$result=$arStoreVars[$var];
2751
		}
2752
		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 42
		return $this->getdatacache($name);
3014 42
	}
3015 42
3016 36
	public function _savedatacache($name,$data,$time="")
3017 36
	{
3018 42
		return $this->savedatacache($name,$data,$time);
3019 42
	}
3020
3021
	public function currentsite($path="", $skipRedirects = false) {
3022
		global $ARCurrent, $ARConfig;
3023
		if (!$path) {
3024
			$path=$this->path;
3025
		}
3026
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3027
		if (!$skipRedirects && @count($ARCurrent->shortcut_redirect)) {
3028 42
			$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
		return $config->site;
3037
	}
3038 3
3039 3
	public function parentsite($site) {
3040 3
	global $ARConfig;
3041 3
		$path=$this->store->make_path($site, "..");
3042 3
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3043 3
		return $config->site;
3044 3
	}
3045
3046 View Code Duplication
	public function currentsection($path="") {
3047
	global $ARConfig;
3048
		if (!$path) {
3049
			$path=$this->path;
3050
		}
3051
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3052
		return $config->section;
3053
	}
3054 18
3055 18 View Code Duplication
	public function parentsection($path) {
3056 18
	global $ARConfig;
3057
		$path=$this->store->make_path($path, "..");
3058
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3059 18
		return $config->section;
3060 18
	}
3061
3062 View Code Duplication
	public function currentproject($path="") {
3063
	global $ARConfig;
3064
		if (!$path) {
3065
			$path=$this->path;
3066
		}
3067
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3068
		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 3
		}
3253
		return $user;
3254 3
	}
3255 3
3256 3
	public function ARinclude($file) {
3257
		include($file);
3258
	}
3259
3260
	public function _load($class) {
3261
		// only allow access to modules in the modules directory.
3262
		$class = preg_replace('/[^a-z0-9\._]/i','',$class);
3263 27
		include_once($this->store->get_config("code")."modules/".$class);
3264 27
	}
3265 27
3266
	public function _import($class) {
3267 27
		// deprecated
3268
		return $this->_load($class);
3269 27
	}
3270 27
3271
	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 27
			return strtr($matches[1],$trans);
3275
		};
3276 27
		//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
		$text = preg_replace_callback(
3281
			"%(\&[a-zA-Z0-9\#]+;)%s",
3282
			$cb,
3283
			$text
3284
		);
3285
		$text = preg_replace($search_clean, $replace_clean, $text);
3286
		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 3
		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
		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 4
			default:
3455 4
				trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $name), E_USER_ERROR);
3456 4
				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
		global $nocache;
3463
		if (($errno & error_reporting()) == 0) {
3464
			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