Merge pull request #1874 from wilr/open6210

API: Add sync_blacklisted_patterns for configuring files to skip in sync()
This commit is contained in:
Ingo Schommer 2013-05-12 15:15:23 -07:00
commit 8c02f10c03
3 changed files with 93 additions and 6 deletions

View File

@ -19,8 +19,27 @@ class Filesystem extends Object {
*/ */
private static $folder_create_mask = 02775; private static $folder_create_mask = 02775;
/**
* @var int
*/
protected static $cache_folderModTime; 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. * Create a folder on the filesystem, recursively.
* Uses {@link Filesystem::$folder_create_mask} to set filesystem permissions. * Uses {@link Filesystem::$folder_create_mask} to set filesystem permissions.

View File

@ -80,12 +80,14 @@ class Folder extends File {
} }
/** /**
* 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() { public function syncChildren() {
$parentID = (int)$this->ID; // parentID = 0 on the singleton, used as the 'root node'; $parentID = (int)$this->ID; // parentID = 0 on the singleton, used as the 'root node';
$added = 0; $added = 0;
$deleted = 0; $deleted = 0;
$skipped = 0;
// First, merge any children that are duplicates // First, merge any children that are duplicates
$duplicateChildrenNames = DB::query("SELECT \"Name\" FROM \"File\"" $duplicateChildrenNames = DB::query("SELECT \"Name\" FROM \"File\""
@ -113,6 +115,7 @@ class Folder extends File {
// We don't use DataObject so that things like subsites doesn't muck with this. // We don't use DataObject so that things like subsites doesn't muck with this.
$dbChildren = DB::query("SELECT * FROM \"File\" WHERE \"ParentID\" = $parentID"); $dbChildren = DB::query("SELECT * FROM \"File\" WHERE \"ParentID\" = $parentID");
$hasDbChild = array(); $hasDbChild = array();
if($dbChildren) { if($dbChildren) {
foreach($dbChildren as $dbChild) { foreach($dbChildren as $dbChild) {
$className = $dbChild['ClassName']; $className = $dbChild['ClassName'];
@ -120,6 +123,7 @@ class Folder extends File {
$hasDbChild[$dbChild['Name']] = new $className($dbChild); $hasDbChild[$dbChild['Name']] = new $className($dbChild);
} }
} }
$unwantedDbChildren = $hasDbChild; $unwantedDbChildren = $hasDbChild;
// if we're syncing a folder with no ID, we assume we're syncing the root assets folder // if we're syncing a folder with no ID, we assume we're syncing the root assets folder
@ -135,13 +139,28 @@ class Folder extends File {
if(file_exists($baseDir)) { if(file_exists($baseDir)) {
$actualChildren = scandir($baseDir); $actualChildren = scandir($baseDir);
foreach($actualChildren as $actualChild) { $ignoreRules = Config::inst()->get('Filesystem', 'sync_blacklisted_patterns');
if($actualChild[0] == '.' || $actualChild[0] == '_' || substr($actualChild,0,6) == 'Thumbs'
|| $actualChild == 'web.config') {
continue; foreach($actualChildren as $actualChild) {
if($ignoreRules) {
$skip = false;
foreach($ignoreRules as $rule) {
if(preg_match($rule, $actualChild)) {
$skip = true;
break;
}
}
if($skip) {
$skipped++;
continue;
}
} }
// A record with a bad class type doesn't deserve to exist. It must be purged! // A record with a bad class type doesn't deserve to exist. It must be purged!
if(isset($hasDbChild[$actualChild])) { if(isset($hasDbChild[$actualChild])) {
$child = $hasDbChild[$actualChild]; $child = $hasDbChild[$actualChild];
@ -166,6 +185,7 @@ class Folder extends File {
$childResult = $child->syncChildren(); $childResult = $child->syncChildren();
$added += $childResult['added']; $added += $childResult['added'];
$deleted += $childResult['deleted']; $deleted += $childResult['deleted'];
$skipped += $childResult['skipped'];
} }
// Clean up the child record from memory after use. Important! // Clean up the child record from memory after use. Important!
@ -182,7 +202,11 @@ class Folder extends File {
DB::query("DELETE FROM \"File\" WHERE \"ID\" = $this->ID"); DB::query("DELETE FROM \"File\" WHERE \"ID\" = $this->ID");
} }
return array('added' => $added, 'deleted' => $deleted); return array(
'added' => $added,
'deleted' => $deleted,
'skipped' => $skipped
);
} }
/** /**

View File

@ -294,4 +294,48 @@ class FolderTest extends SapphireTest {
parent::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());
}
} }