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

ariadne_object::_loadLibrary()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
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
	public function init($store, $path, $data) {
45
		$this->store=$store;
46
		$this->path=$path;
47
		$this->data=$data;
48
		if ( !isset($this->data->config) ) {
49
			$this->data->config = new baseObject();
50
		}
51
	}
52
53
	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
	global $AR, $ARConfig, $ARCurrent, $ARBeenHere, $ARnls;
72
73
		if ( $arCallFunction instanceof \Closure ) {
74
			$arCallFunctionName = 'Closure';
75
		} else {
76
			$arCallFunctionName = (string) $arCallFunction;
77
		}
78
		debug("pobject: ".$this->path.": call($arCallFunctionName, ".debug_serialize($arCallArgs).")","object","all","IN");
79
80
		// default to view.html
81
		if (!$arCallFunction) {
82
			$arCallFunction="view.html";
83
		}
84
		// clear previous results
85
		unset($ARCurrent->arResult);
86
87
		// callstack is needed for getvar()
88
		$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
		$this->pushContext( array(
91
			"arSuperContext" => array(),
92
			"arCurrentObject" => $this,
93
			"scope" => "php",
94
			"arCallFunction" => $arCallFunction
95
		) );
96
97
		// convert the deprecated urlencoded arguments to an array
98
		if (isset($arCallArgs) && is_string($arCallArgs)) {
99
			$ARCurrent->arTemp=$arCallArgs;
100
			$arCallArgs=array();
101
			parse_str($ARCurrent->arTemp, $arCallArgs);
102
		}
103
		// import the arguments in the current scope, but don't overwrite existing
104
		// variables.
105
		if (isset($arCallArgs) && is_array($arCallArgs)) {
106
			extract($arCallArgs,EXTR_SKIP);
107
		}
108
		// now find the initial nls selection (CheckConfig is needed for per
109
		// tree selected defaults)
110
		if ($ARCurrent->nls) {
111
			$this->reqnls=$ARCurrent->nls;
0 ignored issues
show
Bug introduced by
The property reqnls does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
120
			$nls=&$this->nls;
121
		} 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
		if ($nls && isset($this->data->$nls)) {
128
			// now set the data and nlsdata pointers
129
			$this->nlsdata=$this->data->$nls;
0 ignored issues
show
Bug introduced by
The property nlsdata does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
157
		}
158
159
		if ( $arCallFunction instanceof \Closure ) {
160
			$context = $this->getContext(ARCALLINGCONTEXT);
161
			if ( $context["scope"] != "pinp" ) {
162
				$arResult = $arCallFunction($this );
163
			} else {
164
				if ( $this->CheckSilent('read') ) {
165
					$arResult = $arCallFunction($this);
166
				}
167
			}
168
		} else {
169
			if ($arCallFunction[0] === "#") {
170
				$ARCurrent->arCallClassTemplate = true;
171
				$arCallFunction = substr($arCallFunction, 1);
172
			} else {
173
				$ARCurrent->arCallClassTemplate = false;
174
			}
175
176
			if( $arCallFunction == "system.get.phtml" && ( $context = $this->getContext(ARCALLINGCONTEXT) ) && $context["scope"] != "pinp" ) {
177
				$arResult = $this;
178
			} else {
179
				$libtemplate = strpos($arCallFunction,":");
180
				$codedir = $this->store->get_config("code");
181
182
				// if it is a subtype object, disk templates do not exists,
183
				$subcpos = strpos($arType, '.');
184
				if ($subcpos !== false ) {
185
					// subtype, skip looking for templates
186
					$arSuper = substr($arType, 0, $subcpos);
187
					if(!isset($AR->superClass[$arType])){
188
						$AR->superClass[$arType]=$arSuper;
189
					}
190
					$arType=$arSuper;
191
				}
192
193
				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
					$arCallTemplate=$codedir."templates/".$arType."/".$arCallFunction;
198
					if ($libtemplate === false && file_exists($arCallTemplate)) {
199
						//debug('found '.$arCallTemplate, 'all');
200
						// template found
201
						$arCallFunction = $arCallFunctionOrig;
202
						include($arCallTemplate);
203
						break;
204
					} 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
						include($this->store->get_config("code")."templates/".$arType."/default.phtml");
208
						break;
209
					} else {
210
						if (!($arSuper=$AR->superClass[$arType])) {
211
							// no template found, no default.phtml found, try superclass.
212
213
							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
							$arSuper=get_parent_class($arType);
218
219
							$AR->superClass[$arType]=$arSuper;
220
						}
221
						$arType=$arSuper;
222
					}
223
				}
224
			}
225
		}
226
		array_pop($ARCurrent->arCallStack);
227
		$this->popContext();
228
		debug("pobject: call: end","all","all","OUT");
229
		if (isset($ARCurrent->arResult)) {
230
			// pinp templates can return results via putvar("arResult",$result);
231
			$arResult=$ARCurrent->arResult;
232
			unset($ARCurrent->arResult);
233
		}
234
		if (isset($arResult)) {
235
			// only do a return if we really have something to return
236
			return $arResult;
237
		}
238
	}
239
240
	public function ls($path="", $function="list.html", $args="") {
241
		$path=$this->store->make_path($this->path, $path);
242
		return $this->store->call($function, $args, $this->store->ls($path));
243
	}
244
245
	public function get($path, $function="view.html", $args="") {
246
		$path=$this->store->make_path($this->path, $path);
247
		return $this->store->call($function, $args, $this->store->get($path));
248
	}
249
250
	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
		if (!$top) {
254
			$top = $this->currentsection();
255
		} else {
256
			$top = $this->store->make_path($this->path, $top);
257
		}
258
259
		$path=$this->store->make_path($this->path, $path);
260
261
		if ($path != $this->path ) {
262
			$target = current($this->get($path,"system.get.phtml"));
263
		} else {
264
			$target = $this;
265
		}
266
267
		$parents = array();
268
		if (strpos($target->path, $top) === 0) {
269
			$parents[] = $target;
270
			while ($target && $target->path != $top) {
271
				$target = current($target->get($target->parent, "system.get.phtml"));
272
				$parents[] = $target;
273
			}
274
		}
275
		$parents = array_reverse($parents);
276
		$result = array();
277
		foreach ($parents as $parent) {
278
			if ( $parent ) { // might not have read access to this object
279
				$result[] = $parent->call($function, $args);
280
			}
281
		}
282
283
		return $result;
284
	}
285
286
	public function find($path, $criteria, $function="list.html", $args="", $limit=100, $offset=0) {
287
		$path = $this->store->make_path($this->path, $path);
288
		$objects = $this->store->find($path, $criteria, $limit, $offset);
289
		if (!$this->store->error) {
290
			$result = $this->store->call($function, $args, $objects);
291 View Code Duplication
		} else {
292
			$this->error = ar::error( ''.$this->store->error, 1110, $this->store->error );
0 ignored issues
show
Bug introduced by
The property error does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
293
			$result = false;
294
		}
295
		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
	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
							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
						}
