Issues (1751)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

lib/objects/ariadne_object.php (76 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
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 baseObject { // ariadne_object class definition
39
40
	public $store;
41
	public $path;
42
	public $data;
43
44 35
	public function init($store, $path, $data) {
45 35
		$this->store=$store;
46 35
		$this->path=$path;
47 35
		$this->data=$data;
48 35
		if ( !isset($this->data->config) ) {
49 7
			$this->data->config = new baseObject();
50 7
		}
51 35
	}
52
53 35
	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 35
	global $AR, $ARConfig, $ARCurrent, $ARBeenHere, $ARnls;
72
73 35
		if ( $arCallFunction instanceof \Closure ) {
74 2
			$arCallFunctionName = 'Closure';
75 1
		} else {
76 35
			$arCallFunctionName = (string) $arCallFunction;
77
		}
78 35
		debug("pobject: ".$this->path.": call($arCallFunctionName, ".debug_serialize($arCallArgs).")","object","all","IN");
79
80
		// default to view.html
81 35
		if (!$arCallFunction) {
82 5
			$arCallFunction="view.html";
83
		}
84
		// clear previous results
85 35
		unset($ARCurrent->arResult);
86
87
		// callstack is needed for getvar()
88 35
		$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 35
		$this->pushContext( array(
91 35
			"arSuperContext" => array(),
92 35
			"arCurrentObject" => $this,
93 35
			"scope" => "php",
94
			"arCallFunction" => $arCallFunction
95 35
		) );
96
97
		// convert the deprecated urlencoded arguments to an array
98 35
		if (isset($arCallArgs) && is_string($arCallArgs)) {
99 15
			$ARCurrent->arTemp=$arCallArgs;
100 15
			$arCallArgs=array();
101 15
			parse_str($ARCurrent->arTemp, $arCallArgs);
102 15
		}
103
		// import the arguments in the current scope, but don't overwrite existing
104
		// variables.
105 35
		if (isset($arCallArgs) && is_array($arCallArgs)) {
106 15
			extract($arCallArgs,EXTR_SKIP);
107 15
		}
108
		// now find the initial nls selection (CheckConfig is needed for per
109
		// tree selected defaults)
110 35
		if ($ARCurrent->nls) {
111
			$this->reqnls=$ARCurrent->nls;
0 ignored issues
show
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 35
		} else if (isset($ARConfig->cache[$this->path]) && $ARConfig->cache[$this->path]->nls->default) {
113 25
			$this->reqnls = $ARConfig->cache[$this->path]->nls->default;
114 25
		} else {
115 18
			$this->reqnls=$AR->nls->default;
116
		}
117 35
		if (isset($this->data->nls->list[$this->reqnls]) || !isset($this->data->nls)) {
118
			// the requested language is available
119 35
			$this->nls=$this->reqnls;
0 ignored issues
show
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 35
			$nls=&$this->nls;
121 35
		} else {
122
			// the requested language is not available, use default of the
123
			// current object instead.
124
			$this->nls=$this->data->nls->default;
125
			$nls=&$this->nls;
126
		}
127 35
		if ($nls && isset($this->data->$nls)) {
128
			// now set the data and nlsdata pointers
129 33
			$this->nlsdata=$this->data->$nls;
0 ignored issues
show
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 33
			$nlsdata=&$this->nlsdata;
131 33
			$data=&$this->data;
132 33
		} else {
133
			// this object doesn't support nls data
134 9
			$this->nlsdata=$this->data;
135 9
			$nlsdata=&$this->data;
136 9
			$data=&$this->data;
137
		}
138 35
		if (isset($this->data->custom['none'])) {
139 1
			$customdata=$this->data->custom['none'];
140 1
		}
141 35
		if (isset($this->data->custom[$nls])) {
142
			$customnlsdata=$this->data->custom[$nls];
143
		}
144
145 35
		$arCallFunctionOrig = $arCallFunction;
146 35
		if (strpos($arCallFunctionName,"::")!==false) {
147
			// template of a specific class defined via call("class::template");
148 6
			list($arType, $arCallFunction)=explode("::",$arCallFunctionName);
149 6
			$temp = explode(":", $arType );
150 6
			if( count($temp) > 1 ) {
151
				$libname = $temp[0];
152
				$arType = $temp[1];
153
				$arCallFunction = $libname.":".$arCallFunction;
154
			}
155 6
		} else {
156 35
			$arType=$this->type;
0 ignored issues
show
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 35
		if ( $arCallFunction instanceof \Closure ) {
160 1
			$context = $this->getContext(ARCALLINGCONTEXT);
161 1
			if ( $context["scope"] != "pinp" ) {
162
				$arResult = $arCallFunction($this );
163
			} else {
164 1
				if ( $this->CheckSilent('read') ) {
165 1
					$arResult = $arCallFunction($this);
166 1
				}
167
			}
168 1
		} else {
169 35
			if ($arCallFunction[0] === "#") {
170 5
				$ARCurrent->arCallClassTemplate = true;
171
				$arCallFunction = substr($arCallFunction, 1);
172
			} else {
173 35
				$ARCurrent->arCallClassTemplate = false;
174
			}
175
176 35
			if( $arCallFunction == "system.get.phtml" && ( $context = $this->getContext(ARCALLINGCONTEXT) ) && $context["scope"] != "pinp" ) {
177 8
				$arResult = $this;
178 8
			} else {
179 35
				$libtemplate = strpos($arCallFunction,":");
180 35
				$codedir = $this->store->get_config("code");
181
182
				// if it is a subtype object, disk templates do not exists,
183 35
				$subcpos = strpos($arType, '.');
184 35
				if ($subcpos !== false ) {
185
					// subtype, skip looking for templates
186 6
					$arSuper = substr($arType, 0, $subcpos);
187 6
					if(!isset($AR->superClass[$arType])){
188 1
						$AR->superClass[$arType]=$arSuper;
189 1
					}
190 6
					$arType=$arSuper;
191 6
				}
192
193 35
				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 35
					$arCallTemplate=$codedir."templates/".$arType."/".$arCallFunction;
198 35
					if ($libtemplate === false && file_exists($arCallTemplate)) {
199
						//debug('found '.$arCallTemplate, 'all');
200
						// template found
201 33
						$arCallFunction = $arCallFunctionOrig;
202 33
						include($arCallTemplate);
203 33
						break;
204 34
					} 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 2
						include($this->store->get_config("code")."templates/".$arType."/default.phtml");
208 2
						break;
209 6
					} else {
210 34
						if (!($arSuper=$AR->superClass[$arType])) {
211
							// no template found, no default.phtml found, try superclass.
212
213 2
							if (!class_exists($arType, false)) {
214
								// the given class was not yet loaded, so do that now
215
								$this->store->newobject('','',$arType,new baseObject);
216
							}
217 2
							$arSuper=get_parent_class($arType);
218
219 8
							$AR->superClass[$arType]=$arSuper;
220 2
						}
221 34
						$arType=$arSuper;
222 1
					}
223 34
				}
224
			}
225
		}
226 35
		array_pop($ARCurrent->arCallStack);
227 35
		$this->popContext();
228 35
		debug("pobject: call: end","all","all","OUT");
229 35
		if (isset($ARCurrent->arResult)) {
230
			// pinp templates can return results via putvar("arResult",$result);
231 5
			$arResult=$ARCurrent->arResult;
232 5
			unset($ARCurrent->arResult);
233 5
		}
234 35
		if (isset($arResult)) {
235
			// only do a return if we really have something to return
236 35
			return $arResult;
237
		}
238 6
	}
239
240 1
	public function ls($path="", $function="list.html", $args="") {
241
		$path=$this->store->make_path($this->path, $path);
242 1
		return $this->store->call($function, $args, $this->store->ls($path));
243 1
	}
244
245 14
	public function get($path, $function="view.html", $args="") {
246 14
		$path=$this->store->make_path($this->path, $path);
247 14
		return $this->store->call($function, $args, $this->store->get($path));
248 1
	}
249
250 1
	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+) */
252
		/* but this fix should be done in the store, not here */
253 1
		if (!$top) {
254 1
			$top = $this->currentsection();
255 1
		} else {
256 1
			$top = $this->store->make_path($this->path, $top);
257
		}
258
259 1
		$path=$this->store->make_path($this->path, $path);
260
261 1
		if ($path != $this->path ) {
262 1
			$target = current($this->get($path,"system.get.phtml"));
263 1
		} else {
264 1
			$target = $this;
265
		}
266
267 1
		$parents = array();
268 1
		if (strpos($target->path, $top) === 0) {
269 1
			$parents[] = $target;
270 1
			while ($target && $target->path != $top) {
271 1
				$target = current($target->get($target->parent, "system.get.phtml"));
272 1
				$parents[] = $target;
273 1
			}
274 1
		}
275 1
		$parents = array_reverse($parents);
276 1
		$result = array();
277 1
		foreach ($parents as $parent) {
278 1
			if ( $parent ) { // might not have read access to this object
279 1
				$result[] = $parent->call($function, $args);
280 1
			}
281 1
		}
282
283 1
		return $result;
284
	}
285
286 1
	public function find($path, $criteria, $function="list.html", $args="", $limit=100, $offset=0) {
287 1
		$path = $this->store->make_path($this->path, $path);
288 1
		$objects = $this->store->find($path, $criteria, $limit, $offset);
289 1
		if (!$this->store->error) {
290 1
			$result = $this->store->call($function, $args, $objects);
291 1 View Code Duplication
		} else {
292
			$this->error = ar::error( ''.$this->store->error, 1110, $this->store->error );
0 ignored issues
show
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 1
		}
295 1
		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 6
	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 1
							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 1
						}
337
						$record[$wf_prop_field] = $value;
338
					}
339
					$properties[$wf_prop_name][] = $record;
340
				}
341
			}
342
		}
343
344 6
		return $properties;
345
	}
346
347
	/*
348
		saves custom data
349
		returns properties for custom data
350
	*/
351 13
	private function saveCustomData($configcache, $properties) {
352 13
		$custom = $this->getdata("custom", "none");
353 12
		@parse_str($custom);
354 12
		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 12
		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 12
		return $properties;
398
	}
399
400 13
	public function save($properties=array(), $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 12
	global $AR, $ARnls, $ARCurrent;
407 12
		debug("pobject: save([properties], $vtype)","object");
408 12
		debug("pobject: save: path=".$this->path,"object");
409 12
		$configcache=$this->loadConfig();
410 13
		$needsUnlock = false;
411 12
		$arIsNewObject = false;
412 12
		$result = false;
413 12
		$this->error = '';
414 12
		if ($this->arIsNewObject) { // save a new object
0 ignored issues
show
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 6
			debug("pobject: save: new object","all");
416 6
			$this->path = $this->make_path();
417 6
			$arNewParent=$this->make_path("..");
418 6
			$arNewFilename=basename($this->path);
419 6
			$arIsNewObject = true;
420 6
			if (preg_match("|^[a-z0-9_\{\}\.\:-]+$|i",$arNewFilename)) { // no "/" allowed, these will void the 'add' grant check.
421 6
				if (!$this->exists($this->path)) { //arNewFilename)) {
422 6
					if ($this->exists($arNewParent)) {
423 6
						if (!$config = $this->data->config) {
424
							$config=new baseObject();
425
						}
426 6
					} else {
427
						$this->error = ar::error( sprintf($ARnls["err:noparent"],$arNewParent), 1102);
428
					}
429 6
				} else {
430
					$this->error = ar::error( sprintf($ARnls["err:alreadyexists"],$arNewFilename), 1103);
431
				}
432 6
			} else {
433
				$this->error = ar::error( sprintf($ARnls["err:fileillegalchars"],$arNewFilename), 1104);
434
			}
435 6
		} else { // existing object
436 12
			debug("pobject: save: existing object","all");
437 12
			if ($this->exists($this->path)) { // prevent 'funny stuff'
438 12
				if (!$this->lock()) {
439
					$this->error = ar::error( $ARnls["err:objectalreadylocked"], 1105);
440
				} else {
441 12
					$needsUnlock = true;
442 12
					$config = $this->data->config;
443
				}
444 12
			} else {
445
				$this->error = ar::error($ARnls["err:corruptpathnosave"], 1106);
446
			}
447
		}
448
		// pre checks done
449
		// return now on error
450 12
		if ($this->error) {
451
			return $result;;
452
		}
453
454
455 12
		if ($ARCurrent->arCallStack) {
456 12
			$arCallArgs = end($ARCurrent->arCallStack);
457 12
		} else {
458 5
			$arCallArgs = array();
459
		}
460
461 12
		$context = $this->getContext();
462
463 12
		$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
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...
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...
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...
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...
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 12
		if ( $arIsNewObject) {
465 6
			$wf_object->arIsNewObject=$arIsNewObject;
466 6
		}
467
468
		/* save custom data */
469 12
		$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 12
		$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $wf_object));
