Completed
Push — master ( db26d9...e5ef44 )
by Auke
15s
created

lib/objects/ariadne_object.php (19 issues)

Upgrade to new PHP Analysis Engine

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

1
<?php
2
    /******************************************************************
3
     pobject.phtml                                         Muze Ariadne
4
     ------------------------------------------------------------------
5
     Author: Muze ([email protected])
6
     Date: 31 october 2002
7
8
     Copyright 2002 Muze
9
10
     This file is part of Ariadne.
11
12
     Ariadne is free software; you can redistribute it and/or modify
13
     it under the terms of the GNU General Public License as published
14
     by the Free Software Foundation; either version 2 of the License,
15
     or (at your option) any later version.
16
17
     Ariadne is distributed in the hope that it will be useful,
18
     but WITHOUT ANY WARRANTY; without even the implied warranty of
19
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
     GNU General Public License for more details.
21
22
     You should have received a copy of the GNU General Public License
23
     along with Ariadne; if not, write to the Free Software
24
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25
     02111-1307  USA
26
27
    -------------------------------------------------------------------
28
29
     Class inheritance: 	pobject
30
     Description:
31
32
       This is the class definition file of the pobject class.
33
34
    ******************************************************************/
35
36
debug("pobject: Load","object");
37
38
abstract class ariadne_object extends object { // ariadne_object class definition
39
40
	public $store;
41
	public $path;
42
	public $data;
43
44 184
	public function init($store, $path, $data) {
45 184
		$this->store=$store;
46 184
		$this->path=$path;
47 184
		$this->data=$data;
48 184
		if ( !isset($this->data->config) ) {
49 28
			$this->data->config = new object();
50 21
		}
51 184
	}
52
53 184
	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 184
	global $AR, $ARConfig, $ARCurrent, $ARBeenHere, $ARnls;
72
73 184
		if ( $arCallFunction instanceof \Closure ) {
74 4
			$arCallFunctionName = 'Closure';
75 9
		} else {
76 184
			$arCallFunctionName = (string) $arCallFunction;
77
		}
78 184
		debug("pobject: ".$this->path.": call($arCallFunctionName, ".debug_serialize($arCallArgs).")","object","all","IN");
79
80
		// default to view.html
81 184
		if (!$arCallFunction) {
82 15
			$arCallFunction="view.html";
83
		}
84
		// clear previous results
85 184
		unset($ARCurrent->arResult);
86
87
		// callstack is needed for getvar()
88 184
		$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 184
		$this->pushContext( array(
91 184
			"arSuperContext" => array(),
92 184
			"arCurrentObject" => $this,
93 184
			"scope" => "php",
94 46
			"arCallFunction" => $arCallFunction
95 138
		) );
96
97
		// convert the deprecated urlencoded arguments to an array
98 184
		if (isset($arCallArgs) && is_string($arCallArgs)) {
99 184
			$ARCurrent->arTemp=$arCallArgs;
100 184
			$arCallArgs=array();
101 184
			parse_str($ARCurrent->arTemp, $arCallArgs);
102 138
		}
103
		// import the arguments in the current scope, but don't overwrite existing
104
		// variables.
105 184
		if (isset($arCallArgs) && is_array($arCallArgs)) {
106 184
			extract($arCallArgs,EXTR_SKIP);
107 138
		}
108
		// now find the initial nls selection (CheckConfig is needed for per
109
		// tree selected defaults)
110 184
		if ($ARCurrent->nls) {
111
			$this->reqnls=$ARCurrent->nls;
112 184
		} else if (isset($ARConfig->cache[$this->path]) && $ARConfig->cache[$this->path]->nls->default) {
113 100
			$this->reqnls = $ARConfig->cache[$this->path]->nls->default;
114 75
		} else {
115 184
			$this->reqnls=$AR->nls->default;
116
		}
117 184
		if (isset($this->data->nls->list[$this->reqnls]) || !isset($this->data->nls)) {
118
			// the requested language is available
119 184
			$this->nls=$this->reqnls;
120 184
			$nls=&$this->nls;
121 138
		} else {
122
			// the requested language is not available, use default of the
123
			// current object instead.
124
			$this->nls=$this->data->nls->default;
125 3
			$nls=&$this->nls;
126
		}
127 184
		if ($nls && isset($this->data->$nls)) {
128
			// now set the data and nlsdata pointers
129 132
			$this->nlsdata=$this->data->$nls;
130 132
			$nlsdata=&$this->nlsdata;
131 132
			$data=&$this->data;
132 99
		} else {
133
			// this object doesn't support nls data
134 184
			$this->nlsdata=$this->data;
135 184
			$nlsdata=&$this->data;
136 184
			$data=&$this->data;
137 3
		}
138 184
		if (isset($this->data->custom['none'])) {
139 7
			$customdata=$this->data->custom['none'];
140 6
		}
141 184
		if (isset($this->data->custom[$nls])) {
142
			$customnlsdata=$this->data->custom[$nls];
143
		}
144
145 184
		$arCallFunctionOrig = $arCallFunction;
146 184
		if (strpos($arCallFunctionName,"::")!==false) {
147
			// template of a specific class defined via call("class::template");
148 24
			list($arType, $arCallFunction)=explode("::",$arCallFunctionName);
149 24
			$temp = explode(":", $arType );
150 24
			if( count($temp) > 1 ) {
151
				$libname = $temp[0];
152
				$arType = $temp[1];
153 6
				$arCallFunction = $libname.":".$arCallFunction;
154
			}
155 18
		} else {
156 184
			$arType=$this->type;
157
		}
158
159 184
		if ( $arCallFunction instanceof \Closure ) {
160 4
			$context = $this->getContext(ARCALLINGCONTEXT);
161 4
			if ( $context["scope"] != "pinp" ) {
162
				$arResult = $arCallFunction($this );
163
			} else {
164 4
				if ( $this->CheckSilent('read') ) {
165 4
					$arResult = $arCallFunction($this);
166 3
				}
167
			}
168 3
		} else {
169 184
			if ($arCallFunction[0] === "#") {
170 15
				$ARCurrent->arCallClassTemplate = true;
171
				$arCallFunction = substr($arCallFunction, 1);
172
			} else {
173 184
				$ARCurrent->arCallClassTemplate = false;
174
			}
175
176 184
			if( $arCallFunction == "system.get.phtml" && ( $context = $this->getContext(ARCALLINGCONTEXT) ) && $context["scope"] != "pinp" ) {
177 35
				$arResult = $this;
178 24
			} else {
179 184
				$libtemplate = strpos($arCallFunction,":");
180 184
				$codedir = $this->store->get_config("code");
181
182
				// if it is a subtype object, disk templates do not exists,
183 184
				$subcpos = strpos($arType, '.');
184 184
				if ($subcpos !== false ) {
185
					// subtype, skip looking for templates
186 24
					$arSuper = substr($arType, 0, $subcpos);
187 24
					if(!isset($AR->superClass[$arType])){
188 4
						$AR->superClass[$arType]=$arSuper;
189 3
					}
190 24
					$arType=$arSuper;
191 18
				}
192
193 184
				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 184
					$arCallTemplate=$codedir."templates/".$arType."/".$arCallFunction;
198 184
					if ($libtemplate === false && file_exists($arCallTemplate)) {
199
						//debug('found '.$arCallTemplate, 'all');
200
						// template found
201 184
						$arCallFunction = $arCallFunctionOrig;
202 184
						include($arCallTemplate);
203 184
						break;
204 184
					} 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 8
						include($this->store->get_config("code")."templates/".$arType."/default.phtml");
208 11
						break;
209 18
					} else {
210 184
						if (!($arSuper=$AR->superClass[$arType])) {
211
							// no template found, no default.phtml found, try superclass.
212
213 8
							if (!class_exists($arType, false)) {
214
								// the given class was not yet loaded, so do that now
215
								$this->store->newobject('','',$arType,new object);
216
							}
217 11
							$arSuper=get_parent_class($arType);
218
219 26
							$AR->superClass[$arType]=$arSuper;
220 6
						}
221 184
						$arType=$arSuper;
222 3
					}
223 138
				}
224
			}
225 3
		}
226 184
		array_pop($ARCurrent->arCallStack);
227 184
		$this->popContext();
228 184
		debug("pobject: call: end","all","all","OUT");
229 184
		if (isset($ARCurrent->arResult)) {
230
			// pinp templates can return results via putvar("arResult",$result);
231 20
			$arResult=$ARCurrent->arResult;
232 20
			unset($ARCurrent->arResult);
233 15
		}
234 184
		if (isset($arResult)) {
235
			// only do a return if we really have something to return
236 184
			return $arResult;
237
		}
238 24
	}
239
240 3
	public function ls($path="", $function="list.html", $args="") {
241 3
		$path=$this->store->make_path($this->path, $path);
242 3
		return $this->store->call($function, $args, $this->store->ls($path));
243 3
	}
244
245 56
	public function get($path, $function="view.html", $args="") {
246 56
		$path=$this->store->make_path($this->path, $path);
247 56
		return $this->store->call($function, $args, $this->store->get($path));
248 3
	}
249
250 7
	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 4
		if (!$top) {
254 7
			$top = $this->currentsection();
255 3
		} else {
256 7
			$top = $this->store->make_path($this->path, $top);
257
		}
258
259 4
		$path=$this->store->make_path($this->path, $path);
260
261 4
		if ($path != $this->path ) {
262 4
			$target = current($this->get($path,"system.get.phtml"));
263 3
		} else {
264 4
			$target = $this;
265
		}
266
267 4
		$parents = array();
268 4
		if (strpos($target->path, $top) === 0) {
269 4
			$parents[] = $target;
270 4
			while ($target && $target->path != $top) {
271 4
				$target = current($target->get($target->parent, "system.get.phtml"));
272 4
				$parents[] = $target;
273 6
			}
274 3
		}
275 4
		$parents = array_reverse($parents);
276 4
		$result = array();
277 7
		foreach ($parents as $parent) {
278 4
			if ( $parent ) { // might not have read access to this object
279 4
				$result[] = $parent->call($function, $args);
280 3
			}
281 3
		}
282
283 4
		return $result;
284
	}
285
286 4
	public function find($path, $criteria, $function="list.html", $args="", $limit=100, $offset=0) {
287 4
		$path = $this->store->make_path($this->path, $path);
288 4
		$objects = $this->store->find($path, $criteria, $limit, $offset);
289 4
		if (!$this->store->error) {
290 4
			$result = $this->store->call($function, $args, $objects);
291 3 View Code Duplication
		} else {
292
			$this->error = ar::error( ''.$this->store->error, 1110, $this->store->error );
293
			$result = false;
294 3
		}
295 4
		return $result;
296
	}
297
298
	public function count_find($path='', $query='') {
299
		$path=$this->store->make_path($this->path, $path);
300
		if (method_exists($this->store, 'count_find')) {
301
			$result = $this->store->count_find($path, $query, 0);
302
		} else {
303
			$result = $this->store->count($this->store->find($path, $query, 0));
304
		}
305
		return $result;
306
	}
307
308
	public function count_ls($path) {
309
		return $this->store->count($this->store->ls($path));
310
	}
311
312 3
	private function saveMergeWorkflowResult($properties, $wf_result) {
313
		foreach ($wf_result as $wf_prop_name => $wf_prop) {
314
			foreach ($wf_prop as $wf_prop_index => $wf_prop_record) {
315
				if (!isset($wf_prop_record)) {
316
					unset($properties[$wf_prop_name][$wf_prop_index]);
317
				} else {
318
					$record = array();
319 View Code Duplication
					foreach ($wf_prop_record as $wf_prop_field => $wf_prop_value) {
320
						switch (gettype($wf_prop_value)) {
321 3
							case "integer":
322
							case "boolean":
323
							case "double":
324
								$value = $wf_prop_value;
325
								break;
326
							default:
327
								$value = $wf_prop_value;
328
								// backwards compatibility, store will do the escaping from now on
329
								// will be removed in the future
330
								if (substr($wf_prop_value, 0, 1) === "'" && substr($wf_prop_value, -1) === "'"
331
										&& "'".AddSlashes(StripSlashes(substr($wf_prop_value, 1, -1)))."'" == $wf_prop_value) {
332
									$value = stripSlashes(substr($wf_prop_value,1,-1));
333
									// todo add deprecated warning
334
								}
335
336 3
						}
337
						$record[$wf_prop_field] = $value;
338
					}
339
					$properties[$wf_prop_name][] = $record;
340
				}
341
			}
342
		}
343
344
		return $properties;
345
	}
346
347
	/*
348
		saves custom data
349
		returns properties for custom data
350
	*/
351 50
	private function saveCustomData($configcache, $properties) {
352 50
		$custom = $this->getdata("custom", "none");
353 48
		@parse_str($custom);
354 48
		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 48
		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 48
		return $properties;
398
	}
399
400 51
	public function save($properties="", $vtype="") {
401
	/***********************************************************************
402
	  save the current object.
403
	  if this is a new object ($this->arIsNewObject) the path is checked and
404
	  the object is saved under the new path.
405
	***********************************************************************/
406 48
	global $AR, $ARnls, $ARCurrent;
407 48
		debug("pobject: save([properties], $vtype)","object");
408 48
		debug("pobject: save: path=".$this->path,"object");
409 48
		$configcache=$this->loadConfig();
410 50
		$needsUnlock = false;
411 48
		$arIsNewObject = false;
412 48
		$result = false;
413 48
		$this->error = '';
414 48
		if ($this->arIsNewObject) { // save a new object
415 24
			debug("pobject: save: new object","all");
416 24
			$this->path = $this->make_path();
417 24
			$arNewParent=$this->make_path("..");
418 24
			$arNewFilename=basename($this->path);
419 24
			$arIsNewObject = true;
420 24
			if (preg_match("|^[a-z0-9_\{\}\.\:-]+$|i",$arNewFilename)) { // no "/" allowed, these will void the 'add' grant check.
421 24
				if (!$this->exists($this->path)) { //arNewFilename)) {
422 24
					if ($this->exists($arNewParent)) {
423 24
						if (!$config = $this->data->config) {
424 6
							$config=new object();
425
						}
426 18
					} else {
427 6
						$this->error = ar::error( sprintf($ARnls["err:noparent"],$arNewParent), 1102);
428
					}
429 18
				} else {
430 6
					$this->error = ar::error( sprintf($ARnls["err:alreadyexists"],$arNewFilename), 1103);
431
				}
432 18
			} else {
433 6
				$this->error = ar::error( sprintf($ARnls["err:fileillegalchars"],$arNewFilename), 1104);
434
			}
435 18
		} else { // existing object
436 48
			debug("pobject: save: existing object","all");
437 48
			if ($this->exists($this->path)) { // prevent 'funny stuff'
438 48
				if (!$this->lock()) {
439
					$this->error = ar::error( $ARnls["err:objectalreadylocked"], 1105);
440
				} else {
441 48
					$needsUnlock = true;
442 48
					$config = $this->data->config;
443
				}
444 36
			} else {
445
				$this->error = ar::error($ARnls["err:corruptpathnosave"], 1106);
446
			}
447
		}
448
		// pre checks done
449
		// return now on error
450 48
		if ($this->error) {
451
			return $result;;
452
		}
453
454
455 48
		if ($ARCurrent->arCallStack) {
456 48
			$arCallArgs = end($ARCurrent->arCallStack);
457 36
		} else {
458 20
			$arCallArgs = array();
459
		}
460
461 48
		$context = $this->getContext();
462
463 48
		$wf_object = $this->store->newobject($this->path, $this->parent, $this->type, $this->data, $this->id, $this->lastchanged, $this->vtype, 0, $this->priority);
464 48
		if ( $arIsNewObject) {
465 24
			$wf_object->arIsNewObject=$arIsNewObject;
466 18
		}
467
468
		/* save custom data */
469 48
		$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 48
		$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $wf_object));
473
474 48
		$eventData = new object();
475 48
		$eventData->arCallArgs = $arCallArgs;
476 48
		$eventData->arCallFunction	= $context['arCallFunction'];
477 48
		$eventData->arIsNewObject = $arIsNewObject;
478 48
		$eventData->arProperties = $properties;
479 48
		$eventData = ar_events::fire( 'onbeforesave', $eventData );
480
481
		// pop the wf_object, not needed later, the extra scope might hinder other code
482 48
		$this->popContext();
483
484 48
		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 48
		$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 48
		if (isset( $eventData->arProperties ) && is_array( $eventData->arProperties ) ) {
495 49
			$properties = $eventData->arProperties;
496 36
		} else {
497 44
			$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 48
		$arCallArgs['properties'] = $properties;
505 48
		$wf_result = $wf_object->call("user.workflow.pre.html", $arCallArgs);
506
		/* merge workflow properties */
507 48
		if (isset($wf_result) && is_array($wf_result) ){
508
			$properties = $this->saveMergeWorkflowResult($properties,$wf_result);
509
		}
510
511 48
		$this->error = $wf_object->error;
512 48
		$this->priority = $wf_object->priority;
513 48
		$this->data = $wf_object->data;
514 48
		$this->data->config = $config;
515 48
		$this->data->mtime=time();
516 48
		if($arIsNewObject) {
517 24
			$this->data->ctime=$this->data->mtime;
518 18
		}
519
520 48
		$this->data->muser=$AR->user->data->login;
521 48
		if( !$this->data->config->owner ) {
522 24
			if( !$this->data->config->owner_name) {
523 24
				$this->data->config->owner_name=$AR->user->data->name;
524 18
			}
525 24
			$this->data->config->owner=$AR->user->data->login;
526 24
			$properties["owner"][0]["value"]=$this->data->config->owner;
527 18
		}
528 48
		$properties["time"][0]["ctime"]=$this->data->ctime;
529 48
		$properties["time"][0]["mtime"]=$this->data->mtime;
530 48
		$properties["time"][0]["muser"]=$this->data->muser;
531
532
533 48
		if (!$this->error) {
534 48
			if ($this->path=$this->store->save($this->path, $this->type, $this->data, $properties, $vtype, $this->priority)) {
535 48
				unset($this->arIsNewObject);
536 48
				$this->id=$this->exists($this->path);
537 48
				$result=$this->path;
538
539 48
				$config=$this->data->config; // need to set it again, to copy owner config data
540
541 48
				$wf_object = $this->store->newobject($this->path, $this->parent, $this->type, $this->data, $this->id, $this->lastchanged, $this->vtype, 0, $this->priority);
542 48
				$arCallArgs = $eventData->arCallArgs; // returned from onbeforesave event
543 48
				$arCallArgs['properties'] = $properties;
544
545 48
				if ($arIsNewObject) {
546 24
					$wf_object->arIsNewObject = $arIsNewObject;
547 18
				}
548 48
				$wf_result = $wf_object->call("user.workflow.post.html", $arCallArgs);
549 48
				$this->error = $wf_object->error;
550 48
				$this->priority = $wf_object->priority;
551 48
				$this->data = $wf_object->data;
552 48
				$this->data->config = $config;
553
				/* merge workflow properties */
554
555 48
				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 48
				$this->data->config = $config;
565
566
				//$this->ClearCache($this->path, true, false);
567 48
				$eventData->arProperties = $properties;
568 48
				$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $this));
569 48
				ar_events::fire( 'onsave', $eventData ); // nothing to prevent here, so ignore return value
570 48
				$this->popContext();
571 36 View Code Duplication
			} else {
572
				$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
573
				$result = false;
574
			}
