Completed
Push — new-committers ( 29cb6f...bcba16 )
by Sam
12:18 queued 33s
created

Folder::getTitle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/**
3
 * Represents a folder in the assets/ directory.
4
 * The folder path is stored in the "Filename" property.
5
 *
6
 * Updating the "Name" or "Filename" properties on
7
 * a folder object also updates all associated children
8
 * (both {@link File} and {@link Folder} records).
9
 *
10
 * Deleting a folder will also remove the folder from the filesystem,
11
 * including any subfolders and contained files. Use {@link deleteDatabaseOnly()}
12
 * to avoid touching the filesystem.
13
 *
14
 * See {@link File} documentation for more details about the
15
 * relationship between the database and filesystem in the SilverStripe file APIs.
16
 *
17
 * @package framework
18
 * @subpackage filesystem
19
 */
20
class Folder extends File {
21
22
	private static $singular_name = "Folder";
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
23
24
	private static $plural_name = "Folders";
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
25
26
	private static $default_sort = "\"Name\"";
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
27
28
	/**
29
	 *
30
	 */
31
	public function populateDefaults() {
32
		parent::populateDefaults();
33
34
		if(!$this->Name) $this->Name = _t('AssetAdmin.NEWFOLDER',"NewFolder");
35
	}
36
37
	/**
38
	 * Find the given folder or create it both as {@link Folder} database records
39
	 * and on the filesystem. If necessary, creates parent folders as well. If it's
40
	 * unable to find or make the folder, it will return null (as /assets is unable
41
	 * to be represented by a Folder DataObject)
42
	 *
43
	 * @param $folderPath string Absolute or relative path to the file.
44
	 *  If path is relative, its interpreted relative to the "assets/" directory.
45
	 * @return Folder|null
46
	 */
47
	public static function find_or_make($folderPath) {
48
		// Create assets directory, if it is missing
49
		if(!file_exists(ASSETS_PATH)) Filesystem::makeFolder(ASSETS_PATH);
50
51
		$folderPath = trim(Director::makeRelative($folderPath));
52
		// replace leading and trailing slashes
53
		$folderPath = preg_replace('/^\/?(.*)\/?$/', '$1', $folderPath);
54
		$parts = explode("/",$folderPath);
55
56
		$parentID = 0;
57
		$item = null;
58
		$filter = FileNameFilter::create();
59
		foreach($parts as $part) {
60
			if(!$part) continue; // happens for paths with a trailing slash
61
62
			// Ensure search includes folders with illegal characters removed, but
63
			// err in favour of matching existing folders if $folderPath
64
			// includes illegal characters itself.
65
			$partSafe = $filter->filter($part);
66
			$item = Folder::get()->filter(array(
67
				'ParentID' => $parentID,
68
				'Name' => array($partSafe, $part)
69
			))->first();
70
71
			if(!$item) {
72
				$item = new Folder();
73
				$item->ParentID = $parentID;
74
				$item->Name = $partSafe;
75
				$item->Title = $part;
76
				$item->write();
77
			}
78
			if(!file_exists($item->getFullPath())) {
79
				Filesystem::makeFolder($item->getFullPath());
80
			}
81
			$parentID = $item->ID;
82
		}
83
84
		return $item;
85
	}
86
87
	/**
88
	 * Synchronize the file database with the actual content of the assets
89
	 * folder.
90
	 */
91
	public function syncChildren() {
92
		$parentID = (int)$this->ID; // parentID = 0 on the singleton, used as the 'root node';
93
		$added = 0;
94
		$deleted = 0;
95
		$skipped = 0;
96
97
		// First, merge any children that are duplicates
98
		$duplicateChildrenNames = DB::prepared_query(
99
			'SELECT "Name" FROM "File" WHERE "ParentID" = ? GROUP BY "Name" HAVING count(*) > 1',
100
			array($parentID)
101
		)->column();
102
		if($duplicateChildrenNames) foreach($duplicateChildrenNames as $childName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $duplicateChildrenNames of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
103
			// Note, we do this in the database rather than object-model; otherwise we get all sorts of problems
104
			// about deleting files
105
			$children = DB::prepared_query(
106
				'SELECT "ID" FROM "File" WHERE "Name" = ? AND "ParentID" = ?',
107
				array($childName, $parentID)
108
			)->column();
109
			if($children) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $children of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
110
				$keptChild = array_shift($children);
111
				foreach($children as $removedChild) {
112
					DB::prepared_query('UPDATE "File" SET "ParentID" = ? WHERE "ParentID" = ?',
113
										array($keptChild, $removedChild));
114
					DB::prepared_query('DELETE FROM "File" WHERE "ID" = ?', array($removedChild));
115
				}
116
			} else {
117
				user_error("Inconsistent database issue: SELECT ID FROM \"File\" WHERE Name = '$childName'"
118
					. " AND ParentID = $parentID should have returned data", E_USER_WARNING);
119
			}
120
		}
121
122
123
		// Get index of database content
124
		// We don't use DataObject so that things like subsites doesn't muck with this.
125
		$dbChildren = DB::prepared_query('SELECT * FROM "File" WHERE "ParentID" = ?', array($parentID));
126
		$hasDbChild = array();
127
128
		if($dbChildren) {
129
			foreach($dbChildren as $dbChild) {
130
				$className = $dbChild['ClassName'];
131
				if(!$className) $className = "File";
132
				$hasDbChild[$dbChild['Name']] = new $className($dbChild);
133
			}
134
		}
135
136
		$unwantedDbChildren = $hasDbChild;
137
138
		// if we're syncing a folder with no ID, we assume we're syncing the root assets folder
139
		// however the Filename field is populated with "NewFolder", so we need to set this to empty
140
		// to satisfy the baseDir variable below, which is the root folder to scan for new files in
141
		if(!$parentID) $this->Filename = '';
142
143
		// Iterate through the actual children, correcting the database as necessary
144
		$baseDir = $this->FullPath;
0 ignored issues
show
Documentation introduced by
The property FullPath does not exist on object<Folder>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
145
146
		// @todo this shouldn't call die() but log instead
147
		if($parentID && !$this->Filename) die($this->ID . " - " . $this->FullPath);
148
149
		if(file_exists($baseDir)) {
150
			$actualChildren = scandir($baseDir);
151
			$ignoreRules = Filesystem::config()->sync_blacklisted_patterns;
0 ignored issues
show
Documentation introduced by
The property sync_blacklisted_patterns does not exist on object<Config_ForClass>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
152
			$allowedExtensions = File::config()->allowed_extensions;
0 ignored issues
show
Documentation introduced by
The property allowed_extensions does not exist on object<Config_ForClass>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
153
			$checkExtensions = $this->config()->apply_restrictions_to_admin || !Permission::check('ADMIN');
154
155
			foreach($actualChildren as $actualChild) {
156
				$skip = false;
157
158
				// Check ignore patterns
159
				if($ignoreRules) foreach($ignoreRules as $rule) {
160
					if(preg_match($rule, $actualChild)) {
161
						$skip = true;
162
						break;
163
					}
164
				}
165
166
				// Check allowed extensions, unless admin users are allowed to bypass these exclusions
167
				if($checkExtensions
168
					&& ($extension = self::get_file_extension($actualChild))
169
					&& !in_array(strtolower($extension), $allowedExtensions)
170
				) {
171
					$skip = true;
172
				}
173
174
				if($skip) {
175
					$skipped++;
176
					continue;
177
				}
178
179
				// A record with a bad class type doesn't deserve to exist. It must be purged!
180
				if(isset($hasDbChild[$actualChild])) {
181
					$child = $hasDbChild[$actualChild];
182
					if(( !( $child instanceof Folder ) && is_dir($baseDir . $actualChild) )
183
					|| (( $child instanceof Folder ) && !is_dir($baseDir . $actualChild)) ) {
184
						DB::prepared_query('DELETE FROM "File" WHERE "ID" = ?', array($child->ID));
185
						unset($hasDbChild[$actualChild]);
186
					}
187
				}
188
189
				if(isset($hasDbChild[$actualChild])) {
190
					$child = $hasDbChild[$actualChild];
191
					unset($unwantedDbChildren[$actualChild]);
192
				} else {
193
					$added++;
194
					$childID = $this->constructChild($actualChild);
195
					$child = DataObject::get_by_id("File", $childID);
196
				}
197
198
				if( $child && is_dir($baseDir . $actualChild)) {
199
					$childResult = $child->syncChildren();
200
					$added += $childResult['added'];
201
					$deleted += $childResult['deleted'];
202
					$skipped += $childResult['skipped'];
203
				}
204
205
				// Clean up the child record from memory after use. Important!
206
				$child->destroy();
207
				$child = null;
0 ignored issues
show
Unused Code introduced by
$child 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...
208
			}
209
210
			// Iterate through the unwanted children, removing them all
211
			if(isset($unwantedDbChildren)) foreach($unwantedDbChildren as $unwantedDbChild) {
212
				DB::prepared_query('DELETE FROM "File" WHERE "ID" = ?', array($unwantedDbChild->ID));
213
				$deleted++;
214
			}
215
		} else {
216
			DB::prepared_query('DELETE FROM "File" WHERE "ID" = ?', array($this->ID));
217
		}
218
219
		return array(
220
			'added' => $added,
221
			'deleted' => $deleted,
222
			'skipped' => $skipped
223
		);
224
	}
