Completed
Push — dev ( fb2453...84e3a0 )
by Auke
13:56
created

ariadne_object   D

Complexity

Total Complexity 859

Size/Duplication

Total Lines 3502
Duplicated Lines 11.11 %

Coupling/Cohesion

Components 2
Dependencies 7

Test Coverage

Coverage 38.19%
Metric Value
wmc 859
lcom 2
cbo 7
dl 389
loc 3502
ccs 960
cts 2514
cp 0.3819
rs 4.4103

159 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 8 2
A ls() 0 4 1
A get() 0 4 1
C parents() 0 35 8
A find() 4 11 2
A count_find() 0 9 2
A count_ls() 0 3 1
C saveMergeWorkflowResult() 20 34 11
A link() 0 3 1
B delete() 0 30 5
A exists() 0 4 1
B make_path() 0 14 5
A make_ariadne_url() 0 5 1
F call() 0 186 35
C saveCustomData() 0 46 16
F save() 4 193 28
F make_url() 3 88 31
A getContext() 0 4 1
C getConfig() 14 73 15
A getLibraries() 0 5 1
C savecache() 10 47 10
B convertToUTF8() 0 18 6
A _parents() 7 7 2
A _implements() 0 3 1
A sgEnd() 0 7 1
A _sgEnd() 0 3 1
A _sgCall() 0 3 1
A _getdata() 0 3 1
A _gettext() 0 8 2
B _loadtext() 0 33 5
A _make_ariadne_url() 0 3 1
A _make_url() 0 3 1
A _make_local_url() 0 3 1
A _getcache() 0 3 1
A _cached() 0 3 1
A _savecache() 0 3 1
A _getdatacache() 0 3 1
A _savedatacache() 0 4 1
A _validateFormSecret() 0 3 1
A _getValue() 0 3 1
A _setValue() 0 3 1
A _showValue() 0 3 1
A _currentsite() 0 3 1
A _parentsite() 0 3 1
A _currentsection() 0 3 1
A _parentsection() 0 3 1
A _currentproject() 0 3 1
A _parentproject() 0 3 1
A _checkAdmin() 0 3 1
A _checkgrant() 0 9 1
A _checkpublic() 0 4 1
A _count_ls() 0 3 1
A _HTTPRequest() 0 3 1
A _make_filesize() 0 3 1
A _convertToUTF8() 0 3 1
B _preg_replace() 0 18 5
A _loadUserConfig() 0 3 1
A _resetConfig() 0 3 1
D make_local_url() 7 54 18
A AR_implements() 0 4 1
A getlocks() 9 9 2
A lock() 9 9 2
A unlock() 9 9 2
A touch() 3 10 3
B mogrify() 3 16 5
A can_mogrify() 0 6 2
A load_properties() 0 3 1
A _load_properties() 0 3 1
A load_property() 0 3 1
A _load_property() 0 3 1
F GetValidGrants() 41 136 48
A pushContext() 0 7 2
A setContext() 0 4 1
A popContext() 0 4 1
A CheckAdmin() 0 9 3
C CheckLogin() 0 45 13
A CheckPublic() 0 17 3
C CheckSilent() 0 24 7
B CheckNewFile() 0 33 4
A resetConfig() 12 12 3
A clearChildConfigs() 13 13 3
F getConfigData() 0 96 38
C loadConfig() 0 47 9
A loadUserConfig() 0 15 3
C getTemplateFromCache() 24 58 12
C loadLibraryCache() 0 36 12
C loadLibrary() 10 43 11
B mergeLibraryConfig() 0 13 6
A _mergeLibraryConfig() 0 3 1
F getPinpTemplate() 27 150 38
F CheckConfig() 29 299 71
F ClearCache() 0 124 25
C getcache() 6 52 9
A cached() 0 9 2
B getdatacache() 0 23 5
B savedatacache() 4 17 5
A showdata() 0 3 1
A setnls() 0 3 1
A getcharset() 0 3 1
D HTTPRequest() 0 104 25
B make_filesize() 0 17 5
A resetloopcheck() 0 4 1
A _call() 0 7 2
F _call_super() 29 111 20
A _get() 0 9 2
A _call_object() 0 3 1
A _ls() 8 8 2
A _find() 3 13 3
A _exists() 0 3 1
C getvar() 17 28 15
A _getvar() 0 3 1
A putvar() 0 5 1
A _putvar() 0 3 1
A _setnls() 0 3 1
A sgKey() 0 13 3
B sgBegin() 0 28 5
A sgCall() 0 8 2
A _sgBegin() 0 3 1
C _widget() 0 29 8
A _showdata() 0 3 1
A _startsession() 0 5 1
A _putsessionvar() 0 9 2
A _getsessionvar() 0 9 2
A _setsessiontimeout() 0 8 2
A _killsession() 0 8 2
A _sessionid() 0 8 2
A _resetloopcheck() 0 3 1
A _make_path() 0 3 1
B currentsite() 0 17 9
A parentsite() 0 6 2
A currentsection() 8 8 3
A parentsection() 6 6 2
A currentproject() 8 8 3
A parentproject() 0 6 2
B validateFormSecret() 0 12 5
B getValue() 0 17 5
C setValue() 0 40 11
A showValue() 0 5 1
A _getcharset() 0 3 1
A _count_find() 0 3 1
A _getuser() 0 16 4
A ARinclude() 0 3 1
A _load() 0 5 1
A _import() 0 4 1
A html_to_text() 0 17 1
A _html_to_text() 0 3 1
A _newobject() 0 8 1
C _save() 17 37 16
A _is_supported() 0 3 1
A preg_replace_compile() 0 12 2
A _ob_start() 0 3 1
A _loadConfig() 0 3 1
A _loadLibrary() 0 3 1
A _getLibraries() 0 3 1
D _getSetting() 0 28 10
B __call() 0 18 5
B pinpErrorHandler() 0 22 4
B compare_hosts() 0 23 6
D getdata() 25 66 35

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ariadne_object often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ariadne_object, and based on these observations, apply Extract Interface, too.

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

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

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

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

Loading history...
2
    /******************************************************************
3
     pobject.phtml                                         Muze Ariadne
4
     ------------------------------------------------------------------
5
     Author: Muze ([email protected])
6
     Date: 31 october 2002
7
8
     Copyright 2002 Muze
9
10
     This file is part of Ariadne.
11
12
     Ariadne is free software; you can redistribute it and/or modify
13
     it under the terms of the GNU General Public License as published
14
     by the Free Software Foundation; either version 2 of the License,
15
     or (at your option) any later version.
16
17
     Ariadne is distributed in the hope that it will be useful,
18
     but WITHOUT ANY WARRANTY; without even the implied warranty of
19
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
     GNU General Public License for more details.
21
22
     You should have received a copy of the GNU General Public License
23
     along with Ariadne; if not, write to the Free Software
24
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25
     02111-1307  USA
26
27
    -------------------------------------------------------------------
28
29
     Class inheritance: 	pobject
30
     Description:
31
32
       This is the class definition file of the pobject class.
33
34
    ******************************************************************/
35
36
debug("pobject: Load","object");
37
38
abstract class ariadne_object extends object { // ariadne_object class definition
39
40
	public $store;
41
	public $path;
42
	public $data;
43
44 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;
0 ignored issues
show
Bug introduced by
The property reqnls does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
112 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;
0 ignored issues
show
Bug introduced by
The property nls does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
120 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;
0 ignored issues
show
Bug introduced by
The property nlsdata does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
130 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;
0 ignored issues
show
Bug introduced by
The property type does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
157
		}
158
159 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');
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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');
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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+) */
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "$this->store->parents is too slow when a lot of objects are in ariadne (2million+) */"
Loading history...
252
		/* but this fix should be done in the store, not here */
253 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 );
0 ignored issues
show
Bug introduced by
The property error does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
293
			$result = false;
294 3
		}
295 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 3
										&& "'".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 48
	private function saveCustomData($configcache, $properties) {
352 48
		$custom = $this->getdata("custom", "none");
353 48
		@parse_str($custom);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
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
		$i=0;
368 48
		if (isset($this->data->custom) && is_array($this->data->custom)) {
369
			foreach($this->data->custom as $nls => $cdata) {
370
				foreach($cdata as $name => $value){
371
					// one index, this order (name, value, nls) ?
372
					if ($configcache->custom[$name]['containsHTML']) {
373
						$this->_load('mod_url.php');
374
						$value = URL::RAWtoAR($value, $nls);
375
						$this->data->custom[$nls][$name] = $value;
376
					}
377
					if ($configcache->custom[$name]['property']) {
378
						if (isset($value) && is_array($value)) {
379
							foreach($value as $valkey => $valvalue ) {
380
								$properties["custom"][$i]["name"]=$name;
381
								$properties["custom"][$i]["value"]=$valvalue;
382
								$properties["custom"][$i]["nls"]=$nls;
383
								$i++;
384
							}
385
						} else {
386
							$properties["custom"][$i]["name"]=$name;
387
							$properties["custom"][$i]["value"]=$value;
388
							$properties["custom"][$i]["nls"]=$nls;
389
							$i++;
390
						}
391
					}
392
				}
393
			}
394
		}
395 48
		return $properties;
396
	}
397
398 51
	public function save($properties="", $vtype="") {
399
	/***********************************************************************
400
	  save the current object.
401
	  if this is a new object ($this->arIsNewObject) the path is checked and
402
	  the object is saved under the new path.
403
	***********************************************************************/
404 48
	global $AR, $ARnls, $ARCurrent;
405 48
		debug("pobject: save([properties], $vtype)","object");
406 48
		debug("pobject: save: path=".$this->path,"object");
407 48
		$configcache=$this->loadConfig();
408 48
		$needsUnlock = false;
409 48
		$arIsNewObject = false;
410 48
		$result = false;
411 48
		$this->error = '';
412 48
		if ($this->arIsNewObject) { // save a new object
0 ignored issues
show
Bug introduced by
The property arIsNewObject does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
462 48
		if ( $arIsNewObject) {
463 24
			$wf_object->arIsNewObject=$arIsNewObject;
464 18
		}
465
466
		// 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
467 48
		$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $wf_object));
468
469 48
		$eventData = new object();
470 48
		$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
Bug introduced by
The property arCallArgs does not seem to exist in object.

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

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

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

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

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

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

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

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

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

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
510 48
		$this->data->mtime=time();
511 48
		if($arIsNewObject) {
512 24
			$this->data->ctime=$this->data->mtime;
513 18
		}
514
515 48
		$this->data->muser=$AR->user->data->login;
516 48
		if( !$this->data->config->owner ) {
517 24
			if( !$this->data->config->owner_name) {
518 24
				$this->data->config->owner_name=$AR->user->data->name;
519 18
			}
520 24
			$this->data->config->owner=$AR->user->data->login;
521 24
			$properties["owner"][0]["value"]=$this->data->config->owner;
522 18
		}
523 48
		$properties["time"][0]["ctime"]=$this->data->ctime;
524 48
		$properties["time"][0]["mtime"]=$this->data->mtime;
525 48
		$properties["time"][0]["muser"]=$this->data->muser;
526
527
		/* save custom data */
528 48
		$properties = $this->saveCustomData($configcache, $properties);
529
530 48
		if (!$this->error) {
531 48
			if ($this->path=$this->store->save($this->path, $this->type, $this->data, $properties, $vtype, $this->priority)) {
532 48
				unset($this->arIsNewObject);
533 48
				$this->id=$this->exists($this->path);
534 48
				$result=$this->path;
535
536 48
				$config=$this->data->config; // need to set it again, to copy owner config data
537
538 48
				$wf_object = $this->store->newobject($this->path, $this->parent, $this->type, $this->data, $this->id, $this->lastchanged, $this->vtype, 0, $this->priority);
539 48
				$arCallArgs = $eventData->arCallArgs; // returned from onbeforesave event
540 48
				$arCallArgs['properties'] = $properties;
541
542 48
				if ($arIsNewObject) {
543 24
					$wf_object->arIsNewObject = $arIsNewObject;
544 18
				}
545 48
				$wf_result = $wf_object->call("user.workflow.post.html", $arCallArgs);
546 48
				$this->error = $wf_object->error;
547 48
				$this->priority = $wf_object->priority;
548 48
				$this->data = $wf_object->data;
549 48
				$this->data->config = $config;
550
				/* merge workflow properties */
551
552 48
				if (isset($wf_result) && is_array($wf_result) ){
553
					$properties = $this->saveMergeWorkflowResult($properties,$wf_result);
554
555
					if (!$this->store->save($this->path, $this->type, $this->data, $properties, $this->vtype, $this->priority)) {
556
						$this->error = ar::error( ''.$this->store->error, 1108, $this->store->error);
557
						$result = false;
558
					}
559
				}
560
				// all save actions have been done, fire onsave.
561 48
				$this->data->config = $config;
562
563
				//$this->ClearCache($this->path, true, false);
0 ignored issues
show
Unused Code Comprehensibility introduced by
74% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
564 48
				$eventData->arProperties = $properties;
565 48
				$this->pushContext(array('scope' => 'php', 'arCurrentObject' => $this));
566 48
				ar_events::fire( 'onsave', $eventData ); // nothing to prevent here, so ignore return value
567 48
				$this->popContext();
568 36 View Code Duplication
			} else {
569
				$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
570
				$result = false;
571
			}
572 36
		}
573 48
		if( $needsUnlock == true ){
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

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

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

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

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

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

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
700 52
				$checkNLS = $nls;
701 52
				if (!$checkNLS) {
702 28
					$checkNLS = $this->nls;
703 21
				}
704 52
				$urlList = $temp_config->root['list']['nls'][$checkNLS];
705 52
				if (isset($urlList) && is_array($urlList)) {
706
					$url = reset($urlList) . $rootoptions;
707
				} else {
708 52
					$url = $temp_config->root["value"].$rootoptions;
709
				}
710 39
			}
711 52
			$url.=substr($path, strlen($temp_config->root["path"])-1);
712
713 52
			if (is_bool($https)) {
714
				if ($https) {
715
					if ($AR->https) {
716
						$url = preg_replace('/^http:/', 'https:', $url);
717
					}
718
				} else {
719 13
					$url = preg_replace('/^https:/', 'http:', $url);
720
				}
721
			}
722 39
		} else {
723 48
			$checkNLS = $nls;
724 48
			if (!$checkNLS) {
725
				$checkNLS = $this->nls;
726
			}
727 48
			$urlCheck = $temp_config->root['list']['nls'][$checkNLS];
728 48
			if (!is_array($urlCheck)) {
729 48
				$urlCheck = $temp_config->root["value"];
730 36
			}
731 48
			$requestedHost = ldGetRequestedHost();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $requestedHost is correct as ldGetRequestedHost() seems to always returns null.
Loading history...
732 48
			if ($this->compare_hosts($requestedHost, $urlCheck)) {
733
				$url = $requestedHost . $rootoptions;
734
				$url .= substr($path, strlen($temp_config->root["path"])-1);
735
			} else {
736
				//$url=$AR->host.$AR->root.$rootoptions.$path;
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
737 48
				$url = $protocol . $requestedHost . $AR->root . $rootoptions . $path;
0 ignored issues
show
Bug introduced by
The variable $protocol does not exist. Did you forget to declare it?

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
816
		} else {
817 48
			$rest=substr($path, strlen($site));
818
		}
819 48
		return $site_url.$rest;
820
	}