575 36
		}
576 48
		if( $needsUnlock == true ){
577 48
			$this->unlock();
578 36
		}
579
580 48
		if ($this->data->nls->list[$this->nls]) {
581 48
			$mynlsdata=$this->data->{$this->nls};
582 36
		} else if ($this->data->nls->default) {
583
			$mynlsdata=$this->data->{$this->data->nls->default};
584
		} else {
585
			$mynlsdata=$this->data;
586
		}
587
588 48
		unset($this->nlsdata);
589 48
		$this->nlsdata=$mynlsdata;
590
591 48
		debug("pobject: save: end","all");
592 48
		return $result;
593
	}
594
595
	public function link($to) {
596
		return $this->store->link($this->path, $this->make_path($to));
597
	}
598
599
	public function delete() {
600
	global $ARCurrent;
601
		$result	= false;
602
		$this->error = '';
603
		if ($ARCurrent->arCallStack) {
604
			$arCallArgs = end($ARCurrent->arCallStack);
605
		} else {
606
			$arCallArgs = array();
607
		}
608
		$context = $this->getContext();
609
610
		$eventData = new object();
611
		$eventData->arCallArgs = $arCallArgs;
612
		$eventData->arCallFunction = $context['arCallFunction'];
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 56
	public function exists($path) {
631 56
		$path=$this->make_path($path);
632 56
		return $this->store->exists($path);
633
	}
634
635 72
	public function make_path($path="") {
636
		switch($path){
637 72
			case '':
638 72
			case '.':
639 70
			case $this->path:
640 72
				return $this->path;
641
				break;
642 60
			case '..':
643 24
				return $this->parent;
644
				break;
645 45
			default:
646 60
				return $this->store->make_path($this->path, $path);
647 45
		}
648
	}
649
650
	public function make_ariadne_url($path="") {
651
		global $AR;
652
		$path = $this->make_path($path);
653
		return $AR->host . $AR->root . $this->store->get_config('rootoptions') . $path;
654
	}
655
656
657 52
	public function make_url($path="", $nls=false, $session=true, $https=null, $keephost=null) {
658 52
		global $ARConfig, $AR, $ARCurrent;
659
660 52
		$rootoptions=$this->store->get_config('rootoptions');
661 52
		if (!$session || ($nls !== false)) {
662 52
			$rootoptions = "";
663 52
			if ($session && isset($ARCurrent->session->id) && !$AR->hideSessionIDfromURL) {
664
				$rootoptions .= "/-".$ARCurrent->session->id."-";
665
			}
666 52
			if ($nls) {
667 48
				$rootoptions_nonls = $rootoptions;
668 48
				$rootoptions .= '/'.$nls;
669 36
			}
670 39
		}
671 52
		$path=$this->make_path($path);
672
673
		// now run CheckConfig and get the parentsite of the path found
674 52
		if (!$temp_config=$ARConfig->cache[$path]) {
675 4
			$temp_path = $path;
676 4
			while (!($temp_site = $this->currentsite($temp_path)) && $temp_path!='/') {
677
				$temp_path = $this->make_path($temp_path.'../');
678
			}
679 4
			$temp_config=$ARConfig->cache[$temp_site];
680 3
		}
681
682 52
		if ( !isset($keephost) && (
683 52
			(!$nls && $this->compare_hosts($AR->host, $temp_config->root["value"])) ||
684 52
			($nls && ($this->compare_hosts($AR->host, $temp_config->root['list']['nls'][$nls])))
685 39
		)) {
686
			$keephost = false;
687
		}
688
689 52
		if (!$keephost) {
690 52
			if ($nls) {
691 48
				$url=$temp_config->root["list"]["nls"][$nls];
692 48
				if (isset($url) && is_array($url)) {
693
					$url = current( $url );
694
				}
695 48
				if ($url) {
696 View Code Duplication
					if (substr($url, -1)=='/') {
697
						$url=substr($url, 0, -1);
698
					}
699
					$url .= $rootoptions_nonls;
700
				}
701 36
			}
702 52
			if (!$url) {
703 52
				$checkNLS = $nls;
704 52
				if (!$checkNLS) {
705 28
					$checkNLS = $this->nls;
706 21
				}
707 52
				$urlList = $temp_config->root['list']['nls'][$checkNLS];
708 52
				if (isset($urlList) && is_array($urlList)) {
709
					$url = reset($urlList) . $rootoptions;
710
				} else {
711 52
					$url = $temp_config->root["value"].$rootoptions;
712
				}
713 39
			}
714 52
			$url.=substr($path, strlen($temp_config->root["path"])-1);
715
716 52
			if (is_bool($https)) {
717
				if ($https) {
718
					if ($AR->https) {
719
						$url = preg_replace('/^http:/', 'https:', $url);
720
					}
721
				} else {
722 13
					$url = preg_replace('/^https:/', 'http:', $url);
723
				}
724
			}
725 39
		} else {
726 48
			$checkNLS = $nls;
727 48
			if (!$checkNLS) {
728
				$checkNLS = $this->nls;
729
			}
730 48
			$urlCheck = $temp_config->root['list']['nls'][$checkNLS];
731 48
			if (!is_array($urlCheck)) {
732 48
				$urlCheck = $temp_config->root["value"];
733 36
			}
734 48
			$requestedHost = ldGetRequestedHost();
735 48
			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 48
				$url = $protocol . $requestedHost . $AR->root . $rootoptions . $path;
741
			}
742
		}
743 52
		return $url;
744
	}
745
746 52
	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 52
		if (isset($url2) ) {
750 52
			if ( !is_array($url2) ){
751 52
				$url2 = array($url2);
752 39
			}
753 39
		} else {
754 48
			$url2 = array();
755
		}
756
757 52
		$prepurl1 = preg_replace('|^[a-z:]*//|i', '', $url1);
758
759 52
		foreach($url2 as $url) {
760
			if (
761 52
					$url == $url1 ||
762 52
					$prepurl1 == preg_replace('|^[a-z:]*//|i', '', $url2)
763 39
				) {
764 13
				return true;
765
			}
766 39
		}
767 52
		return false;
768
	}
769
770 48
	public function make_local_url($path="", $nls=false, $session=true, $https=null) {
771 48
		global $ARCurrent, $ARConfig;
772 48
		$site = false;
773 48
		$path = $this->make_path($path);
774 48
		$checkpath = $path;
775
776 48
		$redirects = $ARCurrent->shortcut_redirect;
777 48
		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'];
788
			}
789
		}
790
791
		do {
792 48 View Code Duplication
			if (!$config=$ARConfig->cache[$checkpath]) {
793
				$config=($ARConfig->cache[$checkpath]) ? $ARConfig->cache[$checkpath] : $this->loadConfig($checkpath);
794
			}
795 48
			if ($config) {
796 48
				$checkNLS = $nls;
797 48
				if (!$checkNLS) {
798
					$checkNLS = $this->nls;
799
				}
800 48
				$urlCheck = $config->root['list']['nls'][$checkNLS];
801 48
				if (!is_array($urlCheck)) {
802 48
					$urlCheck = $config->root["value"];
803 36
				}
804 48
				$requestedHost = ldGetRequestedHost();
805
806 48
				if ($this->compare_hosts($requestedHost, $urlCheck)) {
807
					$site=$config->site;
808
				}
809 36
			}
810 48
			$prevpath=$checkpath;
811 48
			$checkpath=$this->make_path($checkpath."../");
812 48
		} while ($prevpath!=$checkpath && !$site);
813 48
		if (!$site) {
814 48
			$site='/';
815 36
		}
816 48
		$site_url=$this->make_url($site, $nls, $session, $https, true);
817 48
		if ($newpath) { // $newpath is the destination of a shortcut redirection, with keepurl on
818
			$rest=substr($newpath, strlen($site));
819
		} else {
820 48
			$rest=substr($path, strlen($site));
821
		}
822 48
		return $site_url.$rest;
823
	}
824
825
	public function AR_implements($implements) {
826
		$type = current(explode(".",$this->type));
827
		return $this->store->AR_implements($type, $implements);
828
	}
829
830 View Code Duplication
	public function getlocks() {
831
		global $AR;
832
		if ($this->store->mod_lock) {
833
			$result=$this->store->mod_lock->getlocks($AR->user->data->login);
834
		} else {
835
			$result="";
836
		}
837
		return $result;
838
	}
839
840 48 View Code Duplication
	public function lock($mode="O", $time=0) {
841 48
	global $AR;
842 48
		if ($this->store->mod_lock) {
843 48
			$result=$this->store->mod_lock->lock($AR->user->data->login,$this->path,$mode,$time);
844 36
		} else {
845
			$result=true; // no lock module, so lock is 'set'
846
		}
847 48
		return $result;
848
	}
849
850 48 View Code Duplication
	public function unlock() {
851 48
	global $AR;
852 48
		if ($this->store->mod_lock) {
853 48
			$result=$this->store->mod_lock->unlock($AR->user->data->login,$this->path);
854 36
		} else {
855
			$result=true;
856
		}
857 48
		return $result;
858
	}
859
860
	public function touch($id=0, $timestamp=-1) {
861
		if (!$id) {
862
			$id = $this->id;
863
		}
864
		$result = $this->store->touch($id, $timestamp);
865 View Code Duplication
		if ($this->store->error) {
866
			$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
867
		}
868
		return $result;
869
	}
870
871
	public function mogrify($id=0, $type, $vtype=null) {
872
		if (!$id) {
873
			$id = $this->id;
874
		}
875
		if (!$vtype) {
876
			$vtype = $type;
877
		}
878
		if (strpos($vtype, '.')!==false) {
879
			$vtype = substr($vtype, 0, strpos($vtype, '.'));
880
		}
881
		$result = $this->store->mogrify($id, $type, $vtype);
882 View Code Duplication
		if ($this->store->error) {
883
			$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
884
		}
885
		return $result;
886
	}
887
888
	public function can_mogrify() {
889
		if ($this->path == "/system/users/admin/") {
890
			return false;
891
		}
892
		return true;
893
	}
894
895
	public function load_properties($scope='') {
896
		return $this->store->load_properties($this->id,'',$scope);
897
	}
898
899
	public function _load_properties($scope='') {
900
		return $this->store->load_properties($this->id,'',$scope);
901
	}
902
903
	public function load_property($property, $scope='') {
904
		return $this->store->load_property($this->id,$property,$scope);
905
	}
906
907
	public function _load_property($property, $scope='') {
908
		return $this->store->load_property($this->id,$property,$scope);
909
	}
910
911 4
	public function GetValidGrants($path="") {
912
	/********************************************************************
913
914
	  This function finds all grants in effect on this object for the
915
	  logged in user! $AR->user must already be set.
916
917
	  Grants are checked in the following way:
918
	  1) First all parents of this object are checked for grants for this
919
	     specific user. The 'nearest' grants are valid, and the path of
920
	     parent that set these grants will be the upper limit for the
921
	     checking of group grants.
922
	  2) Now all groups of which the user is a member are checked for
923
	     grants. Likewise, all parents are checked for group grants, upto
924
	     but not including the upperlimit as set in 1. All group grants
925
	     found are merged into one grants list.
926
	  3) If there are gropup grants, this means that there are group
927
	     grants set in a parent nearer to this object than the user grants
928
	     and therefore the groupgrants must be merged with the
929
	     usergrants.
930
931
	  this results in:
932
	  1	/		user: read edit		group: none
933
	  2	/dir/					group: read
934
	  3	/dir2/		user: none		group: read
935
	  4	/dir/dir3/				group2: edit
936
	  case 1: the user takes precedence over the group, grants are 'read edit'
937
	  case 2: groupgrants are merged with usergrants, as its grants are set
938
	          in a 'nearer' parent (itself). grants are 'read edit'.
939
	  case 3: user takes precedence again. grants are 'none'.
940
	  case 4: All group grants are merged with the usergrants.
941
	          Therefore the grants are 'none read edit'.
942
	********************************************************************/
943
944 4
	global $AR;
945
946 4
		if ($AR->user) { 	// login and retrieval of user object
947 4
			if (!$path) {
948 4
				$path=$this->path;
949 3
			}
950 4
			if (!$AR->user->grants[$path]) {
951 4
				$grants=array();
952 4
				$userpath=$AR->user->FindGrants($path, $grants);
953
				// if not already done, find all groups of which the user is a member
954 4
				if (!is_array($AR->user->externalgroupmemberships) || count($AR->user->externalgroupmemberships)==0) {
955 4
					$criteria["members"]["login"]["="]=$AR->user->data->login;
956 3
				} else {
957
					// Use the group memberships of external databases (e.g. LDAP)
958
					$criteria="members.login='".AddSlashes($AR->user->data->login)."'";
959
					foreach (array_keys($AR->user->externalgroupmemberships) as $group) {
960
						$criteria.=" or login.value='".AddSlashes($group)."'";
961
					}
962
				}
963 4
				if (!$AR->user->groups) {
964 4
					$groups=$this->find("/system/groups/",$criteria, "system.get.phtml");
965 4
					if (isset($groups) && is_array($groups)) {
966 4
						foreach($groups as $group ){
967 4
							if (is_object($group)) {
968 4
								$AR->user->groups[$group->path] = $group;
969 3
							}
970 3
						}
971 3
					}
972 4
					if (isset($AR->user->data->config->groups) && is_array($AR->user->data->config->groups)) {
973 4
						foreach ($AR->user->data->config->groups as $groupPath => $groupId) {
974 4
							if (!$AR->user->groups[$groupPath]) {
975 1
								$AR->user->groups[$groupPath] = current($this->get($groupPath, "system.get.phtml"));
976
							}
977 3
						}
978 3
					}
979 4
					if (!$AR->user->groups["/system/groups/public/"]) {
980
						if ($public=current($this->get("/system/groups/public/", "system.get.phtml"))) {
981
							$AR->user->groups[$public->path] = $public;
982
						}
983
					}
984 3
				}
985 4
				if ($AR->user->groups) {
986
					/* check for owner grants (set by system.get.config.phtml) */
987 4
					if (isset($AR->user->ownergrants) && is_array($AR->user->ownergrants)) {
988
						if (!$AR->user->groups["owner"]) {
989
							$AR->user->groups["owner"] = @current($this->get("/system/groups/owner/", "system.get.phtml"));
990
						}
991
						$AR->user->groups["owner"]->data->config->usergrants = $AR->user->ownergrants;
992
					}
993 4 View Code Duplication
					foreach($AR->user->groups as $group){
994 4
						$groupgrants=array();
995 4
						if (is_object($group)) {
996 4
							$group->FindGrants($path, $groupgrants, $userpath);
997 4
							if (isset($grants) && is_array($grants)) {
998 4
								foreach($groupgrants as $gkey => $gval ){
999
									if (isset($grants[$gkey]) && is_array($grants[$gkey]) && is_array($gval)) {
1000
										$grants[$gkey]=array_merge($gval, $grants[$gkey]);
1001
									} else
1002
									if ($gval && !is_array($gval)) {
1003
										$grants[$gkey] = $gval;
1004
									} else
1005
									if ($gval && !$grants[$gkey]) {
1006 1
										$grants[$gkey] = $gval;
1007
									}
1008 3
								}
1009 3
							} else {
1010 1
								$grants = $groupgrants;
1011
							}
1012 3
						}
1013 3
					}
1014 3
				}
1015 4
				if(isset($AR->sgGrants) && is_array($AR->sgGrants) ) {
1016
					ksort($AR->sgGrants);
1017
					$ppath = $this->make_path($path);
1018 View Code Duplication
					foreach( $AR->sgGrants as $sgpath => $sggrants) {
1019
						$sgpath = $this->make_path($sgpath);
1020
						if( substr($ppath, 0, strlen($sgpath)) == $sgpath ) { // sgpath is parent of ppath or equal to ppath
1021
							if (isset($grants) && is_array($grants)) {
1022
								foreach($sggrants as $gkey => $gval ){
1023
									if (isset($grants[$gkey]) && is_array($grants[$gkey]) && is_array($gval)) {
1024
										$grants[$gkey]=array_merge($gval, $grants[$gkey]);
1025
									} else
1026
									if ($gval && !is_array($gval)) {
1027
										$grants[$gkey] = $gval;
1028
									} else
1029
									if ($gval && !$grants[$gkey]) {
1030
										$grants[$gkey] = $gval;
1031
									}
1032
								}
1033
							} else {
1034
								$grants = $sggrants;
1035
							}
1036
						}
1037
					}
1038
				}
1039 4
				$AR->user->grants[$path]=$grants;
1040 3
			}
1041 4
			$grants=$AR->user->grants[$path];
1042
1043 3
		}
1044 4
		debug("pobject: GetValidGrants(user:".$AR->user->data->login."): end ( ".debug_serialize($grants)." )","all");
1045 4
		return $grants;
1046
	}