473
474 12
		$eventData = new baseObject();
475 12
		$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
The property arCallArgs does not seem to exist in baseObject.

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 12
		$eventData->arCallFunction	= $context['arCallFunction'];
0 ignored issues
show
The property arCallFunction does not seem to exist in baseObject.

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 12
		$eventData->arIsNewObject = $arIsNewObject;
0 ignored issues
show
The property arIsNewObject does not seem to exist in baseObject.

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 12
		$eventData->arProperties = $properties;
0 ignored issues
show
The property arProperties does not seem to exist in baseObject.

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 12
		$eventData = ar_events::fire( 'onbeforesave', $eventData );
480
481
		// pop the wf_object, not needed later, the extra scope might hinder other code
482 12
		$this->popContext();
483
484 12
		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 12
		$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 12
		if (isset( $eventData->arProperties ) && is_array( $eventData->arProperties ) ) {
495 12
			$properties = $eventData->arProperties;
496 12
		} else {
497
			$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 12
		$arCallArgs['properties'] = $properties;
505 12
		$wf_result = $wf_object->call("user.workflow.pre.html", $arCallArgs);
506
		/* merge workflow properties */
507 12
		if (isset($wf_result) && is_array($wf_result) ){
508
			$properties = $this->saveMergeWorkflowResult($properties,$wf_result);
509
		}
510
511 12
		$this->error = $wf_object->error;
512 12
		$this->priority = $wf_object->priority;
513 12
		$this->data = $wf_object->data;
514 12
		$this->data->config = $config;
0 ignored issues
show
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 12
		$this->data->mtime=time();
516 12
		if($arIsNewObject) {
517 6
			$this->data->ctime=$this->data->mtime;
518 6
		}
519
520 12
		$this->data->muser=$AR->user->data->login;
521 12
		if( !$this->data->config->owner ) {
522 6
			if( !$this->data->config->owner_name) {
523 6
				$this->data->config->owner_name=$AR->user->data->name;
524 6
			}
525 6
			$this->data->config->owner=$AR->user->data->login;
526 6
			$properties["owner"][0]["value"]=$this->data->config->owner;
527 6
		}
528 12
		$properties["time"][0]["ctime"]=$this->data->ctime;
529 12
		$properties["time"][0]["mtime"]=$this->data->mtime;
530 12
		$properties["time"][0]["muser"]=$this->data->muser;
531
532
533 12
		if (!$this->error) {
534 12
			if ($this->path=$this->store->save($this->path, $this->type, $this->data, $properties, $vtype, $this->priority)) {
535 12
				unset($this->arIsNewObject);
536 12
				$this->id=$this->exists($this->path);
537 12
				$result=$this->path;
538
539 12
				$config=$this->data->config; // need to set it again, to copy owner config data
540
541 12
				$wf_object = $this->store->newobject($this->path, $this->parent, $this->type, $this->data, $this->id, $this->lastchanged, $this->vtype, 0, $this->priority);
542 12
				$arCallArgs = $eventData->arCallArgs; // returned from onbeforesave event
543 12
				$arCallArgs['properties'] = $properties;
544
545 12
				if ($arIsNewObject) {
546 6
					$wf_object->arIsNewObject = $arIsNewObject;
547 6
				}
548 12
				$wf_result = $wf_object->call("user.workflow.post.html", $arCallArgs);
549 12
				$this->error = $wf_object->error;
550 12
				$this->priority = $wf_object->priority;
551 12
				$this->data = $wf_object->data;
552 12
				$this->data->config = $config;
553
				/* merge workflow properties */
554
555 12
				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
				}
563
				// all save actions have been done, fire onsave.
564 12
				$this->data->config = $config;
565
566
				//$this->ClearCache($this->path, true, false);
567 12
				$eventData->arProperties = $properties;
568 12
				$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $this));
569 12
				ar_events::fire( 'onsave', $eventData ); // nothing to prevent here, so ignore return value
570 12
				$this->popContext();
571 12 View Code Duplication
			} else {
572
				$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
573
				$result = false;
574
			}
575 12
		}
576 12
		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 12
			$this->unlock();
578 12
		}
579
580 12
		if ($this->data->nls->list[$this->nls]) {
581 12
			$mynlsdata=$this->data->{$this->nls};
582 12
		} else if ($this->data->nls->default) {
583
			$mynlsdata=$this->data->{$this->data->nls->default};
584
		} else {
585
			$mynlsdata=$this->data;
586
		}
587
588 12
		unset($this->nlsdata);
589 12
		$this->nlsdata=$mynlsdata;
590
591 12
		debug("pobject: save: end","all");
592 12
		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 baseObject();
611
		$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
The property arCallArgs does not seem to exist in baseObject.

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
The property arCallFunction does not seem to exist in baseObject.

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 14
	public function exists($path) {
631 14
		$path=$this->make_path($path);
632 14
		return $this->store->exists($path);
633
	}
634
635 18
	public function make_path($path="") {
636
		switch($path){
637 18
			case '':
638 18
			case '.':
639 18
			case $this->path:
640 18
				return $this->path;
641
				break;
642 15
			case '..':
643 6
				return $this->parent;
644
				break;
645 15
			default:
646 15
				return self::sanitizePath($this->store->make_path($this->path, $path));
647 15
		}
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 13
	public function make_url($path="", $nls=false, $session=true, $https=null, $keephost=null) {
658 13
		global $ARConfig, $AR, $ARCurrent;
659
660 13
		$rootoptions=$this->store->get_config('rootoptions');
661 13
		if (!$session || ($nls !== false)) {
662 13
			$rootoptions = "";
663 13
			if ($session && isset($ARCurrent->session->id) && !$AR->hideSessionIDfromURL) {
664
				$rootoptions .= "/-".$ARCurrent->session->id."-";
665
			}
666 13
			if ($nls) {
667 12
				$rootoptions_nonls = $rootoptions;
668 12
				$rootoptions .= '/'.$nls;
669 12
			}
670 13
		}
671 13
		$path=$this->make_path($path);
672
673
		// now run CheckConfig and get the parentsite of the path found
674 13
		if (!$temp_config=$ARConfig->cache[$path]) {
675 1
			$temp_path = $path;
676 1
			while (!($temp_site = $this->currentsite($temp_path)) && $temp_path!='/') {
677
				$temp_path = $this->make_path($temp_path.'../');
678
			}
679 1
			$temp_config=$ARConfig->cache[$temp_site];
680 1
		}
681
682 13
		if ( !isset($keephost) && (
683 13
			(!$nls && $this->compare_hosts($AR->host, $temp_config->root["value"])) ||
684 13
			($nls && ($this->compare_hosts($AR->host, $temp_config->root['list']['nls'][$nls])))
685 13
		)) {
686
			$keephost = false;
687
		}
688
689 13
		if (!$keephost) {
690 13
			if ($nls) {
691 12
				$url=$temp_config->root["list"]["nls"][$nls];
692 12
				if (isset($url) && is_array($url)) {
693
					$url = current( $url );
694
				}
695 12
				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
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 12
			}
702 13
			if (!$url) {
0 ignored issues
show
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 13
				$checkNLS = $nls;
704 13
				if (!$checkNLS) {
705 7
					$checkNLS = $this->nls;
706 7
				}
707 13
				$urlList = $temp_config->root['list']['nls'][$checkNLS];
708 13
				if (isset($urlList) && is_array($urlList)) {
709
					$url = reset($urlList) . $rootoptions;
710
				} else {
711 13
					$url = $temp_config->root["value"].$rootoptions;
712
				}
713 13
			}
714 13
			$url.=substr($path, strlen($temp_config->root["path"])-1);
715
716 13
			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 13
		} else {
726 12
			$checkNLS = $nls;
727 12
			if (!$checkNLS) {
728
				$checkNLS = $this->nls;
729
			}
730 12
			$urlCheck = $temp_config->root['list']['nls'][$checkNLS];
731 12
			if (!is_array($urlCheck)) {
732 12
				$urlCheck = $temp_config->root["value"];
733 12
			}
734 12
			$requestedHost = ldGetRequestedHost();
0 ignored issues
show
Are you sure the assignment to $requestedHost is correct as ldGetRequestedHost() seems to always returns null.
Loading history...
735 12
			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 12
				$url = $protocol . $requestedHost . $AR->root . $rootoptions . $path;
0 ignored issues
show
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 13
		return self::sanitizeUrl($url);
744
	}
745
746 13
	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 13
		if (isset($url2) ) {
750 13
			if ( !is_array($url2) ){
751 13
				$url2 = array($url2);
752 13
			}
753 13
		} else {
754 12
			$url2 = array();
755
		}
756
757 13
		$prepurl1 = preg_replace('|^[a-z:]*//|i', '', $url1);
758
759 13
		foreach($url2 as $url) {
760
			if (
761 13
					$url == $url1 ||
762 13
					$prepurl1 == preg_replace('|^[a-z:]*//|i', '', $url2)
763 13
				) {
764
				return true;
765
			}
766 13
		}
767 13
		return false;
768
	}
769
770 12
	public function make_local_url($path="", $nls=false, $session=true, $https=null) {
771 12
		global $ARCurrent, $ARConfig;
772 12
		$site = false;
773 12
		$path = $this->make_path($path);
774 12
		$checkpath = $path;
775
776 12
		$redirects = $ARCurrent->shortcut_redirect;
777 12
		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
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 12
			if (!$config=$ARConfig->cache[$checkpath]) {
793
				$config=($ARConfig->cache[$checkpath]) ? $ARConfig->cache[$checkpath] : $this->loadConfig($checkpath);
794
			}
795 12
			if ($config) {
796 12
				$checkNLS = $nls;
797 12
				if (!$checkNLS) {
798
					$checkNLS = $this->nls;
799
				}
800 12
				$urlCheck = $config->root['list']['nls'][$checkNLS];
801 12
				if (!is_array($urlCheck)) {
802 12
					$urlCheck = $config->root["value"];
803 12
				}
804 12
				$requestedHost = ldGetRequestedHost();
0 ignored issues
show
Are you sure the assignment to $requestedHost is correct as ldGetRequestedHost() seems to always returns null.
Loading history...
805
806 12
				if ($this->compare_hosts($requestedHost, $urlCheck)) {
807
					$site=$config->site;
808
				}
809 12
			}
810 12
			$prevpath=$checkpath;
811 12
			$checkpath=$this->make_path($checkpath."../");
812 12
		} while ($prevpath!=$checkpath && !$site);
813 12
		if (!$site) {
814 12
			$site='/';
815 12
		}
816 12
		$site_url=$this->make_url($site, $nls, $session, $https, true);
817 12
		if ($newpath) { // $newpath is the destination of a shortcut redirection, with keepurl on
818
			$rest=substr($newpath, strlen($site));
0 ignored issues
show
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 12
			$rest=substr($path, strlen($site));
821
		}
822 12
		return self::sanitizeUrl($site_url.$rest);
823
	}
824 15
	public function sanitizeUrl($url) {
825
		// remove unexpected chars from the url;
826 15
		return preg_replace("/[^\/{}:.A-Za-z0-9_-]/", "", $url);
827
	}
828 15
	public function sanitizePath($path) {
829
		// remove unexpected chars from the path; same as url for now;
830 15
		return self::sanitizeUrl($path);
831
	}
832
833
	public function AR_implements($implements) {
834
		$type = current(explode(".",$this->type));
835
		return $this->store->AR_implements($type, $implements);
836
	}
837
838 View Code Duplication
	public function getlocks() {
839
		global $AR;
840
		if ($this->store->mod_lock) {
841
			$result=$this->store->mod_lock->getlocks($AR->user->data->login);
842
		} else {
843
			$result="";
844
		}
845
		return $result;
846
	}