821
822
	public function AR_implements($implements) {
823
		$type = current(explode(".",$this->type));
824
		return $this->store->AR_implements($type, $implements);
825
	}
826
827 View Code Duplication
	public function getlocks() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
828
		global $AR;
829
		if ($this->store->mod_lock) {
830
			$result=$this->store->mod_lock->getlocks($AR->user->data->login);
831
		} else {
832
			$result="";
833
		}
834
		return $result;
835
	}
836
837 48 View Code Duplication
	public function lock($mode="O", $time=0) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
838 48
	global $AR;
839 48
		if ($this->store->mod_lock) {
840 48
			$result=$this->store->mod_lock->lock($AR->user->data->login,$this->path,$mode,$time);
841 36
		} else {
842
			$result=true; // no lock module, so lock is 'set'
843
		}
844 48
		return $result;
845
	}
846
847 48 View Code Duplication
	public function unlock() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
848 48
	global $AR;
849 48
		if ($this->store->mod_lock) {
850 48
			$result=$this->store->mod_lock->unlock($AR->user->data->login,$this->path);
851 36
		} else {
852
			$result=true;
853
		}
854 48
		return $result;
855
	}
856
857
	public function touch($id=0, $timestamp=-1) {
858
		if (!$id) {
859
			$id = $this->id;
860
		}
861
		$result = $this->store->touch($id, $timestamp);
862 View Code Duplication
		if ($this->store->error) {
863
			$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error);
864
		}
865
		return $result;
866
	}
867
868
	public function mogrify($id=0, $type, $vtype=null) {
0 ignored issues
show
Coding Style introduced by
Parameters which have default values should be placed at the end.

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

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

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

Let’s take a look at an example:

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

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

    // do something with $myArray
}

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1201
	}
1202
1203 View Code Duplication
	public function resetConfig($path='') {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1204
	global $ARConfig;
1205
		$path = $this->make_path($path);
1206
		if ($ARConfig->cache[$path]) {
1207
			$path = preg_quote($path,'/');
1208
			$keys = preg_grep('/^'.$path.'/',array_keys($ARConfig->cache));
1209
			foreach ($keys as $cachepath) {
1210
				unset($ARConfig->cache[$cachepath]);
1211
				unset($ARConfig->pinpcache[$cachepath]);
1212
			}
1213
		}
1214
	}
1215
1216 36 View Code Duplication
	public function clearChildConfigs($path='') {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1217 36
	global $ARConfig;
1218 36
		$path = $this->make_path($path);
1219 36
		if ($ARConfig->cache[$path]) {
1220 36
			$path = preg_quote($path,'/');
1221 36
			$keys = preg_grep('/^'.$path.'./',array_keys($ARConfig->cache));
1222 36
			foreach($keys as $cachepath) {
1223 4
				unset($ARConfig->cache[$cachepath]);
1224 4
				unset($ARConfig->pinpcache[$cachepath]);
1225 4
				unset($ARConfig->libraries[$cachepath]);
1226 27
			}
1227 27
		}
1228 36
	}
1229
1230 36
	protected function getConfig() {
1231 36
	global $ARConfig, $ARCurrent, $ARConfigChecked;
1232
		// $context=$this->getContext(0);
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1233
		// debug("getConfig(".$this->path.") context: ".$context['scope'] );
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1234
		// debug(print_r($ARConfig->nls, true));
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1235 36
		if( !$ARConfig->cache[$this->parent] && $this->parent!=".." ) {
1236 4
			$parent = current($this->get($this->parent, "system.get.phtml"));
1237 4
			if ($parent) {
1238 4
				$parent->getConfig();
1239 3
			}
1240 3
		}
1241
1242 36
		$this->getConfigData();
1243
1244 36
		$ARConfig->pinpcache[$this->path] = $ARConfig->pinpcache[$this->parent];
1245
		// backwards compatibility when calling templates from config.ini
1246 36
		$prevArConfig = $ARCurrent->arConfig;
1247 36
		$ARCurrent->arConfig = $ARConfig->pinpcache[$this->path];
1248
1249 36
		$arCallArgs['arConfig'] = $ARConfig->pinpcache[$this->path];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$arCallArgs was never initialized. Although not strictly required by PHP, it is generally a good practice to add $arCallArgs = array(); before regardless.

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

Let’s take a look at an example:

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

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

    // do something with $myArray
}

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

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

Loading history...
1250
1251
		/* calling config.ini directly for each system.get.config.phtml call */
1252 36
		$loginSilent = $ARCurrent->arLoginSilent;
1253 36
		$ARCurrent->arLoginSilent = true;
1254
		// debug("getConfig:checkconfig start");
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1255
1256 36
		$initialNLS = $ARCurrent->nls;
1257 36
		$initialConfigChecked = $ARConfigChecked;
1258
1259 36
		$ARConfig->cache[$this->path]->inConfigIni = true;
1260 36
		if ($ARConfig->cache[$this->path]->hasConfigIni && !$this->CheckConfig('config.ini', $arCallArgs)) {
0 ignored issues
show
Documentation introduced by
$arCallArgs is of type array<string,?,{"arConfig":"?"}>, but the function expects a string.

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...
Bug Best Practice introduced by
The expression $this->CheckConfig('config.ini', $arCallArgs) of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

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

$a = canBeFalseAndNull();

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

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
1261
			//debug("pobject::getConfig() loaded config.ini @ ".$this->path);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1262
			// debug("getConfig:checkconfig einde");
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1263 4
			$arConfig = $ARCurrent->arResult;
1264 4
			if (!isset($arConfig)) {
1265
				$arConfig = $ARCurrent->arConfig;
1266
			}
1267 4
			unset($ARCurrent->arResult);
1268 4
			if (isset($arConfig['library']) && is_array($arConfig['library'])) {
1269
				if (!$ARConfig->libraries[$this->path]) {
1270
					$ARConfig->libraries[$this->path] = array();
1271
				}
1272
				foreach ($arConfig['library'] as $libName => $libPath) {
1273
					$this->loadLibrary($libName, $libPath);
1274
				}
1275
				unset($arConfig['library']);
1276
			}
1277 4
			$ARConfig->pinpcache[$this->path] = (array) $arConfig;
1278 3
		}
1279 36
		$ARConfig->cache[$this->path]->inConfigIni = false;
1280 36
		$this->clearChildConfigs( $this->path ); // remove any config data for child objects, since these are set before their parent config was set
1281 36
		$ARConfigChecked = $initialConfigChecked;
1282 36
		$ARCurrent->nls = $initialNLS;
1283
1284 36
		$arConfig = &$ARConfig->pinpcache[$this->path];
1285 36 View Code Duplication
		if (!is_array($arConfig['authentication']['userdirs'])) {
1286
			$arConfig['authentication']['userdirs'] = array('/system/users/');
1287
		} else {
1288 36
			if (reset($arConfig['authentication']['userdirs']) != '/system/users/') {
1289
				array_unshift($arConfig['authentication']['userdirs'], '/system/users/');
1290
			}
1291
		}
1292 36 View Code Duplication
		if (!is_array($arConfig['authentication']['groupdirs'])) {
1293
			$arConfig['authentication']['groupdirs'] = array('/system/groups/');
1294
		} else {
1295 36
			if (reset($arConfig['authentication']['groupdirs']) != '/system/groups/') {
1296
				array_unshift($arConfig['authentication']['groupdirs'], '/system/groups/');
1297
			}
1298
		}
1299
1300 36
		$ARCurrent->arLoginSilent = $loginSilent;
1301 36
		$ARCurrent->arConfig = $prevArConfig;
1302 36
	}
1303
1304 36
	protected function getConfigData() {
1305 36
	global $ARConfig, $AR;
1306 36
		$context = $this->getContext(0);
1307 36
		if (!$ARConfig->cache[$this->path] && $context["scope"] != "pinp") {
1308
			// first inherit parent configuration data
1309 36
			$configcache= clone $ARConfig->cache[$this->parent];
1310 36
			unset($configcache->localTemplates);
1311
			// cache default templates
1312 36
			if (isset($this->data->config->templates) && count($this->data->config->templates)) {
1313
				$configcache->templates=&$this->data->config->templates;
1314
			}
1315 36
			if (isset($this->data->config->privatetemplates) && count($this->data->config->privatetemplates)) {
1316
				$configcache->privatetemplates=&$this->data->config->privatetemplates;
1317
			}
1318
1319
			// Speedup check for config.ini
1320
1321 36
			if(isset($this->data->config->templates) && is_array($this->data->config->templates) ) {
1322 4
				$configcache->localTemplates = $this->data->config->templates;
1323 4
				if( !$configcache->hasDefaultConfigIni ) {
1324 4
					foreach($this->data->config->templates as $type => $templates ) {
1325
						if( isset($templates["config.ini"]) ) {
1326
							$configcache->hasDefaultConfigIni = true;
1327
							$configcache->hasConfigIni = true;
1328
							break;
1329
						}
1330 3
					}
1331 3
				}
1332 3
			}
1333
1334 36
			if( !$configcache->hasDefaultConfigIni ) {
1335 36
				$configcache->hasConfigIni = false;
1336 36
				if(isset($this->data->config->pinp) && is_array($this->data->config->pinp) ) {
1337 4
					foreach( $this->data->config->pinp as $type => $templates ) {
1338 4
						if( isset($templates["config.ini"]) ) {
1339 4
							$configcache->hasConfigIni = true;
1340 4
							break;
1341
						}
1342 3
					}
1343 3
				}
1344 27
			}
1345
1346 36
			$localcachesettings = $this->data->config->cacheSettings;
1347 36
			if (!is_array($localcachesettings) ){
1348 36
				$localcachesettings = array();
1349 27
			}
1350
1351 36
			if (!is_array($configcache->cacheSettings) ) {
1352
				$configcache->cacheSettings = array();
1353
			}
1354
1355 36
			if ($this->data->config->cacheconfig) { // When removing this part, also fix the setting below.
1356 4
				$configcache->cache=$this->data->config->cacheconfig;
1357 3
			}
1358
1359 36
			if (!isset($localcachesettings['serverCache']) && isset($this->data->config->cacheconfig)) {
1360 4
				$localcachesettings["serverCache"] = $this->data->config->cacheconfig;
1361 3
			}
1362
1363 36
			if ($localcachesettings['serverCache'] != 0 ) {
1364 4
				$localcachesettings['serverCacheDefault'] = $localcachesettings['serverCache'];
1365 3
			}
1366
1367 36
			$configcache->cacheSettings = $localcachesettings + $configcache->cacheSettings;
1368
1369
			// store the current object type
1370 36
			$configcache->type = $this->type;
1371
1372 36
			if ($this->data->config->typetree && ($this->data->config->typetree!="inherit")) {
1373
				$configcache->typetree=$this->data->config->typetree;
1374
			}
1375 36
			if (isset($this->data->config->nlsconfig->list)) {
1376 4
				$configcache->nls = clone $this->data->config->nlsconfig;
1377 3
			}
1378
1379 36
			if ($this->data->config->grants["pgroup"]["owner"]) {
1380
				$configcache->ownergrants = $this->data->config->grants["pgroup"]["owner"];
1381
			}
1382 36
			if (isset($configcache->ownergrants) && is_array($configcache->ownergrants)) {
1383
				if ($AR->user && $AR->user->data->login != 'public' && $AR->user->data->login === $this->data->config->owner) {
1384
					$ownergrants = $configcache->ownergrants;
1385
					if (isset($ownergrants) && is_array($ownergrants)) {
1386
						foreach( $ownergrants as $grant => $val ) {
1387
							$AR->user->ownergrants[$this->path][$grant] = $val;
1388
						}
1389
					}
1390
				}
1391
			}
1392
1393 36
			if (isset($this->data->config->customconfig) && is_array($this->data->config->customconfig)) {
1394
				$configcache->custom=array_merge(is_array($configcache->custom)?$configcache->custom:array(), $this->data->config->customconfig);
1395
			}
1396 36
			$ARConfig->cache[$this->path]=$configcache;
1397
1398 27
		}
1399 36
	}
1400
1401 60
	public function loadConfig($path='') {
1402 60
	global $ARConfig, $ARConfigChecked, $ARCurrent;
1403 60
		$path=$this->make_path($path);
1404
		// debug("loadConfig($path)");
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1405 60
		if (!isset($ARConfig->cache[$path]) ) {
1406 36
			$allnls = $ARCurrent->allnls;
1407 36
			$ARCurrent->allnls = true;
1408 36
			$configChecked = $ARConfigChecked;
1409 36
			if (($this->path == $path && !$this->arIsNewObject) || $this->exists($path)) {
1410 36
				$this->pushContext(array("scope" => "php"));
1411 36
				if( $this->path == $path ) {
1412
					// debug("loadConfig: currentpath $path ");
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1413 36
					$this->getConfig();
1414 27
				} else {
1415
					//debug("loadConfig: get path $path ");
1416 4
					$cur_obj = current($this->get($path, "system.get.phtml"));
1417 4
					$cur_obj->getConfig();
1418
				}
1419 36
				$this->popContext();
1420 36
				$result=$ARConfig->cache[$path];
1421 27
			} else if ($path === '/') {
1422
				// special case: / doesn't exists in the store
1423
				$result=$ARConfig->cache['..'];
1424
			} else {
1425
				$parent=$this->make_path($path.'../');
1426
				if (!$ARConfig->cache[$parent]) {
1427
					$this->pushContext(array("scope" => "php"));
1428
					// debug("loadConfig: parent $parent");
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1429
					$cur_obj = current($this->get($parent, "system.get.phtml"));
1430
					if( $cur_obj ) {
1431
						$cur_obj->getConfig();
1432
					}
1433
					$this->popContext();
1434
				}
1435
				$result=$ARConfig->cache[$parent];
1436
				$ARConfig->cache[ $path ] = $result;
1437
				$ARConfig->pinpcache[ $path ] = $ARConfig->pinpcache[ $parent ];
1438
			}
1439
			// restore old ARConfigChecked state
1440 36
			$ARConfigChecked = $configChecked;
1441 36
			$ARCurrent->allnls = $allnls;
1442 27
		} else {
1443
			// debug("loadConfig: exists $path ");
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1444 48
			$result=$ARConfig->cache[$path];
1445
		}
1446 60
		return $result;
1447
	}
