Skip to content

Commit

Permalink
API: Add sync_blacklisted_patterns for configuring files to skip in s…
Browse files Browse the repository at this point in the history
…ync tasks

Fixes http://open.silverstripe.org/ticket/6210.

Replaces the hardcoded file patterns from Folder::syncChildren() with a new static Filesystem::$sync_blacklisted_patterns to describe files and folder names to skip when running Folder::sync().

Added unit test for Folder::sync()

Extended Folder::sync() to report on the number of file / folders skipped.
  • Loading branch information
wilr committed May 11, 2013
1 parent d6733ca commit 1a36bb6
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 5 deletions.
19 changes: 19 additions & 0 deletions filesystem/Filesystem.php
Expand Up @@ -19,8 +19,27 @@ class Filesystem extends Object {
*/
private static $folder_create_mask = 02775;

/**
* @var int
*/
protected static $cache_folderModTime;

/**
* @config
*
* Array of file / folder regex expressions to exclude from the
* {@link Filesystem::sync()}
*
* @var array
*/
private static $sync_blacklisted_patterns = array(
"/^\./",
"/^_combinedfiles$/i",
"/^_resampled$/i",
"/^web.config/i",
"/^Thumbs(.)/"
);

/**
* Create a folder on the filesystem, recursively.
* Uses {@link Filesystem::$folder_create_mask} to set filesystem permissions.
Expand Down
34 changes: 29 additions & 5 deletions filesystem/Folder.php
Expand Up @@ -80,12 +80,14 @@ public static function find_or_make($folderPath) {
}

/**
* Syncronise the file database with the actual content of the assets folder
* Synchronize the file database with the actual content of the assets
* folder.
*/
public function syncChildren() {
$parentID = (int)$this->ID; // parentID = 0 on the singleton, used as the 'root node';
$added = 0;
$deleted = 0;
$skipped = 0;

// First, merge any children that are duplicates
$duplicateChildrenNames = DB::query("SELECT \"Name\" FROM \"File\""
Expand Down Expand Up @@ -113,13 +115,15 @@ public function syncChildren() {
// We don't use DataObject so that things like subsites doesn't muck with this.
$dbChildren = DB::query("SELECT * FROM \"File\" WHERE \"ParentID\" = $parentID");
$hasDbChild = array();

if($dbChildren) {
foreach($dbChildren as $dbChild) {
$className = $dbChild['ClassName'];
if(!$className) $className = "File";
$hasDbChild[$dbChild['Name']] = new $className($dbChild);
}
}

$unwantedDbChildren = $hasDbChild;

// if we're syncing a folder with no ID, we assume we're syncing the root assets folder
Expand All @@ -135,13 +139,28 @@ public function syncChildren() {

if(file_exists($baseDir)) {
$actualChildren = scandir($baseDir);
$ignoreRules = Config::inst()->get('Filesystem', 'sync_blacklisted_patterns');

foreach($actualChildren as $actualChild) {
if($actualChild[0] == '.' || $actualChild[0] == '_' || substr($actualChild,0,6) == 'Thumbs'
|| $actualChild == 'web.config') {
if($ignoreRules) {
$skip = false;

foreach($ignoreRules as $rule) {
if(preg_match($rule, $actualChild)) {
$skip = true;

break;
}
}

if($skip) {
$skipped++;

continue;
continue;
}
}


// A record with a bad class type doesn't deserve to exist. It must be purged!
if(isset($hasDbChild[$actualChild])) {
$child = $hasDbChild[$actualChild];
Expand All @@ -166,6 +185,7 @@ public function syncChildren() {
$childResult = $child->syncChildren();
$added += $childResult['added'];
$deleted += $childResult['deleted'];
$skipped += $childResult['skipped'];
}

// Clean up the child record from memory after use. Important!
Expand All @@ -182,7 +202,11 @@ public function syncChildren() {
DB::query("DELETE FROM \"File\" WHERE \"ID\" = $this->ID");
}

return array('added' => $added, 'deleted' => $deleted);
return array(
'added' => $added,
'deleted' => $deleted,
'skipped' => $skipped
);
}

/**
Expand Down
44 changes: 44 additions & 0 deletions tests/filesystem/FolderTest.php
Expand Up @@ -293,5 +293,49 @@ public function tearDown() {

parent::tearDown();
}

public function testSyncedChildren() {
mkdir(ASSETS_PATH ."/FolderTest");
mkdir(ASSETS_PATH ."/FolderTest/sync");

$files = array(
'.htaccess',
'.git',
'web.config',
'.DS_Store',
'_my_synced_file.txt'
);

$folders = array(
'_combinedfiles',
'_resampled',
'_testsync'
);

foreach($files as $file) {
$fh = fopen(ASSETS_PATH."/FolderTest/sync/$file", "w");
fwrite($fh, 'test');
fclose($fh);
}

foreach($folders as $folder) {
mkdir(ASSETS_PATH ."/FolderTest/sync/". $folder);
}

$folder = Folder::find_or_make('/FolderTest/sync');
$result = $folder->syncChildren();

$this->assertEquals(10, $result['skipped']);
$this->assertEquals(2, $result['added']);

// folder with a path of _test should exist
$this->assertEquals(1, Folder::get()->filter(array(
'Name' => '_testsync'
))->count());

$this->assertEquals(1, File::get()->filter(array(
'Name' => '_my_synced_file.txt'
))->count());
}

}

0 comments on commit 1a36bb6

Please sign in to comment.