847
848 12 View Code Duplication
	public function lock($mode="O", $time=0) {
849 12
	global $AR;
850 12
		if ($this->store->mod_lock) {
851 12
			$result=$this->store->mod_lock->lock($AR->user->data->login,$this->path,$mode,$time);
852 12
		} else {
853
			$result=true; // no lock module, so lock is 'set'
854
		}
855 12
		return $result;
856
	}
857
858 12 View Code Duplication
	public function unlock() {
859 12
	global $AR;
860 12
		if ($this->store->mod_lock) {
861 12
			$result=$this->store->mod_lock->unlock($AR->user->data->login,$this->path);
862 12
		} else {
863
			$result=true;
864
		}
865 12
		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) {
880
		if (!$id) {
881
			$id = $this->id;
882
		}
883
		if (!$vtype) {
884
			$vtype = $type;
885
		}
886
		if (strpos($vtype, '.')!==false) {
887
			$vtype = substr($vtype, 0, strpos($vtype, '.'));
888
		}
889
		$result = $this->store->mogrify($id, $type, $vtype);
890 View Code Duplication
		if ($this->store->error) {
891
			$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
892
		}
893
		return $result;
894
	}
895
896
	public function can_mogrify() {
897
		if ($this->path == "/system/users/admin/") {
898
			return false;
899
		}
900
		return true;
901
	}
902
903
	public function load_properties($scope='') {
904
		return $this->store->load_properties($this->id,'',$scope);
905
	}
906
907
	public function _load_properties($scope='') {
908
		return $this->store->load_properties($this->id,'',$scope);
909
	}
910
911
	public function load_property($property, $scope='') {
912
		return $this->store->load_property($this->id,$property,$scope);
913
	}
914
915
	public function _load_property($property, $scope='') {
916
		return $this->store->load_property($this->id,$property,$scope);
917
	}
918
919 1
	public function GetValidGrants($path="") {
920
	/********************************************************************
921
922
	  This function finds all grants in effect on this object for the
923
	  logged in user! $AR->user must already be set.
924
925
	  Grants are checked in the following way:
926
	  1) First all parents of this object are checked for grants for this
927
	     specific user. The 'nearest' grants are valid, and the path of
928
	     parent that set these grants will be the upper limit for the
929
	     checking of group grants.
930
	  2) Now all groups of which the user is a member are checked for
931
	     grants. Likewise, all parents are checked for group grants, upto
932
	     but not including the upperlimit as set in 1. All group grants
933
	     found are merged into one grants list.
934
	  3) If there are gropup grants, this means that there are group
935
	     grants set in a parent nearer to this object than the user grants
936
	     and therefore the groupgrants must be merged with the
937
	     usergrants.
938
939
	  this results in:
940
	  1	/		user: read edit		group: none
941
	  2	/dir/					group: read
942
	  3	/dir2/		user: none		group: read
943
	  4	/dir/dir3/				group2: edit
944
	  case 1: the user takes precedence over the group, grants are 'read edit'
945
	  case 2: groupgrants are merged with usergrants, as its grants are set
946
	          in a 'nearer' parent (itself). grants are 'read edit'.
947
	  case 3: user takes precedence again. grants are 'none'.
948
	  case 4: All group grants are merged with the usergrants.
949
	          Therefore the grants are 'none read edit'.
950
	********************************************************************/
951
952 1
	global $AR;
953
954 1
		if ($AR->user) { 	// login and retrieval of user object
955 1
			if (!$path) {
956 1
				$path=$this->path;
957 1
			}
958 1
			if (!$AR->user->grants[$path]) {
959 1
				$grants=array();
960 1
				$userpath=$AR->user->FindGrants($path, $grants);
961
				// if not already done, find all groups of which the user is a member
962 1
				if (!is_array($AR->user->externalgroupmemberships) || count($AR->user->externalgroupmemberships)==0) {
963 1
					$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 1
				} else {
965
					// Use the group memberships of external databases (e.g. LDAP)
966
					$criteria="members.login='".AddSlashes($AR->user->data->login)."'";
967
					foreach (array_keys($AR->user->externalgroupmemberships) as $group) {
968
						$criteria.=" or login.value='".AddSlashes($group)."'";
969
					}
970
				}
971 1
				if (!$AR->user->groups) {
972 1
					$groups=$this->find("/system/groups/",$criteria, "system.get.phtml");
973 1
					if (isset($groups) && is_array($groups)) {
974 1
						foreach($groups as $group ){
975 1
							if (is_object($group)) {
976 1
								$AR->user->groups[$group->path] = $group;
977 1
							}
978 1
						}
979 1
					}
980 1
					if (isset($AR->user->data->config->groups) && is_array($AR->user->data->config->groups)) {
981 1
						foreach ($AR->user->data->config->groups as $groupPath => $groupId) {
982 1
							if (!$AR->user->groups[$groupPath]) {
983
								$AR->user->groups[$groupPath] = current($this->get($groupPath, "system.get.phtml"));
984
							}
985 1
						}
986 1
					}
987 1
					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 1
				}
993 1
				if ($AR->user->groups) {
994
					/* check for owner grants (set by system.get.config.phtml) */
995 1
					if (isset($AR->user->ownergrants) && is_array($AR->user->ownergrants)) {
996
						if (!$AR->user->groups["owner"]) {
997
							$AR->user->groups["owner"] = @current($this->get("/system/groups/owner/", "system.get.phtml"));
998
						}
999
						$AR->user->groups["owner"]->data->config->usergrants = $AR->user->ownergrants;
1000
					}
1001 1 View Code Duplication
					foreach($AR->user->groups as $group){
1002 1
						$groupgrants=array();
1003 1
						if (is_object($group)) {
1004 1
							$group->FindGrants($path, $groupgrants, $userpath);
1005 1
							if (isset($grants) && is_array($grants)) {
1006 1
								foreach($groupgrants as $gkey => $gval ){
1007
									if (isset($grants[$gkey]) && is_array($grants[$gkey]) && is_array($gval)) {
1008
										$grants[$gkey]=array_merge($gval, $grants[$gkey]);
1009
									} else
1010
									if ($gval && !is_array($gval)) {
1011
										$grants[$gkey] = $gval;
1012
									} else
1013
									if ($gval && !$grants[$gkey]) {
1014
										$grants[$gkey] = $gval;
1015
									}
1016 1
								}
1017 1
							} else {
1018
								$grants = $groupgrants;
1019
							}
1020 1
						}
1021 1
					}
1022 1
				}
1023 1
				if(isset($AR->sgGrants) && is_array($AR->sgGrants) ) {
1024
					ksort($AR->sgGrants);
1025
					$ppath = $this->make_path($path);
1026 View Code Duplication
					foreach( $AR->sgGrants as $sgpath => $sggrants) {
1027
						$sgpath = $this->make_path($sgpath);
1028
						if( substr($ppath, 0, strlen($sgpath)) == $sgpath ) { // sgpath is parent of ppath or equal to ppath
1029
							if (isset($grants) && is_array($grants)) {
1030
								foreach($sggrants as $gkey => $gval ){
1031
									if (isset($grants[$gkey]) && is_array($grants[$gkey]) && is_array($gval)) {
1032
										$grants[$gkey]=array_merge($gval, $grants[$gkey]);
1033
									} else
1034
									if ($gval && !is_array($gval)) {
1035
										$grants[$gkey] = $gval;
1036
									} else
1037
									if ($gval && !$grants[$gkey]) {
1038
										$grants[$gkey] = $gval;
1039
									}
1040
								}
1041
							} else {
1042
								$grants = $sggrants;
1043
							}
1044
						}
1045
					}
1046
				}
1047 1
				$AR->user->grants[$path]=$grants;
1048 1
			}
1049 1
			$grants=$AR->user->grants[$path];
1050
1051 1
		}
1052 1
		debug("pobject: GetValidGrants(user:".$AR->user->data->login."): end ( ".debug_serialize($grants)." )","all");
0 ignored issues
show
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 1
		return $grants;
1054
	}
1055
1056
1057 35
	public function pushContext($context) {
1058 35
	global $AR;
1059 35
		if(!empty($AR->context)) {
1060 18
			$context = array_merge(end($AR->context), $context);
1061 18
		}
1062 35
		array_push($AR->context, $context);
1063 35
	}
1064
1065
	public function setContext($context, $level=0) {
1066
	global $AR;
1067
		$AR->context[count($AR->context)-(1+$level)]=$context;
1068
	}
1069
1070 35
	public function popContext() {
1071 35
	global $AR;
1072 35
		return array_pop($AR->context);
1073
	}
1074
1075 35
	public static function getContext($level=0) {
1076 35
	global $AR;
1077 35
		return $AR->context[count($AR->context)-(1+$level)];
1078
	}
1079
1080 18
	public function CheckAdmin($user) {
1081 18
	if ($user->data->login == "admin") {
1082 17
			return true;
1083
		}
1084 1
		if ($user->data->groups['/system/groups/admin/']) {
1085
			return true;
1086
		}
1087 1
		return false;
1088
	}
1089
1090 15
	public function CheckLogin($grant, $modifier=ARTHISTYPE) {
1091 15
	global $AR,$ARnls,$ARConfig,$ARCurrent,$ARConfigChecked;
1092 15
		if (!$this->store->is_supported("grants")) {
1093
			debug("pobject: store doesn't support grants");
1094
			return true;
1095
		}
1096 15
		if ($modifier==ARTHISTYPE) {
1097 15
			$modifier=$this->type;
1098 15
		}
1099
1100
		/* load config cache */
1101 15
		if (!isset($ARConfig->cache[$this->path])) {
1102
			// since this is usually run before CheckConfig, make sure
1103
			// it doesn't set cache time
1104
			$realConfigChecked = $ARConfigChecked;
1105
			$ARConfigChecked = true;
1106
			$this->loadConfig();
1107
			$ARConfigChecked = $realConfigChecked;
1108
		}
1109
1110 15
		$isadmin = $this->CheckAdmin($AR->user);
1111
1112 15
		if (!$isadmin && !$AR->user->grants[$this->path]) {
1113
			$grants = $this->GetValidGrants();
1114
		} else {
1115 15
			$grants = $AR->user->grants[$this->path];
1116
		}
1117
1118 15
		if ($AR->user->data->login!="public") {
1119
			// Don't remove this or MSIE users won't get uptodate pages...
1120 15
			ldSetClientCache(false);
1121 15
		}
1122
1123 15
		if ( 	( !$grants[$grant]
1124 15
					|| ( $modifier && is_array($grants[$grant]) && !$grants[$grant][$modifier] )
1125 15
				) && !$isadmin ) {
1126
			// do login
1127
			$arLoginMessage = $ARnls["accessdenied"];
1128
			ldAccessDenied($this->path, $arLoginMessage);
1129
			$result=false;
1130
		} else {
1131 15
			$result=($grants || $isadmin);
1132
		}
1133
1134 15
		$ARCurrent->arLoginSilent=1;
1135 15
		return $result;
1136
	}
1137
1138
1139 1
	public function CheckPublic($grant, $modifier=ARTHISTYPE) {
1140 1
	global $AR;
1141
1142 1
		$result=false;
1143 1
		if (!$AR->public) {
1144 1
			$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $this));
1145 1
				$AR->public=current($this->get("/system/users/public/", "system.get.phtml"));
1146 1
			$this->popContext();
1147 1
		}
1148 1
		if ($AR->public) {
1149 1
			$AR->private=$AR->user;
1150 1
			$AR->user=$AR->public;
1151 1
			$result=$this->CheckSilent($grant, $modifier);
1152 1
			$AR->user=$AR->private;
1153 1
		}
1154 1
		return $result;
1155
	}
1156
1157 11
	public function CheckSilent($grant, $modifier=ARTHISTYPE, $path=".") {
1158 11
	global $AR, $ARConfig;
1159 11
		$path = $this->make_path($path);
1160 11
		if ($modifier==ARTHISTYPE) {
1161 11
			$modifier=$this->type;
1162 11
		}
1163
1164
		/* load config cache */
1165 11
		if (!$ARConfig->cache[$path]) {
1166 2
			$this->loadConfig($path);
1167 2
		}
1168 11
		if ($this->CheckAdmin($AR->user)) {
1169 10
			$result=1;
1170 11
		} else if ($grants=$AR->user->grants[$path]) {
1171
			$result=$grants[$grant];
1172
		} else {
1173 1
			$grants=$this->GetValidGrants();
1174 1
			$result=$grants[$grant];
1175
		}
1176 11
		if ($modifier && is_array($result)) {
1177
			$result=$result[$modifier];
1178
		}
1179 11
		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
The variable $result does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

Let’s take a look at an example:

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

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

    // do something with $myArray
}

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

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