1448
1449
1450
	// TODO: look for a way to merge loadConfig and loadUserConfig into one function
1451
1452 12
	public function loadUserConfig($path='') {
1453 12
	global $ARConfig;
1454 12
		$path = $this->make_path($path);
1455 12
		$parent = $this->make_path($path.'../');
1456
1457 12
		if (!$ARConfig->cache[$path]) {
1458
			$this->loadConfig($path);
1459
		}
1460 12
		if (!$ARConfig->pinpcache[$path]) {
1461
			$config = $ARConfig->pinpcache[$parent];
1462
		} else {
1463 12
			$config = $ARConfig->pinpcache[$path];
1464
		}
1465 12
		return (array)$config;
1466
	}
1467
1468 48
	protected function getTemplateFromCache($path, $type, $function, &$arSuperContext) {
1469 48
	global $AR, $ARConfig;
1470 48
		$templatesList = $ARConfig->libraryCache[$path][$function];
1471 48
		if (!is_array($templatesList)) {
1472 48
			return false;
1473
		}
1474
		foreach ($templatesList as $checkpath => $templates) {
1475
			$arType = $type;
1476
			while ($arType!='ariadne_object') {
1477
//				echo "checking $i::$arType<br>\n";
1478
				if (!$arSuperContext[$checkpath.":".$arType.":".$function] && ($arTemplate=$templates[$arType][$this->reqnls])) {
1479
					$arCallTemplate=$arType.".".$function.".".$this->reqnls;
1480
					$arCallTemplateName = $function;
1481
					$arCallTemplateNLS = $this->reqnls;
1482
					break 2;
1483 View Code Duplication
				} else if (!$arSuperContext[$checkpath.":".$arType.":".$function] && ($arTemplate=$templates[$arType]['any'])) {
1484
					$arCallTemplate=$arType.".".$function.".any";
1485
					$arCallTemplateName = $function;
1486
					$arCallTemplateNLS = "any";
1487
					break 2;
1488
				} else {
1489
1490
					if (!($arSuper=$AR->superClass[$arType])) {
1491
						// no template found, no default.phtml found, try superclass.
1492
						if ($subcpos = strpos($arType, '.')) {
1493
							$arSuper = substr($arType, 0, $subcpos);
1494
						} else {
1495
							if (!class_exists($arType, false)) {
1496
								// the given class was not yet loaded, so do that now
1497
								$arTemp=$this->store->newobject('','',$arType,new object);
1498
							} else {
1499
								$arTemp=new $arType();
1500
							}
1501
							$arSuper=get_parent_class($arTemp);
1502
						}
1503
						$AR->superClass[$arType]=$arSuper;
1504
					}
1505
					$arType=$arSuper;
1506
				}
1507
			}
1508
		}
1509
1510
		$config = ($ARConfig->cache[$arTemplate["arLibraryLocalPath"]]) ? $ARConfig->cache[$arTemplate["arLibraryLocalPath"]] : $this->loadConfig($arTemplate["arLibraryLocalPath"]);
0 ignored issues
show
Bug introduced by
The variable $arTemplate 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...
1511
		$arPrivateTemplate = $config->privatetemplates[$arType][$function];
0 ignored issues
show
Bug introduced by
The variable $arType 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...
1512
1513
		return array(
1514
			"arTemplateId" => $arTemplate["arTemplateId"],
1515
			"arCallTemplate" => $arCallTemplate,
0 ignored issues
show
Bug introduced by
The variable $arCallTemplate 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...
1516
			"arCallType" => $type,
1517
			"arCallTemplateName" => $arCallTemplateName,
0 ignored issues
show
Bug introduced by
The variable $arCallTemplateName 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...
1518
			"arCallTemplateNLS" => $arCallTemplateNLS,
0 ignored issues
show
Bug introduced by
The variable $arCallTemplateNLS 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...
1519
			"arCallTemplateType" => $arType,
1520
			"arCallTemplatePath" => $arTemplate["arLibraryLocalPath"],
1521
			"arLibrary" => "current",
1522
			"arLibraryPath" => $arTemplate["arLibraryPath"],
1523
			"arPrivateTemplate" => $arPrivateTemplate
1524
		);
1525
	}
1526
1527
	public function loadLibraryCache($base, $path, $arLibraryPath = "") {
1528
	global $ARConfig;
1529
		if (!$arLibraryPath) {
1530
			$arLibraryPath = $path;
1531
		}
1532
		$config = ($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
1533
		$templates = $config->localTemplates;
1534
		if (isset($templates) && is_array($templates)) {
1535
			$list = array();
1536
			foreach ($templates as $type => $functions) {
1537
				foreach ($functions as $function => $template) {
1538
					foreach ($template as $nls => $templateId) {
1539
						$list[$function][$type][$nls] = array(
1540
								"arTemplateId" => $templateId,
1541
								"arLibraryPath" => $arLibraryPath,
1542
								"arLibraryLocalPath" => $path
1543
						);
1544
					}
1545
				}
1546
			}
1547
1548
			foreach ($list as $function => $types) {
1549
				if (!is_array($ARConfig->libraryCache[$base][$function])) {
1550
					$ARConfig->libraryCache[$base][$function] = array(
1551
						$path => $types
1552
					);
1553
				} else {
1554
					$ARConfig->libraryCache[$base][$function][$path] = $types;
1555
				}
1556
			}
1557
		}
1558
		list($basetype,) = explode('.', $config->type,2);
1559
		if ($path != '/' && $basetype != 'psection') {
1560
			$this->loadLibraryCache($base, $this->store->make_path($path, '../'), $arLibraryPath);
1561
		}
1562
	}
1563
1564 4
	public function loadLibrary($name, $path) {
1565 4
	global $ARConfig;
1566 4
		$path=$this->make_path($path);
1567 4
		debug("pobject::loadLibrary($name, $path);");
1568 4
		if ($name===ARUNNAMED) {
1569 4
			if (strstr($path, $this->path)===0) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of strstr($path, $this->path) (string) and 0 (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
1570
				return ar::error('You cannot load an unnamed library from a child object.', 1109);
1571
			} else {
1572 4
				if (!$ARConfig->libraries[$this->path]) {
1573 4
					$ARConfig->libraries[$this->path]=array();
1574 3
				}
1575 4
				array_unshift($ARConfig->libraries[$this->path],$path);
1576 4 View Code Duplication
				if (!$ARConfig->cacheableLibraries[$this->path]) {
1577 4
					$ARConfig->cacheableLibraries[$this->path] = array($path);
1578 3
				} else {
1579 1
					array_unshift($ARConfig->cacheableLibraries[$this->path], $path);
1580
				}
1581
			}
1582 3
		} else if ($name && is_string($name)) {
1583
			if (!$ARConfig->cache[$this->path]) {
1584
debug("loadLibrary: loading cache for $this->path");
1585
				$this->loadConfig($this->path);
1586
			}
1587
			$ARConfig->libraries[$this->path][$name]=$path;
1588
			$ARConfig->cache[$this->path]->libraries[$name]=$path;
1589
			$ARConfig->pinpcache[$this->path]["library"][$name] = $path;
1590
		} else if (is_int($name)) {
1591
			if (!$ARConfig->cache[$this->path]) {
1592
				$this->loadConfig($this->path);
1593
			}
1594
			$ARConfig->libraries[$this->path][$name]=$path;
1595 View Code Duplication
			if (!$ARConfig->cacheableLibraries[$this->path]) {
1596
				$ARConfig->cacheableLibraries[$this->path] = array($name => $path);
1597
			} else {
1598
				$ARConfig->cacheableLibraries[$this->path][$name] = $path;
1599
			}
1600
			// make sure that unnamed libraries don't get added to the configcache
1601
			unset($ARConfig->cache[$this->path]->libraries[$name]);
1602
			unset($ARConfig->pinpcache[$this->path]["library"][$name]);
1603
		} else {
1604
			return ar::error('Illegal library name: '.$name, 1110);
1605
		}
1606 4
	}
1607
1608
	// returns a list of libraries loaded on $path
1609
	public function getLibraries($path = '') {
1610
	global $ARConfig;
1611
		$path = $this->make_path($path);
1612
		return (array)$ARConfig->libraries[$path];
1613
	}
1614
1615
	public function mergeLibraryConfig( $defaultLibraryName, $defaults ) {
1616
		$libraryName = ar::getvar('arLibrary');
1617
		if ( is_numeric($libraryName) || $libraryName == 'current' ) { // library is loaded unnamed
1618
			$libraryName = $defaultLibraryName;
1619
		}
1620
		if ( $libraryName ) {
1621
			$userConfig = ar::acquire('defaults.'.$libraryName);
1622
			if (isset($userConfig) && is_array($userConfig) ) {
1623
				$defaults = array_merge( $defaults, $userConfig );
1624
			}
1625
		}
1626
		return array_merge( $defaults, $this->getvar('arCallArgs') );
1627
	}
1628
1629
	public function _mergeLibraryConfig( $defaultLibraryName, $defaults ) {
1630
		return $this->mergeLibraryConfig( $defaultLibraryName, $defaults );
1631
	}
1632
1633 60
	public function getPinpTemplate($arCallFunction='view.html', $path=".", $top="", $inLibrary = false, $librariesSeen = null, $arSuperContext=array()) {
1634 60
	global $ARCurrent, $ARConfig, $AR, $ARConfigChecked;
1635 60
		debug("getPinpTemplate: function: $arCallFunction; path: $path; top: $top; inLib: $inLibrary","class");
1636 60
		$result = array();
1637 60
		if (!$top) {
1638 60
			$top = '/';
1639 45
		}
1640 60
		$path = $this->make_path($path);
1641 60
		if (!is_array($arSuperContext)) {
1642
			$arSuperContext = array();
1643
		}
1644
1645 60
		if (($libpos=strpos($arCallFunction,":"))!==false && $libpos!==strpos($arCallFunction, "::")) {
1646
			// template of a specific library defined via call("library:template");
1647
			$arLibrary = substr($arCallFunction, 0, $libpos);
1648
			if ($arLibrary == 'current') {
1649
				// load the current arLibrary
1650
				$context = $this->getContext(1);
1651
				$arLibrary = $context['arLibrary'];
1652
				$arLibraryPath = $context['arLibraryPath'];
1653 View Code Duplication
			} else {
1654
				$config = (isset($ARConfig->cache[$path])) ? $ARConfig->cache[$path] : $this->loadConfig($path);
1655
				$arLibraryPath = $config->libraries[$arLibrary];
1656
			}
1657
			$arCallFunction = substr($arCallFunction, $libpos+1);
1658
			if ($arLibraryPath) {
1659
				debug("getPinpTemplate: found library '$arLibrary'. Searching for $arCallFunction on '".$config->libraries[$arLibrary]."' up to '$top'");
0 ignored issues
show
Bug introduced by
The variable $config does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1660
				$librariesSeen[$arLibraryPath] = true;
1661
				$inLibrary = true;
1662
				$path = $arLibraryPath;
1663
			} else {
1664
				debug("getPinpTemplate: Failed to find library $arLibrary");
1665
				return false;
1666
			}
1667
			$path = $this->make_path($path);
1668
		}
1669 60
		if (strpos($arCallFunction,"::")!==false) {
1670
			// template of a specific class defined via call("class::template");
1671
			list($arCallType, $arCallFunction)=explode("::",$arCallFunction);
1672
		} else {
1673 60
			$arCallType=$this->type;
1674
		}
1675
1676
		/* first check current templates */
1677 60
		if ($this->path == $path) {
1678 60
			$curr_templates = $this->data->config->pinp;
1679 45
		} else {
1680
			$config = ($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
1681
			$curr_templates = $config->templates;
1682
		}
1683
1684 60
		$checkpath=$path;
1685 60
		$lastcheckedpath="";
1686 60
		$arCallClassTemplate = $ARCurrent->arCallClassTemplate;
1687 60
		$arSetType = $arCallType;
1688 60
		while (!$arCallClassTemplate && !$arCallTemplate && $checkpath!=$lastcheckedpath) {
0 ignored issues
show
Bug introduced by
The variable $arCallTemplate 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...
1689 60
			$lastcheckedpath = $checkpath;
1690 60
			$arType = $arSetType;
1691 60
			while ($arType!='ariadne_object' && !$arCallTemplate) {
1692 60
				if (!$arSuperContext[$checkpath.":".$arType.":".$arCallFunction] && ($arTemplateId=$curr_templates[$arType][$arCallFunction][$this->reqnls])) {
1693
					$arCallTemplate=$arType.".".$arCallFunction.".".$this->reqnls;
1694
					$arCallTemplateName = $arCallFunction;
1695
					$arCallTemplateNLS = $this->reqnls;
1696 60 View Code Duplication
				} else if (!$arSuperContext[$checkpath.":".$arType.":".$arCallFunction] && ($arTemplateId=$curr_templates[$arType][$arCallFunction]['any'])) {
1697 12
					$arCallTemplate=$arType.".".$arCallFunction.".any";
1698 12
					$arCallTemplateName = $arCallFunction;
1699 12
					$arCallTemplateNLS = 'any';
1700 9
				} else {
1701
1702 48
					if (!($arSuper=$AR->superClass[$arType])) {
1703
						// no template found, no default.phtml found, try superclass.
1704
						if ($subcpos = strpos($arType, '.')) {
1705
							$arSuper = substr($arType, 0, $subcpos);
1706
						} else {
1707
							if (!class_exists($arType, false )) {
1708
								// the given class was not yet loaded, so do that now
1709
								$arTemp=$this->store->newobject('','',$arType,new object);
1710
							} else {
1711
								$arTemp=new $arType();
1712
							}
1713
							$arSuper=get_parent_class($arTemp);
1714
						}
1715
						$AR->superClass[$arType]=$arSuper;
1716
					}
1717 48
					$arType=$arSuper;
1718
				}
1719 45
			}
1720 60
			if ($inLibrary) {
1721
1722
				// faster matching on psection, prefix doesn't have to be a valid type
1723
				$prefix = substr($ARConfig->cache[$checkpath]->type,0,8);
1724
1725
				if ($prefix === 'psection') {
1726
					// debug("BREAKING; $arTemplateId");
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1727
					// break search operation when we have found a
1728
					// psection object
1729
					break;
1730
				}
1731
			}
1732
1733 60
			if (!$arTemplateId && $ARConfigChecked) {
0 ignored issues
show
Bug introduced by
The variable $arTemplateId 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...
1734 48
				if ($ARConfig->cacheableLibraries[$checkpath]) {
1735
					foreach ($ARConfig->cacheableLibraries[$checkpath] as $library => $path) {
1736
						if (is_int($library) && !$librariesSeen[$path]) {
1737
							$librariesSeen[$path] = true;
1738
							if ($ARConfigChecked) {
1739
								if (!$ARConfig->librariesCached[$checkpath][$path]) {
1740
									$this->loadLibraryCache($checkpath, $path);
1741
									unset($ARConfig->cacheableLibraries[$checkpath][$library]);
1742
								}
1743
							}
1744
						}
1745
					}
1746
				}
1747
1748 48
				if (isset($ARConfig->cacheableLibraries[$checkpath])) {
1749 48
					$template = $this->getTemplateFromCache($checkpath, $arCallType, $arCallFunction, $arSuperContext);
1750 48
					if ($template["arTemplateId"]) {
1751
						return $template;
1752
					}
1753 36
				}
1754 36
			}
1755 60
			if ($checkpath == $top) {
1756 48
				break;
1757
			}
1758
1759 60
			$checkpath=$this->store->make_path($checkpath, "..");
1760 60
			$config = ($ARConfig->cache[$checkpath]) ? $ARConfig->cache[$checkpath] : $this->loadConfig($checkpath);
1761 60
			$curr_templates = $config->templates;
1762 60
			$arSetType = $arCallType;
1763 45
		}
1764
1765 60
		$config = ($ARConfig->cache[$lastcheckedpath]) ? $ARConfig->cache[$lastcheckedpath] : $this->loadConfig($lastcheckedpath);
1766 60
		$arPrivateTemplate = $config->privatetemplates[$arCallType][$arCallFunction];
1767
1768
		//debug("getPinpTemplate END; $arTemplateId; $checkpath;");
1769 60
		$result["arTemplateId"] = $arTemplateId;
1770 60
		$result["arCallTemplate"] = $arCallTemplate;
1771 60
		$result["arCallType"] = $arCallType;
1772 60
		$result["arCallTemplateName"] = $arCallTemplateName;
0 ignored issues
show
Bug introduced by
The variable $arCallTemplateName 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...
1773 60
		$result["arCallTemplateNLS"] = $arCallTemplateNLS;
0 ignored issues
show
Bug introduced by
The variable $arCallTemplateNLS 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...
1774 60
		$result["arCallTemplateType"] = $arType;
0 ignored issues
show
Bug introduced by
The variable $arType 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...
1775 60
		$result["arCallTemplatePath"] = $lastcheckedpath;
1776 60
		$result["arLibrary"] = $arLibrary;
0 ignored issues
show
Bug introduced by
The variable $arLibrary does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1778 60
		$result["arLibrariesSeen"] = $librariesSeen;
1779 60
		$result["arPrivateTemplate"] = $arPrivateTemplate;
1780
1781 60
		return $result;
1782
	}
1783
1784 64
	public function CheckConfig($arCallFunction="", $arCallArgs="") {
1785
	// returns true when cache isn't up to date and no other template is
1786
	// defined for $path/$function. Else it takes care of output to the
1787
	// browser.
1788
	// All these templates must exist under a fixed directory, $AR->dir->templates
1789 64
	global $nocache, $AR, $ARConfig, $ARCurrent, $ARBeenHere, $ARnls, $ARConfigChecked;
1790 64
		$MAX_LOOP_COUNT=10;
1791
1792
1793
		// system templates (.phtml) have $arCallFunction=='', so the first check in the next line is to
1794
		// make sure that loopcounts don't apply to those templates.
1795 64
		if (0 && $arCallFunction && $ARBeenHere[$this->path][$arCallFunction]>$MAX_LOOP_COUNT) { // protect against infinite loops
1796
			error(sprintf($ARnls["err:maxloopexceed"],$this->path,$arCallFunction,$arCallArgs));
1797
			$this->store->close();
1798
			exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method CheckConfig() contains an exit expression.

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

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

Loading history...
1799
		} else {
1800 64
			$ARBeenHere[$this->path][$arCallFunction]+=1;
1801
1802
			// this will prevent the parents from setting the cache time
1803 64
			$initialConfigChecked = $ARConfigChecked;
1804 64
			$ARConfigChecked = true;
1805 64
			$config = ($ARConfig->cache[$this->path]) ? $ARConfig->cache[$this->path] : $this->loadConfig();
1806 64
			$ARConfigChecked = $initialConfigChecked;
1807 64
			$ARConfig->nls=$config->nls;
1808
1809
1810
			// if a default language is entered in a parent and no language is
1811
			// explicitly selected in the url, use that default.
1812
			// The root starts with the system default (ariadne.phtml config file)
1813 64
			if ( !$ARCurrent->nls ) {
1814 64
				if ( $config->root['nls'] ) {
1815
					$this->reqnls = $config->root['nls'];
1816
					if ( !$ARConfigChecked ) {
1817
						$ARCurrent->nls = $this->reqnls;
1818
					}
1819 64
				} else if ( $config->nls->default ) {
1820 64
					$this->reqnls = $config->nls->default;
1821 64
					$this->nls = $this->reqnls;
1822 64
					if ( !$ARConfigChecked ) {
1823 16
						$ARCurrent->nls = $this->nls;
1824
					}
1825 48
				}
1826 48
			} else {
1827
				$this->reqnls = $ARCurrent->nls;
1828
			}
1829 64
			$nls = &$this->nls;
1830 64
			$reqnls = &$this->reqnls;
1831
1832 64
			if (!$ARConfigChecked && is_object($ARnls)) {
1833
				$ARnls->setLanguage($ARCurrent->nls);
1834
			}
1835
1836
1837 64
			if (!$ARCurrent->arContentTypeSent) {
1838
				ldHeader("Content-Type: text/html; charset=UTF-8");
1839
				$ARCurrent->arContentTypeSent = true;
1840
			}
1841
1842
/*			// FIXME: the acceptlang code works a bit too well.. it overrides psite configuration settings.
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
Comment refers to a FIXME task "the acceptlang code works a bit too well.. it overrides psite configuration settings"
Loading history...
1843
1844
			if ($ARCurrent->acceptlang && !$ARCurrent->nls) {
1845
				if ($ARCurrent->acceptlang && is_array($this->data->nls->list)) {
1846
					$validlangs = array_intersect(array_keys($ARCurrent->acceptlang), array_keys($this->data->nls->list));
1847
				}
1848
				if ($validlangs) {
1849
					$reqnls=array_shift($validlangs);
1850
					$ARCurrent->nls = $reqnls;
1851
				}
1852
			}
1853
*/
1854 64 View Code Duplication
			if (isset($this->data->custom) && is_array($this->data->custom) && $this->data->custom['none']) {
1855 4
				$this->customdata=$this->data->custom['none'];
0 ignored issues
show
Bug introduced by
The property customdata does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

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

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

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

Loading history...
1859
			}
1860
1861 64
			if (!$ARConfigChecked) {
1862
				// this template is the first template called in this request.
1863
				$eventData = new object();
1864
				$eventData->arCallArgs = $arCallArgs;
0 ignored issues
show
Bug introduced by
The property arCallArgs does not seem to exist in object.

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

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

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

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

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

Loading history...
1866
1867
				$ARConfigChecked = true;
1868
				$result = ar_events::fire( 'onbeforeview', $eventData );
0 ignored issues
show
Documentation introduced by
$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...
1869
				$ARConfigChecked = $initialConfigChecked;
1870
				if ( !$result ) { //prevent default action: view
1871
					return false;
1872
				}
1873
			}
1874
1875 64
			if (!$ARConfigChecked) {
1876
				// if this object isn't available in the requested language, show
1877
				// a language select dialog with all available languages for this object.
1878
				if (isset($this->data->nls) && !$this->data->name) {
1879
					if (!$ARCurrent->forcenls && (!isset($this->data->nls->list[$reqnls]) || !$config->nls->list[$reqnls])) {
1880
						if (!$ARCurrent->nolangcheck && $arCallFunction != 'config.ini') {
1881
							$ARCurrent->nolangcheck=1;
1882
							$eventData = new object();
1883
							$eventData->arCallFunction = $arCallFunction;
1884
							$eventData->arCallArgs = $arCallArgs;
1885
							$eventData->arRequestedNLS = $reqnls;
0 ignored issues
show
Bug introduced by
The property arRequestedNLS does not seem to exist in object.

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

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

Loading history...
1886
							$result = ar_events::fire( 'onlanguagenotfound', $eventData );
0 ignored issues
show
Documentation introduced by
$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...
1887
							if ( $result ) { // continue with default action: langaugeselect
1888
								$result->arCallArgs["arOriginalFunction"] = $result->arCallFunction;
1889
								$this->call("user.languageselect.html", $result->arCallArgs);
1890
								return false;
1891
							}
1892
						} else {
1893
							$this->nlsdata=$this->data->$nls;
1894
						}
1895
					} else {
1896
						$this->nlsdata=$this->data->$reqnls;
1897
					}
1898
				}
1899
				$ARCurrent->nolangcheck=1;
1900
			}
1901
1902
			/*
1903
				Set ARConfigChecked to true to indicate that we have been here
1904
				earlier.
1905
			*/
1906 64
			$ARConfigChecked = true;
1907 64
			if ($arCallFunction) { // don't search for templates named ''
1908
				// FIXME: Redirect code has to move to getPinpTemplate()
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "Redirect code has to move to getPinpTemplate"
Loading history...
1909 60
				$redirects	= $ARCurrent->shortcut_redirect;
1910 60
				if (isset($redirects) && is_array($redirects)) {
1911
					$redirpath = $this->path;
1912
					while (!$template['arTemplateId'] &&
0 ignored issues
show
Bug introduced by
The variable $template does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1913
								($redir = array_pop($redirects)) &&
1914
									$redir["keepurl"] &&
1915
										(substr($redirpath, 0, strlen($redir["dest"])) == $redir["dest"])
1916
					) {
1917
						$template = $this->getPinpTemplate($arCallFunction, $redirpath, $redir["dest"]);
1918
						$redirpath = $redir['src'];
1919
					}
1920
1921
					if (!$template["arTemplateId"] && $redirpath) {
1922
						$template = $this->getPinpTemplate($arCallFunction, $redirpath);
1923
					}
1924
				}
1925 60
				if (!$template["arTemplateId"]) {
1926 60
					$template = $this->getPinpTemplate($arCallFunction);
1927 45
				}
1928
1929 60
				if ($template["arCallTemplate"] && $template["arTemplateId"]) {
1930 12
					if (!isset($ARCurrent->cacheTemplateChain)) {
1931
						$ARCurrent->cacheTemplateChain = array();
1932
					}
1933 12
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]])) {
1934 8
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]] = array();
1935 6
					}