337
						$record[$wf_prop_field] = $value;
338
					}
339
					$properties[$wf_prop_name][] = $record;
340
				}
341
			}
342
		}
343
344
		return $properties;
345
	}
346
347
	/*
348
		saves custom data
349
		returns properties for custom data
350
	*/
351
	private function saveCustomData($configcache, $properties) {
352
		$custom = $this->getdata("custom", "none");
353
		@parse_str($custom);
354
		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
		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
		return $properties;
398
	}
399
400
	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
	global $AR, $ARnls, $ARCurrent;
407
		debug("pobject: save([properties], $vtype)","object");
408
		debug("pobject: save: path=".$this->path,"object");
409
		$configcache=$this->loadConfig();
410
		$needsUnlock = false;
411
		$arIsNewObject = false;
412
		$result = false;
413
		$this->error = '';
414
		if ($this->arIsNewObject) { // save a new object
0 ignored issues
show
Bug introduced by
The property arIsNewObject does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
464
		if ( $arIsNewObject) {
465
			$wf_object->arIsNewObject=$arIsNewObject;
466
		}
467
468
		/* save custom data */
469
		$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
		$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $wf_object));
473
474
		$eventData = new baseObject();
475
		$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
Bug introduced by
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
		$eventData->arCallFunction	= $context['arCallFunction'];
0 ignored issues
show
Bug introduced by
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
		$eventData->arIsNewObject = $arIsNewObject;
0 ignored issues
show
Bug introduced by
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
		$eventData->arProperties = $properties;
0 ignored issues
show
Bug introduced by
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
		$eventData = ar_events::fire( 'onbeforesave', $eventData );
480
481
		// pop the wf_object, not needed later, the extra scope might hinder other code
482
		$this->popContext();
483
484
		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
		$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
		if (isset( $eventData->arProperties ) && is_array( $eventData->arProperties ) ) {
495
			$properties = $eventData->arProperties;
496
		} 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
		$arCallArgs['properties'] = $properties;
505
		$wf_result = $wf_object->call("user.workflow.pre.html", $arCallArgs);
506
		/* merge workflow properties */
507
		if (isset($wf_result) && is_array($wf_result) ){
508
			$properties = $this->saveMergeWorkflowResult($properties,$wf_result);
509
		}
510
511
		$this->error = $wf_object->error;
512
		$this->priority = $wf_object->priority;
513
		$this->data = $wf_object->data;
514
		$this->data->config = $config;
0 ignored issues
show
Bug introduced by
The variable $config does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
515
		$this->data->mtime=time();
516
		if($arIsNewObject) {
517
			$this->data->ctime=$this->data->mtime;
518
		}
519
520
		$this->data->muser=$AR->user->data->login;
521
		if( !$this->data->config->owner ) {
522
			if( !$this->data->config->owner_name) {
523
				$this->data->config->owner_name=$AR->user->data->name;
524
			}
525
			$this->data->config->owner=$AR->user->data->login;
526
			$properties["owner"][0]["value"]=$this->data->config->owner;
527
		}
528
		$properties["time"][0]["ctime"]=$this->data->ctime;
529
		$properties["time"][0]["mtime"]=$this->data->mtime;
530
		$properties["time"][0]["muser"]=$this->data->muser;
531
532
533
		if (!$this->error) {
534
			if ($this->path=$this->store->save($this->path, $this->type, $this->data, $properties, $vtype, $this->priority)) {
535
				unset($this->arIsNewObject);
536
				$this->id=$this->exists($this->path);
537
				$result=$this->path;
538
539
				$config=$this->data->config; // need to set it again, to copy owner config data
540
541
				$wf_object = $this->store->newobject($this->path, $this->parent, $this->type, $this->data, $this->id, $this->lastchanged, $this->vtype, 0, $this->priority);
542
				$arCallArgs = $eventData->arCallArgs; // returned from onbeforesave event
543
				$arCallArgs['properties'] = $properties;
544
545
				if ($arIsNewObject) {
546
					$wf_object->arIsNewObject = $arIsNewObject;
547
				}
548
				$wf_result = $wf_object->call("user.workflow.post.html", $arCallArgs);
549
				$this->error = $wf_object->error;
550
				$this->priority = $wf_object->priority;
551
				$this->data = $wf_object->data;
552
				$this->data->config = $config;
553
				/* merge workflow properties */
554
555
				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
				$this->data->config = $config;
565
566
				//$this->ClearCache($this->path, true, false);
567
				$eventData->arProperties = $properties;
568
				$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $this));
569
				ar_events::fire( 'onsave', $eventData ); // nothing to prevent here, so ignore return value
570
				$this->popContext();
571 View Code Duplication
			} else {
572
				$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
573
				$result = false;
574
			}
575
		}
576
		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
			$this->unlock();
578
		}
579
580
		if ($this->data->nls->list[$this->nls]) {
581
			$mynlsdata=$this->data->{$this->nls};
582
		} else if ($this->data->nls->default) {
583
			$mynlsdata=$this->data->{$this->data->nls->default};
584
		} else {
585
			$mynlsdata=$this->data;
586
		}
587
588
		unset($this->nlsdata);
589
		$this->nlsdata=$mynlsdata;
590
591
		debug("pobject: save: end","all");
592
		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
Bug introduced by
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
Bug introduced by
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
	public function exists($path) {
631
		$path=$this->make_path($path);
632
		return $this->store->exists($path);
633
	}