1047
1048
1049 184
	public function pushContext($context) {
1050 184
	global $AR;
1051 184
		if(!empty($AR->context)) {
1052 72
			$context = array_merge(end($AR->context), $context);
1053 54
		}
1054 184
		array_push($AR->context, $context);
1055 184
	}
1056
1057
	public function setContext($context, $level=0) {
1058
	global $AR;
1059
		$AR->context[count($AR->context)-(1+$level)]=$context;
1060
	}
1061
1062 184
	public function popContext() {
1063 184
	global $AR;
1064 184
		return array_pop($AR->context);
1065
	}
1066
1067 184
	public static function getContext($level=0) {
1068 184
	global $AR;
1069 184
		return $AR->context[count($AR->context)-(1+$level)];
1070
	}
1071
1072 72
	public function CheckAdmin($user) {
1073 72
	if ($user->data->login == "admin") {
1074 68
			return true;
1075
		}
1076 4
		if ($user->data->groups['/system/groups/admin/']) {
1077
			return true;
1078
		}
1079 4
		return false;
1080
	}
1081
1082 60
	public function CheckLogin($grant, $modifier=ARTHISTYPE) {
1083 60
	global $AR,$ARnls,$ARConfig,$ARCurrent,$ARConfigChecked;
1084 60
		if (!$this->store->is_supported("grants")) {
1085
			debug("pobject: store doesn't support grants");
1086
			return true;
1087
		}
1088 60
		if ($modifier==ARTHISTYPE) {
1089 60
			$modifier=$this->type;
1090 45
		}
1091
1092
		/* load config cache */
1093 60
		if (!isset($ARConfig->cache[$this->path])) {
1094
			// since this is usually run before CheckConfig, make sure
1095
			// it doesn't set cache time
1096
			$realConfigChecked = $ARConfigChecked;
1097
			$ARConfigChecked = true;
1098
			$this->loadConfig();
1099
			$ARConfigChecked = $realConfigChecked;
1100
		}
1101
1102 60
		$isadmin = $this->CheckAdmin($AR->user);
1103
1104 60
		if (!$isadmin && !$AR->user->grants[$this->path]) {
1105
			$AR->user->grants[$this->path]=$this->GetValidGrants();
1106
		}
1107 60
		if ($AR->user->data->login!="public") {
1108
			// Don't remove this or MSIE users won't get uptodate pages...
1109 60
			ldSetClientCache(false);
1110 45
		}
1111
1112 60
		$grants=$AR->user->grants[$this->path];
1113 60
		if ( 	( !$grants[$grant]
1114 60
					|| ( $modifier && is_array($grants[$grant]) && !$grants[$grant][$modifier] )
1115 60
				) && !$isadmin ) {
1116
			// do login
1117
			$arLoginMessage = $ARnls["accessdenied"];
1118
			ldAccessDenied($this->path, $arLoginMessage);
1119
			$result=false;
1120
		} else {
1121 60
			$result=($grants || $isadmin);
1122
		}
1123
1124 60
		$ARCurrent->arLoginSilent=1;
1125 60
		return $result;
1126
	}
1127
1128
1129 4
	public function CheckPublic($grant, $modifier=ARTHISTYPE) {
1130 4
	global $AR;
1131
1132 4
		$result=false;
1133 4
		if (!$AR->public) {
1134 4
			$this->pushContext(array("scope" => "php"));
1135 4
				$AR->public=current($this->get("/system/users/public/", "system.get.phtml"));
1136 4
			$this->popContext();
1137 3
		}
1138 4
		if ($AR->public) {
1139 4
			$AR->private=$AR->user;
1140 4
			$AR->user=$AR->public;
1141 4
			$result=$this->CheckSilent($grant, $modifier);
1142 4
			$AR->user=$AR->private;
1143 3
		}
1144 4
		return $result;
1145
	}
1146
1147 44
	public function CheckSilent($grant, $modifier=ARTHISTYPE, $path=".") {
1148 44
	global $AR, $ARConfig;
1149 44
		$path = $this->make_path($path);
1150 44
		if ($modifier==ARTHISTYPE) {
1151 44
			$modifier=$this->type;
1152 33
		}
1153
1154
		/* load config cache */
1155 44
		if (!$ARConfig->cache[$path]) {
1156 8
			$this->loadConfig($path);
1157 6
		}
1158 44
		if ($this->CheckAdmin($AR->user)) {
1159 40
			$result=1;
1160 34
		} else if ($grants=$AR->user->grants[$path]) {
1161
			$result=$grants[$grant];
1162
		} else {
1163 4
			$grants=$this->GetValidGrants();
1164 4
			$result=$grants[$grant];
1165
		}
1166 44
		if ($modifier && is_array($result)) {
1167
			$result=$result[$modifier];
1168
		}
1169 44
		return $result;
1170
	}
1171
1172
	public function CheckNewFile($newfilename) {
1173
	global $ARnls;
1174
	/**********************************************************************
1175
1176
	  This function performs all the necessary checks on a path to see
1177
	whether it's a valid path for a new object. This consists of:
1178
	1) checking for invalid characters, valid chars are "a-zA-Z0-9./_-"
1179
	2) checking whether the path starts and ends with a "/".
1180
	3) checking whether the path doesn't exist already.
1181
	4) checking whether the parent exists.
1182
1183
	if all this checks out, it returns 1. If not, $this->error is set to
1184
	the correct error message.
1185
1186
	**********************************************************************/
1187
1188
		$this->error="";
1189
		if (preg_match("|^/[a-z0-9\./_-]*/$|i",$newfilename)) {
1190
			if (!$this->store->exists($newfilename)) {
1191
				$parent=$this->store->make_path($newfilename, "..");
1192
				if ($this->store->exists($parent)) {
1193
					$result=1;
1194
				} else {
1195
					$this->error = ar::error( sprintf($ARnls["err:filenameinvalidnoparent"],$newfilename,$parent), 1102);
1196
				}
1197
			} else {
1198
				$this->error = ar::error( sprintf($ARnls["err:chooseotherfilename"],$newfilename), 1103);
1199
			}
1200
		} else {
1201
			$this->error = ar::error( sprintf($ARnls["err:fileillegalchars"],$newfilename)." ".$ARnls["err:startendslash"], 1104);
1202
		}
1203
		return $result;
0 ignored issues
show
The variable $result does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1204
	}
1205
1206 View Code Duplication
	public function resetConfig($path='') {
1207
	global $ARConfig;
1208
		$path = $this->make_path($path);
1209
		if ($ARConfig->cache[$path]) {
1210
			$path = preg_quote($path,'/');
1211
			$keys = preg_grep('/^'.$path.'/',array_keys($ARConfig->cache));
1212
			foreach ($keys as $cachepath) {
1213
				unset($ARConfig->cache[$cachepath]);
1214
				unset($ARConfig->pinpcache[$cachepath]);
1215
			}
1216
		}
1217
	}
1218
1219 36 View Code Duplication
	public function clearChildConfigs($path='') {
1220 36
	global $ARConfig;
1221 36
		$path = $this->make_path($path);
1222 36
		if ($ARConfig->cache[$path]) {
1223 36
			$path = preg_quote($path,'/');
1224 36
			$keys = preg_grep('/^'.$path.'./',array_keys($ARConfig->cache));
1225 36
			foreach($keys as $cachepath) {
1226 4
				unset($ARConfig->cache[$cachepath]);
1227 4
				unset($ARConfig->pinpcache[$cachepath]);
1228 4
				unset($ARConfig->libraries[$cachepath]);
1229 27
			}
1230 27
		}
1231 36
	}
1232
1233 36
	protected function getConfig() {
1234 36
	global $ARConfig, $ARCurrent, $ARConfigChecked;
1235
		// $context=$this->getContext(0);
1236
		// debug("getConfig(".$this->path.") context: ".$context['scope'] );
1237
		// debug(print_r($ARConfig->nls, true));
1238 36
		if( !$ARConfig->cache[$this->parent] && $this->parent!=".." ) {
1239 4
			$parent = current($this->get($this->parent, "system.get.phtml"));
1240 4
			if ($parent) {
1241 4
				$parent->getConfig();
1242 3
			}
1243 3
		}
1244
1245 36
		$this->getConfigData();
1246
1247 36
		$ARConfig->pinpcache[$this->path] = $ARConfig->pinpcache[$this->parent];
1248
		// backwards compatibility when calling templates from config.ini
1249 36
		$prevArConfig = $ARCurrent->arConfig;
1250 36
		$ARCurrent->arConfig = $ARConfig->pinpcache[$this->path];
1251
1252 36
		$arCallArgs['arConfig'] = $ARConfig->pinpcache[$this->path];
1253
1254
		/* calling config.ini directly for each system.get.config.phtml call */
1255 36
		$loginSilent = $ARCurrent->arLoginSilent;
1256 36
		$ARCurrent->arLoginSilent = true;
1257
		// debug("getConfig:checkconfig start");
1258
1259 36
		$initialNLS = $ARCurrent->nls;
1260 36
		$initialConfigChecked = $ARConfigChecked;
1261
1262 36
		$ARConfig->cache[$this->path]->inConfigIni = true;
1263 36
		if ($ARConfig->cache[$this->path]->hasConfigIni && !$this->CheckConfig('config.ini', $arCallArgs)) {
1264
			//debug("pobject::getConfig() loaded config.ini @ ".$this->path);
1265
			// debug("getConfig:checkconfig einde");
1266 4
			$arConfig = $ARCurrent->arResult;
1267 4
			if (!isset($arConfig)) {
1268
				$arConfig = $ARCurrent->arConfig;
1269
			}
1270 4
			unset($ARCurrent->arResult);
1271 4
			if (isset($arConfig['library']) && is_array($arConfig['library'])) {
1272
				if (!$ARConfig->libraries[$this->path]) {
1273
					$ARConfig->libraries[$this->path] = array();
1274
				}
1275
				foreach ($arConfig['library'] as $libName => $libPath) {
1276
					$this->loadLibrary($libName, $libPath);
1277
				}
1278
				unset($arConfig['library']);
1279
			}
1280 4
			$ARConfig->pinpcache[$this->path] = (array) $arConfig;
1281 3
		}
1282 36
		$ARConfig->cache[$this->path]->inConfigIni = false;
1283 36
		$this->clearChildConfigs( $this->path ); // remove any config data for child objects, since these are set before their parent config was set
1284 36
		$ARConfigChecked = $initialConfigChecked;
1285 36
		$ARCurrent->nls = $initialNLS;
1286
1287 36
		$arConfig = &$ARConfig->pinpcache[$this->path];
1288 36 View Code Duplication
		if (!is_array($arConfig['authentication']['userdirs'])) {
1289
			$arConfig['authentication']['userdirs'] = array('/system/users/');
1290
		} else {
1291 36
			if (reset($arConfig['authentication']['userdirs']) != '/system/users/') {
1292
				array_unshift($arConfig['authentication']['userdirs'], '/system/users/');
1293
			}
1294
		}
1295 36 View Code Duplication
		if (!is_array($arConfig['authentication']['groupdirs'])) {
1296
			$arConfig['authentication']['groupdirs'] = array('/system/groups/');
1297
		} else {
1298 36
			if (reset($arConfig['authentication']['groupdirs']) != '/system/groups/') {
1299
				array_unshift($arConfig['authentication']['groupdirs'], '/system/groups/');
1300
			}
1301
		}
1302
1303 36
		$ARCurrent->arLoginSilent = $loginSilent;
1304 36
		$ARCurrent->arConfig = $prevArConfig;
1305 36
	}
1306
1307 36
	protected function getConfigData() {
1308 36
	global $ARConfig, $AR;
1309 36
		$context = $this->getContext(0);
1310 36
		if (!$ARConfig->cache[$this->path] && $context["scope"] != "pinp") {
1311
			// first inherit parent configuration data
1312 36
			$configcache= clone $ARConfig->cache[$this->parent];
1313 36
			unset($configcache->localTemplates);
1314
			// cache default templates
1315 36
			if (isset($this->data->config->templates) && count($this->data->config->templates)) {
1316
				$configcache->templates=&$this->data->config->templates;
1317
			}
1318 36
			if (isset($this->data->config->privatetemplates) && count($this->data->config->privatetemplates)) {
1319
				$configcache->privatetemplates=&$this->data->config->privatetemplates;
1320
			}
1321
1322
			// Speedup check for config.ini
1323
1324 36
			if(isset($this->data->config->templates) && is_array($this->data->config->templates) ) {
1325 4
				$configcache->localTemplates = $this->data->config->templates;
1326 4
				if( !$configcache->hasDefaultConfigIni ) {
1327 4
					foreach($this->data->config->templates as $type => $templates ) {
1328
						if( isset($templates["config.ini"]) ) {
1329
							$configcache->hasDefaultConfigIni = true;
1330
							$configcache->hasConfigIni = true;
1331
							break;
1332
						}
1333 3
					}
1334 3
				}
1335 3
			}
1336
1337 36
			if( !$configcache->hasDefaultConfigIni ) {
1338 36
				$configcache->hasConfigIni = false;
1339 36
				if(isset($this->data->config->pinp) && is_array($this->data->config->pinp) ) {
1340 4
					foreach( $this->data->config->pinp as $type => $templates ) {
1341 4
						if( isset($templates["config.ini"]) ) {
1342 4
							$configcache->hasConfigIni = true;
1343 4
							break;
1344
						}
1345 3
					}
1346 3
				}
1347 27
			}
1348
1349 36
			$localcachesettings = $this->data->config->cacheSettings;
1350 36
			if (!is_array($localcachesettings) ){
1351 36
				$localcachesettings = array();
1352 27
			}
1353
1354 36
			if (!is_array($configcache->cacheSettings) ) {
1355
				$configcache->cacheSettings = array();
1356
			}
1357
1358 36
			if ($this->data->config->cacheconfig) { // When removing this part, also fix the setting below.
1359 4
				$configcache->cache=$this->data->config->cacheconfig;
1360 3
			}
1361
1362 36
			if (!isset($localcachesettings['serverCache']) && isset($this->data->config->cacheconfig)) {
1363 4
				$localcachesettings["serverCache"] = $this->data->config->cacheconfig;
1364 3
			}
1365
1366 36
			if ($localcachesettings['serverCache'] != 0 ) {
1367 4
				$localcachesettings['serverCacheDefault'] = $localcachesettings['serverCache'];
1368 3
			}
1369
1370 36
			$configcache->cacheSettings = $localcachesettings + $configcache->cacheSettings;
1371
1372
			// store the current object type
1373 36
			$configcache->type = $this->type;
1374
1375 36
			if ($this->data->config->typetree && ($this->data->config->typetree!="inherit")) {
1376
				$configcache->typetree=$this->data->config->typetree;
1377
			}
1378 36
			if (isset($this->data->config->nlsconfig->list)) {
1379 4
				$configcache->nls = clone $this->data->config->nlsconfig;
1380 3
			}
1381
1382 36
			if ($this->data->config->grants["pgroup"]["owner"]) {
1383
				$configcache->ownergrants = $this->data->config->grants["pgroup"]["owner"];
1384
			}
1385 36
			if (isset($configcache->ownergrants) && is_array($configcache->ownergrants)) {
1386
				if ($AR->user && $AR->user->data->login != 'public' && $AR->user->data->login === $this->data->config->owner) {
1387
					$ownergrants = $configcache->ownergrants;
1388
					if (isset($ownergrants) && is_array($ownergrants)) {
1389
						foreach( $ownergrants as $grant => $val ) {
1390
							$AR->user->ownergrants[$this->path][$grant] = $val;
1391
						}
1392
					}
1393
				}
1394
			}
1395
1396 36
			if (isset($this->data->config->customconfig) && is_array($this->data->config->customconfig)) {
1397
				$configcache->custom=array_merge(is_array($configcache->custom)?$configcache->custom:array(), $this->data->config->customconfig);
1398
			}
1399 36
			$ARConfig->cache[$this->path]=$configcache;
1400
1401 27
		}
1402 36
	}
1403
1404 60
	public function loadConfig($path='') {
1405 60
	global $ARConfig, $ARConfigChecked, $ARCurrent;
1406 60
		$path=$this->make_path($path);
1407
		// debug("loadConfig($path)");
1408 60
		if (!isset($ARConfig->cache[$path]) ) {
1409 36
			$allnls = $ARCurrent->allnls;
1410 36
			$ARCurrent->allnls = true;
1411 36
			$configChecked = $ARConfigChecked;
1412 36
			if (($this->path == $path && !$this->arIsNewObject) || $this->exists($path)) {
1413 36
				$this->pushContext(array("scope" => "php"));
1414 36
				if( $this->path == $path ) {
1415
					// debug("loadConfig: currentpath $path ");
1416 36
					$this->getConfig();
1417 27
				} else {
1418
					//debug("loadConfig: get path $path ");
1419 4
					$cur_obj = current($this->get($path, "system.get.phtml"));
1420 4
					$cur_obj->getConfig();
1421
				}
1422 36
				$this->popContext();
1423 36
				$result=$ARConfig->cache[$path];
1424 27
			} else if ($path === '/') {
1425
				// special case: / doesn't exists in the store
1426
				$result=$ARConfig->cache['..'];
1427
			} else {
1428
				$parent=$this->make_path($path.'../');
1429
				if (!$ARConfig->cache[$parent]) {
1430
					$this->pushContext(array("scope" => "php"));
1431
					// debug("loadConfig: parent $parent");
1432
					$cur_obj = current($this->get($parent, "system.get.phtml"));
1433
					if( $cur_obj ) {
1434
						$cur_obj->getConfig();
1435
					}
1436
					$this->popContext();
1437
				}
1438
				$result=$ARConfig->cache[$parent];
1439
				$ARConfig->cache[ $path ] = $result;
1440
				$ARConfig->pinpcache[ $path ] = $ARConfig->pinpcache[ $parent ];
1441
			}
1442
			// restore old ARConfigChecked state
1443 36
			$ARConfigChecked = $configChecked;
1444 36
			$ARCurrent->allnls = $allnls;
1445 27
		} else {
1446
			// debug("loadConfig: exists $path ");
1447 48
			$result=$ARConfig->cache[$path];
1448
		}
1449 60
		return $result;
1450
	}