1936 12
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']])) {
1937 12
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']] = array();
1938 9
					}
1939 12
					if (!isset($ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']])) {
1940 12
						$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']] = 0;
1941 9
					}
1942 12
					$ARCurrent->cacheTemplateChain[$template["arTemplateId"]][$template['arCallTemplate']][$template['arCallTemplateType']]++;
1943
1944
1945 12
					debug("CheckConfig: arCallTemplate=".$template["arCallTemplate"].", arTemplateId=".$template["arTemplateId"],"object");
1946
					// $arCallTemplate=$this->store->get_config("files")."templates".$arCallTemplate;
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1947
					// check if template exists, if it doesn't exist, then continue the original template that called CheckConfig
1948 12
					$arTemplates=$this->store->get_filestore("templates");
1949
					if (
1950 12
						$arTemplates->exists($template["arTemplateId"], $template["arCallTemplate"].".inc")
1951 9
					) {
1952
						// check if the requested language exists, if not do not display anything,
1953
						// unless otherwise indicated by $ARCurrent->allnls
1954
						// This triggers only for pinp templates called by other templates,
1955
						// as the first template (in the url) will first trigger the language
1956
						// choice dialogue instead.
1957 12
						$arLibrary = $template['arLibrary'];
1958 12
						if (is_int($arLibrary)) {
1959
							// set the library name for unnamed libraries to 'current'
1960
							// so that calls using getvar('arLibrary') will keep on working
1961
							$arLibrary = "current";
1962
						}
1963
1964 12 View Code Duplication
						if (!is_string($arCallArgs)) {
1965 12
							$arCallArgs['arCallFunction'] = $arCallFunction;
1966 12
							$arCallArgs['arLibrary'] = $arLibrary;
1967 12
							$arCallArgs['arLibraryPath'] = $template["arLibraryPath"];
1968 9
						}
1969
1970 12
						$ARCurrent->arCallStack[]=$arCallArgs;
1971
						// start running a pinp template
1972
1973 12
						$this->pushContext(
1974
							array(
1975 12
								"scope" => "pinp",
1976 12
								"arLibrary" => $arLibrary,
1977 12
								"arLibraryPath" => $template['arLibraryPath'],
1978 12
								"arCallFunction" => $arCallFunction,
1979 12
								"arCurrentObject" => $this,
1980 12
								"arCallType" => $template['arCallType'],
1981 12
								"arCallTemplateName" => $template['arCallTemplateName'],
1982 12
								"arCallTemplateNLS" => $template['arCallTemplateNLS'],
1983 12
								"arCallTemplateType" => $template['arCallTemplateType'],
1984 12
								"arCallTemplatePath" => $template['arCallTemplatePath'],
1985 12
								"arLibrariesSeen" => $template['arLibrariesSeen']
1986 9
							)
1987 9
						);
1988
1989
						// FIXME: is 2 het correcte getal? Kan dit minder magisch?
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "is 2 het correcte getal? Kan dit minder magisch?"
Loading history...
1990 12
						if (count($ARCurrent->arCallStack) == 2 && $template['arPrivateTemplate']) {
1991
							// Do not allow private templates to be called first in the stack.
1992
							// echo "Bad request";
1993
1994
							// FIXME: Echte header sturen? Of gewoon niet uitvoeren? Wat is het correcte gedrag?
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "Echte header sturen? Of gewoon niet uitvoeren? Wat is het correcte gedrag?"
Loading history...
1995
							// Return true zorgt er voor dat de default 404 handler het oppikt alsof het template niet bestaat.
1996
							$this->popContext();
1997
							array_pop($ARCurrent->arCallStack);
1998
							return true;
1999 12
						} else if ($ARCurrent->forcenls || isset($this->data->nls->list[$reqnls])) {
2000
							// the requested language is available.
2001 12
							$this->nlsdata=$this->data->$reqnls;
2002 12
							$this->nls=$reqnls;
2003 12
							$continue=true;
2004 9
						} else if (!isset($this->data->nls)) {
2005
							// the object has no language support
2006
							$this->nlsdata=$this->data;
2007
							$continue=true;
2008
						} else if (($ARCurrent->allnls) || (!$initialConfigChecked && $ARCurrent->nolangcheck)) {
2009
							// all objects must be displayed
2010
							// $this->reqnls=$this->nls; // set requested nls, for checks
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
2011
							$this->nls = isset($this->data->nls->default) ? $this->data->nls->default : $this->reqnls;
2012
							$this->nlsdata = $this->data->$nls ?: $this->data->{$this->nls} ?: $this->data;
2013
							$continue=true;
2014
						} else {
2015
							debug("CheckConfig: requested language not available, allnls not set","object");
2016
							// -> skip this object (do not run template but do return false)
2017
							$continue=false;
2018
						}
2019 12
						if ($continue) {
2020 12
							$eventData = new object();
2021 12 View Code Duplication
							if ( !$AR->contextCallHandler ) { /* prevent onbeforecall from re-entering here */
2022 12
								$AR->contextCallHandler = true;
2023 12
								$eventData->arCallArgs = $arCallArgs;
2024 12
								$eventData->arCallFunction = $arCallFunction;
2025 12
								$eventData->arContext = $this->getContext();
0 ignored issues
show
Bug introduced by
The property arContext does not seem to exist in object.

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

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

Loading history...
2026 12
								$eventData = ar_events::fire('onbeforecall', $eventData);
0 ignored issues
show
Documentation introduced by
$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...
2027 12
								$ARCurrent->arResult = $eventData->arResult;
2028 12
								$AR->contextCallHandler = false;
2029 12
								$continue = ($eventData!=false);
2030 9
							}
2031 12
							if ( $continue ) {
2032 12
								if (!isset($ARCurrent->cacheCallChainSettings)) {
2033
									$ARCurrent->cacheCallChainSettings = array();
2034
								}
2035 12
								if ($ARConfig->cache[$this->path]->inConfigIni == false) {
2036 8
									$ARCurrent->cacheCallChainSettings[$this->id] = $config->cacheSettings;
2037 6
								}
2038
2039 12
								if ($ARCurrent->ARShowTemplateBorders) {
2040
									echo "<!-- arTemplateStart\nData: ".$this->type." ".$this->path." \nTemplate: ".$template["arCallTemplatePath"]." ".$template["arCallTemplate"]." \nLibrary:".$template["arLibrary"]." -->";
2041
								}
2042 12
								set_error_handler(array('pobject','pinpErrorHandler'),error_reporting());
2043 12
								$arResult=$arTemplates->import($template["arTemplateId"], $template["arCallTemplate"], "", $this);
2044 12
								restore_error_handler();
2045 12
								if (isset($arResult)) {
2046 12
									$ARCurrent->arResult=$arResult;
2047 9
								}
2048 12
								if ($ARCurrent->ARShowTemplateBorders) {
2049
									echo "<!-- arTemplateEnd -->";
2050
								}
2051 12 View Code Duplication
								if ( !$AR->contextCallHandler ) { /* prevent oncall from re-entering here */
2052 12
									$AR->contextCallHandler = true;
2053 12
									$temp = $ARCurrent->arResult; /* event listeners will change ARCurrent->arResult */
2054 12
									$eventData->arResult = $temp;
2055 12
									ar_events::fire('oncall', $eventData );
2056 12
									$ARCurrent->arResult = $temp; /* restore correct result */
2057 12
									$AR->contextCallHandler = false;
2058 9
								}
2059 9
							}
2060 9
						}
2061 12
						array_pop($ARCurrent->arCallStack);
2062 12
						$this->popContext();
2063
2064 12
						if ( !$initialConfigChecked && $arCallFunction != 'config.ini' ) {
2065
							// this template was the first template called in this request.
2066
							$eventData = new object();
2067
							$eventData->arCallArgs = $arCallArgs;
2068
							$eventData->arCallFunction = $arCallFunction;
2069
							ar_events::fire( 'onview', $eventData ); // no default action to prevent, so ignore return value.
0 ignored issues
show
Documentation introduced by
$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...
2070
						}
2071 12
						return false;
2072
					} else {
2073 4
						debug("pobject: CheckConfig: no such file: ".$template["arTemplateId"].$template["arCallTemplate"]."","all");
2074
					}
2075 3
				} else {
2076 48
					debug("CheckConfig: no arCallTemplate ($arCallFunction from '$this->path')","object");
2077
				}
