Completed
Pull Request — master (#86)
by Robbert
14:09
created

store::purge()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 1
ccs 0
cts 0
cp 0
nc 1
1
<?php
2
/******************************************************************************
3
  Generic Store 1.0						Ariadne
4
5
  Copyright (C) 1998-2005  Muze
6
7
  This program is free software; you can redistribute it and/or
8
  modify it under the terms of the GNU General Public License
9
  as published by the Free Software Foundation; either version 2
10
  of the License, or (at your option) any later version.
11
12
  This program is distributed in the hope that it will be useful,
13
  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
  GNU General Public License for more details.
16
17
  You should have received a copy of the GNU General Public License
18
  along with this program; if not, write to the Free Software
19
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21
  --------------------------------------------------------------------------
22
23
  This Is a Generic implementation of the store, all generic functions are defined here
24
25
  the implemented functions are
26
27
	function get_config($field)
28
	function is_supported($feature)
29
	function newobject($path, $parent, $type, $data, $id=0, $lastchanged=0, $vtype="", $size=0, $priority=0)
30
	function close()
31
	function make_path($curr_dir, $path)
32
	function save_properties($properties, $id)
33
	function get_filestore($name)
34
35
*******************************************************************************/
36
37
38
abstract class store {
39
40
	public $error;
41
	public $root;
42
	public $rootoptions;
43
	public $mod_lock;
44
	public $total;
45
	protected $code;
46
	protected $files;
47
	protected $_filestores;
48
	protected $config;
49
50
51
52
	public function __construct($path, $config) {
0 ignored issues
show
Unused Code introduced by
The parameter $path 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 $config 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...
53
		echo "You have not configured the store properly. Please check your configuration files.";
54
		exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method __construct() 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...
55
	}
56
57
	/*  abstract functions
58
		 need implementation in your implementation of this store
59
	*/
60
61
	public abstract function call($template, $args, $objects);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
62
63
	public abstract function count($objects);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
64
65
	public abstract function info($objects);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
66
67
	public abstract function get($path);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
68
	/**********************************************************************************
69
	 This function takes as argument a path to an object in the store and will retrieve
70
	 all the necessary data and return this in the objectlist type needed for
71
	 store->call(). If the requested path does not exist, it will retrieve the object
72
	 with the longest matching path.
73
74
	 $path should always start and end with a '/'.
75
	 **********************************************************************************/
76
77
	public abstract function touch($id, $timestamp = -1);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
78
	/**********************************************************************************
79
	 This function takes as argument a path to an object (or id of an object)
80
     in the store and will set the timestamp to $timestamp.
81
82
	 $path should always start and end with a '/'.
83
	 **********************************************************************************/
84
85
	public abstract function ls($path);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
86
	/**********************************************************************************
87
	 This function takes as argument a path to an object in the store and will retrieve
88
	 all the objects and their data which have this object as their parent. It will
89
	 then return this in the objectlist type needed for store->call(). If the requested
90
	 path does not exist, it will retrieve the object with the longest matching path.
91
92
	 $path should always start and end with a '/'.
93
	 **********************************************************************************/
94
95
	public abstract function parents($path, $top="/");
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
96
	/**********************************************************************************
97
	 This function takes as argument a path to an object in the store. It will return
98
	 all objects with a path which is a substring of the given path. The resulsts are
99
	 ordered by path (length), shortest paths first.
100
	 In effect all parents of an object in the tree are called, in order, starting at
101
	 the root.
102
103
	 $path should always start and end with a '/'.
104
	 **********************************************************************************/
105
106
	public abstract function find($path, $criteria, $limit=100, $offset=0);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
107
	/**********************************************************************************
108
	 This function takes as arguments a path to an object in the store and some search
109
	 criteria. It will search for all matching objects under the given path. If the
110
	 given path is not in this store but in a substore it will not automatically search
111
	 that substore.
112
113
	 $criteria is of the form
114
115
	 $criteria ::= ({ $property_name => ({ $valuename => ({ $compare_function, $value }) }) })
116
117
	 e.g.: $criteria["status"]["value"][">"]="published";
118
119
	 $path should always start and end with a '/'.
120
121
	 **********************************************************************************/
122
123
124
	public abstract function save($path, $type, $data, $properties="", $vtype="", $priority=false);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
125
	/***************************************************************
126
		This function takes as argument a path, type, objectdata and
127
		possibly a properties list and vtype (virtual type).
128
		If there exists no object with the given path, a new object is
129
		saved with the given type, data, properties and vtype, and a
130
		new path is saved pointing to it.
131
		If there does exist an object with the given path, it's object
132
		data is overwritten with the given data and if vtype is set the
133
		current vtype is overwritten with the new one.
134
135
		$path must be an absolute path (containing no '..' and starting
136
			with '/')
137
		$type must be a valid type
138
		$data can be any string (usually a serialized object.)
139
		$properties is a multidimensional hash of the following form:
140
			$properties[{property_name}][][{value_name}]={value}
141
			{property_name} must be a valid property name
142
			{value_name} must be a valid value name for this property
143
			{value} can be a number, boolean or string.
144
		example:
145
			$properties["name"][0]["value"]="A name";
146
			$properties["name"][1]["value"]="A second name!";
147
		if $properties["name"]=1 then all properties for property name
148
			will be removed.
149
150
		$vtype must be a valid type.
151
152
		if $properties or $vtype are not set or empty ("",0 or false)
153
		they will be ignored. $vtype defaults to $type.
154
		Only those properties listed in $properties will be updated.
155
		Any other property set will remain as it was.
156
	***************************************************************/
157
158
159
	protected abstract function purge($path);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
160
	/**********************************************************************
161
		This function will delete the object pointed to by $path and all
162
	other paths pointing to that object. It will then remove any property
163
	for this object from all property tables.
164
		The function returns the number of paths found and removed or 1 if
165
	there was no path found (meaning that the object doesn't exist and
166
	therefor purge succeeded while doing nothing.)
167
168
	 $path should always start and end with a '/'.
169
	**********************************************************************/
170
171
	public abstract function delete($path);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
172
	/**********************************************************************
173
		This function deletes the path given. If this is the last path pointing
174
	to an object, the object will be purged instead.
175
176
	$path should always start and end with a '/'.
177
	**********************************************************************/
178
179
	abstract function exists($path);
180
	/**********************************************************************
181
		This function checks the given path to see if it exists. If it does
182
	it returns the id of the object to which it points. Otherwise it returns
183
	0.
184
185
	$path should always start and end with a '/'.
186
	**********************************************************************/
187
188
189
	public abstract function link($source, $destination);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
190
	/**********************************************************************
191
		Link adds an extra path to an already existing object. It has two
192
	arguments: $source and $destination. $source is an existing path of
193
	an object, $destination is the new path. $destination must not already
194
	exist.
195
196
	$destination should always start and end with a '/'.
197
	**********************************************************************/
198
199
	public abstract function move($source, $destination);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
200
	/**********************************************************************
201
	$destination should always start and end with a '/'.
202
	**********************************************************************/
203
204
205
	public abstract function list_paths($path);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
206
	/**********************************************************************
207
		This function returns an array of all paths pointing to the same object
208
	as $path does.
209
	**********************************************************************/
210
211
	public abstract function AR_implements($type, $implements);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
212
	/**********************************************************************
213
		This function returns 1 if the $type implements the type or
214
	interface in $implements. Otherwise it returns 0.
215
	**********************************************************************/
216
217
	public abstract function load_properties($object, $values="");
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
218
219
	public abstract function load_property($object, $property, $values="");
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
220
221
	public abstract function add_property($object, $property, $values);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
222
223
	public abstract function del_property($object, $property="", $values="");
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
224
225
	protected abstract function get_nextid($path, $mask="{5:id}");
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
226
	/**********************************************************************
227
		'private' function of mysql store. This will return the next
228
		'autoid' for $path.
229
	**********************************************************************/
230
231
232
233
	/*
234
		Implemented functions
235
	*/
236
237 184
	public function get_config($field) {
238
		switch ($field) {
239 184
			case 'code':
240 184
			case 'files':
241 184
			case 'root':
242 184
			case 'rootoptions':
243 184
				$result = $this->$field;
244 184
				break;
245
			default:
246
				$result =  null;
247
				debug("store::get_config: undefined field $field requested","store");
248
				break;
249
		}
250 184
		return $result;
251
	}
252
253 60
	public function is_supported($feature) {
254
	/**********************************************************************************
255
		This function takes as argument a feature description and returns
256
		true if this feature is supported and false otherwise
257
	**********************************************************************************/
258 60
		$result = false;
259
		switch($feature) {
260
			// features depending on config values
261 60
			case 'fulltext_boolean':
262 60
			case 'fulltext':
263 48
				if ($this->config[$feature]) {
264 48
					$result = true;
265 48
				} else {
266
					$result = false;
267
				}
268 48
			break;
269
			// features depending store implementation, if stores don't implements this, they have to override this function
270 60
			case 'grants':
271 60
			case 'regexp':
272 60
				$result = true;
273 60
			break;
274
		}
275 60
		return $result;
276
	}
277
278
	/**********************************************************************************
279
		This functions creates a new ariadne object
280
	**********************************************************************************/
281 184
	public function newobject($path, $parent, $type, $data, $id=0, $lastchanged=0, $vtype="", $size=0, $priority=0) {
282 184
		global $ARnls;
283 184
		$class = $type;
284 184
		if ($subcpos = strpos($type, '.')) {
285 24
			$class = substr($type, 0, $subcpos);
286 24
			$vtype = $class;
287 24
		}
288 184
		if (!class_exists($class)) {
289
			include_once($this->code."objects/".$class.".phtml");
290
		}
291 184
		$object=new $class;
292 184
		$object->type=$type;
293 184
		$object->parent=$parent;
294 184
		$object->id=(int)$id;
295 184
		$object->lastchanged=(int)$lastchanged;
296 184
		$object->vtype=$vtype;
297 184
		$object->size=(int)$size;
298 184
		$object->priority=(int)$priority;
299 184
		$object->ARnls = $ARnls;
300 184
		$object->init($this, $path, $data);
301 184
		return $object;
302
	}
303
304 104
	public function close() {
305
		// This is the destructor function, nothing much to see :)
306 104
		if (is_array($this->_filestores)) {
307
			foreach ($this->_filestores as $filestore) {
308
				$filestore->close();
309
			}
310
		}
311 104
	}
312
313 104
	public function __destruct() {
314 104
		$this->close();
315 104
	}
316
317 112 View Code Duplication
	public function make_path($curr_dir, $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...
318
	/**********************************************************************
319
		This function creates an absolute path from the given starting path
320
	($curr_dir) and a relative (or absolute) path ($path). If $path starts
321
	with a '/' $curr_dir is ignored.
322
	$path must be a string of substrings seperated by '/'. each of these
323
	substrings may consist of charachters and/or numbers. If a substring
324
	is "..", it and the previuos substring will be removed. If a substring
325
	is "." or "", it is removed. All other substrings are then concatenated
326
	with a '/' between them and at the start and the end. This string is
327
	then returned.
328
	**********************************************************************/
329 112
		$this->error = "";
330 112
		$result = "/";
331 112
		if ($path[0] === "/") {
332 108
			$path = substr($path, 1);
333 108
		} else {
334 88
			$path = substr($curr_dir, 1).'/'.$path;
335
		}
336 112
		if ($path) {
337 112
			$splitpath=explode("/", $path);
338 112
			foreach ($splitpath as $pathticle) {
339
				switch($pathticle) {
340 112
					case ".." :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
341 84
						$result = dirname($result);
342
						// if second char of $result is not set, then current result is the rootNode
343 84
						if (isset($result[1])) {
344 84
							$result .= "/";
345 84
						}
346 84
						$result[0] = "/"; // make sure that even under windows, slashes are always forward slashes.
347 84
					break;
348 112
					case "." : break;
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
349 112
					case ""	 : break;
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
350 112
					default:
351 112
						$result .= $pathticle."/";
352 112
					break;
353 112
				}
354 112
			}
355 112
		}
356 112
		return $result;
357
	}
358
359 68
	public function save_properties($properties, $id) {
360
	/********************************************************************
361
		'private' function of mysql.phtml. It updates all property tables
362
		defined in $properties and sets the values to the values in
363
		$properties.
364
	********************************************************************/
365
366 68
		if ($properties && (is_array($properties)) && (is_numeric($id))) {
367 48
			foreach ( $properties as $property => $property_set ) {
368 48
				$this->del_property((int)$id, $property);
369 48
				if (is_array($property_set)) {
370 48
					foreach ( $property_set as $values ) {
371 48
						$this->add_property((int)$id, $property, $values);
372 48
					}
373 48
				}
374 48
			}
375 48
		}
376 68
	}
377
378
379 104
	public function get_filestore($name) {
380 104
		global $AR;
381 104
		if (!$this->_filestores[$name]) {
382 104
			if ($AR->SVN->enabled && ($name == "templates")) {
383
				require_once($this->code."modules/mod_filestore_svn.phtml");
384
				$this->_filestores[$name]=new filestore_svn($name, $this->files, $this);
385
			} else {
386 104
				require_once($this->code."modules/mod_filestore.phtml");
387 104
				$this->_filestores[$name]=new filestore($name, $this->files, $this);
388
			}
389 104
		}
390 104
		return $this->_filestores[$name];
391
	}
392
393 28
	public function get_filestore_svn($name) {
394 28
		require_once($this->code."modules/mod_filestore_svn.phtml");
395 28
		if (!$this->_filestores["svn_" . $name]) {
396 28
			$this->_filestores["svn_" . $name] = new filestore_svn($name, $this->files, $this);
397 28
		}
398 28
		return $this->_filestores["svn_" . $name];
399
	}
400
401 188
	protected function compilerFactory(){
402 188
		switch($this->config["dbms"]){
403 188
			case 'axstore':
404
				return false;
405 188
			default:
406 188
				$compiler = $this->config["dbms"].'_compiler';
407 188
				return new $compiler($this,$this->tbl_prefix);
0 ignored issues
show
Bug introduced by
The property tbl_prefix 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...
408 188
		}
409
	}
410
411 34
	protected function serialize($value, $path) {
412 34
		if ($value->failedDecrypt && $value->originalData) {
413
			$value = $value->originalData;
414
			return $value;
415
		}
416
417
		// Notice: When upgrading to a new crypto format, prepend the object data with a key of the crypto. This way you can be backwards compatible but new objects will be saved in the new crypto.
418 34
		if ($this->config['crypto'] instanceof \Closure) {
419
			$crypto = $this->config['crypto']();
420
			// use the last crypto configured;
421
			$cryptoConfig = end($crypto);
422
			if (is_array($cryptoConfig['paths'])) {
423
				foreach ($cryptoConfig['paths'] as $cryptoPath) {
424
					if (strpos($path, $cryptoPath) === 0) {
425
						$value->ARcrypted = true;
426
						switch ($cryptoConfig['method']) {
427
							case 'ar_crypt':
428
								$key = base64_decode($cryptoConfig['key']);
429
								$crypto = new ar_crypt($key,$cryptoConfig['crypto'],1);
430
								$cryptedValue = $crypto->crypt(serialize($value));
431
								if($cryptedValue !== false ) {
432
									return $cryptoConfig['token'] . ":" . $cryptedValue;
433
								}
434
							break;
435
							default:
436
							break;
437
						}
438
439
					}
440
				}
441
			}
442
		}
443 34
		unset($value->ARcrypted);
444 34
		return serialize($value);
445
	}
446
447 184
	protected function unserialize($value, $path) {
0 ignored issues
show
Unused Code introduced by
The parameter $path 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...
448 184
		if (substr($value, 0, 2) == "O:") {
449 184
			return unserialize($value);
450
		} else if ($this->config['crypto'] instanceof \Closure) {
451
			$crypto = $this->config['crypto']();
452
			foreach ($crypto as $cryptoConfig) {
453
				$cryptoToken = $cryptoConfig['token'];
454
				if (substr($value, 0, strlen($cryptoToken)+1) == ($cryptoToken . ":")) {
455
					$value = substr($value, strlen($cryptoToken)+1);
456
					switch ($cryptoConfig['method']) {
457
						case 'ar_crypt':
458
							$key = base64_decode($cryptoConfig['key']);
459
							$crypto = new ar_crypt($key,$cryptoConfig['crypto'],1);
460
							$decryptedValue =  $crypto->decrypt($value);
461
						break;
462
						default:
463
						break;
464
					}
465
				}
466
			}
467
468
			if (substr($decryptedValue, 0, 2) == "O:") {
469
				return unserialize($decryptedValue);
0 ignored issues
show
Bug introduced by
The variable $decryptedValue 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...
470
			} else {
471
				$dummy = unserialize('O:6:"object":7:{s:5:"value";s:0:"";s:3:"nls";O:6:"object":2:{s:7:"default";s:2:"nl";s:4:"list";a:1:{s:2:"nl";s:10:"Nederlands";}}s:2:"nl";O:6:"object":1:{s:4:"name";s:14:"Crypted object";}s:6:"config";O:6:"object":2:{s:10:"owner_name";s:6:"Nobody";s:5:"owner";s:6:"nobody";}s:5:"mtime";i:0;s:5:"ctime";i:0;s:5:"muser";s:6:"nobody";}');
472
				$dummy->failedDecrypt = true;
473
				$dummy->originalData = $value;
474
				return $dummy;
475
			}
476
		}
477
	}
478
479
} 
480