1451
1452
1453
	// TODO: look for a way to merge loadConfig and loadUserConfig into one function
1454
1455 12
	public function loadUserConfig($path='') {
1456 12
	global $ARConfig;
1457 12
		$path = $this->make_path($path);
1458 12
		$parent = $this->make_path($path.'../');
1459
1460 12
		if (!$ARConfig->cache[$path]) {
1461
			$this->loadConfig($path);
1462
		}
1463 12
		if (!$ARConfig->pinpcache[$path]) {
1464
			$config = $ARConfig->pinpcache[$parent];
1465
		} else {
1466 12
			$config = $ARConfig->pinpcache[$path];
1467
		}
1468 12
		return (array)$config;
1469
	}
1470
1471 48
	protected function getTemplateFromCache($path, $type, $function, &$arSuperContext) {
1472 48
	global $AR, $ARConfig;
1473 48
		$templatesList = $ARConfig->libraryCache[$path][$function];
1474 48
		if (!is_array($templatesList)) {
1475 48
			return false;
1476
		}
1477
		foreach ($templatesList as $checkpath => $templates) {
1478
			$arType = $type;
1479
			while ($arType!='ariadne_object') {
1480
//				echo "checking $i::$arType<br>\n";
1481
				if (!$arSuperContext[$checkpath.":".$arType.":".$function] && ($arTemplate=$templates[$arType][$this->reqnls])) {
1482
					$arCallTemplate=$arType.".".$function.".".$this->reqnls;
1483
					$arCallTemplateName = $function;
1484
					$arCallTemplateNLS = $this->reqnls;
1485
					break 2;
1486 View Code Duplication
				} else if (!$arSuperContext[$checkpath.":".$arType.":".$function] && ($arTemplate=$templates[$arType]['any'])) {
1487
					$arCallTemplate=$arType.".".$function.".any";
1488
					$arCallTemplateName = $function;
1489
					$arCallTemplateNLS = "any";
1490
					break 2;
1491
				} else {
1492
1493
					if (!($arSuper=$AR->superClass[$arType])) {
1494
						// no template found, no default.phtml found, try superclass.
1495
						if ($subcpos = strpos($arType, '.')) {
1496
							$arSuper = substr($arType, 0, $subcpos);
1497
						} else {
1498
							if (!class_exists($arType, false)) {
1499
								// the given class was not yet loaded, so do that now
1500
								$arTemp=$this->store->newobject('','',$arType,new object);
1501
							} else {
1502
								$arTemp=new $arType();
1503
							}
1504
							$arSuper=get_parent_class($arTemp);
1505
						}
1506
						$AR->superClass[$arType]=$arSuper;
1507
					}
1508
					$arType=$arSuper;
1509
				}
1510
			}
1511
		}
1512
1513
		$config = ($ARConfig->cache[$arTemplate["arLibraryLocalPath"]]) ? $ARConfig->cache[$arTemplate["arLibraryLocalPath"]] : $this->loadConfig($arTemplate["arLibraryLocalPath"]);
1514
		$arPrivateTemplate = $config->privatetemplates[$arType][$function];
1515
1516
		return array(
1517
			"arTemplateId" => $arTemplate["arTemplateId"],
1518
			"arCallTemplate" => $arCallTemplate,
1519
			"arCallType" => $type,
1520
			"arCallTemplateName" => $arCallTemplateName,
1521
			"arCallTemplateNLS" => $arCallTemplateNLS,
1522
			"arCallTemplateType" => $arType,
1523
			"arCallTemplatePath" => $arTemplate["arLibraryLocalPath"],
1524
			"arLibrary" => "current",
1525
			"arLibraryPath" => $arTemplate["arLibraryPath"],
1526
			"arPrivateTemplate" => $arPrivateTemplate
1527
		);
1528
	}
1529
1530
	public function loadLibraryCache($base, $path, $arLibraryPath = "") {
1531
	global $ARConfig;
1532
		if (!$arLibraryPath) {
1533
			$arLibraryPath = $path;
1534
		}
1535
		$config = ($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
1536
		$templates = $config->localTemplates;
1537
		if (isset($templates) && is_array($templates)) {
1538
			$list = array();
1539
			foreach ($templates as $type => $functions) {
1540
				foreach ($functions as $function => $template) {
1541
					foreach ($template as $nls => $templateId) {
1542
						$list[$function][$type][$nls] = array(
1543
								"arTemplateId" => $templateId,
1544
								"arLibraryPath" => $arLibraryPath,
1545
								"arLibraryLocalPath" => $path
1546
						);
1547
					}
1548
				}
1549
			}
1550
1551
			foreach ($list as $function => $types) {
1552
				if (!is_array($ARConfig->libraryCache[$base][$function])) {
1553
					$ARConfig->libraryCache[$base][$function] = array(
1554
						$path => $types
1555
					);
1556
				} else {
1557
					$ARConfig->libraryCache[$base][$function][$path] = $types;
1558
				}
1559
			}
1560
		}
1561
		list($basetype,) = explode('.', $config->type,2);
1562
		if ($path != '/' && $basetype != 'psection') {
1563
			$this->loadLibraryCache($base, $this->store->make_path($path, '../'), $arLibraryPath);
1564
		}
1565
	}
1566
1567 4
	public function loadLibrary($name, $path) {
1568 4
	global $ARConfig;
1569 4
		$path=$this->make_path($path);
1570 4
		debug("pobject::loadLibrary($name, $path);");
1571 4
		if ($name===ARUNNAMED) {
1572 4
			if (strstr($path, $this->path)===0) {
1573
				return ar::error('You cannot load an unnamed library from a child object.', 1109);
1574
			} else {
1575 4
				if (!$ARConfig->libraries[$this->path]) {
1576 4
					$ARConfig->libraries[$this->path]=array();
1577 3
				}
1578 4
				array_unshift($ARConfig->libraries[$this->path],$path);
1579 4 View Code Duplication
				if (!$ARConfig->cacheableLibraries[$this->path]) {
1580 4
					$ARConfig->cacheableLibraries[$this->path] = array($path);
1581 3
				} else {
1582 1
					array_unshift($ARConfig->cacheableLibraries[$this->path], $path);
1583
				}
1584
			}
1585 3
		} else if ($name && is_string($name)) {
1586
			if (!$ARConfig->cache[$this->path]) {
1587
debug("loadLibrary: loading cache for $this->path");
1588
				$this->loadConfig($this->path);
1589
			}
1590
			$ARConfig->libraries[$this->path][$name]=$path;
1591
			$ARConfig->cache[$this->path]->libraries[$name]=$path;
1592
			$ARConfig->pinpcache[$this->path]["library"][$name] = $path;
1593
		} else if (is_int($name)) {
1594
			if (!$ARConfig->cache[$this->path]) {
1595
				$this->loadConfig($this->path);
1596
			}
1597
			$ARConfig->libraries[$this->path][$name]=$path;
1598 View Code Duplication
			if (!$ARConfig->cacheableLibraries[$this->path]) {
1599
				$ARConfig->cacheableLibraries[$this->path] = array($name => $path);
1600
			} else {
1601
				$ARConfig->cacheableLibraries[$this->path][$name] = $path;
1602
			}
1603
			// make sure that unnamed libraries don't get added to the configcache
1604
			unset($ARConfig->cache[$this->path]->libraries[$name]);
1605
			unset($ARConfig->pinpcache[$this->path]["library"][$name]);
1606
		} else {
1607
			return ar::error('Illegal library name: '.$name, 1110);
1608
		}
1609 4
	}
1610
1611
	// returns a list of libraries loaded on $path
1612
	public function getLibraries($path = '') {
1613
	global $ARConfig;
1614
		$path = $this->make_path($path);
1615
		return (array)$ARConfig->libraries[$path];
1616
	}
1617
1618
	public function mergeLibraryConfig( $defaultLibraryName, $defaults ) {
1619
		$libraryName = ar::getvar('arLibrary');
1620
		if ( is_numeric($libraryName) || $libraryName == 'current' ) { // library is loaded unnamed
1621
			$libraryName = $defaultLibraryName;
1622
		}
1623
		if ( $libraryName ) {
1624
			$userConfig = ar::acquire('defaults.'.$libraryName);
1625
			if (isset($userConfig) && is_array($userConfig) ) {
1626
				$defaults = array_merge( $defaults, $userConfig );
1627
			}
1628
		}
1629
		return array_merge( $defaults, $this->getvar('arCallArgs') );
1630
	}
1631
1632
	public function _mergeLibraryConfig( $defaultLibraryName, $defaults ) {
1633
		return $this->mergeLibraryConfig( $defaultLibraryName, $defaults );
1634
	}
1635
1636 60
	public function getPinpTemplate($arCallFunction='view.html', $path=".", $top="", $inLibrary = false, $librariesSeen = null, $arSuperContext=array()) {
1637 60
	global $ARCurrent, $ARConfig, $AR, $ARConfigChecked;
1638 60
		debug("getPinpTemplate: function: $arCallFunction; path: $path; top: $top; inLib: $inLibrary","class");
1639 60
		$result = array();
1640 60
		if (!$top) {
1641 60
			$top = '/';
1642 45
		}
1643 60
		$path = $this->make_path($path);
1644 60
		if (!is_array($arSuperContext)) {
1645
			$arSuperContext = array();
1646
		}
1647
1648 60
		if (($libpos=strpos($arCallFunction,":"))!==false && $libpos!==strpos($arCallFunction, "::")) {
1649
			// template of a specific library defined via call("library:template");
1650
			$arLibrary = substr($arCallFunction, 0, $libpos);
1651
			if ($arLibrary == 'current') {
1652
				// load the current arLibrary
1653
				$context = $this->getContext(1);
1654
				$arLibrary = $context['arLibrary'];
1655
				$arLibraryPath = $context['arLibraryPath'];
1656 View Code Duplication
			} else {
1657
				$config = (isset($ARConfig->cache[$path])) ? $ARConfig->cache[$path] : $this->loadConfig($path);
1658
				$arLibraryPath = $config->libraries[$arLibrary];
1659
			}
1660
			$arCallFunction = substr($arCallFunction, $libpos+1);
1661
			if ($arLibraryPath) {
1662
				debug("getPinpTemplate: found library '$arLibrary'. Searching for $arCallFunction on '".$config->libraries[$arLibrary]."' up to '$top'");
1663
				$librariesSeen[$arLibraryPath] = true;
1664
				$inLibrary = true;
1665
				$path = $arLibraryPath;
1666
			} else {
1667
				debug("getPinpTemplate: Failed to find library $arLibrary");
1668
				return false;
1669
			}
1670
			$path = $this->make_path($path);
1671
		}
1672 60
		if (strpos($arCallFunction,"::")!==false) {
1673
			// template of a specific class defined via call("class::template");
1674
			list($arCallType, $arCallFunction)=explode("::",$arCallFunction);
1675
		} else {
1676 60
			$arCallType=$this->type;
1677
		}
1678
1679
		/* first check current templates */
1680 60
		if ($this->path == $path) {
1681 60
			$curr_templates = $this->data->config->pinp;
1682 45
		} else {
1683
			$config = ($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
1684
			$curr_templates = $config->templates;
1685
		}
1686
1687 60
		$checkpath=$path;
1688 60
		$lastcheckedpath="";
1689 60
		$arCallClassTemplate = $ARCurrent->arCallClassTemplate;
1690 60
		$arSetType = $arCallType;
1691 60
		while (!$arCallClassTemplate && !$arCallTemplate && $checkpath!=$lastcheckedpath) {
1692 60
			$lastcheckedpath = $checkpath;
1693 60
			$arType = $arSetType;
1694 60
			while ($arType!='ariadne_object' && !$arCallTemplate) {
1695 60
				if (!$arSuperContext[$checkpath.":".$arType.":".$arCallFunction] && ($arTemplateId=$curr_templates[$arType][$arCallFunction][$this->reqnls])) {
1696
					$arCallTemplate=$arType.".".$arCallFunction.".".$this->reqnls;
1697
					$arCallTemplateName = $arCallFunction;
1698
					$arCallTemplateNLS = $this->reqnls;
1699 60 View Code Duplication
				} else if (!$arSuperContext[$checkpath.":".$arType.":".$arCallFunction] && ($arTemplateId=$curr_templates[$arType][$arCallFunction]['any'])) {
1700 12
					$arCallTemplate=$arType.".".$arCallFunction.".any";
1701 12
					$arCallTemplateName = $arCallFunction;
1702 12
					$arCallTemplateNLS = 'any';
1703 9
				} else {
1704
1705 48
					if (!($arSuper=$AR->superClass[$arType])) {
1706
						// no template found, no default.phtml found, try superclass.
1707
						if ($subcpos = strpos($arType, '.')) {
1708
							$arSuper = substr($arType, 0, $subcpos);
1709
						} else {
1710
							if (!class_exists($arType, false )) {
1711
								// the given class was not yet loaded, so do that now
1712
								$arTemp=$this->store->newobject('','',$arType,new object);
1713
							} else {
1714
								$arTemp=new $arType();
1715
							}
1716
							$arSuper=get_parent_class($arTemp);
1717
						}
1718
						$AR->superClass[$arType]=$arSuper;
1719
					}
1720 48
					$arType=$arSuper;
1721
				}
1722 45
			}
1723 60
			if ($inLibrary) {
1724
1725
				// faster matching on psection, prefix doesn't have to be a valid type
1726
				$prefix = substr($ARConfig->cache[$checkpath]->type,0,8);
1727
1728
				if ($prefix === 'psection') {
1729
					// debug("BREAKING; $arTemplateId");
1730
					// break search operation when we have found a
1731
					// psection object
1732
					break;
1733
				}
1734
			}
1735
1736 60
			if (!$arTemplateId && $ARConfigChecked) {
1737 48
				if ($ARConfig->cacheableLibraries[$checkpath]) {
1738
					foreach ($ARConfig->cacheableLibraries[$checkpath] as $library => $path) {
1739
						if (is_int($library) && !$librariesSeen[$path]) {
1740
							$librariesSeen[$path] = true;
1741
							if ($ARConfigChecked) {
1742
								if (!$ARConfig->librariesCached[$checkpath][$path]) {
1743
									$this->loadLibraryCache($checkpath, $path);
1744
									unset($ARConfig->cacheableLibraries[$checkpath][$library]);
1745
								}
1746
							}
1747
						}
1748
					}
1749
				}
1750
1751 48
				if (isset($ARConfig->cacheableLibraries[$checkpath])) {
1752 48
					$template = $this->getTemplateFromCache($checkpath, $arCallType, $arCallFunction, $arSuperContext);
1753 48
					if ($template["arTemplateId"]) {
1754
						return $template;
1755
					}
1756 36
				}
1757 36
			}
1758 60
			if ($checkpath == $top) {
1759 48
				break;
1760
			}
1761
1762 60
			$checkpath=$this->store->make_path($checkpath, "..");
1763 60
			$config = ($ARConfig->cache[$checkpath]) ? $ARConfig->cache[$checkpath] : $this->loadConfig($checkpath);
1764 60
			$curr_templates = $config->templates;
1765 60
			$arSetType = $arCallType;
1766 45
		}
1767
1768 60
		$config = ($ARConfig->cache[$lastcheckedpath]) ? $ARConfig->cache[$lastcheckedpath] : $this->loadConfig($lastcheckedpath);
1769 60
		$arPrivateTemplate = $config->privatetemplates[$arCallType][$arCallFunction];
1770
1771
		//debug("getPinpTemplate END; $arTemplateId; $checkpath;");
1772 60
		$result["arTemplateId"] = $arTemplateId;
1773 60
		$result["arCallTemplate"] = $arCallTemplate;
1774 60
		$result["arCallType"] = $arCallType;
1775 60
		$result["arCallTemplateName"] = $arCallTemplateName;
1776 60
		$result["arCallTemplateNLS"] = $arCallTemplateNLS;
1777 60
		$result["arCallTemplateType"] = $arType;
1778 60
		$result["arCallTemplatePath"] = $lastcheckedpath;
1779 60
		$result["arLibrary"] = $arLibrary;
1780 60
		$result["arLibraryPath"] = $arLibraryPath;
1781 60
		$result["arLibrariesSeen"] = $librariesSeen;
1782 60
		$result["arPrivateTemplate"] = $arPrivateTemplate;
1783
1784 60
		return $result;
1785
	}
1786
1787 64
	public function CheckConfig($arCallFunction="", $arCallArgs="") {
1788
	// returns true when cache isn't up to date and no other template is
1789
	// defined for $path/$function. Else it takes care of output to the
1790
	// browser.
1791
	// All these templates must exist under a fixed directory, $AR->dir->templates
1792 64
	global $nocache, $AR, $ARConfig, $ARCurrent, $ARBeenHere, $ARnls, $ARConfigChecked;
1793 64
		$MAX_LOOP_COUNT=10;
1794
1795
1796
		// system templates (.phtml) have $arCallFunction=='', so the first check in the next line is to
1797
		// make sure that loopcounts don't apply to those templates.
1798 64
		if (0 && $arCallFunction && $ARBeenHere[$this->path][$arCallFunction]>$MAX_LOOP_COUNT) { // protect against infinite loops
1799
			error(sprintf($ARnls["err:maxloopexceed"],$this->path,$arCallFunction,$arCallArgs));
1800
			$this->store->close();
1801
			exit();
1802
		} else {
1803 64
			$ARBeenHere[$this->path][$arCallFunction]+=1;
1804
1805
			// this will prevent the parents from setting the cache time
1806 64
			$initialConfigChecked = $ARConfigChecked;
1807 64
			$ARConfigChecked = true;
1808 64
			$config = ($ARConfig->cache[$this->path]) ? $ARConfig->cache[$this->path] : $this->loadConfig();
1809 64
			$ARConfigChecked = $initialConfigChecked;
1810 64
			$ARConfig->nls=$config->nls;
1811
1812
1813
			// if a default language is entered in a parent and no language is
1814
			// explicitly selected in the url, use that default.
1815
			// The root starts with the system default (ariadne.phtml config file)
1816 64
			if ( !$ARCurrent->nls ) {
1817 64
				if ( $config->root['nls'] ) {
1818
					$this->reqnls = $config->root['nls'];
1819
					if ( !$ARConfigChecked ) {
1820
						$ARCurrent->nls = $this->reqnls;
1821
					}
1822 64
				} else if ( $config->nls->default ) {
1823 64
					$this->reqnls = $config->nls->default;
1824 64
					$this->nls = $this->reqnls;
1825 64
					if ( !$ARConfigChecked ) {
1826 16
						$ARCurrent->nls = $this->nls;
1827
					}
1828 48
				}
1829 48
			} else {
1830
				$this->reqnls = $ARCurrent->nls;
1831
			}
1832 64
			$nls = &$this->nls;
1833 64
			$reqnls = &$this->reqnls;
1834
1835 64
			if (!$ARConfigChecked && is_object($ARnls)) {
1836
				$ARnls->setLanguage($ARCurrent->nls);
1837
			}
1838
1839
1840 64
			if (!$ARCurrent->arContentTypeSent) {
1841
				ldHeader("Content-Type: text/html; charset=UTF-8");
1842
				$ARCurrent->arContentTypeSent = true;
1843
			}
1844
1845
/*			// FIXME: the acceptlang code works a bit too well.. it overrides psite configuration settings.
1846
1847
			if ($ARCurrent->acceptlang && !$ARCurrent->nls) {
1848
				if ($ARCurrent->acceptlang && is_array($this->data->nls->list)) {
1849
					$validlangs = array_intersect(array_keys($ARCurrent->acceptlang), array_keys($this->data->nls->list));
1850
				}
1851
				if ($validlangs) {
1852
					$reqnls=array_shift($validlangs);
1853
					$ARCurrent->nls = $reqnls;
1854
				}
1855
			}
1856
*/
1857 64 View Code Duplication
			if (isset($this->data->custom) && is_array($this->data->custom) && $this->data->custom['none']) {
1858 4
				$this->customdata=$this->data->custom['none'];
1859 3
			}
1860 64 View Code Duplication
			if (isset($this->data->custom) && is_array($this->data->custom) && $this->data->custom[$nls]) {
1861
				$this->customnlsdata=$this->data->custom[$nls];
1862
			}
1863
1864 64
			if (!$ARConfigChecked) {
1865
				// this template is the first template called in this request.
1866
				$eventData = new object();
1867
				$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
The property arCallArgs does not seem to exist in object.

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

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

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

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

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

Loading history...
1869
1870
				$ARConfigChecked = true;
1871
				$result = ar_events::fire( 'onbeforeview', $eventData );
1872
				$ARConfigChecked = $initialConfigChecked;
1873
				if ( !$result ) { //prevent default action: view
1874
					return false;
1875
				}
1876
			}
1877
1878 64
			if (!$ARConfigChecked) {
1879
				// if this object isn't available in the requested language, show
1880
				// a language select dialog with all available languages for this object.
1881
				if (isset($this->data->nls) && !$this->data->name) {
1882
					if (!$ARCurrent->forcenls && (!isset($this->data->nls->list[$reqnls]) || !$config->nls->list[$reqnls])) {
1883
						if (!$ARCurrent->nolangcheck && $arCallFunction != 'config.ini') {
1884
							$ARCurrent->nolangcheck=1;
1885
							$eventData = new object();
1886
							$eventData->arCallFunction = $arCallFunction;
1887
							$eventData->arCallArgs = $arCallArgs;
1888
							$eventData->arRequestedNLS = $reqnls;
1889
							$result = ar_events::fire( 'onlanguagenotfound', $eventData );
1890
							if ( $result ) { // continue with default action: langaugeselect
1891
								$result->arCallArgs["arOriginalFunction"] = $result->arCallFunction;
1892
								$this->call("user.languageselect.html", $result->arCallArgs);
1893
								return false;
1894
							}
1895
						} else {
1896
							$this->nlsdata=$this->data->$nls;
1897
						}
1898
					} else {
1899
						$this->nlsdata=$this->data->$reqnls;
1900
					}
1901
				}
1902
				$ARCurrent->nolangcheck=1;
1903
			}
1904
1905
			/*
1906
				Set ARConfigChecked to true to indicate that we have been here
1907
				earlier.
1908
			*/
1909 64
			$ARConfigChecked = true;
1910 64
			if ($arCallFunction) { // don't search for templates named ''
1911
				// FIXME: Redirect code has to move to getPinpTemplate()
0 ignored issues
show
Comment refers to a FIXME task "Redirect code has to move to getPinpTemplate"
Loading history...
1912 60
				$redirects	= $ARCurrent->shortcut_redirect;
1913 60
				if (isset($redirects) && is_array($redirects)) {
1914
					$redirpath = $this->path;
1915
					while (!$template['arTemplateId'] &&
0 ignored issues
show
The variable $template does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1916
								($redir = array_pop($redirects)) &&
1917
									$redir["keepurl"] &&
1918
										(substr($redirpath, 0, strlen($redir["dest"])) == $redir["dest"])
1919
					) {
1920
						$template = $this->getPinpTemplate($arCallFunction, $redirpath, $redir["dest"]);
1921
						$redirpath = $redir['src'];
1922
					}
1923
1924
					if (!$template["arTemplateId"] && $redirpath) {
1925
						$template = $this->getPinpTemplate($arCallFunction, $redirpath);
1926
					}
1927
				}
1928 60
				if (!$template["arTemplateId"]) {
1929 60
					$template = $this->getPinpTemplate($arCallFunction);
1930 45
				}
1931
1932 60
				if ($template["arCallTemplate"] && $template["arTemplateId"]) {
1933 12
					if (!isset($ARCurrent->cacheTemplateChain)) {
1934
						$ARCurrent->cacheTemplateChain = array();
1935
					}
1936 12
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]])) {
1937 8
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]] = array();
1938 6
					}