2078
2079 39
			}
2080
		}
2081 56
		return true;
2082
	}
2083
2084
	public function ClearCache($path="", $private=true, $recurse=false) {
2085
	global $AR;
2086
		$norealnode = false;
2087
		if (!$path) {
2088
			$path=$this->path;
2089
		} else {
2090
			$realpath = current($this->get($path, "system.get.path.phtml"));
2091
			if($realpath != false) {
2092
				$path = $realpath;
2093
			} else {
2094
				$norealnode = true;
2095
			}
2096
		}
2097
2098
		if($norealnode !== true) {
2099
			/*
2100
				we don't want to recurse to the currentsite, because the path
2101
				doesn't exists in the database, so it doesn't have a currentsite
2102
2103
				the privatecache should be emptied by delete, or by the cleanup
2104
				cronjob. The current path doesn't exists in the database, so a
2105
				object id which is needed to find the node in the cache, isn't
2106
				available
2107
			*/
2108
2109
			if ($private ) {
2110
				// now remove any private cache entries.
2111
				// FIXME: this doesn't scale very well.
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "this doesn't scale very well"
Loading history...
2112
				//        only scalable solution is storage in a database
2113
				//        but it will need the original path info to
2114
				//        remove recursively fast enough.
2115
				//        this means a change in the filestore api. -> 2.5
2116
2117
				// Use chunks of max 5000 objects at a time to be more memory-efficient;
2118
				$pcache=$this->store->get_filestore("privatecache");
2119
				if ($recurse) {
2120
					$offset = 0;
2121
					$limit = 5000;
2122
					$ids=$this->store->info($this->store->find($path, "" , $limit, $offset));
2123
					while (is_array($ids) && count($ids)) {
2124
						foreach($ids as $value) {
2125
							$eventData = new object();
2126
							$eventData = ar_events::fire( 'onbeforeclearprivatecache', $eventData, $value['type'], $value['path'] );
0 ignored issues
show
Documentation introduced by
$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...
2127
							if ( !$eventData ) {
2128
								continue;
2129
							}
2130
2131
							$pcache->purge($value["id"]);
2132
							ar_events::fire( 'onclearprivatecache', $eventData, $value['type'], $value['path'] );
2133
						}
2134
2135
						$offset += $limit;
2136
						$ids = $this->store->info($this->store->find($path, "", $limit, $offset));
2137
					}
2138
				} else {
2139
					$eventData = new object();
2140
					$eventData = ar_events::fire( 'onbeforeclearprivatecache', $eventData, $this->type, $this->path );
0 ignored issues
show
Documentation introduced by
$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...
2141
					if ( $eventData ) {
2142
						$pcache->purge($this->id);
2143
						ar_events::fire( 'onclearprivatecache', $eventData, $this->type, $this->path );
2144
					}
2145
				}
2146
			}
2147
2148
			// now clear all parents untill the current site
2149
			$site=$this->currentsite($path);
2150
			$project=$this->currentproject($path);
2151
			if ($path!=$site && $path != $project && $path!='/') {
2152
				$parent=$this->make_path($path.'../');
2153
				$this->ClearCache($parent, $private, false);
2154
			}
2155
		}
2156
		$recursed = array();
2157
2158
		// filesystem cache image filenames are always lower case, so
2159
		// use special path for that. Remember 'real' path name for
2160
		// recursion and stuff
2161
		$fs_path=strtolower($path);
2162
		$nlslist=$AR->nls->list;
2163
		$nlslist["."]="default";
2164
		$cache_types[] = "normal";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$cache_types was never initialized. Although not strictly required by PHP, it is generally a good practice to add $cache_types = array(); before regardless.

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

Let’s take a look at an example:

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

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

    // do something with $myArray
}

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

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

Loading history...
2165
		$cache_types[] = "compressed";
2166
		$cache_types[] = "session";
2167
2168
		global $cache_config,$store_config;
2169
		$cachestore=new cache($cache_config);
2170
2171
2172
		$filestore = $this->store->get_config("files");
2173
		foreach($cache_types as $type){
2174
			foreach($nlslist as $nls => $language){
2175
				// break away if nls doesn't exists
2176
				// is dir is cached, so it should not cost more that it add's in speed
2177
				if(!is_dir($filestore."cache/$type/$nls")){
2178
					continue;
2179
				}
2180
2181
				$fpath=$filestore."cache/$type/$nls".$fs_path;
2182
				$hpath=$filestore."cacheheaders/$type/$nls".$fs_path;
2183
				if ($dir=@dir($fpath)) {
2184
					while (false !== ($entry = $dir->read())) {
2185
						if ($entry!="." && $entry!="..") {
2186
							if (is_file($fpath.$entry)) {
2187
								@unlink($fpath.$entry);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2188
								@unlink($hpath.$entry);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2189
								$cachestore->delete("/".$type."/".$nls.$fs_path.$entry);
2190
							} else if ( $recurse && !$recursed[$entry]) {
2191
								$this->ClearCache($path.$entry."/", false, true);
2192
								$recursed[$entry]=true;
2193
							}
2194
						}
2195
					}
2196
					$dir->close();
2197
					// remove empty directory entry's, hide errors about directory entry's with content
2198
					@rmdir($fpath);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2199
					@rmdir($hpath);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2200
				} else if (file_exists(substr($fpath,0,-1)."=")) {
2201
					@unlink(substr($fpath,0,-1)."=");
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2202
					@unlink(substr($hpath,0,-1)."=");
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2203
					$cachestore->delete("/".$type."/".$nls.substr($fs_path,0,-1)."=");
2204
				}
2205
			}
2206
		}
2207
	}
2208
2209
	public function getcache($name, $nls="") {
2210
		global $ARCurrent, $ARnls;
2211
		$result=false;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

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

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

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

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

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

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

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

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

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

Loading history...
2215
			if (!$nls) {
2216
				$nls=$this->nls;
2217
			}
2218
			$file=$nls.".".$name;
2219
2220
			$minfresh = time();
2221
			if (isset($ARCurrent->RequestCacheControl["min-fresh"])) {
2222
				$minfresh += $ARCurrent->RequestCacheControl["min-fresh"];
2223
			}
2224
2225
			$pcache=$this->store->get_filestore("privatecache");
2226
			if ( $pcache->exists($this->id, $file) &&
2227
			     ($pcache->mtime($this->id, $file) > ($minfresh) )  ) {
2228
2229
				$result = $pcache->read($this->id, $file);
2230
2231
				$contentType = $ARCurrent->ldHeaders['content-type'];
2232
				if (preg_match('|^content-type:[ ]*([^ /]+)/|i', $contentType, $matches)) {
2233
					$contentType = $matches[1];
2234
				} else {
2235
					$contentType = '';
2236
				}
2237
2238 View Code Duplication
				if (!$contentType || strtolower($contentType) == 'text') {
2239
					require_once($this->store->get_config('code')."modules/mod_url.php");
2240
					$temp = explode('.', $file);
2241
					$imageNLS = $temp[0];
2242
					$result = URL::ARtoRAW($result, $imageNLS);
0 ignored issues
show
Unused Code introduced by
The call to URL::ARtoRAW() has too many arguments starting with $imageNLS.

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

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

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

Loading history...
2243
				}
2244
			} else {
2245
				$result=false;
2246
				$ARCurrent->cache[]=$file;
2247
				ob_start();
2248
				/* output buffering is recursive, so this won't interfere with
2249
				   normal page caching, unless you forget to call savecache()...
2250
				   so normal pagecache needs to check $ARCurrent->cache, if it's
2251
				   not empty, issue a warning and don't cache the outputbuffer...
2252
				   savecache() must then pop the stack.
2253
				*/
2254
			}
2255
		} else {
2256
			$this->error = ar::error($ARnls["err:nonamecache"], 1111);
2257
			$result = false;
2258
		}
2259
		return $result;
2260
	}
2261
2262
	public function cached($name, $nls="") {
2263
		if ($image=$this->getcache($name, $nls)) {
2264
			echo $image;
2265
			$result=true;
2266
		} else {
2267
			$result=false;
2268
		}
2269
		return $result;
2270
	}
2271
2272
	public function savecache($time="") {
2273
		global $ARCurrent, $ARnls, $DB;
2274
		$result = false;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

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

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

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

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

Loading history...
2275
		$this->error = '';
2276
		if (!$time) {
2277
			$time=2; // 'freshness' in hours.
2278
		}
2279
		if ($file=array_pop($ARCurrent->cache)) {
2280
			$image=ob_get_contents();
2281
			if ($image !== false) {
2282
				$result = $image;
2283
2284
				$contentType = $ARCurrent->ldHeaders['content-type'];
2285
				if (preg_match('|^content-type:[ ]*([^ /]+)/|i', $contentType, $matches)) {
2286
					$contentType = $matches[1];
2287
				} else {
2288
					$contentType = '';
2289
				}
2290
2291 View Code Duplication
				if (!$contentType || strtolower($contentType) == 'text') {
2292
					require_once($this->store->get_config('code')."modules/mod_url.php");
2293
					$temp = explode('.', $file);
2294
					$imageNLS = $temp[0];
2295
					$image = URL::RAWtoAR($image, $imageNLS);
2296
				}
2297
2298
				if( $time > 0  && $DB["wasUsed"] == 0) {
2299
					$pcache=$this->store->get_filestore("privatecache");
2300
					$pcache->write($image, $this->id, $file);
2301
					$time=time()+($time*3600);
2302 View Code Duplication
					if (!$pcache->touch($this->id, $file, $time)) {
2303
						$this->error = ar::error("savecache: ERROR: couldn't touch $file", 1113);
2304
						$result = false;
2305
					}
2306
				}
2307
				ob_end_clean();
2308
				echo $image;
2309
			} else {
2310
				debug("skipped saving cache - ob_get_contents returned false so output buffering was not active", "all");
2311
				$result = false;
2312
			}
2313
		} else {
2314
			$this->error = ar::error($ARnls["err:savecachenofile"], 1112);
2315
			$result = false;
2316
		}
2317
		return $result;
2318
	}
2319
2320
	public function getdatacache($name) {
2321
		global $ARCurrent, $ARnls;
2322
		$result=false;
2323
		$this->error = '';
2324
		if ($name) {
2325
2326
			$minfresh = time();
2327
			if (isset($ARCurrent->RequestCacheControl["min-fresh"])) {
2328
				$minfresh += $ARCurrent->RequestCacheControl["min-fresh"];
2329
			}
2330
2331
			$pcache=$this->store->get_filestore("privatecache");
2332
			if ( $pcache->exists($this->id, $name) &&
2333
			     ($pcache->mtime($this->id, $name) > $minfresh) ) {
2334
				$result = unserialize($pcache->read($this->id, $name));
2335
			} else {
2336
				debug("getdatacache: $name doesn't exists, returning false.","all");
2337
			}
2338
		} else {
2339
			$this->error = ar::error($ARnls["err:nonamecache"], 1111);
2340
		}
2341
		return $result;
2342
	}