Loading history...
1264
1265
		/* calling config.ini directly for each system.get.config.phtml call */
1266 9
		$loginSilent = $ARCurrent->arLoginSilent;
1267 9
		$ARCurrent->arLoginSilent = true;
1268
		// debug("getConfig:checkconfig start");
1269
1270 9
		$initialNLS = $ARCurrent->nls;
1271 9
		$initialConfigChecked = $ARConfigChecked;
1272
1273 9
		$ARConfig->cache[$this->path]->inConfigIni = true;
1274 9
		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 1
			$arConfig = $ARCurrent->arResult;
1278 1
			if (!isset($arConfig)) {
1279
				$arConfig = $ARCurrent->arConfig;
1280
			}
1281 1
			unset($ARCurrent->arResult);
1282 1
			if (isset($arConfig['library']) && is_array($arConfig['library'])) {
1283
				if (!$ARConfig->libraries[$this->path]) {
1284
					$ARConfig->libraries[$this->path] = array();
1285
				}
1286
				foreach ($arConfig['library'] as $libName => $libPath) {
1287
					$this->loadLibrary($libName, $libPath);
1288
				}
1289
				unset($arConfig['library']);
1290
			}
1291 1
			$ARConfig->pinpcache[$this->path] = (array) $arConfig;
1292 1
		}
1293 9
		$ARConfig->cache[$this->path]->inConfigIni = false;
1294 9
		$this->clearChildConfigs( $this->path ); // remove any config data for child objects, since these are set before their parent config was set
1295 9
		$ARConfigChecked = $initialConfigChecked;
1296 9
		$ARCurrent->nls = $initialNLS;
1297
1298 9
		$arConfig = &$ARConfig->pinpcache[$this->path];
1299 9 View Code Duplication
		if (!is_array($arConfig['authentication']['userdirs'])) {
1300
			$arConfig['authentication']['userdirs'] = array('/system/users/');
1301
		} else {
1302 9
			if (reset($arConfig['authentication']['userdirs']) != '/system/users/') {
1303
				array_unshift($arConfig['authentication']['userdirs'], '/system/users/');
1304
			}
1305
		}
1306 9 View Code Duplication
		if (!is_array($arConfig['authentication']['groupdirs'])) {
1307
			$arConfig['authentication']['groupdirs'] = array('/system/groups/');
1308
		} else {
1309 9
			if (reset($arConfig['authentication']['groupdirs']) != '/system/groups/') {
1310
				array_unshift($arConfig['authentication']['groupdirs'], '/system/groups/');
1311
			}
1312
		}
1313
1314 9
		$ARCurrent->arLoginSilent = $loginSilent;
1315 9
		$ARCurrent->arConfig = $prevArConfig;
1316 9
		$this->popContext();
1317 9
	}
1318
1319 9
	protected function getConfigData() {
1320 9
	global $ARConfig, $AR;
1321 9
		$context = $this->getContext(0);
1322 9
		if (!$ARConfig->cache[$this->path] && $context["scope"] != "pinp") {
1323
			// first inherit parent configuration data
1324 9
			$configcache= clone $ARConfig->cache[$this->parent];
1325 9
			$configcache->localTemplates = [];
1326 9
			$configcache->pinpTemplates = [];
1327 9
			$configcache->id = $this->id;
1328
1329
			// cache default templates
1330 9
			if (isset($this->data->config->templates) && count($this->data->config->templates)) {
1331
				$configcache->pinpTemplates    = $this->data->config->pinp;
1332
				$configcache->privatetemplates = $this->data->config->privatetemplates;
1333
				$configcache->localTemplates   = $this->data->config->templates;
1334
1335
				if( !$configcache->hasDefaultConfigIni ) {
1336
					foreach($configcache->localTemplates as $type => $templates ) {
1337
						if( isset($templates["config.ini"]) ) {
1338
							$configcache->hasDefaultConfigIni = true;
1339
							$configcache->hasConfigIni = true;
1340
							break;
1341
						}
1342
					}
1343
				}
1344 9
			} else if (isset($this->data->config->pinp) && count($this->data->config->pinp)) {
1345 1
				$configcache->pinpTemplates    = $this->data->config->pinp;
1346 1
			}
1347
1348 9
			if( !$configcache->hasDefaultConfigIni ) {
1349 9
				$configcache->hasConfigIni = false;
1350 9
				if(isset($this->data->config->pinp) && is_array($this->data->config->pinp) ) {
1351 1
					foreach( $this->data->config->pinp as $type => $templates ) {
1352 1
						if( isset($templates["config.ini"]) ) {
1353 1
							$configcache->hasConfigIni = true;
1354 1
							break;
1355
						}
1356 1
					}
1357 1
				}
1358 9
			}
1359
1360 9
			$localcachesettings = $this->data->config->cacheSettings;
1361 9
			if (!is_array($localcachesettings) ){
1362 9
				$localcachesettings = array();
1363 9
			}
1364
1365 9
			if (!is_array($configcache->cacheSettings) ) {
1366
				$configcache->cacheSettings = array();
1367
			}
1368
1369 9
			if ($this->data->config->cacheconfig) { // When removing this part, also fix the setting below.
1370 1
				$configcache->cache=$this->data->config->cacheconfig;
1371 1
			}
1372
1373 9
			if (!isset($localcachesettings['serverCache']) && isset($this->data->config->cacheconfig)) {
1374 1
				$localcachesettings["serverCache"] = $this->data->config->cacheconfig;
1375 1
			}
1376
1377 9
			if ($localcachesettings['serverCache'] != 0 ) {
1378 1
				$localcachesettings['serverCacheDefault'] = $localcachesettings['serverCache'];
1379 1
			}
1380
1381 9
			$configcache->cacheSettings = $localcachesettings + $configcache->cacheSettings;
1382
1383
			// store the current object type
1384 9
			$configcache->type = $this->type;
1385
1386 9
			if ($this->data->config->typetree && ($this->data->config->typetree!="inherit")) {
1387
				$configcache->typetree=$this->data->config->typetree;
1388
			}
1389 9
			if (isset($this->data->config->nlsconfig->list)) {
1390 1
				$configcache->nls = clone $this->data->config->nlsconfig;
1391 1
			}
1392
1393 9
			if ($this->data->config->grants["pgroup"]["owner"]) {
1394
				$configcache->ownergrants = $this->data->config->grants["pgroup"]["owner"];
1395
			}
1396 9
			if (isset($configcache->ownergrants) && is_array($configcache->ownergrants)) {
1397
				if ($AR->user && $AR->user->data->login != 'public' && $AR->user->data->login === $this->data->config->owner) {
1398
					$ownergrants = $configcache->ownergrants;
1399
					if (isset($ownergrants) && is_array($ownergrants)) {
1400
						foreach( $ownergrants as $grant => $val ) {
1401
							$AR->user->ownergrants[$this->path][$grant] = $val;
1402
						}
1403
					}
1404
				}
1405
			}
1406
1407 9
			if (isset($this->data->config->customconfig) && is_array($this->data->config->customconfig)) {
1408
				$configcache->custom=array_merge(is_array($configcache->custom)?$configcache->custom:array(), $this->data->config->customconfig);
1409
			}
1410 9
			$ARConfig->cache[$this->path]=$configcache;
1411
1412 9
		}
1413 9
	}
1414
1415 16
	public function loadConfig($path='') {
1416 16
	global $ARConfig, $ARConfigChecked, $ARCurrent;
1417 16
		$path=$this->make_path($path);
1418
		// debug("loadConfig($path)");
1419 16
		if (!isset($ARConfig->cache[$path]) ) {
1420 9
			$allnls = $ARCurrent->allnls;
1421 9
			$ARCurrent->allnls = true;
1422 9
			$configChecked = $ARConfigChecked;
1423 9
			if (($this->path == $path && !$this->arIsNewObject) || $this->exists($path)) {
1424 9
				$this->pushContext(array("scope" => "php"));
1425 9
				if( $this->path == $path ) {
1426
					// debug("loadConfig: currentpath $path ");
1427 9
					$this->getConfig();
1428 9
				} else {
1429
					//debug("loadConfig: get path $path ");
1430 1
					$cur_obj = current($this->get($path, "system.get.phtml"));
1431 1
					$cur_obj->getConfig();
1432
				}
1433 9
				$this->popContext();
1434 9
				$result=$ARConfig->cache[$path];
1435 9
			} else if ($path === '/') {
1436
				// special case: / doesn't exists in the store
1437
				$result=$ARConfig->cache['..'];
1438
			} else {
1439
				$parent=$this->make_path($path.'../');
1440
				if (!$ARConfig->cache[$parent]) {
1441
					$this->pushContext(array("scope" => "php"));
1442
					// debug("loadConfig: parent $parent");
1443
					$cur_obj = current($this->get($parent, "system.get.phtml"));
1444
					if( $cur_obj ) {
1445
						$cur_obj->getConfig();
1446
					}
1447
					$this->popContext();
1448
				}
1449
				$result=$ARConfig->cache[$parent];
1450
				$ARConfig->cache[ $path ] = $result;
1451
				$ARConfig->pinpcache[ $path ] = $ARConfig->pinpcache[ $parent ];
1452
			}
1453
			// restore old ARConfigChecked state
1454 9
			$ARConfigChecked = $configChecked;
1455 9
			$ARCurrent->allnls = $allnls;
1456 9
		} else {
1457
			// debug("loadConfig: exists $path ");
1458 13
			$result=$ARConfig->cache[$path];
1459
		}
1460 16
		return $result;
1461
	}
1462
1463
1464
	// TODO: look for a way to merge loadConfig and loadUserConfig into one function
1465
1466 3
	public function loadUserConfig($path='') {
1467 3
	global $ARConfig;
1468 3
		$path = $this->make_path($path);
1469 3
		$parent = $this->make_path($path.'../');
1470
1471 3
		if (!$ARConfig->cache[$path]) {
1472
			$this->loadConfig($path);
1473
		}
1474 3
		if (!$ARConfig->pinpcache[$path]) {
1475
			$config = $ARConfig->pinpcache[$parent];
1476
		} else {
1477 3
			$config = $ARConfig->pinpcache[$path];
1478
		}
1479 3
		return (array)$config;
1480
	}
1481
1482 1
	public function loadLibrary($name, $path) {
1483 1
	global $ARConfig;
1484 1
		$path=$this->make_path($path);
1485 1
		debug("pobject::loadLibrary($name, $path);");
1486 1
		if ($name===ARUNNAMED) {
1487 1
			if (strstr($path, $this->path)===0) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of strstr($path, $this->path) (string) and 0 (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
1488
				return ar::error('You cannot load an unnamed library from a child object.', 1109);
1489
			} else {
1490 1
				if (!isset($ARConfig->libraries[$this->path])) {
1491 1
					$ARConfig->libraries[$this->path] = [ $path ];
1492 1
				} else {
1493
					array_unshift($ARConfig->libraries[$this->path],$path);
1494
				}
1495
			}
1496 1
		} 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 1
	}
1504
1505
	// returns a list of libraries loaded on $path
1506
	public function getLibraries($path = '') {
1507
	global $ARConfig;
1508
		$path = $this->make_path($path);
1509
		return (array)$ARConfig->libraries[$path];
1510
	}
1511
1512
	public function mergeLibraryConfig( $defaultLibraryName, $defaults ) {
1513
		$libraryName = ar::getvar('arLibrary');
1514
		if ( is_numeric($libraryName) || $libraryName == 'current' ) { // library is loaded unnamed
1515
			$libraryName = $defaultLibraryName;
1516
		}
1517
		if ( $libraryName ) {
1518
			$userConfig = ar::acquire('defaults.'.$libraryName);
1519
			if (isset($userConfig) && is_array($userConfig) ) {
1520
				$defaults = array_merge( $defaults, $userConfig );
1521
			}
1522
		}
1523
		return array_merge( $defaults, $this->getvar('arCallArgs') );
1524
	}
1525
1526
	public function _mergeLibraryConfig( $defaultLibraryName, $defaults ) {
1527
		return $this->mergeLibraryConfig( $defaultLibraryName, $defaults );
1528
	}