225
226
	/**
227
	 * Construct a child of this Folder with the given name.
228
	 * It does this without actually using the object model, as this starts messing
229
	 * with all the data.  Rather, it does a direct database insert.
230
	 *
231
	 * @param string $name Name of the file or folder
232
	 * @return integer the ID of the newly saved File record
233
	 */
234
	public function constructChild($name) {
235
		// Determine the class name - File, Folder or Image
236
		$baseDir = $this->FullPath;
0 ignored issues
show
Documentation introduced by
The property FullPath does not exist on object<Folder>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
237
		if(is_dir($baseDir . $name)) {
238
			$className = "Folder";
239
		} else {
240
			$className = File::get_class_for_file_extension(pathinfo($name, PATHINFO_EXTENSION));
241
		}
242
243
		$ownerID = Member::currentUserID();
244
245
		$filename = $this->Filename . $name;
246
		if($className == 'Folder' ) $filename .= '/';
247
248
		$nowExpression = DB::get_conn()->now();
249
		DB::prepared_query("INSERT INTO \"File\"
250
			(\"ClassName\", \"ParentID\", \"OwnerID\", \"Name\", \"Filename\", \"Created\", \"LastEdited\", \"Title\")
251
			VALUES (?, ?, ?, ?, ?, $nowExpression, $nowExpression, ?)",
252
			array($className, $this->ID, $ownerID, $name, $filename, $name)
253
		);
254
255
		return DB::get_generated_id("File");
256
	}
257
258
	/**
259
	 * Take a file uploaded via a POST form, and save it inside this folder.
260
	 * File names are filtered through {@link FileNameFilter}, see class documentation
261
	 * on how to influence this behaviour.
262
	 */
263
	public function addUploadToFolder($tmpFile) {
264
		if(!is_array($tmpFile)) {
265
			user_error("Folder::addUploadToFolder() Not passed an array."
266
				. " Most likely, the form hasn't got the right enctype", E_USER_ERROR);
267
		}
268
		if(!isset($tmpFile['size'])) {
269
			return;
270
		}
271
272
		$base = BASE_PATH;
273
		// $parentFolder = Folder::findOrMake("Uploads");
274
275
		// Generate default filename
276
		$nameFilter = FileNameFilter::create();
277
		$file = $nameFilter->filter($tmpFile['name']);
278
		while($file[0] == '_' || $file[0] == '.') {
279
			$file = substr($file, 1);
280
		}
281
282
		$file = $this->RelativePath . $file;
283
		Filesystem::makeFolder(dirname("$base/$file"));
284
285
		$doubleBarrelledExts = array('.gz', '.bz', '.bz2');
286
287
		$ext = "";
288
		if(preg_match('/^(.*)(\.[^.]+)$/', $file, $matches)) {
289
			$file = $matches[1];
290
			$ext = $matches[2];
291
			// Special case for double-barrelled
292
			if(in_array($ext, $doubleBarrelledExts) && preg_match('/^(.*)(\.[^.]+)$/', $file, $matches)) {
293
				$file = $matches[1];
294
				$ext = $matches[2] . $ext;
295
			}
296
		}
297
		$origFile = $file;
0 ignored issues
show
Unused Code introduced by
$origFile 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...
298
299
		$i = 1;
300
		while(file_exists("$base/$file$ext")) {
301
			$i++;
302
			$oldFile = $file;
303
304
			if(strpos($file, '.') !== false) {
305
				$file = preg_replace('/[0-9]*(\.[^.]+$)/', $i . '\\1', $file);
306
			} elseif(strpos($file, '_') !== false) {
307
				$file = preg_replace('/_([^_]+$)/', '_' . $i, $file);
308
			} else {
309
				$file .= '_'.$i;
310
			}
311
312
			if($oldFile == $file && $i > 2) user_error("Couldn't fix $file$ext with $i", E_USER_ERROR);
313
		}
314
315
		if (move_uploaded_file($tmpFile['tmp_name'], "$base/$file$ext")) {
316
			// Update with the new image
317
			return $this->constructChild(basename($file . $ext));
318
		} else {
319
			if(!file_exists($tmpFile['tmp_name'])) {
320
				user_error("Folder::addUploadToFolder: '$tmpFile[tmp_name]' doesn't exist", E_USER_ERROR);
321
			} else {
322
				user_error("Folder::addUploadToFolder: Couldn't copy '$tmpFile[tmp_name]' to '$base/$file$ext'",
323
					E_USER_ERROR);
324
			}
325
			return false;
326
		}
327
	}
328
329
	protected function validate() {
330
		return new ValidationResult(true);
331
	}
332
333
	//-------------------------------------------------------------------------------------------------
334
	// Data Model Definition
335
336
	public function getRelativePath() {
337
		return parent::getRelativePath() . "/";
338
	}
339
340
	public function onBeforeDelete() {
341
		if($this->ID && ($children = $this->AllChildren())) {
342
			foreach($children as $child) {
343
				if(!$this->Filename || !$this->Name || !file_exists($this->getFullPath())) {
344
					$child->setField('Name',null);
345
					$child->Filename = null;
346
				}
347
				$child->delete();
348
			}
349
		}
350
351
		// Do this after so a folder's contents are removed before we delete the folder.
352
		if($this->Filename && $this->Name && file_exists($this->getFullPath())) {
353
			$files = glob( $this->getFullPath() . '/*' );
354
355
			if( !$files || ( count( $files ) == 1 && preg_match( '/\/_resampled$/', $files[0] ) ) )
0 ignored issues
show
Bug Best Practice introduced by
The expression $files of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
356
				Filesystem::removeFolder( $this->getFullPath() );
357
		}
358
359
		parent::onBeforeDelete();
360
	}
361
362
	/**
363
	 * Return the relative URL of an icon for this file type
364
	 *
365
	 * @return String
366
	 */
367
	public function Icon() {
368
		return FRAMEWORK_DIR . "/images/app_icons/folder_32.png";
369
	}
370
371
	/** Override setting the Title of Folders to that Name, Filename and Title are always in sync.
372
	 * Note that this is not appropriate for files, because someone might want to create a human-readable name
373
	 * of a file that is different from its name on disk. But folders should always match their name on disk. */
374
	public function setTitle($title) {
375
		$this->setName($title);
376
	}
377
378
	public function getTitle() {
379
		return $this->Name;
380
	}
381
382
	public function setName($name) {
383
		parent::setName($name);
384
		$this->setField('Title', $this->Name);
385
	}
386
387
	public function setFilename($filename) {
388
		$this->setField('Title',pathinfo($filename, PATHINFO_BASENAME));
389
		parent::setFilename($filename);
390
	}
391
392
	/**
393
	 * A folder doesn't have a (meaningful) file size.
394
	 *
395
	 * @return Null
396
	 */
397
	public function getSize() {
398
		return null;
399
	}
400
401
	/**
402
	 * Delete the database record (recursively for folders) without touching the filesystem
403
	 */
404
	public function deleteDatabaseOnly() {
405
		if($children = $this->myChildren()) {
406
			foreach($children as $child) $child->deleteDatabaseOnly();
407
		}
408
409
		parent::deleteDatabaseOnly();
410
	}
411
412
	/**
413
	 * Returns all children of this folder
414
	 *
415
	 * @return DataList
416
	 */
417
	public function myChildren() {
418
		return File::get()->filter("ParentID", $this->ID);
419
	}
420
421
	/**
422
	 * Returns true if this folder has children
423
	 *
424
	 * @return bool
425
	 */
426
	public function hasChildren() {
427
		return $this->myChildren()->exists();
428
	}
429
430
	/**
431
	 * Returns true if this folder has children
432
	 *
433
	 * @return bool
434
	 */
435
	public function hasChildFolders() {
436
		return $this->ChildFolders()->exists();
437
	}
438
439
	/**
440
	 * Overloaded to call recursively on all contained {@link File} records.
441
	 */
442
	public function updateFilesystem() {
443
		parent::updateFilesystem();
444
445
		// Note: Folders will have been renamed on the filesystem already at this point,
446
		// File->updateFilesystem() needs to take this into account.
447
		if($this->ID && ($children = $this->AllChildren())) {
448
			foreach($children as $child) {
449
				$child->updateFilesystem();
450
				$child->write();
451
			}
452
		}
453
	}
454
455
	/**
456
	 * Return the FieldList used to edit this folder in the CMS.
457
	 * You can modify this FieldList by subclassing folder, or by creating a {@link DataExtension}
458
	 * and implemeting updateCMSFields(FieldList $fields) on that extension.
459
	 */
460
	public function getCMSFields() {
461
		// Hide field on root level, which can't be renamed
462
		if(!$this->ID || $this->ID === "root") {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $this->ID (integer) and 'root' (string) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
463
			$titleField = new HiddenField("Name");
464
		} else {
465
			$titleField = new TextField("Name", $this->fieldLabel('Name'));
466
		}
467
468
		$fields = new FieldList(
469
			$titleField,
470
			new HiddenField('ParentID')
471
		);
472
		$this->extend('updateCMSFields', $fields);
473
474
		return $fields;
475
	}
476
477
	/**
478
	 * Get the children of this folder that are also folders.
479
	 *
480
	 * @return DataList
481
	 */
482
	public function ChildFolders() {
483
		return Folder::get()->filter('ParentID', $this->ID);
484
	}
485
486
	/**
487
	 * Get the number of children of this folder that are also folders.
488
	 */
489
	public function numChildFolders() {
490
		return $this->ChildFolders()->count();
491
	}
492
	/**
493
	 * @return String
494
	 */
495
	public function CMSTreeClasses() {
496
		$classes = sprintf('class-%s', $this->class);
497
498
		if(!$this->canDelete())
499
			$classes .= " nodelete";
500
501
		if(!$this->canEdit())
502
			$classes .= " disabled";
503
504
		$classes .= $this->markingClasses('numChildFolders');
505
506
		return $classes;
507
	}
508
509
	/**
510
	 * @return string
511
	 */
512
	public function getTreeTitle() {
513
		return $treeTitle = sprintf(
0 ignored issues
show
Unused Code introduced by
$treeTitle 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...
514
			"<span class=\"jstree-foldericon\"></span><span class=\"item\">%s</span>",
515
			Convert::raw2xml(str_replace(array("\n","\r"),"",$this->Title))
516
		);
517
	}
518
}
519