2343
2344
	public function savedatacache($name,$data,$time="") {
2345
		global $DB;
2346
		$this->error = '';
2347
		if (!$time) {
2348
			$time=2; // 'freshness' in hours.
2349
		}
2350
		$pcache=$this->store->get_filestore("privatecache");
2351
		if( $time > 0  && $DB["wasUsed"] == 0) {
2352
			$pcache->write(serialize($data), $this->id, $name);
2353
			$time=time()+($time*3600);
2354 View Code Duplication
			if (!$pcache->touch($this->id, $name, $time)) {
2355
				$this->error = ar::error('Could not touch '.$name, 1113);
2356
				return false;
2357
			}
2358
		}
2359
		return true;
2360
	}
2361
2362 52
	public function getdata($varname, $nls="none", $emptyResult=false) {
0 ignored issues
show
Coding Style introduced by
getdata uses the super-global variable $_POST which is generally not recommended.

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

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

// Better
class Router
{
    private $host;

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

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

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

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

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

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

// Better
class Router
{
    private $host;

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

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

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

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
2363
	// function to retrieve variables from $this->data, with the correct
2364
	// language version.
2365 52
	global $ARCurrent;
2366
2367 52
		$result = false;
2368 52
		if ($nls!="none") {
2369 48 View Code Duplication
			if ($ARCurrent->arCallStack) {
2370 48
				$arCallArgs=end($ARCurrent->arCallStack);
2371 48
				if (isset($arCallArgs) && is_array($arCallArgs)) {
2372 48
					extract($arCallArgs);
2373 36
				} else if (is_string($arCallArgs)) {
2374
					Parse_Str($arCallArgs);
2375
				}
2376 36
			}
2377 48
			if (isset(${$nls}[$varname])) {
2378 28
				$result=${$nls}[$varname];
2379 48
			} else if (isset($ARCurrent->$nls) && isset($ARCurrent->$nls->$varname)) {
2380
				$result=$ARCurrent->$nls->$varname;
2381 48
			} else if (($values=$_POST[$nls]) && isset($values[$varname])) {
2382
				$result=$values[$varname];
2383 48
			} else if (($values=$_GET[$nls]) && isset($values[$varname])) {
2384
				$result=$values[$varname];
2385 48
			} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$nls][$varname])) {
2386
				$result=$arStoreVars[$nls][$varname];
2387 48
			} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$nls][$varname])) {
2388
				$result=$arStoreVars[$nls][$varname];
2389
			}
2390 48
			if ($result===false) {
2391 48
				if (isset($this->data->${nls}) && isset($this->data->${nls}->${varname})) {
2392 30
					$result=$this->data->${nls}->${varname};
2393 18
				}
2394 36
			}
2395 36
		} else { // language independant variable.
2396 52 View Code Duplication
			if ($ARCurrent->arCallStack) {
2397 52
				$arCallArgs=end($ARCurrent->arCallStack);
2398 52
				if (isset($arCallArgs) && is_array($arCallArgs)) {
2399 48
					extract($arCallArgs);
2400 43
				} else if (is_string($arCallArgs)) {
2401
					Parse_Str($arCallArgs);
2402
				}
2403 39
			}
2404 52
			if (isset($$varname)) {
2405 24
				$result=$$varname;
2406 52
			} else if (isset($ARCurrent->$varname)) {
2407
				$result=$ARCurrent->$varname;
2408 52 View Code Duplication
			} else if (isset($_POST[$varname])) {
2409
				$result=$_POST[$varname];
2410 52
			} else if (isset($_GET[$varname])) {
2411
				$result=$_GET[$varname];
2412 52
			} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$varname])) {
2413
				$result=$arStoreVars[$varname];
2414 52
			} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$varname])) {
2415
				$result=$arStoreVars[$varname];
2416
			}
2417 52
			if ($result===false) {
2418 52
				if (isset($this->data->$varname)) {
2419 24
					$result=$this->data->$varname;
2420 18
				}
2421 39
			}
2422
		}
2423 52
		if ( $result === false ) {
2424 52
			$result = $emptyResult;
2425 39
		}
2426 52
		return $result;
2427
	}
2428
2429
	public function showdata($varname, $nls="none", $emptyResult=false) {
2430
		echo htmlspecialchars($this->getdata($varname, $nls, $emptyResult), ENT_QUOTES, 'UTF-8');
2431
	}
2432
2433
	public function setnls($nls) {
2434
		ldSetNls($nls);
2435
	}
2436
2437
	public function getcharset() {
2438
		return "UTF-8";
2439
	}
2440
2441
	public function HTTPRequest($method, $url, $postdata = "", $port=80 ) {
2442
		$maxtries = 5;
2443
		$tries = 0;
2444
		$redirecting = true;
2445
2446
		if(isset($postdata) && is_array($postdata)) {
2447
			foreach($postdata as $key=>$val) {
2448
				if(!is_integer($key)) {
2449
					$data .= "$key=".urlencode($val)."&";
0 ignored issues
show
Bug introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2450
				}
2451
			}
2452
		} else {
2453
			$data = $postdata;
2454
		}
2455
2456
		while ($redirecting && $tries < $maxtries) {
2457
			$tries++;
2458
			// get host name and URI from URL, URI not needed though
2459
			preg_match("/^([htps]*:\/\/)?([^\/]+)(.*)/i", $url, $matches);
2460
			$host = $matches[2];
2461
			$uri = $matches[3];
2462
			if (!$matches[1]) {
2463
				$url="http://".$url;
2464
			}
2465
			$connection = @fsockopen( $host, $port, $errno, $errstr, 120);
2466
			if( $connection ) {
2467
				if( strtoupper($method) == "GET" ) {
2468
					if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

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

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

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

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
2469
						$uri .= "?" . $data;
2470
					}
2471
					fputs( $connection, "GET $uri HTTP/1.0\r\n");
2472
				} else if( strtoupper($method) == "POST" ) {
2473
					fputs( $connection, "POST $uri HTTP/1.0\r\n");
2474
				} else {
2475
					fputs( $connection, "$method $uri HTTP/1.0\r\n");
2476
				}
2477
2478
				fputs( $connection, "Host: $host\r\n");
2479
				fputs( $connection, "Accept: */*\r\n");
2480
				fputs( $connection, "Accept: image/gif\r\n");
2481
				fputs( $connection, "Accept: image/x-xbitmap\r\n");
2482
				fputs( $connection, "Accept: image/jpeg\r\n");
2483
2484
				if( strtoupper($method) == "POST" ) {
2485
					$strlength = strlen( $data);
2486
					fputs( $connection, "Content-type: application/x-www-form-urlencoded\r\n" );
2487
					fputs( $connection, "Content-length: ".$strlength."\r\n\r\n");
2488
					fputs( $connection, $data."\r\n");
2489
				}
2490
2491
				fputs( $connection, "\r\n" , 2);
2492
2493
				$headerContents = '';
2494
				$headerStart = 0;
2495
				$headerEnd = 0;
2496
				$redirecting = false;
2497
2498
				while (!feof($connection)) {
2499
					$currentLine = fgets ($connection, 1024);
2500
					if ($headerEnd && $redirecting) {
2501
						break;
2502
					} else if ($headerEnd && !$redirecting) {
2503
						//this is the html from the page
2504
						$contents = $contents . $currentLine;
0 ignored issues
show
Bug introduced by
The variable $contents does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2505
					} else if ( preg_match("/^HTTP/", $currentLine) ) {
2506
						//came to the start of the header
2507
						$headerStart = 1;
2508
						$headerContents = $currentLine;
2509
					} else if ( $headerStart && preg_match('/^[\n\r\t ]*$/', $currentLine) ) {
2510
						//came to the end of the header
2511
						$headerEnd = 1;
2512
					} else {
2513
						//this is the header, if you want it...
2514
						if (preg_match("/^Location: (.+?)\n/is",$currentLine,$matches) ) {
2515
							$headerContents .= $currentLine;
2516
							//redirects are sometimes relative
2517
							$newurl = $matches[1];
2518
							if (!preg_match("/http:\/\//i", $newurl, $matches) ) {
2519
								$url .= $newurl;
2520
							} else {
2521
								$url = $newurl;
2522
							}
2523
							//extra \r's get picked up sometimes
2524
							//i think only with relative redirects
2525
							//this is a quick fix.
2526
							$url = preg_replace("/\r/s","",$url);
2527
							$redirecting = true;
2528
						} else {
2529
							$headerContents.=$currentLine;
2530
						}
2531
					}
2532
				}
2533
			} else {
2534
				$this->error="$errstr ($errno)";
2535
				$contents=false;
2536
				$url = "";
2537
			}
2538
			@fclose($connection);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2539
		}
2540
		if (($method!="GET") && ($method!="POST")) {
2541
			$contents=$headerContents."\n".$contents;
0 ignored issues
show
Bug introduced by
The variable $headerContents does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
2551
		}
2552
		while ( (count($suffixes) > 1) && ($size > 1024) ){
2553
			$size = $size / 1024;
2554
			array_shift($suffixes);
2555
		}
2556
		$size = round($size,$precision);
2557
		if($precision==0){ // compatible with the old make_filesize
2558
			$size = intval($size);
2559
		}
2560
		$result = $size." ".array_shift($suffixes);
2561
		return $result;
2562
	}
2563
2564
	public function convertToUTF8($data, $charset = "CP1252") {
2565
2566
		include_once($this->store->get_config("code")."modules/mod_unicode.php");
2567
2568
		if (isset($data) && is_array($data)) {
2569
			foreach($data as $key => $val){
2570
				$data[$key] = $this->convertToUTF8($val, $charset);
2571
			}
2572
		} else
2573
		if (is_object($data)) {
2574
			foreach($data as $key => $val){
2575
				$data->$key = $this->convertToUTF8($val, $charset);
2576
			}
2577
		} else {
2578
			$data = unicode::convertToUTF8($charset, $data);
2579
		}
2580
		return $data;
2581
	}
2582
2583 28
	public function resetloopcheck() {
2584 28
		global $ARBeenHere;
2585 28
		$ARBeenHere=array();
2586 28
	}
2587
2588
/********************************************************************
2589
2590
  "safe" functions.
2591
2592
  The following functions are safe versions of existing functions
2593
  above.
2594
  - They don't change anything in the database.
2595
    This means that to save/delete something, a user will need to call
2596
    "system.save.data.phtml" or "system.delete.phtml" which check grants.
2597
  - All functions except _get and _exists don't take a path as
2598
    argument, they use the current objects path instead.
2599
2600
  These are meant to be used by 'pinp' versions of templates,
2601
  meaning user defined templates. 'pinp' rewrites call to functions
2602
  to the form '$this->_function'.
2603
2604
  All pinp files automatically first call CheckLogin('read').
2605
2606
********************************************************************/
2607
2608
	public function _call($function, $args="") {
2609
		// remove possible path information (greedy match)
2610
		if ( !( $function instanceof \Closure ) ) {
2611
			$function = basename( (string) $function );
2612
		}
2613
		return $this->call($function, $args);
0 ignored issues
show
Bug introduced by
It seems like $function can also be of type object<Closure>; however, ariadne_object::call() does only seem to accept string, maybe add an additional type check?

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

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

    return array();
}

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

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

Loading history...
Documentation introduced by
$args is of type string, 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...
2614
	}
2615
2616
	public function _call_super($arCallArgs="") {
2617
	global $ARCurrent, $AR;
2618
		$context = $this->getContext();
2619
		if (!$arCallArgs) {
2620
			$arCallArgs = end($ARCurrent->arCallStack);
2621
		}
2622
		$arSuperContext = (array)$context['arSuperContext'];
2623
		$arLibrary		= $context['arLibrary'];
2624
		$arLibraryPath	= $context['arLibraryPath'];
2625
		$arCallType		= $context['arCallTemplateType'];
2626
		$arSuperPath	= $context['arCallTemplatePath'];
2627
		$arLibrariesSeen = $context['arLibrariesSeen'];
2628
		$arCallFunction = $arSuperFunction = $context['arCallFunction'];
2629
		if ($arLibrary) {
2630
			$arSuperFunction = str_replace($arLibrary.':', '', $arCallFunction);
2631
		}
2632
		if (strpos($arSuperFunction, "::") !== false) {
2633
			// template of a specific class defined via call("class::template");
2634
			list($arBaseType, $arSuperFunction)=explode("::", $arSuperFunction);
0 ignored issues
show
Unused Code introduced by
The assignment to $arBaseType is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

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

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

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

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

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

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

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

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

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

Loading history...
2701
					$eventData = ar_events::fire('onbeforecall', $eventData);
0 ignored issues
show
Documentation introduced by
$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...
2702
					$ARCurrent->arResult = $eventData->arResult;
2703
					$AR->contextCallHandler = false;
2704
					$continue = ($eventData!=false);
2705
				}
2706
				if ( $continue ) {
2707
					set_error_handler(array('pobject','pinpErrorHandler'),error_reporting());
2708
					$arResult = $arTemplates->import($template["arTemplateId"], $template["arCallTemplate"], "", $this);
2709
					restore_error_handler();
2710
2711 View Code Duplication
					if ( !$AR->contextCallHandler ) { /* prevent oncall from re-entering here */
2712
						$AR->contextCallHandler = true;
2713
						$temp = $ARCurrent->arResult; /* event listeners will change ARCurrent->arResult */
2714
						$eventData->arResult = $arResult;
2715
						ar_events::fire('oncall', $eventData );
2716
						$ARCurrent->arResult = $temp; /* restore correct result */
2717
						$AR->contextCallHandler = false;
2718
					}
2719
				}
2720
				array_pop($ARCurrent->arCallStack);
2721
				$this->popContext();
2722
			}
2723
		}
2724
2725
		return $arResult;
0 ignored issues
show
Bug introduced by
The variable $arResult does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2726
	}
2727
2728
	public function _get($path, $function="view.html", $args="") {
2729
		// remove possible path information (greedy match)
2730
		if ( !($function instanceof \Closure) ) {
2731
			$function = basename( (string) $function);
2732
		}
2733
		return $this->store->call($function, $args,
2734
			$this->store->get(
2735
				$this->make_path($path)));
2736
	}
2737
2738
	public function _call_object($object, $function, $args="") {
2739
		return $object->call($function, $args);
2740
	}
2741
2742 View Code Duplication
	public function _ls($function="list.html", $args="") {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2743
		// remove possible path information (greedy match)
2744
		if ( ! ( $function instanceof \Closure ) ) {
2745
			$function = basename( (string) $function );
2746
		}
2747
		return $this->store->call($function, $args,
2748
			$this->store->ls($this->path));
2749
	}
2750
2751 View Code Duplication
	public function _parents($function="list.html", $args="", $top="") {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2752
		// remove possible path information (greedy match)
2753
		if ( !($function instanceof \Closure ) ) {
2754
			$function = basename( (string) $function);
2755
		}
2756
		return $this->parents($this->path, $function, $args, $top);
2757
	}