1529
1530 15
	protected function findTemplateOnPath($path, $arCallFunction, $arType, $reqnls, &$arSuperContext){
1531
1532 15
		while ($arType!='ariadne_object' ) {
1533 15
			list($arMatchType,$arMatchSubType) = explode('.',$arType,2);
1534 15
			$local = ($path === $this->path);
1535 15
			$templates = ar('template')->ls($path);
1536 15
			if(isset($templates[$arCallFunction])) {
1537 3
				$template = null;
1538 3
				if (!isset($arSuperContext[$path.":".$arType.":".$arCallFunction])) {
1539
					$template = array_reduce($templates[$arCallFunction] , function($carry, $item) use ($arMatchType,$arMatchSubType, $reqnls, $local) {
1540 3
						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 3
							if ($item['type'] === $arMatchType && ($item['subtype'] == $arMatchSubType) ) {
1542 3
								if (isset($carry) && $carry['language'] !== 'any') {
1543
									return $carry;
1544 3
								} else if ($item['language'] === 'any' || $item['language'] === $reqnls ) {
1545 3
									return $item;
1546
								}
1547
							}
1548
						}
1549
						return $carry;
1550 3
					}, null);
1551 3
				}
1552 3
				if ( isset($template) && !isset($arSuperContext[$path.":".$arType.":".$arCallFunction])) {
1553 3
					return $template;
1554
				}
1555
			}
1556 12
			if (!isset($AR->superClass[$arType])) {
1557
				// no template found, no default.phtml found, try superclass.
1558 12
				if ($subcpos = strpos($arType, '.')) {
1559 6
					$arSuper = substr($arType, 0, $subcpos);
1560 6
				} else {
1561 12
					if (!class_exists($arType, false )) {
1562
						// the given class was not yet loaded, so do that now
1563
						$arTemp=$this->store->newobject('','',$arType,new baseObject);
1564
					} else {
1565 12
						$arTemp=new $arType();
1566
					}
1567 12
					$arSuper=get_parent_class($arTemp);
1568
				}
1569 12
				$AR->superClass[$arType]=$arSuper;
0 ignored issues
show
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 12
			} else {
1571
				$arSuper=$AR->superClass[$arType];
1572
			}
1573 12
			$arType=$arSuper;
1574 12
		}
1575
1576 12
		return null;
1577
	}
1578
1579 15
	public function getPinpTemplate($arCallFunction='view.html', $path=".", $top="", $inLibrary = false, $librariesSeen = null, $arSuperContext=array()) {
1580 15
	global $ARCurrent, $ARConfig, $AR, $ARConfigChecked;
1581 15
		debug("getPinpTemplate: function: $arCallFunction; path: $path; top: $top; inLib: $inLibrary","class");
1582 15
		$result = array();
0 ignored issues
show
$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 15
		if (!$top) {
1584 15
			$top = '/';
1585 15
		}
1586 15
		$path = $this->make_path($path);
1587 15
		if (!is_array($arSuperContext)) {
1588
			$arSuperContext = array();
1589
		}
1590
1591 15
		$matches = [];
1592 15
		preg_match('/^
1593
		    ( (?<libname> [^:]+) :  )?
1594
		    ( (?<calltype>[^:]+) :: )?
1595
		      (?<template>[^:]+)
1596 15
		    $/x', $arCallFunction, $matches);
1597
1598 15
		$arCallFunction = $matches['template'];
1599
1600 15
		if($matches['calltype'] != '') {
1601
			$arCallType = $matches['calltype'];
1602
		} else {
1603 15
			$arCallType = $this->type;
1604
		}
1605
1606 15
		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
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
The variable $arLibraryPath does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1630
				$librariesSeen[$arLibraryPath] = true;
1631
				$inLibrary = true;
1632
				$path = $arLibraryPath;
1633
			} else {
1634
				debug("getPinpTemplate: Failed to find library $arLibrary");
1635
			}
1636
			$path = $this->make_path($path);
1637
		}
1638
1639 15
		$checkpath           = $path;
1640 15
		$lastcheckedpath     = "";
1641 15
		$arCallClassTemplate = $ARCurrent->arCallClassTemplate;
1642 15
		$reqnls              = $this->reqnls;
1643 15
		$template            = null;
1644 15
		while (!$arCallClassTemplate && !isset($template) && $checkpath!=$lastcheckedpath) {
1645 15
			$lastcheckedpath = $checkpath;
1646
1647 15
			$template = $this->findTemplateOnPath( $checkpath, $arCallFunction, $arCallType, $reqnls, $arSuperContext);
1648
1649 15
			if (isset($template)) {
1650
				// haal info uit template
1651
				// debug("getPinpTemplate: found ".$arCallFunction." on ".$checkpath);
1652 15
			} else if ($inLibrary) {
1653
1654
				// faster matching on psection, prefix doesn't have to be a valid type
1655
				$prefix = substr($ARConfig->cache[$checkpath]->type,0,8);
1656
1657
				if ($prefix === 'psection') {
1658
					 // debug("BREAKING; $arTemplateId");
1659
					// break search operation when we have found a
1660
					// psection object
1661
					break;
1662
				}
1663
			} else {
1664 12
				if (isset($ARConfig->libraries[$checkpath])) {
1665
					// need to check for unnamed libraries
1666 12
					$libraries = array_filter($ARConfig->libraries[$checkpath],'is_int',ARRAY_FILTER_USE_KEY);
1667 12
					foreach( $libraries as $key => $libpath ) {
1668 12
						$arLibraryPath = $libpath;
1669 12
						$arLibrary     = $key;
1670
1671 12
						$libprevpath = null;
1672 12
						while($libpath != $libprevpath ) {
1673 12
							$libprevpath = $libpath;
1674
1675 12
							$template = $this->findTemplateOnPath( $libpath, $arCallFunction, $arCallType, $reqnls, $arSuperContext);
1676 12
							if (isset($template)) {
1677
								break 2;
1678
							}
1679
1680 12
							$prefix = substr($ARConfig->cache[$libpath]->type,0,8);
1681 12
							if ($prefix === 'psection' || $top == $libpath) {
1682 12
								break;
1683
							}
1684
1685 12
							$libpath = $this->store->make_path($libpath, "..");
1686 12
						}
1687 12
					}
1688 12
					debug("getPinpTemplate: found ".$arCallFunction." on ".$template['path']);
1689 12
				}
1690
1691
			}
1692
1693 15
			if ($checkpath == $top) {
1694 12
				break;
1695
			}
1696
1697 15
			debug("getPinpTemplate: DONE checking for ".$arCallFunction." on ".$checkpath);
1698 15
			$checkpath=$this->store->make_path($checkpath, "..");
1699
			
1700 15
		}
1701 15
		$result = null;
1702 15
		if(isset($template)) {
1703 3
			$result = [];
1704
			//debug("getPinpTemplate END; ".$template['id'] .' '.$template['path']);
1705 3
			$type = $template['type'];
1706 3
			if(isset($template['subtype'])) {
1707
				$type .= '.' . $template['subtype'];
1708
			}
1709 3
			$result["arTemplateId"]       = $template['id'];
1710 3
			$result["arCallTemplate"]     = $template['filename'];
1711 3
			$result["arCallType"]         = $arCallType;
1712 3
			$result["arCallTemplateName"] = $arCallFunction;
1713 3
			$result["arCallTemplateNLS"]  = $template['language'];
1714 3
			$result["arCallTemplateType"] = $type;
1715 3
			$result["arCallTemplatePath"] = $template['path'];
1716 3
			$result["arLibrary"]          = $arLibrary;
0 ignored issues
show
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 3
			$result["arLibraryPath"]      = $arLibraryPath;
1718 3
			$result["arLibrariesSeen"]    = $librariesSeen;
1719 3
			$result["arPrivateTemplate"]  = $template['private'];
1720 3
		}
1721 15
		return $result;
1722
	}
1723
1724 16
	public function CheckConfig($arCallFunction="", $arCallArgs="") {
1725
	// returns true when cache isn't up to date and no other template is
1726
	// defined for $path/$function. Else it takes care of output to the
1727
	// browser.
1728
	// All these templates must exist under a fixed directory, $AR->dir->templates
1729 16
	global $nocache, $AR, $ARConfig, $ARCurrent, $ARBeenHere, $ARnls, $ARConfigChecked;
1730 16
		$MAX_LOOP_COUNT=10;
1731
1732
1733
		// system templates (.phtml) have $arCallFunction=='', so the first check in the next line is to
1734
		// make sure that loopcounts don't apply to those templates.
1735 16
		if (0 && $arCallFunction && $ARBeenHere[$this->path][$arCallFunction]>$MAX_LOOP_COUNT) { // protect against infinite loops
1736
			error(sprintf($ARnls["err:maxloopexceed"],$this->path,$arCallFunction,$arCallArgs));
1737
			$this->store->close();
1738
			exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method CheckConfig() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1739
		} else {
1740 16
			$ARBeenHere[$this->path][$arCallFunction]+=1;
1741
1742
			// this will prevent the parents from setting the cache time
1743 16
			$initialConfigChecked = $ARConfigChecked;
1744 16
			$ARConfigChecked = true;
1745 16
			$config = ($ARConfig->cache[$this->path]) ? $ARConfig->cache[$this->path] : $this->loadConfig();
1746 16
			$ARConfigChecked = $initialConfigChecked;
1747 16
			$ARConfig->nls=$config->nls;
1748
1749
1750
			// if a default language is entered in a parent and no language is
1751
			// explicitly selected in the url, use that default.
1752
			// The root starts with the system default (ariadne.phtml config file)
1753 16
			if ( !$ARCurrent->nls ) {
1754 16
				if ( $config->root['nls'] ) {
1755
					$this->reqnls = $config->root['nls'];
1756
					if ( !$ARConfigChecked ) {
1757
						$ARCurrent->nls = $this->reqnls;
1758
					}
1759 16
				} else if ( $config->nls->default ) {
1760 16
					$this->reqnls = $config->nls->default;
1761 16
					$this->nls = $this->reqnls;
1762 16
					if ( !$ARConfigChecked ) {
1763
						$ARCurrent->nls = $this->nls;
1764
					}
1765 16
				}
1766 16
			} else {
1767
				$this->reqnls = $ARCurrent->nls;
1768
			}
1769 16
			$nls = &$this->nls;
1770 16
			$reqnls = &$this->reqnls;
1771
1772 16
			if (!$ARConfigChecked && is_object($ARnls)) {
1773
				$ARnls->setLanguage($ARCurrent->nls);
1774
			}
1775
1776
1777 16
			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.
1783
1784
			if ($ARCurrent->acceptlang && !$ARCurrent->nls) {
1785
				if ($ARCurrent->acceptlang && is_array($this->data->nls->list)) {
1786
					$validlangs = array_intersect(array_keys($ARCurrent->acceptlang), array_keys($this->data->nls->list));
1787
				}
1788
				if ($validlangs) {
1789
					$reqnls=array_shift($validlangs);
1790
					$ARCurrent->nls = $reqnls;
1791
				}
1792
			}
1793
*/
1794 16 View Code Duplication
			if (isset($this->data->custom) && is_array($this->data->custom) && $this->data->custom['none']) {
1795 1
				$this->customdata=$this->data->custom['none'];
0 ignored issues
show
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 1
			}
1797 16 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
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 16
			if (!$ARConfigChecked) {
1802
				// this template is the first template called in this request.
1803
				$eventData = new baseObject();
1804
				$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
The property arCallArgs does not seem to exist in baseObject.

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
The property arCallFunction does not seem to exist in baseObject.

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

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

Loading history...
1806
1807
				$ARConfigChecked = true;
1808
				$result = ar_events::fire( 'onbeforeview', $eventData );
1809
				$ARConfigChecked = $initialConfigChecked;
1810
				if ( !$result ) { //prevent default action: view
1811
					return false;
1812
				}
1813
			}
1814
1815 16
			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 baseObject();
1823
							$eventData->arCallFunction = $arCallFunction;
1824
							$eventData->arCallArgs = $arCallArgs;
1825
							$eventData->arRequestedNLS = $reqnls;
0 ignored issues
show
The property arRequestedNLS does not seem to exist in baseObject.

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1853
							($redir = array_pop($redirects)) &&
1854
							$redir["keepurl"] &&
1855
							(substr($redirpath, 0, strlen($redir["dest"])) == $redir["dest"])
1856
					) {
1857
						$template = $this->getPinpTemplate($arCallFunction, $redirpath, $redir["dest"]);
1858
						$redirpath = $redir['src'];
1859
					}
1860
1861
					if (!$template["arTemplateId"] && $redirpath) {
1862
						$template = $this->getPinpTemplate($arCallFunction, $redirpath);
1863
					}
1864
				}