1939 12
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']])) {
1940 12
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']] = array();
1941 9
					}
1942 12
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']])) {
1943 12
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']] = 0;
1944 9
					}
1945 12
					$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']]++;
1946
1947
1948 12
					debug("CheckConfig: arCallTemplate=".$template["arCallTemplate"].", arTemplateId=".$template["arTemplateId"],"object");
1949
					// $arCallTemplate=$this->store->get_config("files")."templates".$arCallTemplate;
1950
					// check if template exists, if it doesn't exist, then continue the original template that called CheckConfig
1951 12
					$arTemplates=$this->store->get_filestore("templates");
1952
					if (
1953 12
						$arTemplates->exists($template["arTemplateId"], $template["arCallTemplate"].".inc")
1954 9
					) {
1955
						// check if the requested language exists, if not do not display anything,
1956
						// unless otherwise indicated by $ARCurrent->allnls
1957
						// This triggers only for pinp templates called by other templates,
1958
						// as the first template (in the url) will first trigger the language
1959
						// choice dialogue instead.
1960 12
						$arLibrary = $template['arLibrary'];
1961 12
						if (is_int($arLibrary)) {
1962
							// set the library name for unnamed libraries to 'current'
1963
							// so that calls using getvar('arLibrary') will keep on working
1964
							$arLibrary = "current";
1965
						}
1966
1967 12 View Code Duplication
						if (!is_string($arCallArgs)) {
1968 12
							$arCallArgs['arCallFunction'] = $arCallFunction;
1969 12
							$arCallArgs['arLibrary'] = $arLibrary;
1970 12
							$arCallArgs['arLibraryPath'] = $template["arLibraryPath"];
1971 9
						}
1972
1973 12
						$ARCurrent->arCallStack[]=$arCallArgs;
1974
						// start running a pinp template
1975
1976 12
						$this->pushContext(
1977
							array(
1978 12
								"scope" => "pinp",
1979 12
								"arLibrary" => $arLibrary,
1980 12
								"arLibraryPath" => $template['arLibraryPath'],
1981 12
								"arCallFunction" => $arCallFunction,
1982 12
								"arCurrentObject" => $this,
1983 12
								"arCallType" => $template['arCallType'],
1984 12
								"arCallTemplateName" => $template['arCallTemplateName'],
1985 12
								"arCallTemplateNLS" => $template['arCallTemplateNLS'],
1986 12
								"arCallTemplateType" => $template['arCallTemplateType'],
1987 12
								"arCallTemplatePath" => $template['arCallTemplatePath'],
1988 12
								"arLibrariesSeen" => $template['arLibrariesSeen']
1989 9
							)
1990 9
						);
1991
1992
						// FIXME: is 2 het correcte getal? Kan dit minder magisch?
1993 12
						if (count($ARCurrent->arCallStack) == 2 && $template['arPrivateTemplate']) {
1994
							// Do not allow private templates to be called first in the stack.
1995
							// echo "Bad request";
1996
1997
							// FIXME: Echte header sturen? Of gewoon niet uitvoeren? Wat is het correcte gedrag?
1998
							// Return true zorgt er voor dat de default 404 handler het oppikt alsof het template niet bestaat.
1999
							$this->popContext();
2000
							array_pop($ARCurrent->arCallStack);
2001
							return true;
2002 12
						} else if ($ARCurrent->forcenls || isset($this->data->nls->list[$reqnls])) {
2003
							// the requested language is available.
2004 12
							$this->nlsdata=$this->data->$reqnls;
2005 12
							$this->nls=$reqnls;
2006 12
							$continue=true;
2007 9
						} else if (!isset($this->data->nls)) {
2008
							// the object has no language support
2009
							$this->nlsdata=$this->data;
2010
							$continue=true;
2011
						} else if (($ARCurrent->allnls) || (!$initialConfigChecked && $ARCurrent->nolangcheck)) {
2012
							// all objects must be displayed
2013
							// $this->reqnls=$this->nls; // set requested nls, for checks
2014
							$this->nls = isset($this->data->nls->default) ? $this->data->nls->default : $this->reqnls;
2015
							$this->nlsdata = $this->data->$nls ?: $this->data->{$this->nls} ?: $this->data;
2016
							$continue=true;
2017
						} else {
2018
							debug("CheckConfig: requested language not available, allnls not set","object");
2019
							// -> skip this object (do not run template but do return false)
2020
							$continue=false;
2021
						}
2022 12
						if ($continue) {
2023 12
							$eventData = new object();
2024 12 View Code Duplication
							if ( !$AR->contextCallHandler ) { /* prevent onbeforecall from re-entering here */
2025 12
								$AR->contextCallHandler = true;
2026 12
								$eventData->arCallArgs = $arCallArgs;
2027 12
								$eventData->arCallFunction = $arCallFunction;
2028 12
								$eventData->arContext = $this->getContext();
0 ignored issues
show
The property arContext does not seem to exist in object.

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

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

Loading history...
2029 12
								$eventData = ar_events::fire('onbeforecall', $eventData);
0 ignored issues
show
$eventData is of type object<object>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
2030 12
								$ARCurrent->arResult = $eventData->arResult;
2031 12
								$AR->contextCallHandler = false;
2032 12
								$continue = ($eventData!=false);
2033 9
							}
2034 12
							if ( $continue ) {
2035 12
								if (!isset($ARCurrent->cacheCallChainSettings)) {
2036
									$ARCurrent->cacheCallChainSettings = array();
2037
								}
2038 12
								if ($ARConfig->cache[$this->path]->inConfigIni == false) {
2039 8
									$ARCurrent->cacheCallChainSettings[$this->id] = $config->cacheSettings;
2040 6
								}
2041
2042 12
								if ($ARCurrent->ARShowTemplateBorders) {
2043
									echo "<!-- arTemplateStart\nData: ".$this->type." ".$this->path." \nTemplate: ".$template["arCallTemplatePath"]." ".$template["arCallTemplate"]." \nLibrary:".$template["arLibrary"]." -->";
2044
								}
2045 12
								set_error_handler(array('pobject','pinpErrorHandler'),error_reporting());
2046 12
								$func = $arTemplates->import($template["arTemplateId"], $template["arCallTemplate"]);
2047 12
								if(is_callable($func)){
2048 12
									$arResult = $func($this);
2049 9
								}
2050 12
								restore_error_handler();
2051 12
								if (isset($arResult)) {
2052 12
									$ARCurrent->arResult=$arResult;
2053 9
								}
2054 12
								if ($ARCurrent->ARShowTemplateBorders) {
2055
									echo "<!-- arTemplateEnd -->";
2056
								}
2057 12 View Code Duplication
								if ( !$AR->contextCallHandler ) { /* prevent oncall from re-entering here */
2058 12
									$AR->contextCallHandler = true;
2059 12
									$temp = $ARCurrent->arResult; /* event listeners will change ARCurrent->arResult */
2060 12
									$eventData->arResult = $temp;
2061 12
									ar_events::fire('oncall', $eventData );
2062 12
									$ARCurrent->arResult = $temp; /* restore correct result */
2063 12
									$AR->contextCallHandler = false;
2064 9
								}
2065 9
							}
2066 9
						}
2067 12
						array_pop($ARCurrent->arCallStack);
2068 12
						$this->popContext();
2069
2070 12
						if ( !$initialConfigChecked && $arCallFunction != 'config.ini' ) {
2071
							// this template was the first template called in this request.
2072
							$eventData = new object();
2073
							$eventData->arCallArgs = $arCallArgs;
2074
							$eventData->arCallFunction = $arCallFunction;
2075
							ar_events::fire( 'onview', $eventData ); // no default action to prevent, so ignore return value.
2076
						}
2077 12
						return false;
2078
					} else {
2079 4
						debug("pobject: CheckConfig: no such file: ".$template["arTemplateId"].$template["arCallTemplate"]."","all");
2080
					}
2081 3
				} else {
2082 48
					debug("CheckConfig: no arCallTemplate ($arCallFunction from '$this->path')","object");
2083
				}
2084
2085 39
			}
2086
		}
2087 56
		return true;
2088
	}
2089
2090 24
	public function ClearCache($path="", $private=true, $recurse=false) {
2091 24
	global $AR;
2092 24
		$norealnode = false;
2093 24
		if (!$path) {
2094
			$path=$this->path;
2095
		} else {
2096 24
			$realpath = current($this->get($path, "system.get.path.phtml"));
2097 24
			if($realpath != false) {
2098 24
				$path = $realpath;
2099 18
			} else {
2100
				$norealnode = true;
2101
			}
2102
		}
2103
2104 24
		if($norealnode !== true) {
2105
			/*
2106
				we don't want to recurse to the currentsite, because the path
2107
				doesn't exists in the database, so it doesn't have a currentsite
2108
2109
				the privatecache should be emptied by delete, or by the cleanup
2110
				cronjob. The current path doesn't exists in the database, so a
2111
				object id which is needed to find the node in the cache, isn't
2112
				available
2113
			*/
2114
2115 24
			if ($private ) {
2116
				// now remove any private cache entries.
2117
				// FIXME: this doesn't scale very well.
2118
				//        only scalable solution is storage in a database
2119
				//        but it will need the original path info to
2120
				//        remove recursively fast enough.
2121
				//        this means a change in the filestore api. -> 2.5
2122
2123
				// Use chunks of max 5000 objects at a time to be more memory-efficient;
2124 24
				$pcache=$this->store->get_filestore("privatecache");
2125 24
				if ($recurse) {
2126
					$offset = 0;
2127
					$limit = 5000;
2128
					$ids=$this->store->info($this->store->find($path, "" , $limit, $offset));
2129
					while (is_array($ids) && count($ids)) {
2130
						foreach($ids as $value) {
2131
							$eventData = new object();
2132
							$eventData = ar_events::fire( 'onbeforeclearprivatecache', $eventData, $value['type'], $value['path'] );
2133
							if ( !$eventData ) {
2134
								continue;
2135
							}
2136
2137
							$pcache->purge($value["id"]);
2138
							ar_events::fire( 'onclearprivatecache', $eventData, $value['type'], $value['path'] );
2139
						}
2140
2141
						$offset += $limit;
2142
						$ids = $this->store->info($this->store->find($path, "", $limit, $offset));
2143
					}
2144
				} else {
2145 24
					$eventData = new object();
2146 24
					$eventData = ar_events::fire( 'onbeforeclearprivatecache', $eventData, $this->type, $this->path );
2147 24
					if ( $eventData ) {
2148 24
						$pcache->purge($this->id);
2149 24
						ar_events::fire( 'onclearprivatecache', $eventData, $this->type, $this->path );
2150 18
					}
2151
				}
2152 18
			}
2153
2154
			// now clear all parents untill the current site
2155 24
			$site=$this->currentsite($path);
2156 24
			$project=$this->currentproject($path);
2157 24
			if ($path!=$site && $path != $project && $path!='/') {
2158 24
				$parent=$this->make_path($path.'../');
2159 24
				$this->ClearCache($parent, $private, false);
2160 18
			}
2161 18
		}
2162 24
		$recursed = array();
2163
2164
		// filesystem cache image filenames are always lower case, so
2165
		// use special path for that. Remember 'real' path name for
2166
		// recursion and stuff
2167 24
		$fs_path=strtolower($path);
2168 24
		$nlslist=$AR->nls->list;
2169 24
		$nlslist["."]="default";
2170 24
		$cache_types[] = "normal";
2171 24
		$cache_types[] = "compressed";
2172 24
		$cache_types[] = "session";
2173
2174 24
		global $cache_config,$store_config;
2175 24
		$cachestore=new cache($cache_config);
2176
2177
2178 24
		$filestore = $this->store->get_config("files");
2179 24
		foreach($cache_types as $type){
2180 24
			foreach($nlslist as $nls => $language){
2181
				// break away if nls doesn't exists
2182
				// is dir is cached, so it should not cost more that it add's in speed
2183 24
				if(!is_dir($filestore."cache/$type/$nls")){
2184 24
					continue;
2185
				}
2186
2187
				$fpath=$filestore."cache/$type/$nls".$fs_path;
2188
				$hpath=$filestore."cacheheaders/$type/$nls".$fs_path;
2189
				if ($dir=@dir($fpath)) {
2190
					while (false !== ($entry = $dir->read())) {
2191
						if ($entry!="." && $entry!="..") {
2192
							if (is_file($fpath.$entry)) {
2193
								@unlink($fpath.$entry);
2194
								@unlink($hpath.$entry);
2195
								$cachestore->delete("/".$type."/".$nls.$fs_path.$entry);
2196
							} else if ( $recurse && !$recursed[$entry]) {
2197
								$this->ClearCache($path.$entry."/", false, true);
2198
								$recursed[$entry]=true;
2199
							}
2200
						}
2201
					}
2202
					$dir->close();
2203
					// remove empty directory entry's, hide errors about directory entry's with content
2204
					@rmdir($fpath);
2205
					@rmdir($hpath);
2206
				} else if (file_exists(substr($fpath,0,-1)."=")) {
2207
					@unlink(substr($fpath,0,-1)."=");
2208
					@unlink(substr($hpath,0,-1)."=");
2209 6
					$cachestore->delete("/".$type."/".$nls.substr($fs_path,0,-1)."=");
2210
				}
2211 18
			}
2212 18
		}
2213 24
	}