2758
2759
	public function _find($criteria, $function="list.html", $args="", $limit=100, $offset=0) {
2760
		$this->error = '';
2761
		// remove possible path information (greedy match)
2762
		if ( !($function instanceof \Closure ) ) {
2763
			$function = basename( (string) $function);
2764
		}
2765
		$result = $this->store->call($function, $args,
2766
			$this->store->find($this->path, $criteria, $limit, $offset));
2767 View Code Duplication
		if ($this->store->error) {
2768
			$this->error = ar::error( ''.$this->store->error, 1107, $this->store->error );
2769
		}
2770
		return $result;
2771
	}
2772
2773
	public function _exists($path) {
2774
		return $this->store->exists($this->make_path($path));
2775
	}
2776
2777
	public function _implements($implements) {
2778
		return $this->AR_implements($implements);
2779
	}
2780
2781 52
	public function getvar($var) {
0 ignored issues
show
Coding Style introduced by
getvar uses the super-global variable $_POST which is generally not recommended.

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

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

// Better
class Router
{
    private $host;

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

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

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

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

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

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

// Better
class Router
{
    private $host;

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

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

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

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
2782 52
	global $ARCurrent, $ARConfig; // Warning: if you add other variables here, make sure you cannot get at it through $$var.
2783
2784 52 View Code Duplication
		if ($ARCurrent->arCallStack) {
2785 48
			$arCallArgs=end($ARCurrent->arCallStack);
2786 48
			if (isset($arCallArgs) && is_array($arCallArgs)) {
2787 36
				extract($arCallArgs);
2788 40
			} else if (is_string($arCallArgs)) {
2789
				Parse_Str($arCallArgs);
2790
			}
2791 36
		}
2792 52
		if (isset($$var) && ($var!='ARConfig')) {
2793 16
			$result=$$var;
2794 52
		} else if (isset($ARCurrent->$var)) {
2795
			$result=$ARCurrent->$var;
2796 52
		} else if (isset($ARConfig->pinpcache[$this->path][$var])) {
2797
			$result=$ARConfig->pinpcache[$this->path][$var];
2798 52 View Code Duplication
		} else if (isset($_POST[$var])) {
2799
			$result=$_POST[$var];
2800 52
		} else if (isset($_GET[$var])) {
2801
			$result=$_GET[$var];
2802 52
		} else if (($arStoreVars=$_POST["arStoreVars"]) && isset($arStoreVars[$var])) {
2803
			$result=$arStoreVars[$var];
2804 52
		} else if (($arStoreVars=$_GET["arStoreVars"]) && isset($arStoreVars[$var])) {
2805
			$result=$arStoreVars[$var];
2806
		}
2807 52
		return $result;
2808
	}
2809
2810
	public function _getvar($var) {
2811
		return $this->getvar($var);
2812
	}
2813
2814
	public function putvar($var, $value) {
2815
		global $ARCurrent;
2816
2817
		$ARCurrent->$var=$value;
2818
	}
2819
2820
	public function _putvar($var, $value) {
2821
		return $this->putvar($var, $value);
2822
	}
2823
2824
	public function _setnls($nls) {
2825
		$this->setnls($nls);
2826
	}
2827
2828
	// not exposed to pinp for obvious reasons
2829
	public function sgKey($grants) {
2830
		global $AR;
2831
		if( !$AR->sgSalt || !$this->CheckSilent("config") ) {
2832
			return false;
2833
		}
2834
		// serialize the grants so the order does not matter, mod_grant takes care of the sorting for us
2835
		$this->_load("mod_grant.php");
2836
		$mg = new mod_grant();
2837
		$grantsarray = array();
2838
		$mg->compile($grants, $grantsarray);
2839
		$grants = serialize($grantsarray);
2840
		return sha1( $AR->sgSalt . $grants . $this->path);
2841
	}
2842
2843
	public function sgBegin($grants, $key = '', $path = '.') {
2844
		global $AR;
2845
		$result = false;
2846
		$context = $this->getContext();
2847
		$path    = $this->make_path($path);
2848
2849
		// serialize the grants so the order does not matter, mod_grant takes care of the sorting for us
2850
		$this->_load("mod_grant.php");
2851
		$mg = new mod_grant();
2852
		$grantsarray = array();
2853
		$mg->compile($grants, $grantsarray);
2854
2855
		if ($context['scope'] == 'pinp') {
2856
			$checkgrants = serialize($grantsarray);
2857
			$check = ( $AR->sgSalt ? sha1( $AR->sgSalt . $checkgrants . $path) : false ); // not using suKey because that checks for config grant
2858
		} else {
2859
			$check = true;
2860
			$key = true;
2861
		}
2862
		if( $check !== false && $check === $key ) {
2863
			$AR->user->grants = array(); // unset all grants for the current user, this makes sure GetValidGrants gets called again for this path and all childs
2864
			$grantsarray = (array)$AR->sgGrants[$path];
2865
			$mg->compile($grants, $grantsarray);
2866
			$AR->sgGrants[$path] = $grantsarray;
2867
			$result = true;
2868
		}
2869
		return $result;
2870
	}
2871
2872
	public function sgEnd($path = '.') {
2873
		global $AR;
2874
		$AR->user->grants = array(); // unset all grants for the current user, this makes sure GetValidGrants gets called again for this path and all childs
2875
		$path = $this->make_path( $path );
2876
		unset($AR->sgGrants[$path]);
2877
		return true; // temp return true;
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
2878
	}
2879
2880
	public function sgCall($grants, $key, $function="view.html", $args="") {
2881
		$result = false;
2882
		if( $this->sgBegin($grants, $key ) ) {
2883
			$result = $this->call($function, $args);
0 ignored issues
show
Documentation introduced by
$args is of type string, 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...
2884
			$this->sgEnd();
2885
		}
2886
		return $result;
2887
	}
2888
2889
	public function _sgBegin($grants, $key, $path = '.') {
2890
		return $this->sgBegin($grants, $key, $path);
2891
	}
2892
2893
	public function _sgEnd($path = '.') {
2894
		return $this->sgEnd($path);
2895
	}
2896
2897
	public function _sgCall($grants, $key, $function="view.html", $args="") {
2898
		return $this->sgCall($grants, $key, $function, $args);
2899
	}
2900
2901
	public function _widget($arWidgetName, $arWidgetTemplate, $arWidgetArgs="", $arWidgetType="lib") {
2902
	global $AR, $ARConfig, $ARCurrent, $ARnls;
2903
2904
		$arWidgetName=preg_replace("/[^a-zA-Z0-9\/]/","",$arWidgetName);
2905
		$arWidgetTemplate=preg_replace("/[^a-zA-Z0-9\.]/","",$arWidgetTemplate);
2906
		$wgResult=null;
2907
		if ($arWidgetType=="www") {
2908
			$coderoot=$AR->dir->root;
2909
		} else {
2910
			$coderoot=$this->store->get_config("code");
2911
		}
2912
		if (file_exists($coderoot."widgets/$arWidgetName")) {
2913
			if (file_exists($coderoot."widgets/$arWidgetName/$arWidgetTemplate")) {
2914
				if (isset($arWidgetArgs) && is_array($arWidgetArgs)) {
2915
					extract($arWidgetArgs);
2916
				} else if (is_string($arWidgetArgs)) {
2917
					Parse_str($arWidgetArgs);
2918
				}
2919
				include($coderoot."widgets/$arWidgetName/$arWidgetTemplate");
2920
			} else {
2921
				error("Template $arWidgetTemplate for widget $arWidgetName not found.");
2922
			}
2923
		} else {
2924
			error(sprintf($ARnls["err:widgetnotfound"],$arWidgetName));
2925
		}
2926
		if ($wgResult) {
2927
			return $wgResult;
2928
		}
2929
	}
2930
2931
	public function _getdata($varname, $nls="none", $emptyResult=false) {
2932
		return $this->getdata($varname, $nls, $emptyResult);
2933
	}
2934
2935
	public function _showdata($varname, $nls="none", $emptyResult=false) {
2936
		$this->showdata($varname, $nls, $emptyResult);
2937
	}
2938
2939
	public function _gettext($index=false) {
2940
	global $ARnls;
2941
		if (!$index) {
2942
			return $ARnls;
2943
		} else {
2944
			return $ARnls[$index];
2945
		}
2946
	}
2947
2948
	public function _loadtext($nls, $section="") {
2949
	global $ARnls, $ARCurrent;
2950
		if( is_object($ARnls) ) {
2951
			$ARnls->load($section, $nls);
2952
			$ARnls->setLanguage($nls);
2953
			$this->ARnls = $ARnls;
0 ignored issues
show
Bug introduced by
The property ARnls does not exist. Did you maybe forget to declare it?

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

class MyClass { }

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

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

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
2954
		} else { // older loaders and other shizzle
2955
2956
			$nls = preg_replace('/[^a-z]*/i','',$nls);
2957
			$section = preg_replace('/[^a-z0-9\._:-]*/i','',$section);
2958
			if (!$section) {
2959
				include($this->store->get_config("code")."nls/".$nls);
2960
				$this->ARnls = array_merge((array)$this->ARnls, $ARnls);
2961
			} else {
2962
				$nlsfile = $this->store->get_config("code")."nls/".$section.".".$nls;
2963
				if(strpos($nlsfile, ':') === false && file_exists($nlsfile)) {
2964
					include($nlsfile);
2965
					$this->ARnls = array_merge((array)$this->ARnls, $ARnls);
2966
				} else {
2967
					// current result;
2968
					$arResult = $ARCurrent->arResult;
2969
					$this->pushContext(array());
2970
						$oldnls = $this->reqnls;
2971
						$this->reqnls = $nls;
2972
						$this->CheckConfig($section, array('nls' => $nls));
0 ignored issues
show
Documentation introduced by
array('nls' => $nls) is of type array<string,?,{"nls":"?"}>, but the function expects a string.

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...
2973
						$this->reqnls = $oldnls;
2974
					$this->popContext();
2975
					// reset current result (CheckConfig may have changed it when it should not have).
2976
					$ARCurrent->arResult = $arResult;
2977
				}
2978
			}
2979
		}
2980
	}
2981
2982
	public function _startsession() {
2983
	global $ARCurrent;
2984
		ldStartSession(0);
2985
		return $ARCurrent->session->id;
2986
	}
2987
2988
	public function _putsessionvar($varname, $varvalue) {
2989
	global $ARCurrent;
2990
2991
		if ($ARCurrent->session) {
2992
			return $ARCurrent->session->put($varname, $varvalue);
2993
		} else {
2994
			return false;
2995
		}
2996
	}
2997
2998
	public function _getsessionvar($varname) {
2999
	global $ARCurrent;
3000
3001
		if ($ARCurrent->session) {
3002
			return $ARCurrent->session->get($varname);
3003
		} else {
3004
			return false;
3005
		}
3006
	}
3007
3008
	public function _setsessiontimeout($timeout = 0) {
3009
	global $ARCurrent;
3010
		if ($ARCurrent->session) {
3011
			return $ARCurrent->session->setTimeout($timeout);
3012
		} else {
3013
			return false;
3014
		}
3015
	}
3016
3017
	public function _killsession() {
3018
	global $ARCurrent;
3019
3020
		if ($ARCurrent->session) {
3021
			$ARCurrent->session->kill();
3022
			unset($ARCurrent->session);
3023
		}
3024
	}
3025
3026
	public function _sessionid() {
3027
	global $ARCurrent;
3028
		if ($ARCurrent->session) {
3029
			return $ARCurrent->session->id;
3030
		} else {
3031
			return 0;
3032
		}
3033
	}
3034
3035
	public function _resetloopcheck() {
3036
		return $this->resetloopcheck();
3037
	}
3038
3039
	public function _make_path($path="") {
3040
		return $this->make_path($path);
3041
	}
3042
3043
	public function _make_ariadne_url($path="") {
3044
		return $this->make_ariadne_url($path);
3045
	}
3046
3047
	public function _make_url($path="", $nls=false, $session=true, $https=null, $keephost=null) {
3048
		return $this->make_url($path, $nls, $session, $https, $keephost);
3049
	}
3050
3051
	public function _make_local_url($path="", $nls=false, $session=true, $https=null) {
3052
		return $this->make_local_url($path, $nls, $session, $https);
3053
	}
3054
3055
	public function _getcache($name, $nls='') {
3056
		return $this->getcache($name, $nls);
3057
	}
3058
3059
	public function _cached($name, $nls='') {
3060
		return $this->cached($name, $nls);
3061
	}
3062
3063
	public function _savecache($time="") {
3064
		return $this->savecache($time);
3065
	}
3066
3067
	public function _getdatacache($name) {
3068
		return $this->getdatacache($name);
3069
	}
3070
3071
	public function _savedatacache($name,$data,$time="")
3072
	{
3073
		return $this->savedatacache($name,$data,$time);
3074
	}
3075
3076 56
	public function currentsite($path="", $skipRedirects = false) {
3077 56
		global $ARCurrent, $ARConfig;
3078 56
		if (!$path) {
3079 48
			$path=$this->path;
3080 36
		}
3081 56
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3082 56
		if (!$skipRedirects && @count($ARCurrent->shortcut_redirect)) {
3083
			$redir = end($ARCurrent->shortcut_redirect);
3084
			if ($redir["keepurl"] && substr($path, 0, strlen($redir["dest"])) == $redir["dest"]) {
3085
				if (substr($config->site, 0, strlen($redir["dest"]))!=$redir["dest"]) {
3086
					// search currentsite from the reference
3087
					$config = ($ARConfig->cache[$redir['src']]) ? $ARConfig->cache[$redir['src']] : $this->loadConfig($redir['src']);
3088
				}
3089
			}
3090
		}
3091 56
		return $config->site;
3092
	}
3093
3094
	public function parentsite($site) {
3095
	global $ARConfig;
3096
		$path=$this->store->make_path($site, "..");
3097
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3098
		return $config->site;
3099
	}
3100
3101 4 View Code Duplication
	public function currentsection($path="") {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3102 4
	global $ARConfig;
3103 4
		if (!$path) {
3104 4
			$path=$this->path;
3105 3
		}
3106 4
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3107 4
		return $config->section;
3108
	}
3109
3110 View Code Duplication
	public function parentsection($path) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3111
	global $ARConfig;
3112
		$path=$this->store->make_path($path, "..");
3113
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3114
		return $config->section;
3115
	}
3116
3117 View Code Duplication
	public function currentproject($path="") {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3118
	global $ARConfig;
3119
		if (!$path) {
3120
			$path=$this->path;
3121
		}
3122
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3123
		return $config->project;
3124
	}
3125
3126
	public function parentproject($path) {
3127
	global $ARConfig;
3128
		$path=$this->store->make_path($path, "..");
3129
		$config=($ARConfig->cache[$path]) ? $ARConfig->cache[$path] : $this->loadConfig($path);
3130
		return $config->project;
3131
	}
3132
3133
	public function validateFormSecret() {
3134
		global $ARCurrent;
3135
		if (!$ARCurrent->session) {
3136
			return true;
3137
		}
3138
3139
		if ($ARCurrent->session && $ARCurrent->session->data && $ARCurrent->session->data->formSecret) {
3140
			$formSecret = $this->getvar("formSecret");
3141
			return ($formSecret === $ARCurrent->session->data->formSecret);
3142
		}
3143
		return false;
3144
	}
3145
3146
	public function _validateFormSecret() {
3147
		return $this->validateFormSecret();
3148
	}
3149
3150
	public function getValue($name, $nls=false) {
3151
	global $ARCurrent;
3152
		switch ($nls) {
3153
			case "none":
3154
				$result = $this->data->$name;
3155
			break;
3156
			case false:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
3157
				$nls = $ARCurrent->nls;
3158
				if (!isset($this->data->$nls) || !isset($this->data->$nls->$name)) {
3159
					$result = $this->data->$name;
3160
					break;
3161
				}
3162
			default:
3163
				$result = $this->data->$nls->$name;
3164
		}
3165
		return $result;
3166
	}
3167
3168
	public function setValue($name, $value, $nls=false) {
3169
3170
	global $AR, $ARConfig;
3171
		if ($value === null) {
3172
			if ($nls && $nls!="none") {
3173
				unset($this->data->$nls->$name);
3174
				if (!count(get_object_vars($this->data->$nls))) {
3175
					unset($this->data->$nls);
3176
					unset($this->data->nls->list[$nls]);
3177
					if (!count($this->data->nls->list)) {
3178
						unset($this->data->nls->list);
3179
						unset($this->data->nls);
3180
					} else {
3181
						if ($this->data->nls->default == $nls) {
3182
							if ($this->data->nls->list[$ARConfig->nls->default]) {
3183
								$this->data->nls->default = $ARConfig->nls->default;
3184
							} else {
3185
								list($this->data->nls->default) = each($this->data->nls->list);
3186
							}
3187
						}
3188
					}
3189
				}
3190
			} else {
3191
				unset($this->data->$name);
3192
			}
3193
		} else
3194
		if (!$nls) {
3195
			$this->data->$name = $value;
3196
		} else {
3197
			if (!$this->data->$nls) {
3198
				$this->data->$nls = new object;
3199
				if (!$this->data->nls) {
3200
					$this->data->nls = new object;
3201
					$this->data->nls->default = $nls;
0 ignored issues
show
Bug introduced by
The property default does not seem to exist in object.

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

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

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

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

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

Loading history...
3204
			}
3205
			$this->data->$nls->$name = $value;
3206
		}
3207
	}
3208
3209
	public function showValue($name, $nls=false) {
3210
		$result = $this->getValue($name, $nls);
3211
		echo $result;
3212
		return $result;
3213
	}
3214
3215
	public function _getValue($name, $nls=false) {
3216
		return $this->getValue($name, $nls);
3217
	}
3218
3219
	public function _setValue($name, $value, $nls=false) {
3220
		return $this->setValue($name, $value, $nls);
3221
	}
3222
3223
	public function _showValue($name, $nls=false) {
3224
		return $this->showValue($name, $nls);
3225
	}
3226
3227
	public function _currentsite($path="", $skipRedirects = false) {
3228
		return $this->currentsite( $path, $skipRedirects );
3229
	}
3230
3231
	public function _parentsite($site) {
3232
		return $this->parentsite($site);
3233
	}
3234
3235
	public function _currentsection() {
3236
		return $this->currentsection();
3237
	}
3238
3239
	public function _parentsection($section) {
3240
		return $this->parentsection($section);
3241
	}
3242
3243
	public function _currentproject() {
3244
		return $this->currentproject();
3245
	}
3246
3247
	public function _parentproject($path) {
3248
		return $this->parentproject($path);
3249
	}
3250
3251
	public function _checkAdmin($user) {
3252
		return $this->CheckAdmin($user);
3253
	}
3254
3255
	public function _checkgrant($grant, $modifier=ARTHISTYPE, $path=".") {
3256
		// as this is called within a pinp template,
3257
		// all the grants are already loaded, so
3258
		// checksilent will fullfill our needs
3259
		$this->pushContext(array("scope" => "php"));
3260
			$result = $this->CheckSilent($grant, $modifier, $path);
3261
		$this->popContext();
3262
		return $result;
3263
	}
3264
3265
	public function _checkpublic($grant, $modifier=ARTHISTYPE) {
3266
3267
		return $this->CheckPublic($grant, $modifier);
3268
	}
3269
3270
	public function _getcharset() {
3271
		return $this->getcharset();
3272
	}
3273
3274
	public function _count_find($query='') {
3275
		return $this->count_find($this->path, $query);
3276
	}
3277
3278
	public function _count_ls() {
3279
		return $this->count_ls($this->path);
3280
	}
3281
3282
	public function _HTTPRequest($method, $url, $postdata = "", $port=80) {
3283
		return $this->HTTPRequest($method, $url, $postdata, $port);
3284
	}
3285
3286
	public function _make_filesize( $size="" ,$precision=0) {
3287
		return $this->make_filesize( $size ,$precision);
3288
	}
3289
3290
	public function _convertToUTF8($data, $charset = "CP1252") {
3291
		return $this->convertToUTF8($data,$charset);
3292
	}
3293
3294
	public function _getuser() {
3295
	global $AR;
3296
		if ($AR->pinp_user && $AR->pinp_user->data->login == $AR->user->data->login) {
3297
			$user = $AR->pinp_user;
3298
		} else {
3299
			$this->pushContext(array("scope" => "php"));
3300
				if ( $AR->user instanceof ariadne_object ) {
3301
					$user = current($AR->user->get(".", "system.get.phtml"));
3302
				} else {
3303
					$user = $AR->user;
3304
				}
3305
				$AR->pinp_user = $user;
3306
			$this->popContext();
3307
		}
3308
		return $user;
3309
	}
3310
3311
	public function ARinclude($file) {
3312
		include($file);
3313
	}
3314
3315 4
	public function _load($class) {
3316
		// only allow access to modules in the modules directory.
3317 4
		$class = preg_replace('/[^a-z0-9\._]/i','',$class);
3318 4
		include_once($this->store->get_config("code")."modules/".$class);
3319 4
	}
3320
3321
	public function _import($class) {
3322
		// deprecated
3323
		return $this->_load($class);
3324
	}
3325
3326 52
	public function html_to_text($text) {
3327 52
		$trans = array_flip(get_html_translation_table(HTML_ENTITIES));
3328 52
		$cb  = function($matches) use ($trans) {
3329
			return strtr($matches[1],$trans);
3330 52
		};
3331
		//strip nonbreaking space, strip script and style blocks, strip html tags, convert html entites, strip extra white space
3332 52
		$search_clean = array("%&nbsp;%i", "%<(script|style)[^>]*>.*?<\/(script|style)[^>]*>%si", "%<[\/]*[^<>]*>%Usi", "%\s+%");
3333 52
		$replace_clean = array(" ", " ", " ", " ");
3334
3335 52
		$text = preg_replace_callback(
3336 52
			"%(\&[a-zA-Z0-9\#]+;)%s",
3337 39
			$cb,
3338
			$text
3339 39
		);
3340 52
		$text = preg_replace($search_clean, $replace_clean, $text);
3341 52
		return $text;
3342
	}
3343
3344
	public function _html_to_text($text) {
3345
		return $this->html_to_text($text);
3346
	}
3347
3348
	public function _newobject($filename, $type) {
3349
		$newpath=$this->make_path($filename);
3350
		$newparent=$this->store->make_path($newpath, "..");
3351
		$data=new object;
3352
		$object=$this->store->newobject($newpath, $newparent, $type, $data);
3353
		$object->arIsNewObject=true;
3354
		return $object;
3355
	}
3356
3357
	public function _save($properties="", $vtype="") {
3358
		if (isset($properties) && is_array($properties)) {
3359
			// isn't this double work, the save function doesn this again
3360
			foreach ($properties as $prop_name => $prop) {
3361
				foreach ($prop as $prop_index => $prop_record) {
3362
					$record = array();
3363 View Code Duplication
					foreach ($prop_record as $prop_field => $prop_value) {
3364
						switch (gettype($prop_value)) {
3365
							case "integer":
3366
							case "boolean":
3367
							case "double":
3368
								$value = $prop_value;
3369
							break;
3370
							default:
3371
								$value = $prop_value;
3372
								if (substr($prop_value, 0, 1) === "'" && substr($prop_value, -1) === "'"
3373
										&& "'".AddSlashes(StripSlashes(substr($prop_value, 1, -1)))."'" == $prop_value) {
3374
									$value = stripSlashes(substr($prop_value,1,-1));
3375
									// todo add deprecated warning
3376
								}
3377
						}
3378
						$record[$prop_field] = $value;
3379
					}
3380
					$properties[$prop_name][$prop_index] = $record;
3381
				}
3382
			}
3383
		}
3384
3385
		if ($this->arIsNewObject && $this->CheckSilent('add', $this->type)) {
3386
			unset($this->data->config);
3387
			$result = $this->save($properties, $vtype);
0 ignored issues
show
Bug introduced by
It seems like $properties can also be of type array or null; however, ariadne_object::save() does only seem to accept string, maybe add an additional type check?

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

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

    return array();
}

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

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

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

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

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

    return array();
}

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

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

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

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
3393
	}
3394
3395
	public function _is_supported($feature) {
3396
		return $this->store->is_supported($feature);
3397
	}
3398
3399
	/*
3400
		since the preg_replace() function is able to execute normal php code
3401
		we have to intercept all preg_replace() calls and parse the
3402
		php code with the pinp parser.
3403
	*/
3404
3405
3406
	/*	this is a private function used by the _preg_replace wrapper */
3407
	// FIXME: remove this function when the minimal php version for ariadne is raised to php 7.0
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "remove this function when the minimal php version for ariadne is raised to php 7.0"
Loading history...
3408
	protected function preg_replace_compile($pattern, $replacement) {
3409
	global $AR;
3410
		include_once($this->store->get_config("code")."modules/mod_pinp.phtml");
3411
		preg_match("/^\s*(.)/", $pattern, $regs);
3412
		$delim = $regs[1];
3413
		if (@eregi("\\${delim}[^$delim]*\\${delim}.*e.*".'$', $pattern)) {
3414
			$pinp = new pinp($AR->PINP_Functions, 'local->', '$AR_this->_');
3415
			return substr($pinp->compile("<pinp>$replacement</pinp>"), 5, -2);
3416
		} else {
3417
			return $replacement;
3418
		}
3419
	}
3420
3421
	public function _preg_replace($pattern, $replacement, $text, $limit = -1) {
3422
		if (version_compare(PHP_VERSION, '7.0.0', '<')) {
3423
			if (isset($pattern) && is_array($pattern)) {
3424
				$newrepl = array();
3425
				reset($replacement);
3426
				foreach ($pattern as $i_pattern) {
3427
					list(, $i_replacement) = each($replacement);
3428
					$newrepl[] = $this->preg_replace_compile($i_pattern, $i_replacement);
3429
				}
3430
			} else {
3431
				$newrepl = $this->preg_replace_compile($pattern, $replacement);
3432
			}
3433
		} else {
3434
			// php7 is safe, no more eval
3435
			$newrepl = $replacement;
3436
		}
3437
		return preg_replace($pattern, $newrepl, $text, $limit);
3438
	}
3439
3440
	/* ob_start accepts a callback but we don't want that
3441
	 * this wrapper removes the arguments from the ob_start call
3442
	 */
3443
	public function _ob_start() {
3444
		return ob_start();
3445
	}
3446
3447
	public function _loadConfig($path='') {
3448
		return clone $this->loadConfig($path);
3449
	}
3450
3451
	public function _loadUserConfig($path='') {
3452
		return $this->loadUserConfig($path);
3453
	}
3454
3455
	public function _loadLibrary($name, $path) {
3456 4
		return $this->loadLibrary($name, $path);
3457
	}
3458
3459
	public function _resetConfig($path='') {
3460
		return $this->resetConfig($path);
3461
	}
3462
3463
	public function _getLibraries($path = '') {
3464
		return $this->getLibraries($path);
3465
	}
3466
3467
3468
	public function _getSetting($setting) {
3469
	global $AR;
3470
3471
		switch ($setting) {
3472
			case 'www':
3473
			case 'dir:www':
3474
				return $AR->dir->www;
3475
			case 'images':
3476
			case 'dir:images':
3477
				return $AR->dir->images;
3478
			case 'ARSessionKeyCheck':
3479
				$result = null;
3480
				if (function_exists('ldGenerateSessionKeyCheck')) {
3481
					$result = ldGenerateSessionKeyCheck();
3482
				}
3483
				return $result;
3484
			break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
3485
			case 'nls:list':
3486
				return $AR->nls->list;
3487
			break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
3488
			case 'nls:default':
3489
				return $AR->nls->default;
3490
			break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
3491
			case 'svn':
3492
				return $AR->SVN->enabled;
3493
			break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
3494
		}
3495
	}
3496
3497
	public function __call($name,$arguments) {
3498
		if ( $name[0] == '_' ) {
3499
			$fname = substr($name, 1);
3500
			if ( isset($this->{$fname}) && $this->{$fname} instanceof \Closure ) {
3501
				\Closure::bind( $this->{$fname}, $this );
3502
				return call_user_func_array( $this->{$fname}, $arguments);
3503
			}
3504
		}
3505
		switch($name) {
3506
			case "implements":
3507
				return $this->AR_implements($arguments[0]);
3508
			break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
3509
			default:
3510
				trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $name), E_USER_ERROR);
3511
				return false;
3512
			break;
3513
		}
3514
	}
3515
3516
	static public function pinpErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) {
0 ignored issues
show
Unused Code introduced by
The parameter $errfile is not used and could be removed.

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

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

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

Loading history...
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
3517 4
		global $nocache;
3518 4
		if (($errno & error_reporting()) == 0) {
3519 4
			return true;
3520
		}
3521
3522
		$nocache = true;
3523
		$context = pobject::getContext();
3524
		if ($context["arLibraryPath"]) { //  != null) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
3525
			$msg = "Error on line $errline in ".$context['arCallTemplateType'].'::'.$context['arCallFunction'] ." in library ".$context["arLibraryPath"] ."\n".$errstr."\n";
3526
		} else {
3527
			$msg = "Error on line $errline in ".$context['arCallTemplateType'].'::'.$context['arCallFunction'] ." on object ".$context['arCurrentObject']->path."\n".$errstr."\n";
3528
		}
3529
		$display = ini_get('display_errors');
3530
3531
		if($display) {
3532
			echo $msg;
3533
		}
3534
		error_log($msg);
3535
3536
		return false;
3537
	}
3538
3539
} // end of ariadne_object class definition
3540