1865 15
				if (!$template["arTemplateId"]) {
1866 15
					$template = $this->getPinpTemplate($arCallFunction);
1867 15
				}
1868
1869 15
				if ($template["arCallTemplate"] && $template["arTemplateId"]) {
1870 3
					if (!isset($ARCurrent->cacheTemplateChain)) {
1871
						$ARCurrent->cacheTemplateChain = array();
1872
					}
1873 3
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]])) {
1874 2
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]] = array();
1875 2
					}
1876 3
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']])) {
1877 3
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']] = array();
1878 3
					}
1879 3
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']])) {
1880 3
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']] = 0;
1881 3
					}
1882 3
					$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']]++;
1883
1884
1885 3
					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 3
					$arTemplates=$this->store->get_filestore("templates");
0 ignored issues
show
$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 3
					$exists = ar('template')->exists($template['arCallTemplatePath'],$template["arCallTemplate"]);
1890 3
					if ( $exists ) {
1891
						// check if the requested language exists, if not do not display anything,
1892
						// unless otherwise indicated by $ARCurrent->allnls
1893
						// This triggers only for pinp templates called by other templates,
1894
						// as the first template (in the url) will first trigger the language
1895
						// choice dialogue instead.
1896 3
						$arLibrary = $template['arLibrary'];
1897 3
						if (is_int($arLibrary)) {
1898
							// set the library name for unnamed libraries to 'current'
1899
							// so that calls using getvar('arLibrary') will keep on working
1900
							$arLibrary = "current";
1901
						}
1902
1903 3 View Code Duplication
						if (!is_string($arCallArgs)) {
1904 3
							$arCallArgs['arCallFunction'] = $arCallFunction;
1905 3
							$arCallArgs['arLibrary']      = $arLibrary;
1906 3
							$arCallArgs['arLibraryPath']  = $template["arLibraryPath"];
1907 3
						}
1908
1909 3
						$ARCurrent->arCallStack[]=$arCallArgs;
1910
						// start running a pinp template
1911
1912 3
						$this->pushContext(
1913
							array(
1914 3
								"scope"              => "pinp",
1915 3
								"arLibrary"          => $arLibrary,
1916 3
								"arLibraryPath"      => $template['arLibraryPath'],
1917 3
								"arCallFunction"     => $arCallFunction,
1918 3
								"arCurrentObject"    => $this,
1919 3
								"arCallType"         => $template['arCallType'],
1920 3
								"arCallTemplateName" => $template['arCallTemplateName'],
1921 3
								"arCallTemplateNLS"  => $template['arCallTemplateNLS'],
1922 3
								"arCallTemplateType" => $template['arCallTemplateType'],
1923 3
								"arCallTemplatePath" => $template['arCallTemplatePath'],
1924 3
								"arLibrariesSeen"    => $template['arLibrariesSeen']
1925 3
							)
1926 3
						);
1927
1928
						// FIXME: is 2 het correcte getal? Kan dit minder magisch?
1929 3
						if (count($ARCurrent->arCallStack) == 2 && true === $template['arPrivateTemplate']) {
1930
							// Do not allow private templates to be called first in the stack.
1931
							// echo "Bad request";
1932
1933
							// FIXME: Echte header sturen? Of gewoon niet uitvoeren? Wat is het correcte gedrag?
1934
							// Return true zorgt er voor dat de default 404 handler het oppikt alsof het template niet bestaat.
1935
							$this->popContext();
1936
							array_pop($ARCurrent->arCallStack);
1937
							return true;
1938 3
						} else if ($ARCurrent->forcenls || isset($this->data->nls->list[$reqnls])) {
1939
							// the requested language is available.
1940 3
							$this->nlsdata=$this->data->$reqnls;
1941 3
							$this->nls=$reqnls;
1942 3
							$continue=true;
1943 3
						} else if (!isset($this->data->nls)) {
1944
							// the object has no language support
1945
							$this->nlsdata=$this->data;
1946
							$continue=true;
1947
						} else if (($ARCurrent->allnls) || (!$initialConfigChecked && $ARCurrent->nolangcheck)) {
1948
							// all objects must be displayed
1949
							// $this->reqnls=$this->nls; // set requested nls, for checks
1950
							$this->nls = isset($this->data->nls->default) ? $this->data->nls->default : $this->reqnls;
1951
							$this->nlsdata = $this->data->$nls ?: $this->data->{$this->nls} ?: $this->data;
1952
							$continue=true;
1953
						} else {
1954
							debug("CheckConfig: requested language not available, allnls not set","object");
1955
							// -> skip this object (do not run template but do return false)
1956
							$continue=false;
1957
						}
1958 3
						if ($continue) {
1959 3
							$eventData = new baseObject();
1960 3 View Code Duplication
							if ( !$AR->contextCallHandler ) { /* prevent onbeforecall from re-entering here */
1961 3
								$AR->contextCallHandler = true;
1962 3
								$eventData->arCallArgs = $arCallArgs;
1963 3
								$eventData->arCallFunction = $arCallFunction;
1964 3
								$eventData->arContext = $this->getContext();
0 ignored issues
show
The property arContext does not seem to exist in baseObject.

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 3
								$eventData = ar_events::fire('onbeforecall', $eventData);
1966 3
								$ARCurrent->arResult = $eventData->arResult;
1967 3
								$AR->contextCallHandler = false;
1968 3
								$continue = ($eventData!=false);
1969 3
							}
1970 3
							if ( $continue ) {
1971 3
								if (!isset($ARCurrent->cacheCallChainSettings)) {
1972
									$ARCurrent->cacheCallChainSettings = array();
1973
								}
1974 3
								if ($ARConfig->cache[$this->path]->inConfigIni == false) {
1975 2
									$ARCurrent->cacheCallChainSettings[$this->id] = $config->cacheSettings;
1976 2
								}
1977
1978 3
								if ($ARCurrent->ARShowTemplateBorders) {
1979
									echo "<!-- arTemplateStart\nData: ".$this->type." ".$this->path." \nTemplate: ".$template["arCallTemplatePath"]." ".$template["arCallTemplate"]." \nLibrary:".$template["arLibrary"]." -->";
1980
								}
1981 3
								set_error_handler(array('pobject','pinpErrorHandler'),error_reporting());
1982 3
								$func = ar('template')->get($template['arCallTemplatePath'],$template['arCallTemplate']);
1983 3
								if(is_callable($func)){
1984 3
									$arResult = $func($this);
1985 3
								}
1986 3
								restore_error_handler();
1987 3
								if (isset($arResult)) {
1988 3
									$ARCurrent->arResult=$arResult;
1989 3
								}
1990 3
								if ($ARCurrent->ARShowTemplateBorders) {
1991
									echo "<!-- arTemplateEnd -->";
1992
								}
1993 3 View Code Duplication
								if ( !$AR->contextCallHandler ) { /* prevent oncall from re-entering here */
1994 3
									$AR->contextCallHandler = true;
1995 3
									$temp = $ARCurrent->arResult; /* event listeners will change ARCurrent->arResult */
1996 3
									$eventData->arResult = $temp;
1997 3
									ar_events::fire('oncall', $eventData );
1998 3
									$ARCurrent->arResult = $temp; /* restore correct result */
1999 3
									$AR->contextCallHandler = false;
2000 3
								}
2001 3
							}
2002 3
						}
2003 3
						array_pop($ARCurrent->arCallStack);
2004 3
						$this->popContext();
2005
2006 3
						if ( !$initialConfigChecked && $arCallFunction != 'config.ini' ) {
2007
							// this template was the first template called in this request.
2008
							$eventData = new baseObject();
2009
							$eventData->arCallArgs = $arCallArgs;
2010
							$eventData->arCallFunction = $arCallFunction;
2011
							ar_events::fire( 'onview', $eventData ); // no default action to prevent, so ignore return value.
2012
						}
2013 3
						return false;
2014
					} else {
2015 1
						debug("pobject: CheckConfig: no such file: ".$template["arTemplateId"].$template["arCallTemplate"]."","all");
2016
					}
2017 1
				} else {
2018 12
					debug("CheckConfig: no arCallTemplate ($arCallFunction from '$this->path')","object");
2019
				}
2020
2021 13
			}
2022
		}
2023 14
		return true;
2024
	}
2025
2026 6
	public function ClearCache($path="", $private=true, $recurse=false) {
2027 6
	global $AR;
2028 6
		$norealnode = false;
2029 6
		if (!$path) {
2030
			$path=$this->path;
2031
		} else {
2032 6
			$realpath = current($this->get($path, "system.get.path.phtml"));
2033 6
			if($realpath != false) {
2034 6
				$path = $realpath;
2035 6
			} else {
2036
				$norealnode = true;
2037
			}
2038
		}
2039
2040 6
		if($norealnode !== true) {
2041
			/*
2042
				we don't want to recurse to the currentsite, because the path
2043
				doesn't exists in the database, so it doesn't have a currentsite
2044
2045
				the privatecache should be emptied by delete, or by the cleanup
2046
				cronjob. The current path doesn't exists in the database, so a
2047
				object id which is needed to find the node in the cache, isn't
2048
				available
2049
			*/
2050
2051 6
			if ($private ) {
2052
				// now remove any private cache entries.
2053
				// FIXME: this doesn't scale very well.
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 6
				$pcache=$this->store->get_filestore("privatecache");
2061 6
				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 baseObject();
2068
							$eventData = ar_events::fire( 'onbeforeclearprivatecache', $eventData, $value['type'], $value['path'] );
2069
							if ( !$eventData ) {
2070
								continue;
2071
							}
2072
2073
							$pcache->purge($value["id"]);
2074
							ar_events::fire( 'onclearprivatecache', $eventData, $value['type'], $value['path'] );
2075
						}
2076
2077
						$offset += $limit;
2078
						$ids = $this->store->info($this->store->find($path, "", $limit, $offset));
2079
					}
2080
				} else {
2081 6
					$eventData = new baseObject();
2082 6
					$eventData = ar_events::fire( 'onbeforeclearprivatecache', $eventData, $this->type, $this->path );
2083 6
					if ( $eventData ) {
2084 6
						$pcache->purge($this->id);
2085 6
						ar_events::fire( 'onclearprivatecache', $eventData, $this->type, $this->path );
2086 6
					}
2087
				}
2088 6
			}
2089
2090
			// now clear all parents untill the current site
2091 6
			$site=$this->currentsite($path);
2092 6
			$project=$this->currentproject($path);
2093 6
			if ($path!=$site && $path != $project && $path!='/') {
2094 6
				$parent=$this->make_path($path.'../');
2095 6
				$this->ClearCache($parent, $private, false);
2096 6
			}
2097 6
		}
2098 6
		$recursed = array();
2099
2100
		// filesystem cache image filenames are always lower case, so
2101
		// use special path for that. Remember 'real' path name for
2102
		// recursion and stuff
2103 6
		$fs_path=strtolower($path);
2104 6
		$nlslist=$AR->nls->list;
2105 6
		$nlslist["."]="default";
2106 6
		$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 6
		$cache_types[] = "compressed";
2108 6
		$cache_types[] = "session";
2109
2110 6
		global $cache_config,$store_config;
2111 6
		$cachestore=new cache($cache_config);
2112
2113
2114 6
		$filestore = $this->store->get_config("files");
2115 6
		foreach($cache_types as $type){
2116 6
			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 6
				if(!is_dir($filestore."cache/$type/$nls")){
2120 6
					continue;
2121
				}
2122
2123
				$fpath=$filestore."cache/$type/$nls".$fs_path;
2124
				$hpath=$filestore."cacheheaders/$type/$nls".$fs_path;
2125
				if ($dir=@dir($fpath)) {
2126
					while (false !== ($entry = $dir->read())) {
2127
						if ($entry!="." && $entry!="..") {
2128
							if (is_file($fpath.$entry)) {
2129
								@unlink($fpath.$entry);
2130
								@unlink($hpath.$entry);
2131
								$cachestore->delete("/".$type."/".$nls.$fs_path.$entry);
2132
							} else if ( $recurse && !$recursed[$entry]) {
2133
								$this->ClearCache($path.$entry."/", false, true);
2134
								$recursed[$entry]=true;
2135
							}
2136
						}
2137
					}
2138
					$dir->close();
2139
					// remove empty directory entry's, hide errors about directory entry's with content
2140
					@rmdir($fpath);
2141
					@rmdir($hpath);
2142
				} else if (file_exists(substr($fpath,0,-1)."=")) {
2143
					@unlink(substr($fpath,0,-1)."=");
2144
					@unlink(substr($hpath,0,-1)."=");
2145
					$cachestore->delete("/".$type."/".$nls.substr($fs_path,0,-1)."=");
2146
				}
2147 6
			}