634
635
	public function make_path($path="") {
636
		switch($path){
637
			case '':
638
			case '.':
639
			case $this->path:
640
				return $this->path;
641
				break;
642
			case '..':
643
				return $this->parent;
644
				break;
645
			default:
646
				return self::sanitizePath($this->store->make_path($this->path, $path));
647
		}
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
	public function make_url($path="", $nls=false, $session=true, $https=null, $keephost=null) {
658
		global $ARConfig, $AR, $ARCurrent;
659
660
		$rootoptions=$this->store->get_config('rootoptions');
661
		if (!$session || ($nls !== false)) {
662
			$rootoptions = "";
663
			if ($session && isset($ARCurrent->session->id) && !$AR->hideSessionIDfromURL) {
664
				$rootoptions .= "/-".$ARCurrent->session->id."-";
665
			}
666
			if ($nls) {
667
				$rootoptions_nonls = $rootoptions;
668
				$rootoptions .= '/'.$nls;
669
			}
670
		}
671
		$path=$this->make_path($path);
672
673
		// now run CheckConfig and get the parentsite of the path found
674
		if (!$temp_config=$ARConfig->cache[$path]) {
675
			$temp_path = $path;
676
			while (!($temp_site = $this->currentsite($temp_path)) && $temp_path!='/') {
677
				$temp_path = $this->make_path($temp_path.'../');
678
			}
679
			$temp_config=$ARConfig->cache[$temp_site];
680
		}
681
682
		if ( !isset($keephost) && (
683
			(!$nls && $this->compare_hosts($AR->host, $temp_config->root["value"])) ||
684
			($nls && ($this->compare_hosts($AR->host, $temp_config->root['list']['nls'][$nls])))
685
		)) {
686
			$keephost = false;
687
		}
688
689
		if (!$keephost) {
690
			if ($nls) {
691
				$url=$temp_config->root["list"]["nls"][$nls];
692
				if (isset($url) && is_array($url)) {
693
					$url = current( $url );
694
				}
695
				if ($url) {
696 View Code Duplication
					if (substr($url, -1)=='/') {
697
						$url=substr($url, 0, -1);
698
					}
699
					$url .= $rootoptions_nonls;
0 ignored issues
show
Bug introduced by
The variable $rootoptions_nonls does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
703
				$checkNLS = $nls;
704
				if (!$checkNLS) {
705
					$checkNLS = $this->nls;
706
				}
707
				$urlList = $temp_config->root['list']['nls'][$checkNLS];
708
				if (isset($urlList) && is_array($urlList)) {
709
					$url = reset($urlList) . $rootoptions;
710
				} else {
711
					$url = $temp_config->root["value"].$rootoptions;
712
				}
713
			}
714
			$url.=substr($path, strlen($temp_config->root["path"])-1);
715
716
			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
		} else {
726
			$checkNLS = $nls;
727
			if (!$checkNLS) {
728
				$checkNLS = $this->nls;
729
			}
730
			$urlCheck = $temp_config->root['list']['nls'][$checkNLS];
731
			if (!is_array($urlCheck)) {
732
				$urlCheck = $temp_config->root["value"];
733
			}
734
			$requestedHost = ldGetRequestedHost();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $requestedHost is correct as ldGetRequestedHost() seems to always returns null.
Loading history...
735
			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
				$url = $protocol . $requestedHost . $AR->root . $rootoptions . $path;
0 ignored issues
show
Bug introduced by
The variable $protocol does not exist. Did you forget to declare it?

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

Loading history...
741
			}
742
		}
743
		return self::sanitizeUrl($url);
744
	}
745
746
	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
		if (isset($url2) ) {
750
			if ( !is_array($url2) ){
751
				$url2 = array($url2);
752
			}
753
		} else {
754
			$url2 = array();
755
		}
756
757
		$prepurl1 = preg_replace('|^[a-z:]*//|i', '', $url1);
758
759
		foreach($url2 as $url) {
760
			if (
761
					$url == $url1 ||
762
					$prepurl1 == preg_replace('|^[a-z:]*//|i', '', $url2)
763
				) {
764
				return true;
765
			}
766
		}
767
		return false;
768
	}
