summaryrefslogtreecommitdiff
path: root/js/dojo/dojox/data/demos/stores/filestore_funcs.php
blob: ff611397407f00c2b3a2f638c38a9c9f5ba8ecd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
<?php
	/**
	 *  Helper function to convert a simple pattern to a regular expression for matching.
	 * 
	 *	Returns a regular expression object that conforms to the defined conversion rules.
	 *		For example:  
	 *		ca*   -> /^ca.*$/
	 *		*ca*  -> /^.*ca.*$/
	 *		*c\*a*  -> /^.*c\*a.*$/
	 *		*c\*a?*  -> /^.*c\*a..*$/
	 *		and so on.
	 *
	 * @param pattern: string
	 *		A simple matching pattern to convert that follows basic rules:
	 *			* Means match anything, so ca* means match anything starting with ca
	 *			? Means match single character.  So, b?b will match to bob and bab, and so on.
	 *      	\ is an escape character.  So for example, \* means do not treat * as a match, but literal character *.
	 *  			To use a \ as a character in the string, it must be escaped.  So in the pattern it should be 
	 *				represented by \\ to be treated as an ordinary \ character instead of an escape.
	 */
	function patternToRegExp(/*String*/$pattern){
		$rxp = "^";
		$c = "";
		$len = strlen($pattern);
		for ($i = 0; $i < $len; $i++) {
			$c = $pattern[$i];
			switch ($c) {
				case '\\':
					$rxp = $rxp.$c;
					$i++;
					$rxp = $rxp.$pattern[$i];
					break;
				case '*':
					$rxp = $rxp.".*"; break;
				case '?':
					$rxp = $rxp."."; break;
				case '$':
				case '^':
				case '/':
				case '+':
				case '.':
				case '|':
				case '(':
				case ')':
				case '{':
				case '}':
				case '[':
				case ']':
					$rxp = $rxp."\\"; //fallthrough
				default:
					$rxp = $rxp.$c;
			}
		}
		return "(".$rxp."$)";
	}

	/**
	 * Function to load all file info from a particular directory.
	 *
	 * @param $dir The dir to seach from, relative to $rootDir.
	 * @param $rootDir The directory where the file service is rooted, used as separate var to allow easier checking and prevention of ../ing out of the tree.
	 * @param $recurse Whether or not to deep scan the dir and return all subfiles, or just return the toplevel files.
	 * @param $dirsOnly boolean to enote to only return directory names, not filenames.
	 * @param $expand boolean to indicate whether or not to inflate all children files along a path/file, or leave them as stubs.
	 * @param $showHiddenFiles boolean to indicate to return hidden files as part of the list.
	 */
	function getAllfiles($dir, $rootDir, $recurse, $dirsOnly, $expand, $showHiddenFiles) { 
		//  summary:
		//      A function to obtain all the files in a particular directory (file or dir)
		$files = array();
		$dirHandle = opendir($rootDir."/".$dir);
		if ($dirHandle) {
			while($file = readdir($dirHandle)) {
				if ($file) {
					if ($file != ".." && $file != ".") {
						$path = $dir."/".$file;
						$fileObj = generateFileObj($file, $dir, $rootDir,$expand,$showHiddenFiles);
						if (is_dir($rootDir."/".$path)) {
							if ($recurse) {
								if ($showHiddenFiles || $fileObj["name"][0] != '.') {
									$subfiles = getAllfiles($path,$rootDir,$recurse,$dirsOnly,$expand,$showHiddenFiles);
									$length = count($subfiles);
									for ($i = 0; $i < $length; $i++) {
										$files[] = $subfiles[$i];
									}
								}
							}
						}
						if (!$dirsOnly || $fileObj["directory"]) {
							if ($showHiddenFiles || $fileObj["name"][0] !== '.') {
								$files[] = $fileObj;
							}
						}
					}
				}
			}
		}
		closedir($dirHandle);
		return $files;
	}

	/** 
	 * Function to generate an associative map of data about a specific file.
	 * @param $file The name of the file this object represents.
	 * @param $dir The sub-path that contains the file defined by $file
	 * @param $rootDir The directory from which to append dir and name to get the full path to the file.
	 * @param $expand boolean to denote that if the file is a directory, expand all children in the children attribute 
	 *        to a a full object
	 * @param $showHiddenFiles boolean to denote if hidden files should be shown in-view or not.
	 *
	 * @return Associative Map.   The details about the file:
	 *  $file["name"] - Returns the shortname of the file.
	 *  $file["parentDir"] - Returns the relative path from the service root for the parent directory containing file $file["name"]
	 *  $file["path"] - The relative path to the file.
	 *  $file["directory"] - Boolean indicator if the file represents a directory.
	 *  $file["size"] - The size of the file, in bytes.
	 *  $file["modified] - The modified date of the file in milliseconds since Jan 1st, 1970.
	 *  $file["children"] - Children files of a directory.  Empty if a standard file.
	 */
	function generateFileObj($file, $dir, $rootDir, $expand, $showHiddenFiles) {
		//  summary:
		//      Function to generate an object representation of a disk file.
		$path = $file;
		if ($dir != "." && $dir != "./") {
			$path = $dir."/".$file;
		}

		$fullPath = $rootDir."/".$path;

		$atts = stat($fullPath);

		$rootPath = realPath($rootDir);                                       
		$resolvedDir = realPath($rootDir."/".$dir);
		$resolvedFullPath = realPath($fullPath);

		//Try to normalize down the paths so it does a consistent return.
		if (strcmp($rootPath, $resolvedDir) === 0) {
			$dir = ".";
		} else {
			$dir = substr($resolvedDir, (strlen($rootPath) + 1), strlen($resolvedDir));
			$dir = "./".str_replace("\\","/",$dir);
		}
		if (strcmp($rootPath, $resolvedFullPath) === 0) {
			$path = ".";
		} else {
			$path = substr($resolvedFullPath, (strlen($rootPath) + 1), strlen($resolvedFullPath));
			$path = "./".str_replace("\\","/",$path);
		}

		$fObj = array();
		$fObj["name"] = $file;
		$fObj["parentDir"] = $dir;
		$fObj["path"] = $path;
		$fObj["directory"] = is_dir($fullPath);
		$fObj["size"] = filesize($fullPath);
		$fObj["modified"] = $atts[9];

		if (is_dir($fullPath)) {
			$children = array();
			$dirHandle = opendir($fullPath);
			while($cFile = readdir($dirHandle)) {
				if ($cFile) {
					if ($cFile != ".." && $cFile != ".") {
						if ($showHiddenFiles || $cFile[0] != '.') {
							if (!$expand) {
								$children[] = $cFile;
							}else{
								$children[] = generateFileObj($cFile, $path, $rootDir, $expand, $showHiddenFiles);
							}
						}
					}
				}
			}
			closedir($dirHandle);
			$fObj["children"] = $children;
		}
		return $fObj;
	}

	/**
	 * A field comparator class, whose role it is to define which fields on an associaive map to compare on
	 * and provide the comparison function to do so.
	 */
	class FieldComparator {
		var $field;
		var $descending = false;

		/**
		 * Constructor.
		 * @param $f The field of the item to compare.
		 * @param $d Parameter denoting whether it should be ascending or descending.  Default is ascending.
		 */
		function FieldComparator($f, $d) {
			$this->field = $f;
			$this->descending = $d;
		}

		/**
		 * Function to compare file objects A and B on the field defined by $this->field.
		 * @param $fileA The first file to compare.
		 * @param #fileB The second file to compare.
		 */
		function compare($fileA,$fileB){
			$f = $this->field;
			$a = $fileA[$f];
			$b = $fileB[$f];

			$ret = 0;
			if (is_string($a) && is_string($b)) {
				$ret = strcmp($a,$b);
			} else if($a > $b || $a === null){
				$ret = 1;
			}else if($a < $b || $b === null){
				$ret = -1;
			}

			if (property_exists($this, "descending") && $this->descending == true) {
				$ret = $ret * -1;
			}

			if ($ret > 0) {
				$ret = 1;
			} else if ($ret < 0) {
				$ret = -1;
			}
			return $ret; //int, {-1,0,1}
		}
	}

	/**
	 * A compound comparator class, whose role it is to sequentially call a set of comparators on two objects and 
	 * return the combined result of the comparison.
	 */
	class CompoundComparator {
		//Comparator chain.
		var $comparators = array();

		/**
		 * Function to compare two objects $a and $b, using the chain of comparators.
		 * @param $a The first object to compare.  
		 * @param $b The second object to compare.
		 * @returns -1, 0, 1.  -1 if a < b, 1 if a > b, and 0 if a = b.
		 */
		function compare($a, $b) {
			$ret = 0;
			$size = count($this->comparators);
			for ($i = 0; $i < $size; $i++) {
				$comp = $this->comparators[$i];
				$ret = $comp->compare($a, $b);
				if ($ret != 0) {
					break;
				}
			}
			return $ret;
		}

		/**
		 * Function to add a comparator to the chain.
		 * @param $comp The comparator to add.
		 */
		function addComparator($comp){
			$this->comparators[] = $comp;
		}
	}

	/**
	 * A function to create a Comparator class with chained comparators based off the sort specification passed into the store.
	 * @param $sortSpec The Sort specification, which is an array of sort objects containing ( attribute: "someStr": descending: true|fase}
	 * @returns The constructed comparator.
	 */
	function createComparator($sortSpec) {
		//Function to construct the class that handles chained comparisons.
		$comparator = new CompoundComparator();
		$size = count($sortSpec);
		for ($i = 0; $i < $size; $i++) {
			$sort = $sortSpec[$i];
			$desc = false;
			if(property_exists($sort, "descending")){
				$desc = $sort->descending;
			}
			$fileComp = new FieldComparator($sort->attribute,$desc);
			$comparator->addComparator($fileComp);
		}
		return $comparator;
	}

	/**
	 * Function to match a set of queries against a directory and possibly all subfiles.
	 * @param query The Query send in to process and test against.
	 * @param patterns The set of regexp patterns generated off the query.
	 * @param dir the directory to search in.
	 * @param recurse Whether or not to recurse into subdirs and test files there too.
	 *
	 * @return Array.  Returns an array of all matches of the query.
	 */
	function matchFiles($query, $patterns, $ignoreCase, $dir, $rootDir, $recurse, $dirsOnly, $expand, $showHiddenFiles) {
		$files = array();
		$fullDir = $rootDir."/".$dir;

		if ($fullDir != null && is_dir($fullDir)) {

			$dirHandle = opendir($fullDir);
			while ($file = readdir($dirHandle)) {
				if ($file != "." && $file != "..") {
					$item = generateFileObj($file, $dir, $rootDir, $expand,$showHiddenFiles);
					$keys = array_keys($patterns);
					$total = count($keys);
					for ($i = 0; $i < $total; $i++) {
						$key = $keys[$i];
						$pattern = $query[$key];
						$matched = containsValue($item,$key,$query[$key],$patterns[$key], $ignoreCase);
						if (!$matched) {
							break;
						}
					}
					if ($matched) {
						if (!$dirsOnly || $item["directory"]) {
							if ($showHiddenFiles || $item["name"][0] != '.') {
								$files[] = $item;
							}
						}
					}

					if (is_dir($rootDir."/".$item["path"]) && $recurse) {
						if ($showHiddenFiles || $item["name"][0] != '.') {
							$files = array_merge($files, matchFiles($query, $patterns, $ignoreCase, $item["path"], $rootDir, $recurse, $dirsOnly, $expand, $showHiddenFiles));
						}
					}
				}
			}
			closedir($dirHandle);
		}
		return $files;
	}

	/**
	 * Function to handle comparing the value of an attribute on a file item.
	 * @param item  The item to examine.
	 * @param attr The attribute of the tem to examine.
	 * @parma value The value to compare it to.
	 * @param rExp A regular Expression pattern object generated off 'value' if any.
	 * 
	 * @returns boolean denoting if the value was matched or not.
	 */
	function containsValue($item, $attr, $value, $rExp, $ignoreCase) {
		$matched = false;
		$possibleValue = $item[$attr];
		if ($possibleValue === null && $value === null) {
			$matched = true;
		} else {
			if ($rExp != null && is_string($possibleValue)) {
				if ($ignoreCase) {
					$matched = eregi($rExp, $possibleValue);
				} else {
					$matched = ereg($rExp, $possibleValue);
				}

			} else {
				if ($value != null && $possibleValue != null) {
					$matched = ($value == $possibleValue);
				}
			}
		}              
		return $matched;
	}
// No closing PHP tag on purpose.  Do not want it to print whitepace and thus not allow setting headers later.