2148 6
		}
2149 6
	}
2150
2151
	public function getcache($name, $nls="") {
2152
		global $ARCurrent, $ARnls;
2153
		$result=false;
0 ignored issues
show
$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
$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
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
$result is not used, you could remove the assignment.

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

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

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

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

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

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

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

// Better
class Router
{
    private $host;

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

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

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

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
2306
	// function to retrieve variables from $this->data, with the correct
2307
	// language version.
2308 13
	global $ARCurrent;
2309
2310 13
		$result = false;
2311 13
		if ($nls!="none") {
2312 12 View Code Duplication
			if ($ARCurrent->arCallStack) {
2313 12
				$arCallArgs=end($ARCurrent->arCallStack);
2314 12
				if (isset($arCallArgs) && is_array($arCallArgs)) {
2315 12
					extract($arCallArgs);
2316 12
				} else if (is_string($arCallArgs)) {
2317
					Parse_Str($arCallArgs);
2318
				}
2319 12
			}
2320 12
			if (isset(${$nls}[$varname])) {
2321 7
				$result=${$nls}[$varname];
2322 12
			} else if (isset($ARCurrent->$nls) && isset($ARCurrent->$nls->$varname)) {
2323
				$result=$ARCurrent->$nls->$varname;
2324 12
			} else if (($values=$_POST[$nls]) && isset($values[$varname])) {
2325
				$result=$values[$varname];
2326 12
			} else if (($values=$_GET[$nls]) && isset($values[$varname])) {
2327
				$result=$values[$varname];
2328 12
			} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$nls][$varname])) {
2329
				$result=$arStoreVars[$nls][$varname];
2330 12
			} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$nls][$varname])) {
2331
				$result=$arStoreVars[$nls][$varname];
2332
			}
2333 12 View Code Duplication
			if ($result===false) {
2334 12
				if (isset($this->data->{$nls}) && isset($this->data->{$nls}->{$varname})) {
2335 6
					$result=$this->data->{$nls}->{$varname};
2336 6
				}
2337 12
			}
2338 12
		} else { // language independant variable.
2339 13 View Code Duplication
			if ($ARCurrent->arCallStack) {
2340 13
				$arCallArgs=end($ARCurrent->arCallStack);
2341 13
				if (isset($arCallArgs) && is_array($arCallArgs)) {
2342 12
					extract($arCallArgs);
2343 13
				} else if (is_string($arCallArgs)) {
2344
					Parse_Str($arCallArgs);
2345
				}
2346 13
			}
2347 13
			if (isset($$varname)) {
2348 6
				$result=$$varname;
2349 13
			} else if (isset($ARCurrent->$varname)) {
2350
				$result=$ARCurrent->$varname;
2351 13 View Code Duplication
			} else if (isset($_POST[$varname])) {
2352
				$result=$_POST[$varname];
2353 13
			} else if (isset($_GET[$varname])) {
2354
				$result=$_GET[$varname];
2355 13
			} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$varname])) {
2356
				$result=$arStoreVars[$varname];
2357 13
			} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$varname])) {
2358
				$result=$arStoreVars[$varname];
2359
			}
2360 13
			if ($result===false) {
2361 13
				if (isset($this->data->$varname)) {
2362 6
					$result=$this->data->$varname;
2363 6
				}
2364 13
			}
2365
		}
2366 13
		if ( $result === false ) {
2367 13
			$result = $emptyResult;
2368 13
		}
2369 13
		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
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
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
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
The property size does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
2494
		}
2495
		while ( (count($suffixes) > 1) && ($size > 1024) ){
2496
			$size = $size / 1024;
2497
			array_shift($suffixes);
2498
		}
2499
		$size = round($size,$precision);
2500
		if($precision==0){ // compatible with the old make_filesize
2501
			$size = intval($size);
2502
		}
2503
		$result = $size." ".array_shift($suffixes);
2504
		return $result;
2505
	}
2506
2507
	public function convertToUTF8($data, $charset = "CP1252") {
2508
2509
		include_once($this->store->get_config("code")."modules/mod_unicode.php");
2510
2511
		if (isset($data) && is_array($data)) {
2512
			foreach($data as $key => $val){
2513
				$data[$key] = $this->convertToUTF8($val, $charset);
2514
			}
2515
		} else
2516
		if (is_object($data)) {
2517
			foreach($data as $key => $val){
2518
				$data->$key = $this->convertToUTF8($val, $charset);
2519
			}
2520
		} else {
2521
			$data = unicode::convertToUTF8($charset, $data);
2522
		}
2523
		return $data;
2524
	}
2525
2526 7
	public function resetloopcheck() {
2527 7
		global $ARBeenHere;
2528 7
		$ARBeenHere=array();
2529 7
	}
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
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
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()
2586
		$redirects	= $ARCurrent->shortcut_redirect;
2587
		if (isset($redirects) && is_array($redirects)) {
2588
			$redirpath = $this->path;
2589
			while (!$template['arTemplateId'] &&
0 ignored issues
show
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 baseObject();
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
The property arCallArgs does not seem to exist in baseObject.

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
The property arCallFunction does not seem to exist in baseObject.

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
The property arContext does not seem to exist in baseObject.

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
The variable $arResult does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2661
						ar_events::fire('oncall', $eventData );
2662
						$ARCurrent->arResult = $temp; /* restore correct result */
2663
						$AR->contextCallHandler = false;
2664
					}
2665
				}
2666
				array_pop($ARCurrent->arCallStack);
2667
				$this->popContext();
2668
			}
2669
		}
2670
		return $arResult;
2671
	}
2672
2673
	public function _get($path, $function="view.html", $args="") {
2674
		// remove possible path information (greedy match)
2675
		if ( !($function instanceof \Closure) ) {
2676
			$function = basename( (string) $function);
2677
		}
2678
		return $this->store->call($function, $args,
2679
			$this->store->get(
2680
				$this->make_path($path)));
2681
	}
2682
2683
	public function _call_object($object, $function, $args="") {
2684
		return $object->call($function, $args);
2685
	}
2686
2687 View Code Duplication
	public function _ls($function="list.html", $args="") {
2688
		// remove possible path information (greedy match)
2689
		if ( ! ( $function instanceof \Closure ) ) {
2690
			$function = basename( (string) $function );
2691
		}
2692
		return $this->store->call($function, $args,
2693
			$this->store->ls($this->path));
2694
	}
2695
2696 View Code Duplication
	public function _parents($function="list.html", $args="", $top="") {
2697
		// remove possible path information (greedy match)
2698
		if ( !($function instanceof \Closure ) ) {
2699
			$function = basename( (string) $function);
2700
		}
2701
		return $this->parents($this->path, $function, $args, $top);
2702
	}
2703
2704
	public function _find($criteria, $function="list.html", $args="", $limit=100, $offset=0) {
2705
		$this->error = '';
2706
		// remove possible path information (greedy match)
2707
		if ( !($function instanceof \Closure ) ) {
2708
			$function = basename( (string) $function);
2709
		}
2710
		$result = $this->store->call($function, $args,
2711
			$this->store->find($this->path, $criteria, $limit, $offset));
2712 View Code Duplication
		if ($this->store->error) {
2713
			$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error );
2714
		}
2715
		return $result;
2716
	}
2717
2718
	public function _exists($path) {
2719
		return $this->store->exists($this->make_path($path));
2720
	}
2721
2722
	public function _implements($implements) {
2723
		return $this->AR_implements($implements);
2724
	}
2725
2726 13
	public function getvar($var) {
0 ignored issues
show
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...
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 13
	global $ARCurrent, $ARConfig; // Warning: if you add other variables here, make sure you cannot get at it through $$var.
2728
2729 13 View Code Duplication
		if ($ARCurrent->arCallStack) {
2730 12
			$arCallArgs=end($ARCurrent->arCallStack);
2731 12
			if (isset($arCallArgs) && is_array($arCallArgs)) {
2732 9
				extract($arCallArgs);
2733 12
			} else if (is_string($arCallArgs)) {
2734
				Parse_Str($arCallArgs);
2735
			}
2736 12
		}
2737 13
		if (isset($$var) && ($var!='ARConfig')) {
2738 4
			$result=$$var;
2739 13
		} else if (isset($ARCurrent->$var)) {
2740
			$result=$ARCurrent->$var;
2741 13
		} else if (isset($ARConfig->pinpcache[$this->path][$var])) {
2742
			$result=$ARConfig->pinpcache[$this->path][$var];
2743 13 View Code Duplication
		} else if (isset($_POST[$var])) {
2744
			$result=$_POST[$var];
2745 13
		} else if (isset($_GET[$var])) {
2746
			$result=$_GET[$var];
2747 13
		} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$var])) {
2748
			$result=$arStoreVars[$var];
2749 13
		} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$var])) {
2750
			$result=$arStoreVars[$var];
2751
		}
2752 13
		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
The property ARnls does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
2899
		} else { // older loaders and other shizzle
2900
2901
			$nls = preg_replace('/[^a-z]*/i','',$nls);
2902
			$section = preg_replace('/[^a-z0-9\._:-]*/i','',$section);
2903
			if (!$section) {
2904
				include($this->store->get_config("code")."nls/".$nls);
2905
				$this->ARnls = array_merge((array)$this->ARnls, $ARnls);
2906
			} else {
2907
				$nlsfile = $this->store->get_config("code")."nls/".$section.".".$nls;
2908
				if(strpos($nlsfile, ':') === false && file_exists($nlsfile)) {
2909
					include($nlsfile);
2910
					$this->ARnls = array_merge((array)$this->ARnls, $ARnls);
2911
				} else {
2912
					// current result;
2913
					$arResult = $ARCurrent->arResult;
2914
					$this->pushContext(array());
2915
						$oldnls = $this->reqnls;
2916
						$this->reqnls = $nls;
2917
						$this->CheckConfig($section, array('nls' => $nls));
2918
						$this->reqnls = $oldnls;
2919
					$this->popContext();
2920
					// reset current result (CheckConfig may have changed it when it should not have).
2921
					$ARCurrent->arResult = $arResult;
2922
				}
2923
			}
2924
		}
2925
	}
2926
2927
	public function _startsession() {
2928
	global $ARCurrent;
2929
		ldStartSession(0);
2930
		return $ARCurrent->session->id;
2931
	}
2932
2933
	public function _putsessionvar($varname, $varvalue) {
2934
	global $ARCurrent;
2935
2936
		if ($ARCurrent->session) {
2937
			return $ARCurrent->session->put($varname, $varvalue);
2938
		} else {
2939
			return false;
2940
		}
2941
	}
2942
2943
	public function _getsessionvar($varname) {
2944
	global $ARCurrent;
2945
2946
		if ($ARCurrent->session) {
2947
			return $ARCurrent->session->get($varname);
2948
		} else {
2949
			return false;
2950
		}
2951
	}
2952
2953
	public function _setsessiontimeout($timeout = 0) {
2954
	global $ARCurrent;
2955
		if ($ARCurrent->session) {
2956
			return $ARCurrent->session->setTimeout($timeout);
2957
		} else {
2958
			return false;
2959
		}
2960
	}
2961
2962
	public function _killsession() {
2963
	global $ARCurrent;
2964
2965
		if ($ARCurrent->session) {
2966
			$ARCurrent->session->kill();
2967
			unset($ARCurrent->session);
2968
		}
2969
	}
2970
2971
	public function _sessionid() {
2972
	global $ARCurrent;
2973
		if ($ARCurrent->session) {
2974
			return $ARCurrent->session->id;
2975
		} else {
2976
			return 0;
2977
		}
2978
	}
2979
2980
	public function _resetloopcheck() {
2981
		return $this->resetloopcheck();
2982
	}
2983
2984
	public function _make_path($path="") {
2985
		return $this->make_path($path);
2986
	}
2987
2988
	public function _make_ariadne_url($path="") {
2989
		return $this->make_ariadne_url($path);
2990
	}