769
770
	public function make_local_url($path="", $nls=false, $session=true, $https=null) {
771
		global $ARCurrent, $ARConfig;
772
		$site = false;
773
		$path = $this->make_path($path);
774
		$checkpath = $path;
775
776
		$redirects = $ARCurrent->shortcut_redirect;
777
		if (isset($redirects) && is_array($redirects)) {
778
			$newpath = $checkpath;
779
			$c_redirects = count($redirects);
780
			$c_redirects_done = 0;
781 View Code Duplication
			while (count($redirects) && ($redir = array_pop($redirects)) && $redir['keepurl'] && substr($newpath, 0, strlen($redir['dest'])) == $redir['dest']) {
782
				$c_redirects_done++;
783
				$newpath = $redir['src'].substr($newpath, strlen($redir['dest']));
784
			}
785
786
			if ($c_redirects_done == $c_redirects) {
787
				$checkpath = $redir['src'];
0 ignored issues
show
Bug introduced by
The variable $redir does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
819
		} else {
820
			$rest=substr($path, strlen($site));
821
		}
822
		return self::sanitizeUrl($site_url.$rest);
823
	}
824
	public function sanitizeUrl($url) {
825
		// remove unexpected chars from the url;
826
		return preg_replace("/[^\/{}:.A-Za-z0-9_-]/", "", $url);
827
	}
828
	public function sanitizePath($path) {
829
		// remove unexpected chars from the path; same as url for now;
830
		return self::sanitizeUrl($path);
831
	}
832
833
	public function AR_implements($implements) {
834
		$type = current(explode(".",$this->type));
835
		return $this->store->AR_implements($type, $implements);
836
	}
837
838 View Code Duplication
	public function getlocks() {
839
		global $AR;
840
		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 View Code Duplication
	public function lock($mode="O", $time=0) {
849
	global $AR;
850
		if ($this->store->mod_lock) {
851
			$result=$this->store->mod_lock->lock($AR->user->data->login,$this->path,$mode,$time);
852
		} else {
853
			$result=true; // no lock module, so lock is 'set'
854
		}
855
		return $result;
856
	}
857
858 View Code Duplication
	public function unlock() {
859
	global $AR;
860
		if ($this->store->mod_lock) {
861
			$result=$this->store->mod_lock->unlock($AR->user->data->login,$this->path);
862
		} else {
863
			$result=true;
864
		}
865
		return $result;
866
	}
867
868
	public function touch($id=0, $timestamp=-1) {
869
		if (!$id) {
870
			$id = $this->id;
871
		}
872
		$result = $this->store->touch($id, $timestamp);
873 View Code Duplication
		if ($this->store->error) {
874
			$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
875
		}
876
		return $result;
877
	}
878
879
	public function mogrify($id=0, $type, $vtype=null) {
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
	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
	global $AR;
953
954
		if ($AR->user) { 	// login and retrieval of user object
955
			if (!$path) {
956
				$path=$this->path;
957
			}
958
			if (!$AR->user->grants[$path]) {
959
				$grants=array();
960
				$userpath=$AR->user->FindGrants($path, $grants);
961
				// if not already done, find all groups of which the user is a member
962
				if (!is_array($AR->user->externalgroupmemberships) || count($AR->user->externalgroupmemberships)==0) {
963
					$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
				} 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
				if (!$AR->user->groups) {
972
					$groups=$this->find("/system/groups/",$criteria, "system.get.phtml");
973
					if (isset($groups) && is_array($groups)) {
974
						foreach($groups as $group ){
975
							if (is_object($group)) {
976
								$AR->user->groups[$group->path] = $group;
977
							}
978
						}
979
					}
980
					if (isset($AR->user->data->config->groups) && is_array($AR->user->data->config->groups)) {
981
						foreach ($AR->user->data->config->groups as $groupPath => $groupId) {
982
							if (!$AR->user->groups[$groupPath]) {
983
								$AR->user->groups[$groupPath] = current($this->get($groupPath, "system.get.phtml"));
984
							}
985
						}
986
					}
987
					if (!$AR->user->groups["/system/groups/public/"]) {
988
						if ($public=current($this->get("/system/groups/public/", "system.get.phtml"))) {
989
							$AR->user->groups[$public->path] = $public;
990
						}
991
					}
992
				}
993
				if ($AR->user->groups) {
994
					/* check for owner grants (set by system.get.config.phtml) */
995
					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 View Code Duplication
					foreach($AR->user->groups as $group){
1002
						$groupgrants=array();
1003
						if (is_object($group)) {
1004
							$group->FindGrants($path, $groupgrants, $userpath);
1005
							if (isset($grants) && is_array($grants)) {
1006
								foreach($groupgrants as $gkey => $gval ){
1007
									if (isset($grants[$gkey]) && is_array($grants[$gkey]) && is_array($gval)) {
1008
										$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
								}
1017
							} else {
1018
								$grants = $groupgrants;
1019
							}
1020
						}
1021
					}
1022
				}
1023
				if(isset($AR->sgGrants) && is_array($AR->sgGrants) ) {
1024
					ksort($AR->sgGrants);
1025
					$ppath = $this->make_path($path);
1026 View Code Duplication
					foreach( $AR->sgGrants as $sgpath => $sggrants) {
1027
						$sgpath = $this->make_path($sgpath);
1028
						if( substr($ppath, 0, strlen($sgpath)) == $sgpath ) { // sgpath is parent of ppath or equal to ppath
1029
							if (isset($grants) && is_array($grants)) {
1030
								foreach($sggrants as $gkey => $gval ){
1031
									if (isset($grants[$gkey]) && is_array($grants[$gkey]) && is_array($gval)) {
1032
										$grants[$gkey]=array_merge($gval, $grants[$gkey]);
1033
									} else
1034
									if ($gval && !is_array($gval)) {
1035
										$grants[$gkey] = $gval;
1036
									} else
1037
									if ($gval && !$grants[$gkey]) {
1038
										$grants[$gkey] = $gval;
1039
									}
1040
								}
1041
							} else {
1042
								$grants = $sggrants;
1043
							}
1044
						}
1045
					}
1046
				}
1047
				$AR->user->grants[$path]=$grants;
1048
			}
1049
			$grants=$AR->user->grants[$path];
1050
1051
		}
1052
		debug("pobject: GetValidGrants(user:".$AR->user->data->login."): end ( ".debug_serialize($grants)." )","all");
0 ignored issues
show
Bug introduced by
The variable $grants does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1214
	}
1215
1216 View Code Duplication
	public function resetConfig($path='') {
1217
	global $ARConfig;
1218
		$path = $this->make_path($path);
1219
		if ($ARConfig->cache[$path]) {
1220
			$path = preg_quote($path,'/');
1221
			$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 View Code Duplication
	public function clearChildConfigs($path='') {
1230
	global $ARConfig;
1231
		$path = $this->make_path($path);
1232
		if ($ARConfig->cache[$path]) {
1233
			$path = preg_quote($path,'/');
1234
			$keys = preg_grep('/^'.$path.'./',array_keys($ARConfig->cache));
1235
			foreach($keys as $cachepath) {
1236
				unset($ARConfig->cache[$cachepath]);
1237
				unset($ARConfig->pinpcache[$cachepath]);
1238
				unset($ARConfig->libraries[$cachepath]);
1239
			}
1240
		}
1241
	}
1242
1243
	protected function getConfig() {
1244
	global $ARConfig, $ARCurrent, $ARConfigChecked;
1245
		$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
		if( !$ARConfig->cache[$this->parent] && $this->parent!=".." ) {
1250
			$parent = current($this->get($this->parent, "system.get.phtml"));
1251
			if ($parent) {
1252
				$parent->getConfig();
1253
			}
1254
		}
1255
1256
		$this->getConfigData();
1257
1258
		$ARConfig->pinpcache[$this->path] = $ARConfig->pinpcache[$this->parent];
1259
		// backwards compatibility when calling templates from config.ini
1260
		$prevArConfig = $ARCurrent->arConfig;
1261
		$ARCurrent->arConfig = $ARConfig->pinpcache[$this->path];
1262
1263
		$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
		$loginSilent = $ARCurrent->arLoginSilent;
1267
		$ARCurrent->arLoginSilent = true;
1268
		// debug("getConfig:checkconfig start");
1269
1270
		$initialNLS = $ARCurrent->nls;
1271
		$initialConfigChecked = $ARConfigChecked;
1272
1273
		$ARConfig->cache[$this->path]->inConfigIni = true;
1274
		if ($ARConfig->cache[$this->path]->hasConfigIni && !$this->CheckConfig('config.ini', $arCallArgs)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->CheckConfig('config.ini', $arCallArgs) of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

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

$a = canBeFalseAndNull();

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

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

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

Loading history...
1541
							if ($item['type'] === $arMatchType && ($item['subtype'] == $arMatchSubType) ) {
1542
								if (isset($carry) && $carry['language'] !== 'any') {
1543
									return $carry;
1544
								} else if ($item['language'] === 'any' || $item['language'] === $reqnls ) {
1545
									return $item;
1546
								}
1547
							}
1548
						}
1549
						return $carry;
1550
					}, null);
1551
				}
1552
				if ( isset($template) && !isset($arSuperContext[$path.":".$arType.":".$arCallFunction])) {
1553
					return $template;
1554
				}
1555
			}
1556
			if (!isset($AR->superClass[$arType])) {
1557
				// no template found, no default.phtml found, try superclass.
1558
				if ($subcpos = strpos($arType, '.')) {
1559
					$arSuper = substr($arType, 0, $subcpos);
1560
				} else {
1561
					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
						$arTemp=new $arType();
1566
					}
1567
					$arSuper=get_parent_class($arTemp);
1568
				}
1569
				$AR->superClass[$arType]=$arSuper;
0 ignored issues
show
Bug introduced by
The variable $AR does not exist. Did you forget to declare it?

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

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

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

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

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1630
				$librariesSeen[$arLibraryPath] = true;
1631
				$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
		$checkpath           = $path;
1640
		$lastcheckedpath     = "";
1641
		$arCallClassTemplate = $ARCurrent->arCallClassTemplate;
1642
		$reqnls              = $this->reqnls;
1643
		$template            = null;
1644
		while (!$arCallClassTemplate && !isset($template) && $checkpath!=$lastcheckedpath) {
1645
			$lastcheckedpath = $checkpath;
1646
1647
			$template = $this->findTemplateOnPath( $checkpath, $arCallFunction, $arCallType, $reqnls, $arSuperContext);
1648
1649
			if (isset($template)) {
1650
				// haal info uit template
1651
				// debug("getPinpTemplate: found ".$arCallFunction." on ".$checkpath);
1652
			} else if ($inLibrary) {
1653
1654
				// faster matching on psection, prefix doesn't have to be a valid type
1655
				$prefix = substr($ARConfig->cache[$checkpath]->type,0,8);
1656
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
				if (isset($ARConfig->libraries[$checkpath])) {
1665
					// need to check for unnamed libraries
1666
					$libraries = array_filter($ARConfig->libraries[$checkpath],'is_int',ARRAY_FILTER_USE_KEY);
1667
					foreach( $libraries as $key => $libpath ) {
1668
						$arLibraryPath = $libpath;
1669
						$arLibrary     = $key;
1670
1671
						$libprevpath = null;
1672
						while($libpath != $libprevpath ) {
1673
							$libprevpath = $libpath;
1674
1675
							$template = $this->findTemplateOnPath( $libpath, $arCallFunction, $arCallType, $reqnls, $arSuperContext);
1676
							if (isset($template)) {
1677
								break 2;
1678
							}
1679
1680
							$prefix = substr($ARConfig->cache[$libpath]->type,0,8);
1681
							if ($prefix === 'psection' || $top == $libpath) {
1682
								break;
1683
							}
1684
1685
							$libpath = $this->store->make_path($libpath, "..");
1686
						}
1687
					}
1688
					debug("getPinpTemplate: found ".$arCallFunction." on ".$template['path']);
1689
				}
1690
1691
			}
1692
1693
			if ($checkpath == $top) {
1694
				break;
1695
			}
1696
1697
			debug("getPinpTemplate: DONE checking for ".$arCallFunction." on ".$checkpath);
1698
			$checkpath=$this->store->make_path($checkpath, "..");
1699
			
1700
		}
1701
		$result = null;
1702
		if(isset($template)) {
1703
			$result = [];
1704
			//debug("getPinpTemplate END; ".$template['id'] .' '.$template['path']);
1705
			$type = $template['type'];
1706
			if(isset($template['subtype'])) {
1707
				$type .= '.' . $template['subtype'];
1708
			}
1709
			$result["arTemplateId"]       = $template['id'];
1710
			$result["arCallTemplate"]     = $template['filename'];
1711
			$result["arCallType"]         = $arCallType;
1712
			$result["arCallTemplateName"] = $arCallFunction;
1713
			$result["arCallTemplateNLS"]  = $template['language'];
1714
			$result["arCallTemplateType"] = $type;
1715
			$result["arCallTemplatePath"] = $template['path'];
1716
			$result["arLibrary"]          = $arLibrary;
0 ignored issues
show
Bug introduced by
The variable $arLibrary does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1717
			$result["arLibraryPath"]      = $arLibraryPath;
1718
			$result["arLibrariesSeen"]    = $librariesSeen;
1719
			$result["arPrivateTemplate"]  = $template['private'];
1720
		}
1721
		return $result;
1722
	}
1723
1724
	public function CheckConfig($arCallFunction="", $arCallArgs="") {
1725
	// returns true when cache isn't up to date and no other template is
1726
	// defined for $path/$function. Else it takes care of output to the
1727
	// browser.
1728
	// All these templates must exist under a fixed directory, $AR->dir->templates
1729
	global $nocache, $AR, $ARConfig, $ARCurrent, $ARBeenHere, $ARnls, $ARConfigChecked;
1730
		$MAX_LOOP_COUNT=10;
1731
1732
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
		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
			$ARBeenHere[$this->path][$arCallFunction]+=1;
1741
1742
			// this will prevent the parents from setting the cache time
1743
			$initialConfigChecked = $ARConfigChecked;
1744
			$ARConfigChecked = true;
1745
			$config = ($ARConfig->cache[$this->path]) ? $ARConfig->cache[$this->path] : $this->loadConfig();
1746
			$ARConfigChecked = $initialConfigChecked;
1747
			$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
			if ( !$ARCurrent->nls ) {
1754
				if ( $config->root['nls'] ) {
1755
					$this->reqnls = $config->root['nls'];
1756
					if ( !$ARConfigChecked ) {
1757
						$ARCurrent->nls = $this->reqnls;
1758
					}
1759
				} else if ( $config->nls->default ) {
1760
					$this->reqnls = $config->nls->default;
1761
					$this->nls = $this->reqnls;
1762
					if ( !$ARConfigChecked ) {
1763
						$ARCurrent->nls = $this->nls;
1764
					}
1765
				}
1766
			} else {
1767
				$this->reqnls = $ARCurrent->nls;
1768
			}
1769
			$nls = &$this->nls;
1770
			$reqnls = &$this->reqnls;
1771
1772
			if (!$ARConfigChecked && is_object($ARnls)) {
1773
				$ARnls->setLanguage($ARCurrent->nls);
1774
			}
1775
1776
1777
			if (!$ARCurrent->arContentTypeSent) {
1778
				ldHeader("Content-Type: text/html; charset=UTF-8");
1779
				$ARCurrent->arContentTypeSent = true;
1780
			}
1781
1782
/*			// FIXME: the acceptlang code works a bit too well.. it overrides psite configuration settings.
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 View Code Duplication
			if (isset($this->data->custom) && is_array($this->data->custom) && $this->data->custom['none']) {
1795
				$this->customdata=$this->data->custom['none'];
0 ignored issues
show
Bug introduced by
The property customdata does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

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

Loading history...
1799
			}
1800
1801
			if (!$ARConfigChecked) {
1802
				// this template is the first template called in this request.
1803
				$eventData = new baseObject();
1804
				$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
Bug introduced by
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
Bug introduced by
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
			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
Bug introduced by
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
			$ARConfigChecked = true;
1847
			if ($arCallFunction) { // don't search for templates named ''
1848
				// FIXME: Redirect code has to move to getPinpTemplate()
1849
				$redirects	= $ARCurrent->shortcut_redirect;
1850
				if (isset($redirects) && is_array($redirects)) {
1851
					$redirpath = $this->path;
1852
					while (!$template['arTemplateId'] &&
0 ignored issues
show
Bug introduced by
The variable $template does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

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

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

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

Loading history...
1889
					$exists = ar('template')->exists($template['arCallTemplatePath'],$template["arCallTemplate"]);
1890
					if ( $exists ) {
1891
						// check if the requested language exists, if not do not display anything,
1892
						// unless otherwise indicated by $ARCurrent->allnls
1893
						// This triggers only for pinp templates called by other templates,
1894
						// as the first template (in the url) will first trigger the language
1895
						// choice dialogue instead.
1896
						$arLibrary = $template['arLibrary'];
1897
						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 View Code Duplication
						if (!is_string($arCallArgs)) {
1904
							$arCallArgs['arCallFunction'] = $arCallFunction;
1905
							$arCallArgs['arLibrary']      = $arLibrary;
1906
							$arCallArgs['arLibraryPath']  = $template["arLibraryPath"];
1907
						}
1908
1909
						$ARCurrent->arCallStack[]=$arCallArgs;
1910
						// start running a pinp template
1911
1912
						$this->pushContext(
1913
							array(
1914
								"scope"              => "pinp",
1915
								"arLibrary"          => $arLibrary,
1916
								"arLibraryPath"      => $template['arLibraryPath'],
1917
								"arCallFunction"     => $arCallFunction,
1918
								"arCurrentObject"    => $this,
1919
								"arCallType"         => $template['arCallType'],
1920
								"arCallTemplateName" => $template['arCallTemplateName'],
1921
								"arCallTemplateNLS"  => $template['arCallTemplateNLS'],
1922
								"arCallTemplateType" => $template['arCallTemplateType'],
1923
								"arCallTemplatePath" => $template['arCallTemplatePath'],
1924
								"arLibrariesSeen"    => $template['arLibrariesSeen']
1925
							)
1926
						);
1927
1928
						// FIXME: is 2 het correcte getal? Kan dit minder magisch?
1929
						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
						} else if ($ARCurrent->forcenls || isset($this->data->nls->list[$reqnls])) {
1939
							// the requested language is available.
1940
							$this->nlsdata=$this->data->$reqnls;
1941
							$this->nls=$reqnls;
1942
							$continue=true;
1943
						} else if (!isset($this->data->nls)) {
1944
							// the object has no language support
1945
							$this->nlsdata=$this->data;
1946
							$continue=true;
1947
						} else if (($ARCurrent->allnls) || (!$initialConfigChecked && $ARCurrent->nolangcheck)) {
1948
							// all objects must be displayed
1949
							// $this->reqnls=$this->nls; // set requested nls, for checks
1950
							$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
						if ($continue) {
1959
							$eventData = new baseObject();
1960 View Code Duplication
							if ( !$AR->contextCallHandler ) { /* prevent onbeforecall from re-entering here */
1961
								$AR->contextCallHandler = true;
1962
								$eventData->arCallArgs = $arCallArgs;
1963
								$eventData->arCallFunction = $arCallFunction;
1964
								$eventData->arContext = $this->getContext();
0 ignored issues
show
Bug introduced by
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
								$eventData = ar_events::fire('onbeforecall', $eventData);
1966
								$ARCurrent->arResult = $eventData->arResult;
1967
								$AR->contextCallHandler = false;
1968
								$continue = ($eventData!=false);
1969
							}
1970
							if ( $continue ) {
1971
								if (!isset($ARCurrent->cacheCallChainSettings)) {
1972
									$ARCurrent->cacheCallChainSettings = array();
1973
								}
1974
								if ($ARConfig->cache[$this->path]->inConfigIni == false) {
1975
									$ARCurrent->cacheCallChainSettings[$this->id] = $config->cacheSettings;
1976
								}
1977
1978
								if ($ARCurrent->ARShowTemplateBorders) {
1979
									echo "<!-- arTemplateStart\nData: ".$this->type." ".$this->path." \nTemplate: ".$template["arCallTemplatePath"]." ".$template["arCallTemplate"]." \nLibrary:".$template["arLibrary"]." -->";
1980
								}
1981
								set_error_handler(array('pobject','pinpErrorHandler'),error_reporting());
1982
								$func = ar('template')->get($template['arCallTemplatePath'],$template['arCallTemplate']);
1983
								if(is_callable($func)){
1984
									$arResult = $func($this);
1985
								}
1986
								restore_error_handler();
1987
								if (isset($arResult)) {
1988
									$ARCurrent->arResult=$arResult;
1989
								}
1990
								if ($ARCurrent->ARShowTemplateBorders) {
1991
									echo "<!-- arTemplateEnd -->";
1992
								}
1993 View Code Duplication
								if ( !$AR->contextCallHandler ) { /* prevent oncall from re-entering here */
1994
									$AR->contextCallHandler = true;
1995
									$temp = $ARCurrent->arResult; /* event listeners will change ARCurrent->arResult */
1996
									$eventData->arResult = $temp;
1997
									ar_events::fire('oncall', $eventData );
1998
									$ARCurrent->arResult = $temp; /* restore correct result */
1999
									$AR->contextCallHandler = false;
2000
								}
2001
							}
2002
						}