2214
2215
	public function getcache($name, $nls="") {
2216
		global $ARCurrent, $ARnls;
2217
		$result=false;
0 ignored issues
show
$result is not used, you could remove the assignment.

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

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

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

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

Loading history...
2218
		$this->error = '';
2219
		if ($name) {
2220
			$result=false;
0 ignored issues
show
$result is not used, you could remove the assignment.

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

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

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

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

Loading history...
2221
			if (!$nls) {
2222
				$nls=$this->nls;
2223
			}
2224
			$file=$nls.".".$name;
2225
2226
			$minfresh = time();
2227
			if (isset($ARCurrent->RequestCacheControl["min-fresh"])) {
2228
				$minfresh += $ARCurrent->RequestCacheControl["min-fresh"];
2229
			}
2230
2231
			$pcache=$this->store->get_filestore("privatecache");
2232
			if ( $pcache->exists($this->id, $file) &&
2233
			     ($pcache->mtime($this->id, $file) > ($minfresh) )  ) {
2234
2235
				$result = $pcache->read($this->id, $file);
2236
2237
				$contentType = $ARCurrent->ldHeaders['content-type'];
2238
				if (preg_match('|^content-type:[ ]*([^ /]+)/|i', $contentType, $matches)) {
2239
					$contentType = $matches[1];
2240
				} else {
2241
					$contentType = '';
2242
				}
2243
2244 View Code Duplication
				if (!$contentType || strtolower($contentType) == 'text') {
2245
					require_once($this->store->get_config('code')."modules/mod_url.php");
2246
					$temp = explode('.', $file);
2247
					$imageNLS = $temp[0];
2248
					$result = URL::ARtoRAW($result, $imageNLS);
2249
				}
2250
			} else {
2251
				$result=false;
2252
				$ARCurrent->cache[]=$file;
2253
				ob_start();
2254
				/* output buffering is recursive, so this won't interfere with
2255
				   normal page caching, unless you forget to call savecache()...
2256
				   so normal pagecache needs to check $ARCurrent->cache, if it's
2257
				   not empty, issue a warning and don't cache the outputbuffer...
2258
				   savecache() must then pop the stack.
2259
				*/
2260
			}
2261
		} else {
2262
			$this->error = ar::error($ARnls["err:nonamecache"], 1111);
2263
			$result = false;
2264
		}
2265
		return $result;
2266
	}
2267
2268
	public function cached($name, $nls="") {
2269
		if ($image=$this->getcache($name, $nls)) {
2270
			echo $image;
2271
			$result=true;
2272
		} else {
2273
			$result=false;
2274
		}
2275
		return $result;
2276
	}
2277
2278
	public function savecache($time="") {
2279
		global $ARCurrent, $ARnls, $DB;
2280
		$result = false;
0 ignored issues
show
$result is not used, you could remove the assignment.

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

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

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

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

Loading history...
2281
		$this->error = '';
2282
		if (!$time) {
2283
			$time=2; // 'freshness' in hours.
2284
		}
2285
		if ($file=array_pop($ARCurrent->cache)) {
2286
			$image=ob_get_contents();
2287
			if ($image !== false) {
2288
				$result = $image;
2289
2290
				$contentType = $ARCurrent->ldHeaders['content-type'];
2291
				if (preg_match('|^content-type:[ ]*([^ /]+)/|i', $contentType, $matches)) {
2292
					$contentType = $matches[1];
2293
				} else {
2294
					$contentType = '';
2295
				}
2296
2297 View Code Duplication
				if (!$contentType || strtolower($contentType) == 'text') {
2298
					require_once($this->store->get_config('code')."modules/mod_url.php");
2299
					$temp = explode('.', $file);
2300
					$imageNLS = $temp[0];
2301
					$image = URL::RAWtoAR($image, $imageNLS);
2302
				}
2303
2304
				if( $time > 0  && $DB["wasUsed"] == 0) {
2305
					$pcache=$this->store->get_filestore("privatecache");
2306
					$pcache->write($image, $this->id, $file);
2307
					$time=time()+($time*3600);
2308 View Code Duplication
					if (!$pcache->touch($this->id, $file, $time)) {
2309
						$this->error = ar::error("savecache: ERROR: couldn't touch $file", 1113);
2310
						$result = false;
2311
					}
2312
				}
2313
				ob_end_clean();
2314
				echo $image;
2315
			} else {
2316
				debug("skipped saving cache - ob_get_contents returned false so output buffering was not active", "all");
2317
				$result = false;
2318
			}
2319
		} else {
2320
			$this->error = ar::error($ARnls["err:savecachenofile"], 1112);
2321
			$result = false;
2322
		}
2323
		return $result;
2324
	}
2325
2326
	public function getdatacache($name) {
2327
		global $ARCurrent, $ARnls;
2328
		$result=false;
2329
		$this->error = '';
2330
		if ($name) {
2331
2332
			$minfresh = time();
2333
			if (isset($ARCurrent->RequestCacheControl["min-fresh"])) {
2334
				$minfresh += $ARCurrent->RequestCacheControl["min-fresh"];
2335
			}
2336
2337
			$pcache=$this->store->get_filestore("privatecache");
2338
			if ( $pcache->exists($this->id, $name) &&
2339
			     ($pcache->mtime($this->id, $name) > $minfresh) ) {
2340
				$result = unserialize($pcache->read($this->id, $name));
2341
			} else {
2342
				debug("getdatacache: $name doesn't exists, returning false.","all");
2343
			}
2344
		} else {
2345
			$this->error = ar::error($ARnls["err:nonamecache"], 1111);
2346
		}
2347
		return $result;
2348
	}
2349
2350
	public function savedatacache($name,$data,$time="") {
2351
		global $DB;
2352
		$this->error = '';
2353
		if (!$time) {
2354
			$time=2; // 'freshness' in hours.
2355
		}
2356
		$pcache=$this->store->get_filestore("privatecache");
2357
		if( $time > 0  && $DB["wasUsed"] == 0) {
2358
			$pcache->write(serialize($data), $this->id, $name);
2359
			$time=time()+($time*3600);
2360 View Code Duplication
			if (!$pcache->touch($this->id, $name, $time)) {
2361
				$this->error = ar::error('Could not touch '.$name, 1113);
2362
				return false;
2363
			}
2364
		}
2365
		return true;
2366
	}
2367
2368 52
	public function getdata($varname, $nls="none", $emptyResult=false) {
2369
	// function to retrieve variables from $this->data, with the correct
2370
	// language version.
2371 52
	global $ARCurrent;
2372
2373 52
		$result = false;
2374 52
		if ($nls!="none") {
2375 48 View Code Duplication
			if ($ARCurrent->arCallStack) {
2376 48
				$arCallArgs=end($ARCurrent->arCallStack);
2377 48
				if (isset($arCallArgs) && is_array($arCallArgs)) {
2378 48
					extract($arCallArgs);
2379 36
				} else if (is_string($arCallArgs)) {
2380
					Parse_Str($arCallArgs);
2381
				}
2382 36
			}
2383 48
			if (isset(${$nls}[$varname])) {
2384 28
				$result=${$nls}[$varname];
2385 48
			} else if (isset($ARCurrent->$nls) && isset($ARCurrent->$nls->$varname)) {
2386
				$result=$ARCurrent->$nls->$varname;
2387 48
			} else if (($values=$_POST[$nls]) && isset($values[$varname])) {
2388
				$result=$values[$varname];
2389 48
			} else if (($values=$_GET[$nls]) && isset($values[$varname])) {
2390
				$result=$values[$varname];
2391 48
			} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$nls][$varname])) {
2392
				$result=$arStoreVars[$nls][$varname];
2393 48
			} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$nls][$varname])) {
2394
				$result=$arStoreVars[$nls][$varname];
2395
			}
2396 48
			if ($result===false) {
2397 48
				if (isset($this->data->${nls}) && isset($this->data->${nls}->${varname})) {
2398 30
					$result=$this->data->${nls}->${varname};
2399 18
				}
2400 36
			}
2401 36
		} else { // language independant variable.
2402 52 View Code Duplication
			if ($ARCurrent->arCallStack) {
2403 52
				$arCallArgs=end($ARCurrent->arCallStack);
2404 52
				if (isset($arCallArgs) && is_array($arCallArgs)) {
2405 48
					extract($arCallArgs);
2406 43
				} else if (is_string($arCallArgs)) {
2407
					Parse_Str($arCallArgs);
2408
				}
2409 39
			}
2410 52
			if (isset($$varname)) {
2411 24
				$result=$$varname;
2412 52
			} else if (isset($ARCurrent->$varname)) {
2413
				$result=$ARCurrent->$varname;
2414 52 View Code Duplication
			} else if (isset($_POST[$varname])) {
2415
				$result=$_POST[$varname];
2416 52
			} else if (isset($_GET[$varname])) {
2417
				$result=$_GET[$varname];
2418 52
			} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$varname])) {
2419
				$result=$arStoreVars[$varname];
2420 52
			} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$varname])) {
2421
				$result=$arStoreVars[$varname];
2422
			}
2423 52
			if ($result===false) {
2424 52
				if (isset($this->data->$varname)) {
2425 24
					$result=$this->data->$varname;
2426 18
				}
2427 39
			}
2428
		}
2429 52
		if ( $result === false ) {
2430 52
			$result = $emptyResult;
2431 39
		}
2432 52
		return $result;
2433
	}
2434
2435
	public function showdata($varname, $nls="none", $emptyResult=false) {
2436
		echo htmlspecialchars($this->getdata($varname, $nls, $emptyResult), ENT_QUOTES, 'UTF-8');
2437
	}
2438
2439
	public function setnls($nls) {
2440
		ldSetNls($nls);
2441
	}
2442
2443
	public function getcharset() {
2444
		return "UTF-8";
2445
	}
2446
2447
	public function HTTPRequest($method, $url, $postdata = "", $port=80 ) {
2448
		$maxtries = 5;
2449
		$tries = 0;
2450
		$redirecting = true;
2451
2452
		if(isset($postdata) && is_array($postdata)) {
2453
			foreach($postdata as $key=>$val) {
2454
				if(!is_integer($key)) {
2455
					$data .= "$key=".urlencode($val)."&";
2456
				}
2457
			}
2458
		} else {
2459
			$data = $postdata;
2460
		}
2461
2462
		while ($redirecting && $tries < $maxtries) {
2463
			$tries++;
2464
			// get host name and URI from URL, URI not needed though
2465
			preg_match("/^([htps]*:\/\/)?([^\/]+)(.*)/i", $url, $matches);
2466
			$host = $matches[2];
2467
			$uri = $matches[3];
2468
			if (!$matches[1]) {
2469
				$url="http://".$url;
2470
			}
2471
			$connection = @fsockopen( $host, $port, $errno, $errstr, 120);
2472
			if( $connection ) {
2473
				if( strtoupper($method) == "GET" ) {
2474
					if ($data) {
2475
						$uri .= "?" . $data;
2476
					}
2477
					fputs( $connection, "GET $uri HTTP/1.0\r\n");
2478
				} else if( strtoupper($method) == "POST" ) {
2479
					fputs( $connection, "POST $uri HTTP/1.0\r\n");
2480
				} else {
2481
					fputs( $connection, "$method $uri HTTP/1.0\r\n");
2482
				}
2483
2484
				fputs( $connection, "Host: $host\r\n");
2485
				fputs( $connection, "Accept: */*\r\n");
2486
				fputs( $connection, "Accept: image/gif\r\n");
2487
				fputs( $connection, "Accept: image/x-xbitmap\r\n");
2488
				fputs( $connection, "Accept: image/jpeg\r\n");
2489
2490
				if( strtoupper($method) == "POST" ) {
2491
					$strlength = strlen( $data);
2492
					fputs( $connection, "Content-type: application/x-www-form-urlencoded\r\n" );
2493
					fputs( $connection, "Content-length: ".$strlength."\r\n\r\n");
2494
					fputs( $connection, $data."\r\n");
2495
				}
2496
2497
				fputs( $connection, "\r\n" , 2);
2498
2499
				$headerContents = '';
2500
				$headerStart = 0;
2501
				$headerEnd = 0;
2502
				$redirecting = false;
2503
2504
				while (!feof($connection)) {
2505
					$currentLine = fgets ($connection, 1024);
2506
					if ($headerEnd && $redirecting) {
2507
						break;
2508
					} else if ($headerEnd && !$redirecting) {
2509
						//this is the html from the page
2510
						$contents = $contents . $currentLine;
2511
					} else if ( preg_match("/^HTTP/", $currentLine) ) {
2512
						//came to the start of the header
2513
						$headerStart = 1;
2514
						$headerContents = $currentLine;
2515
					} else if ( $headerStart && preg_match('/^[\n\r\t ]*$/', $currentLine) ) {
2516
						//came to the end of the header
2517
						$headerEnd = 1;
2518
					} else {
2519
						//this is the header, if you want it...
2520
						if (preg_match("/^Location: (.+?)\n/is",$currentLine,$matches) ) {
2521
							$headerContents .= $currentLine;
2522
							//redirects are sometimes relative
2523
							$newurl = $matches[1];
2524
							if (!preg_match("/http:\/\//i", $newurl, $matches) ) {
2525
								$url .= $newurl;
2526
							} else {
2527
								$url = $newurl;
2528
							}
2529
							//extra \r's get picked up sometimes
2530
							//i think only with relative redirects
2531
							//this is a quick fix.
2532
							$url = preg_replace("/\r/s","",$url);
2533
							$redirecting = true;
2534
						} else {
2535
							$headerContents.=$currentLine;
2536
						}
2537
					}
2538
				}
2539
			} else {
2540
				$this->error="$errstr ($errno)";
2541
				$contents=false;
2542
				$url = "";
2543
			}
2544
			@fclose($connection);
2545
		}
2546
		if (($method!="GET") && ($method!="POST")) {
2547
			$contents=$headerContents."\n".$contents;
2548
		}
2549
		return $contents;
2550
	}
2551
2552
	public function make_filesize( $size="" ,$precision=0) {
2553
		$suffixes = array('B','KB','MB','GB','TB','PB','EB','ZB','YB');
2554
2555
		if( $size === "" ) {
2556
			$size = $this->size;
2557
		}
2558
		while ( (count($suffixes) > 1) && ($size > 1024) ){
2559
			$size = $size / 1024;
2560
			array_shift($suffixes);
2561
		}
2562
		$size = round($size,$precision);
2563
		if($precision==0){ // compatible with the old make_filesize
2564
			$size = intval($size);
2565
		}
2566
		$result = $size." ".array_shift($suffixes);
2567
		return $result;
2568
	}
2569
2570
	public function convertToUTF8($data, $charset = "CP1252") {
2571
2572
		include_once($this->store->get_config("code")."modules/mod_unicode.php");
2573
2574
		if (isset($data) && is_array($data)) {
2575
			foreach($data as $key => $val){
2576
				$data[$key] = $this->convertToUTF8($val, $charset);
2577
			}
2578
		} else
2579
		if (is_object($data)) {
2580
			foreach($data as $key => $val){
2581
				$data->$key = $this->convertToUTF8($val, $charset);
2582
			}
2583
		} else {
2584
			$data = unicode::convertToUTF8($charset, $data);
2585
		}
2586
		return $data;
2587
	}
2588
2589 28
	public function resetloopcheck() {
2590 28
		global $ARBeenHere;
2591 28
		$ARBeenHere=array();
2592 28
	}
2593
2594
/********************************************************************
2595
2596
  "safe" functions.
2597
2598
  The following functions are safe versions of existing functions
2599
  above.
2600
  - They don't change anything in the database.
2601
    This means that to save/delete something, a user will need to call
2602
    "system.save.data.phtml" or "system.delete.phtml" which check grants.
2603
  - All functions except _get and _exists don't take a path as
2604
    argument, they use the current objects path instead.
2605
2606
  These are meant to be used by 'pinp' versions of templates,
2607
  meaning user defined templates. 'pinp' rewrites call to functions
2608
  to the form '$this->_function'.
2609
2610
  All pinp files automatically first call CheckLogin('read').
2611
2612
********************************************************************/
2613
2614
	public function _call($function, $args="") {
2615
		// remove possible path information (greedy match)
2616
		if ( !( $function instanceof \Closure ) ) {
2617
			$function = basename( (string) $function );
2618
		}
2619
		return $this->call($function, $args);
2620
	}