2991
2992
	public function _make_url($path="", $nls=false, $session=true, $https=null, $keephost=null) {
2993
		return $this->make_url($path, $nls, $session, $https, $keephost);
2994
	}
2995
2996
	public function _make_local_url($path="", $nls=false, $session=true, $https=null) {
2997
		return $this->make_local_url($path, $nls, $session, $https);
2998
	}
2999
3000
	public function _getcache($name, $nls='') {
3001
		return $this->getcache($name, $nls);
3002
	}
3003
3004
	public function _cached($name, $nls='') {
3005
		return $this->cached($name, $nls);
3006
	}
3007
3008
	public function _savecache($time="") {
3009
		return $this->savecache($time);
3010
	}
3011
3012
	public function _getdatacache($name) {
3013
		return $this->getdatacache($name);
3014
	}
3015
3016
	public function _savedatacache($name,$data,$time="")
3017
	{
3018
		return $this->savedatacache($name,$data,$time);
3019
	}
3020
3021 14
	public function currentsite($path="", $skipRedirects = false) {
3022 14
		global $ARCurrent, $ARConfig;
3023 14
		if (!$path) {
3024 12
			$path=$this->path;
3025 12
		}
3026 14
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3027 14
		if (!$skipRedirects && @count($ARCurrent->shortcut_redirect)) {
3028
			$redir = end($ARCurrent->shortcut_redirect);
3029
			if ($redir["keepurl"] && substr($path, 0, strlen($redir["dest"])) == $redir["dest"]) {
3030
				if (substr($config->site, 0, strlen($redir["dest"]))!=$redir["dest"]) {
3031
					// search currentsite from the reference
3032
					$config = ($ARConfig->cache[$redir['src']]) ? $ARConfig->cache[$redir['src']] : $this->loadConfig($redir['src']);
3033
				}
3034
			}
3035
		}
3036 14
		return $config->site;
3037
	}
3038
3039
	public function parentsite($site) {
3040
	global $ARConfig;
3041
		$path=$this->store->make_path($site, "..");
3042
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3043
		return $config->site;
3044
	}
3045
3046 1 View Code Duplication
	public function currentsection($path="") {
3047 1
	global $ARConfig;
3048 1
		if (!$path) {
3049 1
			$path=$this->path;
3050 1
		}
3051 1
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3052 1
		return $config->section;
3053
	}
3054
3055 View Code Duplication
	public function parentsection($path) {
3056
	global $ARConfig;
3057
		$path=$this->store->make_path($path, "..");
3058
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3059
		return $config->section;
3060
	}
3061
3062 6 View Code Duplication
	public function currentproject($path="") {
3063 6
	global $ARConfig;
3064 6
		if (!$path) {
3065
			$path=$this->path;
3066
		}
3067 6
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3068 6
		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:
3102
				$nls = $ARCurrent->nls;
3103 View Code Duplication
				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 baseObject;
3144
				if (!$this->data->nls) {
3145
					$this->data->nls = new baseObject;
3146
					$this->data->nls->default = $nls;
0 ignored issues
show
The property default does not seem to exist in baseObject.

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
The property list does not seem to exist in baseObject.

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

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

Loading history...
3149
			}
3150
			$this->data->$nls->$name = $value;
3151
		}
3152
	}
3153
3154
	public function showValue($name, $nls=false) {
3155
		$result = $this->getValue($name, $nls);
3156
		echo $result;
3157
		return $result;
3158
	}
3159
3160
	public function _getValue($name, $nls=false) {
3161
		return $this->getValue($name, $nls);
3162
	}
3163
3164
	public function _setValue($name, $value, $nls=false) {
3165
		return $this->setValue($name, $value, $nls);
3166
	}
3167
3168
	public function _showValue($name, $nls=false) {
3169
		return $this->showValue($name, $nls);
3170
	}
3171
3172
	public function _currentsite($path="", $skipRedirects = false) {
3173
		return $this->currentsite( $path, $skipRedirects );
3174
	}
3175
3176
	public function _parentsite($site) {
3177
		return $this->parentsite($site);
3178
	}
3179
3180
	public function _currentsection() {
3181
		return $this->currentsection();
3182
	}
3183
3184
	public function _parentsection($section) {
3185
		return $this->parentsection($section);
3186
	}
3187
3188
	public function _currentproject() {
3189
		return $this->currentproject();
3190
	}
3191
3192
	public function _parentproject($path) {
3193
		return $this->parentproject($path);
3194
	}
3195
3196
	public function _checkAdmin($user) {
3197
		return $this->CheckAdmin($user);
3198
	}
3199
3200
	public function _checkgrant($grant, $modifier=ARTHISTYPE, $path=".") {
3201
		// as this is called within a pinp template,
3202
		// all the grants are already loaded, so
3203
		// checksilent will fullfill our needs
3204
		$this->pushContext(array("scope" => "php"));
3205
			$result = $this->CheckSilent($grant, $modifier, $path);
3206
		$this->popContext();
3207
		return $result;
3208
	}
3209
3210
	public function _checkpublic($grant, $modifier=ARTHISTYPE) {
3211
3212
		return $this->CheckPublic($grant, $modifier);
3213
	}
3214
3215
	public function _getcharset() {
3216
		return $this->getcharset();
3217
	}
3218
3219
	public function _count_find($query='') {
3220
		return $this->count_find($this->path, $query);
3221
	}
3222
3223
	public function _count_ls() {
3224
		return $this->count_ls($this->path);
3225
	}
3226
3227
	public function _HTTPRequest($method, $url, $postdata = "", $port=80) {
3228
		return $this->HTTPRequest($method, $url, $postdata, $port);
3229
	}
3230
3231
	public function _make_filesize( $size="" ,$precision=0) {
3232
		return $this->make_filesize( $size ,$precision);
3233
	}
3234
3235
	public function _convertToUTF8($data, $charset = "CP1252") {
3236
		return $this->convertToUTF8($data,$charset);
3237
	}
3238
3239
	public function _getuser() {
3240
	global $AR;
3241
		if ($AR->pinp_user && $AR->pinp_user->data->login == $AR->user->data->login) {
3242
			$user = $AR->pinp_user;
3243
		} else {
3244
			$this->pushContext(array("scope" => "php"));
3245
				if ( $AR->user instanceof ariadne_object ) {
3246
					$user = current($AR->user->get(".", "system.get.phtml"));
3247
				} else {
3248
					$user = $AR->user;
3249
				}
3250
				$AR->pinp_user = $user;
3251
			$this->popContext();
3252
		}
3253
		return $user;
3254
	}
3255
3256
	public function ARinclude($file) {
3257
		include($file);
3258
	}
3259
3260 1
	public function _load($class) {
3261
		// only allow access to modules in the modules directory.
3262 1
		$class = preg_replace('/[^a-z0-9\._]/i','',$class);
3263 1
		include_once($this->store->get_config("code")."modules/".$class);
3264 1
	}
3265
3266
	public function _import($class) {
3267
		// deprecated
3268
		return $this->_load($class);
3269
	}
3270
3271 1
	public function html_to_text($text) {
3272 1
		$trans = array_flip(get_html_translation_table(HTML_ENTITIES));
3273 1
		$cb  = function($matches) use ($trans) {
3274
			return strtr($matches[1],$trans);
3275 1
		};
3276
		//strip nonbreaking space, strip script and style blocks, strip html tags, convert html entites, strip extra white space
3277 1
		$search_clean = array("%&nbsp;%i", "%<(script|style)[^>]*>.*?<\/(script|style)[^>]*>%si", "%<[\/]*[^<>]*>%Usi", "%\s+%");
3278 1
		$replace_clean = array(" ", " ", " ", " ");
3279
3280 1
		$text = preg_replace_callback(
3281 1
			"%(\&[a-zA-Z0-9\#]+;)%s",
3282 1
			$cb,
3283
			$text
3284 1
		);
3285 1
		$text = preg_replace($search_clean, $replace_clean, $text);
3286 1
		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 baseObject;
3297
		$object=$this->store->newobject($newpath, $newparent, $type, $data);
3298
		$object->arIsNewObject=true;
3299
		return $object;
3300
	}
3301
3302
	public function _save($properties=array(), $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
It seems like $properties can also be of type null; however, ariadne_object::save() does only seem to accept array, 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
It seems like $properties can also be of type null; however, ariadne_object::save() does only seem to accept array, 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
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
3353
	protected function preg_replace_compile($pattern, $replacement) {
3354
	global $AR;
3355
		include_once($this->store->get_config("code")."modules/mod_pinp.phtml");
3356
		preg_match("/^\s*(.)/", $pattern, $regs);
3357
		$delim = $regs[1];
3358
		if (@eregi("\\${delim}[^$delim]*\\${delim}.*e.*".'$', $pattern)) {
3359
			$pinp = new pinp($AR->PINP_Functions, 'local->', '$AR_this->_');
3360
			return substr($pinp->compile("<pinp>$replacement</pinp>"), 5, -2);
3361
		} else {
3362
			return $replacement;
3363
		}
3364
	}
3365
3366
	public function _preg_replace($pattern, $replacement, $text, $limit = -1) {
3367
		if (version_compare(PHP_VERSION, '7.0.0', '<')) {
3368
			if (isset($pattern) && is_array($pattern)) {
3369
				$newrepl = array();
3370
				reset($replacement);
3371
				foreach ($pattern as $i_pattern) {
3372
					list(, $i_replacement) = each($replacement);
3373
					$newrepl[] = $this->preg_replace_compile($i_pattern, $i_replacement);
3374
				}
3375
			} else {
3376
				$newrepl = $this->preg_replace_compile($pattern, $replacement);
3377
			}
3378
		} else {
3379
			// php7 is safe, no more eval
3380
			$newrepl = $replacement;
3381
		}
3382
		return preg_replace($pattern, $newrepl, $text, $limit);
3383
	}
3384
3385
	/* ob_start accepts a callback but we don't want that
3386
	 * this wrapper removes the arguments from the ob_start call
3387
	 */
3388
	public function _ob_start() {
3389
		return ob_start();
3390
	}
3391
3392
	public function _loadConfig($path='') {
3393
		return clone $this->loadConfig($path);
3394
	}
3395
3396
	public function _loadUserConfig($path='') {
3397
		return $this->loadUserConfig($path);
3398
	}
3399
3400
	public function _loadLibrary($name, $path) {
3401 1
		return $this->loadLibrary($name, $path);
3402
	}
3403
3404
	public function _resetConfig($path='') {
3405
		return $this->resetConfig($path);
3406
	}
3407
3408
	public function _getLibraries($path = '') {
3409
		return $this->getLibraries($path);
3410
	}
3411
3412
3413
	public function _getSetting($setting) {
3414
	global $AR;
3415
3416
		switch ($setting) {
3417
			case 'www':
3418
			case 'dir:www':
3419
				return $AR->dir->www;
3420
			case 'images':
3421
			case 'dir:images':
3422
				return $AR->dir->images;
3423
			case 'ARSessionKeyCheck':
3424
				$result = null;
3425
				if (function_exists('ldGenerateSessionKeyCheck')) {
3426
					$result = ldGenerateSessionKeyCheck();
3427
				}
3428
				return $result;
3429
			break;
3430
			case 'nls:list':
3431
				return $AR->nls->list;
3432
			break;
3433
			case 'nls:default':
3434
				return $AR->nls->default;
3435
			break;
3436
			case 'svn':
3437
				return $AR->SVN->enabled;
3438
			break;
3439
		}
3440
	}
3441
3442
	public function __call($name,$arguments) {
3443
		if ( $name[0] == '_' ) {
3444
			$fname = substr($name, 1);
3445
			if ( isset($this->{$fname}) && $this->{$fname} instanceof \Closure ) {
3446
				\Closure::bind( $this->{$fname}, $this );
3447
				return call_user_func_array( $this->{$fname}, $arguments);
3448
			}
3449
		}
3450
		switch($name) {
3451
			case "implements":
3452
				return $this->AR_implements($arguments[0]);
3453
			break;
3454
			default:
3455
				trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $name), E_USER_ERROR);
3456
				return false;
3457
			break;
3458
		}
3459
	}
3460
3461
	static public function pinpErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) {
0 ignored issues
show
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...
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...
3462 2
		global $nocache;
3463 2
		if (($errno & error_reporting()) == 0) {
3464 2
			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