2003
						array_pop($ARCurrent->arCallStack);
2004
						$this->popContext();
2005
2006
						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
						return false;
2014
					} else {
2015
						debug("pobject: CheckConfig: no such file: ".$template["arTemplateId"].$template["arCallTemplate"]."","all");
2016
					}
2017
				} else {
2018
					debug("CheckConfig: no arCallTemplate ($arCallFunction from '$this->path')","object");
2019
				}
2020
2021
			}
2022
		}
2023
		return true;
2024
	}
2025
2026
	public function ClearCache($path="", $private=true, $recurse=false) {
2027
	global $AR;
2028
		$norealnode = false;
2029
		if (!$path) {
2030
			$path=$this->path;
2031
		} else {
2032
			$realpath = current($this->get($path, "system.get.path.phtml"));
2033
			if($realpath != false) {
2034
				$path = $realpath;
2035
			} else {
2036
				$norealnode = true;
2037
			}
2038
		}
2039
2040
		if($norealnode !== true) {
2041
			/*
2042
				we don't want to recurse to the currentsite, because the path
2043
				doesn't exists in the database, so it doesn't have a currentsite
2044
2045
				the privatecache should be emptied by delete, or by the cleanup
2046
				cronjob. The current path doesn't exists in the database, so a
2047
				object id which is needed to find the node in the cache, isn't
2048
				available
2049
			*/
2050
2051
			if ($private ) {
2052
				// 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
				$pcache=$this->store->get_filestore("privatecache");
2061
				if ($recurse) {
2062
					$offset = 0;
2063
					$limit = 5000;
2064
					$ids=$this->store->info($this->store->find($path, "" , $limit, $offset));
2065
					while (is_array($ids) && count($ids)) {
2066
						foreach($ids as $value) {
2067
							$eventData = new 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
					$eventData = new baseObject();
2082
					$eventData = ar_events::fire( 'onbeforeclearprivatecache', $eventData, $this->type, $this->path );
2083
					if ( $eventData ) {
2084
						$pcache->purge($this->id);
2085
						ar_events::fire( 'onclearprivatecache', $eventData, $this->type, $this->path );
2086
					}
2087
				}
2088
			}
2089
2090
			// now clear all parents untill the current site
2091
			$site=$this->currentsite($path);
2092
			$project=$this->currentproject($path);
2093
			if ($path!=$site && $path != $project && $path!='/') {
2094
				$parent=$this->make_path($path.'../');
2095
				$this->ClearCache($parent, $private, false);
2096
			}
2097
		}
2098
		$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
		$fs_path=strtolower($path);
2104
		$nlslist=$AR->nls->list;
2105
		$nlslist["."]="default";
2106
		$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
		$cache_types[] = "compressed";
2108
		$cache_types[] = "session";
2109
2110
		global $cache_config,$store_config;
2111
		$cachestore=new cache($cache_config);
2112
2113
2114
		$filestore = $this->store->get_config("files");
2115
		foreach($cache_types as $type){
2116
			foreach($nlslist as $nls => $language){
2117
				// break away if nls doesn't exists
2118
				// is dir is cached, so it should not cost more that it add's in speed
2119
				if(!is_dir($filestore."cache/$type/$nls")){
2120
					continue;
2121
				}
2122
2123
				$fpath=$filestore."cache/$type/$nls".$fs_path;
2124
				$hpath=$filestore."cacheheaders/$type/$nls".$fs_path;
2125
				if ($dir=@dir($fpath)) {
2126
					while (false !== ($entry = $dir->read())) {
2127
						if ($entry!="." && $entry!="..") {
2128
							if (is_file($fpath.$entry)) {
2129
								@unlink($fpath.$entry);
2130
								@unlink($hpath.$entry);
2131
								$cachestore->delete("/".$type."/".$nls.$fs_path.$entry);
2132
							} else if ( $recurse && !$recursed[$entry]) {
2133
								$this->ClearCache($path.$entry."/", false, true);
2134
								$recursed[$entry]=true;
2135
							}
2136
						}
2137
					}
2138
					$dir->close();
2139
					// 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
			}
2148
		}
2149
	}
2150
2151
	public function getcache($name, $nls="") {
2152
		global $ARCurrent, $ARnls;
2153
		$result=false;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// Better
class Router
{
    private $host;

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

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

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

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

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

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

// Better
class Router
{
    private $host;

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

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

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

    return array();
}

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

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

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

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

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

// Better
class Router
{
    private $host;

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

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

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

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

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

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

// Better
class Router
{
    private $host;

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

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

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

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
2899
		} else { // older loaders and other shizzle
2900
2901
			$nls = preg_replace('/[^a-z]*/i','',$nls);
2902
			$section = preg_replace('/[^a-z0-9\._:-]*/i','',$section);
2903
			if (!$section) {
2904
				include($this->store->get_config("code")."nls/".$nls);
2905
				$this->ARnls = array_merge((array)$this->ARnls, $ARnls);
2906
			} else {
2907
				$nlsfile = $this->store->get_config("code")."nls/".$section.".".$nls;
2908
				if(strpos($nlsfile, ':') === false && file_exists($nlsfile)) {
2909
					include($nlsfile);
2910
					$this->ARnls = array_merge((array)$this->ARnls, $ARnls);
2911
				} else {
2912
					// current result;
2913
					$arResult = $ARCurrent->arResult;
2914
					$this->pushContext(array());
2915
						$oldnls = $this->reqnls;
2916
						$this->reqnls = $nls;
2917
						$this->CheckConfig($section, array('nls' => $nls));
2918
						$this->reqnls = $oldnls;
2919
					$this->popContext();
2920
					// reset current result (CheckConfig may have changed it when it should not have).
2921
					$ARCurrent->arResult = $arResult;
2922
				}
2923
			}
2924
		}
2925
	}
2926
2927
	public function _startsession() {
2928
	global $ARCurrent;
2929
		ldStartSession(0);
2930
		return $ARCurrent->session->id;
2931
	}
2932
2933
	public function _putsessionvar($varname, $varvalue) {
2934
	global $ARCurrent;
2935
2936
		if ($ARCurrent->session) {
2937
			return $ARCurrent->session->put($varname, $varvalue);
2938
		} else {
2939
			return false;
2940
		}
2941
	}
2942
2943
	public function _getsessionvar($varname) {
2944
	global $ARCurrent;
2945
2946
		if ($ARCurrent->session) {
2947
			return $ARCurrent->session->get($varname);
2948
		} else {
2949
			return false;
2950
		}
2951
	}
2952
2953
	public function _setsessiontimeout($timeout = 0) {
2954
	global $ARCurrent;
2955
		if ($ARCurrent->session) {
2956
			return $ARCurrent->session->setTimeout($timeout);
2957
		} else {
2958
			return false;
2959
		}
2960
	}
2961
2962
	public function _killsession() {
2963
	global $ARCurrent;
2964
2965
		if ($ARCurrent->session) {
2966
			$ARCurrent->session->kill();
2967
			unset($ARCurrent->session);
2968
		}
2969
	}
2970
2971
	public function _sessionid() {
2972
	global $ARCurrent;
2973
		if ($ARCurrent->session) {
2974
			return $ARCurrent->session->id;
2975
		} else {
2976
			return 0;
2977
		}
2978
	}
2979
2980
	public function _resetloopcheck() {
2981
		return $this->resetloopcheck();
2982
	}
2983
2984
	public function _make_path($path="") {
2985
		return $this->make_path($path);
2986
	}
2987
2988
	public function _make_ariadne_url($path="") {
2989
		return $this->make_ariadne_url($path);
2990
	}
2991
2992
	public function _make_url($path="", $nls=false, $session=true, $https=null, $keephost=null) {
2993
		return $this->make_url($path, $nls, $session, $https, $keephost);
2994
	}
2995
2996
	public function _make_local_url($path="", $nls=false, $session=true, $https=null) {
2997
		return $this->make_local_url($path, $nls, $session, $https);
2998
	}
2999
3000
	public function _getcache($name, $nls='') {
3001
		return $this->getcache($name, $nls);
3002
	}
3003
3004
	public function _cached($name, $nls='') {
3005
		return $this->cached($name, $nls);
3006
	}
3007
3008
	public function _savecache($time="") {
3009
		return $this->savecache($time);
3010
	}
3011
3012
	public function _getdatacache($name) {
3013
		return $this->getdatacache($name);
3014
	}
3015
3016
	public function _savedatacache($name,$data,$time="")
3017
	{
3018
		return $this->savedatacache($name,$data,$time);
3019
	}
3020
3021
	public function currentsite($path="", $skipRedirects = false) {
3022
		global $ARCurrent, $ARConfig;
3023
		if (!$path) {
3024
			$path=$this->path;
3025
		}
3026
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3027
		if (!$skipRedirects && @count($ARCurrent->shortcut_redirect)) {
3028
			$redir = end($ARCurrent->shortcut_redirect);
3029
			if ($redir["keepurl"] && substr($path, 0, strlen($redir["dest"])) == $redir["dest"]) {
3030
				if (substr($config->site, 0, strlen($redir["dest"]))!=$redir["dest"]) {
3031
					// search currentsite from the reference
3032
					$config = ($ARConfig->cache[$redir['src']]) ? $ARConfig->cache[$redir['src']] : $this->loadConfig($redir['src']);
3033
				}
3034
			}
3035
		}
3036
		return $config->site;
3037
	}
3038
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 View Code Duplication
	public function currentsection($path="") {
3047
	global $ARConfig;
3048
		if (!$path) {
3049
			$path=$this->path;
3050
		}
3051
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3052
		return $config->section;
3053
	}
3054
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 View Code Duplication
	public function currentproject($path="") {
3063
	global $ARConfig;
3064
		if (!$path) {
3065
			$path=$this->path;
3066
		}
3067
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3068
		return $config->project;
3069
	}
3070
3071
	public function parentproject($path) {
3072
	global $ARConfig;
3073
		$path=$this->store->make_path($path, "..");
3074
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3075
		return $config->project;
3076
	}
3077
3078
	public function validateFormSecret() {
3079
		global $ARCurrent;
3080
		if (!$ARCurrent->session) {
3081
			return true;
3082
		}
3083
3084
		if ($ARCurrent->session && $ARCurrent->session->data && $ARCurrent->session->data->formSecret) {
3085
			$formSecret = $this->getvar("formSecret");
3086
			return ($formSecret === $ARCurrent->session->data->formSecret);
3087
		}
3088
		return false;
3089
	}
3090
3091
	public function _validateFormSecret() {
3092
		return $this->validateFormSecret();
3093
	}
3094
3095
	public function getValue($name, $nls=false) {
3096
	global $ARCurrent;
3097
		switch ($nls) {
3098
			case "none":
3099
				$result = $this->data->$name;
3100
			break;
3101
			case false:
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
Bug introduced by
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
Bug introduced by
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
	public function _load($class) {
3261
		// only allow access to modules in the modules directory.
3262
		$class = preg_replace('/[^a-z0-9\._]/i','',$class);
3263
		include_once($this->store->get_config("code")."modules/".$class);
3264
	}
3265
3266
	public function _import($class) {
3267
		// deprecated
3268
		return $this->_load($class);
3269
	}
3270
3271
	public function html_to_text($text) {
3272
		$trans = array_flip(get_html_translation_table(HTML_ENTITIES));
3273
		$cb  = function($matches) use ($trans) {
3274
			return strtr($matches[1],$trans);
3275
		};
3276
		//strip nonbreaking space, strip script and style blocks, strip html tags, convert html entites, strip extra white space
3277
		$search_clean = array("%&nbsp;%i", "%<(script|style)[^>]*>.*?<\/(script|style)[^>]*>%si", "%<[\/]*[^<>]*>%Usi", "%\s+%");
3278
		$replace_clean = array(" ", " ", " ", " ");
3279
3280
		$text = preg_replace_callback(
3281
			"%(\&[a-zA-Z0-9\#]+;)%s",
3282
			$cb,
3283
			$text
3284
		);
3285
		$text = preg_replace($search_clean, $replace_clean, $text);
3286
		return $text;
3287
	}
3288
3289
	public function _html_to_text($text) {
3290
		return $this->html_to_text($text);
3291
	}
3292
3293
	public function _newobject($filename, $type) {
3294
		$newpath=$this->make_path($filename);
3295
		$newparent=$this->store->make_path($newpath, "..");
3296
		$data=new 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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
3338
	}
3339
3340
	public function _is_supported($feature) {
3341
		return $this->store->is_supported($feature);
3342
	}
3343
3344
	/*
3345
		since the preg_replace() function is able to execute normal php code
3346
		we have to intercept all preg_replace() calls and parse the
3347
		php code with the pinp parser.
3348
	*/
3349
3350
3351
	/*	this is a private function used by the _preg_replace wrapper */
3352
	// FIXME: remove this function when the minimal php version for ariadne is raised to php 7.0
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
		return $this->loadLibrary($name, $path);
3402
	}
3403
3404
	public function _resetConfig($path='') {
3405
		return $this->resetConfig($path);
3406
	}
3407
3408
	public function _getLibraries($path = '') {
3409
		return $this->getLibraries($path);
3410
	}
3411
3412
3413
	public function _getSetting($setting) {
3414
	global $AR;
3415
3416
		switch ($setting) {
3417
			case 'www':
3418
			case 'dir:www':
3419
				return $AR->dir->www;
3420
			case 'images':
3421
			case 'dir:images':
3422
				return $AR->dir->images;
3423
			case 'ARSessionKeyCheck':
3424
				$result = null;
3425
				if (function_exists('ldGenerateSessionKeyCheck')) {
3426
					$result = ldGenerateSessionKeyCheck();
3427
				}
3428
				return $result;
3429
			break;
3430
			case 'nls:list':
3431
				return $AR->nls->list;
3432
			break;
3433
			case 'nls:default':
3434
				return $AR->nls->default;
3435
			break;
3436
			case 'svn':
3437
				return $AR->SVN->enabled;
3438
			break;
3439
		}
3440
	}
3441
3442
	public function __call($name,$arguments) {
3443
		if ( $name[0] == '_' ) {
3444
			$fname = substr($name, 1);
3445
			if ( isset($this->{$fname}) && $this->{$fname} instanceof \Closure ) {
3446
				\Closure::bind( $this->{$fname}, $this );
3447
				return call_user_func_array( $this->{$fname}, $arguments);
3448
			}
3449
		}
3450
		switch($name) {
3451
			case "implements":
3452
				return $this->AR_implements($arguments[0]);
3453
			break;
3454
			default:
3455
				trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $name), E_USER_ERROR);
3456
				return false;
3457
			break;
3458
		}
3459
	}
3460
3461
	static public function pinpErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) {
0 ignored issues
show
Unused Code introduced by
The parameter $errfile is not used and could be removed.

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

Loading history...
Unused Code introduced by
The parameter $errcontext is not used and could be removed.

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

Loading history...
3462
		global $nocache;
3463
		if (($errno & error_reporting()) == 0) {
3464
			return true;
3465
		}
3466
3467
		$nocache = true;
3468
		$context = pobject::getContext();
3469
		if ($context["arLibraryPath"]) { //  != null) {
3470
			$msg = "Error on line $errline in ".$context['arCallTemplateType'].'::'.$context['arCallFunction'] ." in library ".$context["arLibraryPath"] ."\n".$errstr."\n";
3471
		} else {
3472
			$msg = "Error on line $errline in ".$context['arCallTemplateType'].'::'.$context['arCallFunction'] ." on object ".$context['arCurrentObject']->path."\n".$errstr."\n";
3473
		}
3474
		$display = ini_get('display_errors');
3475
3476
		if($display) {
3477
			echo $msg;
3478
		}
3479
		error_log($msg);
3480
3481
		return false;
3482
	}
3483
3484
} // end of ariadne_object class definition
3485