2621
2622
	public function _call_super($arCallArgs="") {
2623
	global $ARCurrent, $AR;
2624
		$context = $this->getContext();
2625
		if (!$arCallArgs) {
2626
			$arCallArgs = end($ARCurrent->arCallStack);
2627
		}
2628
		$arSuperContext = (array)$context['arSuperContext'];
2629
		$arLibrary		= $context['arLibrary'];
2630
		$arLibraryPath	= $context['arLibraryPath'];
2631
		$arCallType		= $context['arCallTemplateType'];
2632
		$arSuperPath	= $context['arCallTemplatePath'];
2633
		$arLibrariesSeen = $context['arLibrariesSeen'];
2634
		$arCallFunction = $arSuperFunction = $context['arCallFunction'];
2635
		if ($arLibrary) {
2636
			$arSuperFunction = str_replace($arLibrary.':', '', $arCallFunction);
2637
		}
2638
		if (strpos($arSuperFunction, "::") !== false) {
2639
			// template of a specific class defined via call("class::template");
2640
			list($arBaseType, $arSuperFunction)=explode("::", $arSuperFunction);
2641
		}
2642
		// remove current library path from the arLibrariesSeen array so that
2643
		// Ariadne will be able to re-enter the library and toggle the arSuperContext boolean there.
2644
		unset($arLibrariesSeen[$arLibraryPath]);
2645
		$arSuperContext[$arSuperPath.":".$arCallType.":".$arSuperFunction] = true;
2646
2647
		debug("call_super: searching for the template following (path: $arSuperPath; type: $arCallType; function: $arCallFunction) from $this->path");
2648
		// FIXME: Redirect code has to move to getPinpTemplate()
0 ignored issues
show
Comment refers to a FIXME task "Redirect code has to move to getPinpTemplate"
Loading history...
2649
		$redirects	= $ARCurrent->shortcut_redirect;
2650
		if (isset($redirects) && is_array($redirects)) {
2651
			$redirpath = $this->path;
2652
			while (!$template['arTemplateId'] &&
0 ignored issues
show
The variable $template does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2653
						($redir = array_pop($redirects)) &&
2654
							$redir["keepurl"] &&
2655
								(substr($redirpath, 0, strlen($redir["dest"])) == $redir["dest"])
2656
			) {
2657
				debug("call_super: following shortcut redirect: $redirpath; to ".$redir["dest"]);
2658
				$template = $this->getPinpTemplate($arCallFunction, $redirpath, $redir["dest"], false, $arLibrariesSeen, $arSuperContext);
2659
				$redirpath = $redir['src'];
2660
			}
2661 View Code Duplication
			if (!$template["arTemplateId"]) {
2662
				$template = $this->getPinpTemplate($arCallFunction, $redirpath, '', false, $arLibrariesSeen, $arSuperContext);
2663
			}
2664
		}
2665 View Code Duplication
		if (!$template["arTemplateId"]) {
2666
			$template = $this->getPinpTemplate($arCallFunction, $this->path, '', false, $arLibrariesSeen, $arSuperContext);
2667
		}
2668
		if ($template["arCallTemplate"] && $template["arTemplateId"]) {
2669
			$arTemplates=$this->store->get_filestore("templates");
2670
			if ($arTemplates->exists($template["arTemplateId"], $template["arCallTemplate"].".inc")) {
2671
				debug("call_super: found template ".$template["arCallTemplate"]." on object with id ".$template["arTemplateId"]);
2672
				$arLibrary = $template['arLibrary'];
2673
				debug("call_super: found template on ".$template["arTemplateId"]);
2674
				if (is_int($arLibrary)) {
2675
					// set the library name for unnamed libraries to 'current'
2676
					// so that calls using getvar('arLibrary') will keep on working
2677
					$arLibrary = "current";
2678
				}
2679 View Code Duplication
				if (!is_string($arCallArgs)) {
2680
					$arCallArgs['arCallFunction'] = $arCallFunction;
2681
					$arCallArgs['arLibrary'] = $arLibrary;
2682
					$arCallArgs['arLibraryPath'] = $template["arLibraryPath"];
2683
				}
2684
				$ARCurrent->arCallStack[]=$arCallArgs;
2685
				$this->pushContext(
2686
					array(
2687
						"scope" => "pinp",
2688
						"arSuperContext" => $arSuperContext,
2689
						"arLibrary" => $arLibrary,
2690
						"arLibraryPath" => $template['arLibraryPath'],
2691
						"arCallFunction" => $arCallFunction,
2692
						"arCurrentObject" => $this,
2693
						"arCallType" => $template['arCallType'],
2694
						"arCallTemplateName" => $template['arCallTemplateName'],
2695
						"arCallTemplateNLS"  => $template['arCallTemplateNLS'],
2696
						"arCallTemplateType" => $template['arCallTemplateType'],
2697
						"arCallTemplatePath" => $template['arCallTemplatePath']
2698
					)
2699
				);
2700
				$continue = true;
2701
				$eventData = new object();
2702 View Code Duplication
				if ( !$AR->contextCallHandler ) { /* prevent onbeforecall from re-entering here */
2703
					$AR->contextCallHandler = true;
2704
					$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
The property arCallArgs does not seem to exist in object.

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

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

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

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

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

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

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

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

Loading history...
2707
					$eventData = ar_events::fire('onbeforecall', $eventData);
0 ignored issues
show
$eventData is of type object<object>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
2708
					$ARCurrent->arResult = $eventData->arResult;
2709
					$AR->contextCallHandler = false;
2710
					$continue = ($eventData!=false);
2711
				}
2712
				if ( $continue ) {
2713
					set_error_handler(array('pobject','pinpErrorHandler'),error_reporting());
2714
					$func = $arTemplates->import($template["arTemplateId"], $template["arCallTemplate"]);
2715
					if(is_callable($func)){
2716
						$arResult = $func($this);
2717
					}
2718
					restore_error_handler();
2719
2720 View Code Duplication
					if ( !$AR->contextCallHandler ) { /* prevent oncall from re-entering here */
2721
						$AR->contextCallHandler = true;
2722
						$temp = $ARCurrent->arResult; /* event listeners will change ARCurrent->arResult */
2723
						$eventData->arResult = $arResult;
2724
						ar_events::fire('oncall', $eventData );
2725
						$ARCurrent->arResult = $temp; /* restore correct result */
2726
						$AR->contextCallHandler = false;
2727
					}
2728
				}
2729
				array_pop($ARCurrent->arCallStack);
2730
				$this->popContext();
2731
			}
2732
		}
2733
2734
		return $arResult;
2735
	}
2736
2737
	public function _get($path, $function="view.html", $args="") {
2738
		// remove possible path information (greedy match)
2739
		if ( !($function instanceof \Closure) ) {
2740
			$function = basename( (string) $function);
2741
		}
2742
		return $this->store->call($function, $args,
2743
			$this->store->get(
2744
				$this->make_path($path)));
2745
	}
2746
2747
	public function _call_object($object, $function, $args="") {
2748
		return $object->call($function, $args);
2749
	}
2750
2751 View Code Duplication
	public function _ls($function="list.html", $args="") {
2752
		// remove possible path information (greedy match)
2753
		if ( ! ( $function instanceof \Closure ) ) {
2754
			$function = basename( (string) $function );
2755
		}
2756
		return $this->store->call($function, $args,
2757
			$this->store->ls($this->path));
2758
	}
2759
2760 View Code Duplication
	public function _parents($function="list.html", $args="", $top="") {
2761
		// remove possible path information (greedy match)
2762
		if ( !($function instanceof \Closure ) ) {
2763
			$function = basename( (string) $function);
2764
		}
2765
		return $this->parents($this->path, $function, $args, $top);
2766
	}
2767
2768
	public function _find($criteria, $function="list.html", $args="", $limit=100, $offset=0) {
2769
		$this->error = '';
2770
		// remove possible path information (greedy match)
2771
		if ( !($function instanceof \Closure ) ) {
2772
			$function = basename( (string) $function);
2773
		}
2774
		$result = $this->store->call($function, $args,
2775
			$this->store->find($this->path, $criteria, $limit, $offset));
2776 View Code Duplication
		if ($this->store->error) {
2777
			$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error );
2778
		}
2779
		return $result;
2780
	}
2781
2782
	public function _exists($path) {
2783
		return $this->store->exists($this->make_path($path));
2784
	}
2785
2786
	public function _implements($implements) {
2787
		return $this->AR_implements($implements);
2788
	}
2789
2790 52
	public function getvar($var) {
2791 52
	global $ARCurrent, $ARConfig; // Warning: if you add other variables here, make sure you cannot get at it through $$var.
2792
2793 52 View Code Duplication
		if ($ARCurrent->arCallStack) {
2794 48
			$arCallArgs=end($ARCurrent->arCallStack);
2795 48
			if (isset($arCallArgs) && is_array($arCallArgs)) {
2796 36
				extract($arCallArgs);
2797 40
			} else if (is_string($arCallArgs)) {
2798
				Parse_Str($arCallArgs);
2799
			}
2800 36
		}
2801 52
		if (isset($$var) && ($var!='ARConfig')) {
2802 16
			$result=$$var;
2803 52
		} else if (isset($ARCurrent->$var)) {
2804
			$result=$ARCurrent->$var;
2805 52
		} else if (isset($ARConfig->pinpcache[$this->path][$var])) {
2806
			$result=$ARConfig->pinpcache[$this->path][$var];
2807 52 View Code Duplication
		} else if (isset($_POST[$var])) {
2808
			$result=$_POST[$var];
2809 52
		} else if (isset($_GET[$var])) {
2810
			$result=$_GET[$var];
2811 52
		} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$var])) {
2812
			$result=$arStoreVars[$var];
2813 52
		} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$var])) {
2814
			$result=$arStoreVars[$var];
2815
		}
2816 52
		return $result;
2817
	}
2818
2819
	public function _getvar($var) {
2820
		return $this->getvar($var);
2821
	}
2822
2823
	public function putvar($var, $value) {
2824
		global $ARCurrent;
2825
2826
		$ARCurrent->$var=$value;
2827
	}
2828
2829
	public function _putvar($var, $value) {
2830
		return $this->putvar($var, $value);
2831
	}
2832
2833
	public function _setnls($nls) {
2834
		$this->setnls($nls);
2835
	}
2836
2837
	// not exposed to pinp for obvious reasons
2838
	public function sgKey($grants) {
2839
		global $AR;
2840
		if( !$AR->sgSalt || !$this->CheckSilent("config") ) {
2841
			return false;
2842
		}
2843
		// serialize the grants so the order does not matter, mod_grant takes care of the sorting for us
2844
		$this->_load("mod_grant.php");
2845
		$mg = new mod_grant();
2846
		$grantsarray = array();
2847
		$mg->compile($grants, $grantsarray);
2848
		$grants = serialize($grantsarray);
2849
		return sha1( $AR->sgSalt . $grants . $this->path);
2850
	}
2851
2852
	public function sgBegin($grants, $key = '', $path = '.') {
2853
		global $AR;
2854
		$result = false;
2855
		$context = $this->getContext();
2856
		$path    = $this->make_path($path);
2857
2858
		// serialize the grants so the order does not matter, mod_grant takes care of the sorting for us
2859
		$this->_load("mod_grant.php");
2860
		$mg = new mod_grant();
2861
		$grantsarray = array();
2862
		$mg->compile($grants, $grantsarray);
2863
2864
		if ($context['scope'] == 'pinp') {
2865
			$checkgrants = serialize($grantsarray);
2866
			$check = ( $AR->sgSalt ? sha1( $AR->sgSalt . $checkgrants . $path) : false ); // not using suKey because that checks for config grant
2867
		} else {
2868
			$check = true;
2869
			$key = true;
2870
		}
2871
		if( $check !== false && $check === $key ) {
2872
			$AR->user->grants = array(); // unset all grants for the current user, this makes sure GetValidGrants gets called again for this path and all childs
2873
			$grantsarray = (array)$AR->sgGrants[$path];
2874
			$mg->compile($grants, $grantsarray);
2875
			$AR->sgGrants[$path] = $grantsarray;
2876
			$result = true;
2877
		}
2878
		return $result;
2879
	}
2880
2881
	public function sgEnd($path = '.') {
2882
		global $AR;
2883
		$AR->user->grants = array(); // unset all grants for the current user, this makes sure GetValidGrants gets called again for this path and all childs
2884
		$path = $this->make_path( $path );
2885
		unset($AR->sgGrants[$path]);
2886
		return true; // temp return true;
2887
	}
2888
2889
	public function sgCall($grants, $key, $function="view.html", $args="") {
2890
		$result = false;
2891
		if( $this->sgBegin($grants, $key ) ) {
2892
			$result = $this->call($function, $args);
2893
			$this->sgEnd();
2894
		}
2895
		return $result;
2896
	}
2897
2898
	public function _sgBegin($grants, $key, $path = '.') {
2899
		return $this->sgBegin($grants, $key, $path);
2900
	}
2901
2902
	public function _sgEnd($path = '.') {
2903
		return $this->sgEnd($path);
2904
	}
2905
2906
	public function _sgCall($grants, $key, $function="view.html", $args="") {
2907
		return $this->sgCall($grants, $key, $function, $args);
2908
	}
2909
2910
	public function _widget($arWidgetName, $arWidgetTemplate, $arWidgetArgs="", $arWidgetType="lib") {
2911
	global $AR, $ARConfig, $ARCurrent, $ARnls;
2912
2913
		$arWidgetName=preg_replace("/[^a-zA-Z0-9\/]/","",$arWidgetName);
2914
		$arWidgetTemplate=preg_replace("/[^a-zA-Z0-9\.]/","",$arWidgetTemplate);
2915
		$wgResult=null;
2916
		if ($arWidgetType=="www") {
2917
			$coderoot=$AR->dir->root;
2918
		} else {
2919
			$coderoot=$this->store->get_config("code");
2920
		}
2921
		if (file_exists($coderoot."widgets/$arWidgetName")) {
2922
			if (file_exists($coderoot."widgets/$arWidgetName/$arWidgetTemplate")) {
2923
				if (isset($arWidgetArgs) && is_array($arWidgetArgs)) {
2924
					extract($arWidgetArgs);
2925
				} else if (is_string($arWidgetArgs)) {
2926
					Parse_str($arWidgetArgs);
2927
				}
2928
				include($coderoot."widgets/$arWidgetName/$arWidgetTemplate");
2929
			} else {
2930
				error("Template $arWidgetTemplate for widget $arWidgetName not found.");
2931
			}
2932
		} else {
2933
			error(sprintf($ARnls["err:widgetnotfound"],$arWidgetName));
2934
		}
2935
		if ($wgResult) {
2936
			return $wgResult;
2937
		}
2938
	}
2939
2940
	public function _getdata($varname, $nls="none", $emptyResult=false) {
2941
		return $this->getdata($varname, $nls, $emptyResult);
2942
	}
2943
2944
	public function _showdata($varname, $nls="none", $emptyResult=false) {
2945
		$this->showdata($varname, $nls, $emptyResult);
2946
	}
2947
2948
	public function _gettext($index=false) {
2949
	global $ARnls;
2950
		if (!$index) {
2951
			return $ARnls;
2952
		} else {
2953
			return $ARnls[$index];
2954
		}
2955
	}
2956
2957
	public function _loadtext($nls, $section="") {
2958
	global $ARnls, $ARCurrent;
2959
		if( is_object($ARnls) ) {
2960
			$ARnls->load($section, $nls);
2961
			$ARnls->setLanguage($nls);
2962
			$this->ARnls = $ARnls;
2963
		} else { // older loaders and other shizzle
2964
2965
			$nls = preg_replace('/[^a-z]*/i','',$nls);
2966
			$section = preg_replace('/[^a-z0-9\._:-]*/i','',$section);
2967
			if (!$section) {
2968
				include($this->store->get_config("code")."nls/".$nls);
2969
				$this->ARnls = array_merge((array)$this->ARnls, $ARnls);
2970
			} else {
2971
				$nlsfile = $this->store->get_config("code")."nls/".$section.".".$nls;
2972
				if(strpos($nlsfile, ':') === false && file_exists($nlsfile)) {
2973
					include($nlsfile);
2974
					$this->ARnls = array_merge((array)$this->ARnls, $ARnls);
2975
				} else {
2976
					// current result;
2977
					$arResult = $ARCurrent->arResult;
2978
					$this->pushContext(array());
2979
						$oldnls = $this->reqnls;
2980
						$this->reqnls = $nls;
2981
						$this->CheckConfig($section, array('nls' => $nls));
2982
						$this->reqnls = $oldnls;
2983
					$this->popContext();
2984
					// reset current result (CheckConfig may have changed it when it should not have).
2985
					$ARCurrent->arResult = $arResult;
2986
				}
2987
			}
2988
		}
2989
	}
2990
2991
	public function _startsession() {
2992
	global $ARCurrent;
2993
		ldStartSession(0);
2994
		return $ARCurrent->session->id;
2995
	}
2996
2997
	public function _putsessionvar($varname, $varvalue) {
2998
	global $ARCurrent;
2999
3000
		if ($ARCurrent->session) {
3001
			return $ARCurrent->session->put($varname, $varvalue);
3002
		} else {
3003
			return false;
3004
		}
3005
	}
3006
3007
	public function _getsessionvar($varname) {
3008
	global $ARCurrent;
3009
3010
		if ($ARCurrent->session) {
3011
			return $ARCurrent->session->get($varname);
3012
		} else {
3013
			return false;
3014
		}
3015
	}
3016
3017
	public function _setsessiontimeout($timeout = 0) {
3018
	global $ARCurrent;
3019
		if ($ARCurrent->session) {
3020
			return $ARCurrent->session->setTimeout($timeout);
3021
		} else {
3022
			return false;
3023
		}
3024
	}
3025
3026
	public function _killsession() {
3027
	global $ARCurrent;
3028
3029
		if ($ARCurrent->session) {
3030
			$ARCurrent->session->kill();
3031
			unset($ARCurrent->session);
3032
		}
3033
	}
3034
3035
	public function _sessionid() {
3036
	global $ARCurrent;
3037
		if ($ARCurrent->session) {
3038
			return $ARCurrent->session->id;
3039
		} else {
3040
			return 0;
3041
		}
3042
	}
3043
3044
	public function _resetloopcheck() {
3045
		return $this->resetloopcheck();
3046
	}
3047
3048
	public function _make_path($path="") {
3049
		return $this->make_path($path);
3050
	}
3051
3052
	public function _make_ariadne_url($path="") {
3053
		return $this->make_ariadne_url($path);
3054
	}
3055
3056
	public function _make_url($path="", $nls=false, $session=true, $https=null, $keephost=null) {
3057
		return $this->make_url($path, $nls, $session, $https, $keephost);
3058
	}
3059
3060
	public function _make_local_url($path="", $nls=false, $session=true, $https=null) {
3061
		return $this->make_local_url($path, $nls, $session, $https);
3062
	}
3063
3064
	public function _getcache($name, $nls='') {
3065
		return $this->getcache($name, $nls);
3066
	}
3067
3068
	public function _cached($name, $nls='') {
3069
		return $this->cached($name, $nls);
3070
	}
3071
3072
	public function _savecache($time="") {
3073
		return $this->savecache($time);
3074
	}
3075
3076
	public function _getdatacache($name) {
3077
		return $this->getdatacache($name);
3078
	}
3079
3080
	public function _savedatacache($name,$data,$time="")
3081
	{
3082
		return $this->savedatacache($name,$data,$time);
3083
	}
3084
3085 56
	public function currentsite($path="", $skipRedirects = false) {
3086 56
		global $ARCurrent, $ARConfig;
3087 56
		if (!$path) {
3088 48
			$path=$this->path;
3089 36
		}
3090 56
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3091 56
		if (!$skipRedirects && @count($ARCurrent->shortcut_redirect)) {
3092
			$redir = end($ARCurrent->shortcut_redirect);
3093
			if ($redir["keepurl"] && substr($path, 0, strlen($redir["dest"])) == $redir["dest"]) {
3094
				if (substr($config->site, 0, strlen($redir["dest"]))!=$redir["dest"]) {
3095
					// search currentsite from the reference
3096
					$config = ($ARConfig->cache[$redir['src']]) ? $ARConfig->cache[$redir['src']] : $this->loadConfig($redir['src']);
3097
				}
3098
			}
3099
		}
3100 56
		return $config->site;
3101
	}
3102
3103
	public function parentsite($site) {
3104
	global $ARConfig;
3105
		$path=$this->store->make_path($site, "..");
3106
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3107
		return $config->site;
3108
	}
3109
3110 4 View Code Duplication
	public function currentsection($path="") {
3111 4
	global $ARConfig;
3112 4
		if (!$path) {
3113 4
			$path=$this->path;
3114 3
		}
3115 4
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3116 4
		return $config->section;
3117
	}
3118
3119 View Code Duplication
	public function parentsection($path) {
3120
	global $ARConfig;
3121
		$path=$this->store->make_path($path, "..");
3122
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3123
		return $config->section;
3124
	}
3125
3126 24 View Code Duplication
	public function currentproject($path="") {
3127 24
	global $ARConfig;
3128 24
		if (!$path) {
3129
			$path=$this->path;
3130
		}
3131 24
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3132 24
		return $config->project;
3133
	}
3134
3135
	public function parentproject($path) {
3136
	global $ARConfig;
3137
		$path=$this->store->make_path($path, "..");
3138
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3139
		return $config->project;
3140
	}
3141
3142
	public function validateFormSecret() {
3143
		global $ARCurrent;
3144
		if (!$ARCurrent->session) {
3145
			return true;
3146
		}
3147
3148
		if ($ARCurrent->session && $ARCurrent->session->data && $ARCurrent->session->data->formSecret) {
3149
			$formSecret = $this->getvar("formSecret");
3150
			return ($formSecret === $ARCurrent->session->data->formSecret);
3151
		}
3152
		return false;
3153
	}
3154
3155
	public function _validateFormSecret() {
3156
		return $this->validateFormSecret();
3157
	}
3158
3159
	public function getValue($name, $nls=false) {
3160
	global $ARCurrent;
3161
		switch ($nls) {
3162
			case "none":
3163
				$result = $this->data->$name;
3164
			break;
3165
			case false:
3166
				$nls = $ARCurrent->nls;
3167
				if (!isset($this->data->$nls) || !isset($this->data->$nls->$name)) {
3168
					$result = $this->data->$name;
3169
					break;
3170
				}
3171
			default:
3172
				$result = $this->data->$nls->$name;
3173
		}
3174
		return $result;
3175
	}
3176
3177
	public function setValue($name, $value, $nls=false) {
3178
3179
	global $AR, $ARConfig;
3180
		if ($value === null) {
3181
			if ($nls && $nls!="none") {
3182
				unset($this->data->$nls->$name);
3183
				if (!count(get_object_vars($this->data->$nls))) {
3184
					unset($this->data->$nls);
3185
					unset($this->data->nls->list[$nls]);
3186
					if (!count($this->data->nls->list)) {
3187
						unset($this->data->nls->list);
3188
						unset($this->data->nls);
3189
					} else {
3190
						if ($this->data->nls->default == $nls) {
3191
							if ($this->data->nls->list[$ARConfig->nls->default]) {
3192
								$this->data->nls->default = $ARConfig->nls->default;
3193
							} else {
3194
								list($this->data->nls->default) = each($this->data->nls->list);
3195
							}
3196
						}
3197
					}
3198
				}
3199
			} else {
3200
				unset($this->data->$name);
3201
			}
3202
		} else
3203
		if (!$nls) {
3204
			$this->data->$name = $value;
3205
		} else {
3206
			if (!$this->data->$nls) {
3207
				$this->data->$nls = new object;
3208
				if (!$this->data->nls) {
3209
					$this->data->nls = new object;
3210
					$this->data->nls->default = $nls;
3211
				}
3212
				$this->data->nls->list[$nls] = $AR->nls->list[$nls];
3213
			}
3214
			$this->data->$nls->$name = $value;
3215
		}
3216
	}
3217
3218
	public function showValue($name, $nls=false) {
3219
		$result = $this->getValue($name, $nls);
3220
		echo $result;
3221
		return $result;
3222
	}
3223
3224
	public function _getValue($name, $nls=false) {
3225
		return $this->getValue($name, $nls);
3226
	}
3227
3228
	public function _setValue($name, $value, $nls=false) {
3229
		return $this->setValue($name, $value, $nls);
3230
	}
3231
3232
	public function _showValue($name, $nls=false) {
3233
		return $this->showValue($name, $nls);
3234
	}
3235
3236
	public function _currentsite($path="", $skipRedirects = false) {
3237
		return $this->currentsite( $path, $skipRedirects );
3238
	}
3239
3240
	public function _parentsite($site) {
3241
		return $this->parentsite($site);
3242
	}
3243
3244
	public function _currentsection() {
3245
		return $this->currentsection();
3246
	}
3247
3248
	public function _parentsection($section) {
3249
		return $this->parentsection($section);
3250
	}
3251
3252
	public function _currentproject() {
3253
		return $this->currentproject();
3254
	}
3255
3256
	public function _parentproject($path) {
3257
		return $this->parentproject($path);
3258
	}
3259
3260
	public function _checkAdmin($user) {
3261
		return $this->CheckAdmin($user);
3262
	}
3263
3264
	public function _checkgrant($grant, $modifier=ARTHISTYPE, $path=".") {
3265
		// as this is called within a pinp template,
3266
		// all the grants are already loaded, so
3267
		// checksilent will fullfill our needs
3268
		$this->pushContext(array("scope" => "php"));
3269
			$result = $this->CheckSilent($grant, $modifier, $path);
3270
		$this->popContext();
3271
		return $result;
3272
	}
3273
3274
	public function _checkpublic($grant, $modifier=ARTHISTYPE) {
3275
3276
		return $this->CheckPublic($grant, $modifier);
3277
	}
3278
3279
	public function _getcharset() {
3280
		return $this->getcharset();
3281
	}
3282
3283
	public function _count_find($query='') {
3284
		return $this->count_find($this->path, $query);
3285
	}
3286
3287
	public function _count_ls() {
3288
		return $this->count_ls($this->path);
3289
	}
3290
3291
	public function _HTTPRequest($method, $url, $postdata = "", $port=80) {
3292
		return $this->HTTPRequest($method, $url, $postdata, $port);
3293
	}
3294
3295
	public function _make_filesize( $size="" ,$precision=0) {
3296
		return $this->make_filesize( $size ,$precision);
3297
	}
3298
3299
	public function _convertToUTF8($data, $charset = "CP1252") {
3300
		return $this->convertToUTF8($data,$charset);
3301
	}
3302
3303
	public function _getuser() {
3304
	global $AR;
3305
		if ($AR->pinp_user && $AR->pinp_user->data->login == $AR->user->data->login) {
3306
			$user = $AR->pinp_user;
3307
		} else {
3308
			$this->pushContext(array("scope" => "php"));
3309
				if ( $AR->user instanceof ariadne_object ) {
3310
					$user = current($AR->user->get(".", "system.get.phtml"));
3311
				} else {
3312
					$user = $AR->user;
3313
				}
3314
				$AR->pinp_user = $user;
3315
			$this->popContext();
3316
		}
3317
		return $user;
3318
	}
3319
3320
	public function ARinclude($file) {
3321
		include($file);
3322
	}
3323
3324 4
	public function _load($class) {
3325
		// only allow access to modules in the modules directory.
3326 4
		$class = preg_replace('/[^a-z0-9\._]/i','',$class);
3327 4
		include_once($this->store->get_config("code")."modules/".$class);
3328 4
	}
3329
3330
	public function _import($class) {
3331
		// deprecated
3332
		return $this->_load($class);
3333
	}
3334
3335 16
	public function html_to_text($text) {
3336 16
		$trans = array_flip(get_html_translation_table(HTML_ENTITIES));
3337 16
		$cb  = function($matches) use ($trans) {
3338
			return strtr($matches[1],$trans);
3339 16
		};
3340
		//strip nonbreaking space, strip script and style blocks, strip html tags, convert html entites, strip extra white space
3341 16
		$search_clean = array("%&nbsp;%i", "%<(script|style)[^>]*>.*?<\/(script|style)[^>]*>%si", "%<[\/]*[^<>]*>%Usi", "%\s+%");
3342 16
		$replace_clean = array(" ", " ", " ", " ");
3343
3344 16
		$text = preg_replace_callback(
3345 16
			"%(\&[a-zA-Z0-9\#]+;)%s",
3346 15
			$cb,
3347
			$text
3348 15
		);
3349 16
		$text = preg_replace($search_clean, $replace_clean, $text);
3350 16
		return $text;
3351
	}
3352
3353
	public function _html_to_text($text) {
3354
		return $this->html_to_text($text);
3355
	}
3356
3357
	public function _newobject($filename, $type) {
3358
		$newpath=$this->make_path($filename);
3359
		$newparent=$this->store->make_path($newpath, "..");
3360
		$data=new object;
3361
		$object=$this->store->newobject($newpath, $newparent, $type, $data);
3362
		$object->arIsNewObject=true;
3363
		return $object;
3364
	}
3365
3366
	public function _save($properties="", $vtype="") {
3367
		if (isset($properties) && is_array($properties)) {
3368
			// isn't this double work, the save function doesn this again
3369
			foreach ($properties as $prop_name => $prop) {
3370
				foreach ($prop as $prop_index => $prop_record) {
3371
					$record = array();
3372 View Code Duplication
					foreach ($prop_record as $prop_field => $prop_value) {
3373
						switch (gettype($prop_value)) {
3374
							case "integer":
3375
							case "boolean":
3376
							case "double":
3377
								$value = $prop_value;
3378
							break;
3379
							default:
3380
								$value = $prop_value;
3381
								if (substr($prop_value, 0, 1) === "'" && substr($prop_value, -1) === "'"
3382
										&& "'".AddSlashes(StripSlashes(substr($prop_value, 1, -1)))."'" == $prop_value) {
3383
									$value = stripSlashes(substr($prop_value,1,-1));
3384
									// todo add deprecated warning
3385
								}
3386
						}
3387
						$record[$prop_field] = $value;
3388
					}
3389
					$properties[$prop_name][$prop_index] = $record;
3390
				}
3391
			}
3392
		}
3393
3394
		if ($this->arIsNewObject && $this->CheckSilent('add', $this->type)) {
3395
			unset($this->data->config);
3396
			$result = $this->save($properties, $vtype);
0 ignored issues
show
It seems like $properties can also be of type array or null; however, ariadne_object::save() does only seem to accept string, maybe add an additional type check?

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

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

    return array();
}

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

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

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

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

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

    return array();
}

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
3402
	}
3403
3404
	public function _is_supported($feature) {
3405
		return $this->store->is_supported($feature);
3406
	}
3407
3408
	/*
3409
		since the preg_replace() function is able to execute normal php code
3410
		we have to intercept all preg_replace() calls and parse the
3411
		php code with the pinp parser.
3412
	*/
3413
3414
3415
	/*	this is a private function used by the _preg_replace wrapper */
3416
	// FIXME: remove this function when the minimal php version for ariadne is raised to php 7.0
3417
	protected function preg_replace_compile($pattern, $replacement) {
3418
	global $AR;
3419
		include_once($this->store->get_config("code")."modules/mod_pinp.phtml");
3420
		preg_match("/^\s*(.)/", $pattern, $regs);
3421
		$delim = $regs[1];
3422
		if (@eregi("\\${delim}[^$delim]*\\${delim}.*e.*".'$', $pattern)) {
3423
			$pinp = new pinp($AR->PINP_Functions, 'local->', '$AR_this->_');
3424
			return substr($pinp->compile("<pinp>$replacement</pinp>"), 5, -2);
3425
		} else {
3426
			return $replacement;
3427
		}
3428
	}
3429
3430
	public function _preg_replace($pattern, $replacement, $text, $limit = -1) {
3431
		if (version_compare(PHP_VERSION, '7.0.0', '<')) {
3432
			if (isset($pattern) && is_array($pattern)) {
3433
				$newrepl = array();
3434
				reset($replacement);
3435
				foreach ($pattern as $i_pattern) {
3436
					list(, $i_replacement) = each($replacement);
3437
					$newrepl[] = $this->preg_replace_compile($i_pattern, $i_replacement);
3438
				}
3439
			} else {
3440
				$newrepl = $this->preg_replace_compile($pattern, $replacement);
3441
			}
3442
		} else {
3443
			// php7 is safe, no more eval
3444
			$newrepl = $replacement;
3445
		}
3446
		return preg_replace($pattern, $newrepl, $text, $limit);
3447
	}
3448
3449
	/* ob_start accepts a callback but we don't want that
3450
	 * this wrapper removes the arguments from the ob_start call
3451
	 */
3452
	public function _ob_start() {
3453
		return ob_start();
3454
	}
3455
3456
	public function _loadConfig($path='') {
3457
		return clone $this->loadConfig($path);
3458
	}
3459
3460
	public function _loadUserConfig($path='') {
3461
		return $this->loadUserConfig($path);
3462
	}
3463
3464
	public function _loadLibrary($name, $path) {
3465 4
		return $this->loadLibrary($name, $path);
3466
	}
3467
3468
	public function _resetConfig($path='') {
3469
		return $this->resetConfig($path);
3470
	}
3471
3472
	public function _getLibraries($path = '') {
3473
		return $this->getLibraries($path);
3474
	}
3475
3476
3477
	public function _getSetting($setting) {
3478
	global $AR;
3479
3480
		switch ($setting) {
3481
			case 'www':
3482
			case 'dir:www':
3483
				return $AR->dir->www;
3484
			case 'images':
3485
			case 'dir:images':
3486
				return $AR->dir->images;
3487
			case 'ARSessionKeyCheck':
3488
				$result = null;
3489
				if (function_exists('ldGenerateSessionKeyCheck')) {
3490
					$result = ldGenerateSessionKeyCheck();
3491
				}
3492
				return $result;
3493
			break;
3494
			case 'nls:list':
3495
				return $AR->nls->list;
3496
			break;
3497
			case 'nls:default':
3498
				return $AR->nls->default;
3499
			break;
3500
			case 'svn':
3501
				return $AR->SVN->enabled;
3502
			break;
3503
		}
3504
	}
3505
3506
	public function __call($name,$arguments) {
3507
		if ( $name[0] == '_' ) {
3508
			$fname = substr($name, 1);
3509
			if ( isset($this->{$fname}) && $this->{$fname} instanceof \Closure ) {
3510
				\Closure::bind( $this->{$fname}, $this );
3511
				return call_user_func_array( $this->{$fname}, $arguments);
3512
			}
3513
		}
3514
		switch($name) {
3515
			case "implements":
3516
				return $this->AR_implements($arguments[0]);
3517
			break;
3518
			default:
3519
				trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $name), E_USER_ERROR);
3520
				return false;
3521
			break;
3522
		}
3523
	}
3524
3525
	static public function pinpErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) {
3526 7
		global $nocache;
3527 7
		if (($errno & error_reporting()) == 0) {
3528 7
			return true;
3529
		}
3530
3531
		$nocache = true;
3532
		$context = pobject::getContext();
3533
		if ($context["arLibraryPath"]) { //  != null) {
3534
			$msg = "Error on line $errline in ".$context['arCallTemplateType'].'::'.$context['arCallFunction'] ." in library ".$context["arLibraryPath"] ."\n".$errstr."\n";
3535
		} else {
3536
			$msg = "Error on line $errline in ".$context['arCallTemplateType'].'::'.$context['arCallFunction'] ." on object ".$context['arCurrentObject']->path."\n".$errstr."\n";
3537
		}
3538
		$display = ini_get('display_errors');
3539
3540
		if($display) {
3541
			echo $msg;
3542
		}
3543
		error_log($msg);
3544
3545
		return false;
3546
	}
3547
3548
} // end of ariadne_object class definition
3549