diff --git a/code/AssetAdmin.php b/code/AssetAdmin.php index 1d49a6fe..71be5637 100755 --- a/code/AssetAdmin.php +++ b/code/AssetAdmin.php @@ -235,8 +235,8 @@ HTML; ); $fileList->setFolder($record); $fileList->setPopupCaption("View/Edit Asset"); - - if($record) { + + if($record) { $nameField = ($id != "root") ? new TextField("Name", "Folder Name") : new HiddenField("Name"); if( $record->userCanEdit() ) { $deleteButton = new InlineFormAction('deletemarked',_t('AssetAdmin.DELSELECTED','Delete selected files'), 'delete'); @@ -265,8 +265,21 @@ HTML; new LiteralField("UploadIframe", $this->getUploadIframe() ) - ) - ), + ), + new Tab("Unused files", + new LiteralField("UnusedAssets", + "

Unused files

" + ), + $this->getAssetList(), + new LiteralField("UnusedThumbnails", + "
+
+

Unused thumbnails

+ Delete unused thumbnails +
" + ) + ) + ), new HiddenField("ID") ); @@ -668,4 +681,136 @@ JS; return parent::save($urlParams, $form); } + + /** + * ################################# + * Garbage collection. + * ################################# + */ + + /** + * Removes all unused thumbnails, and echos status message to user. + * + * @returns null + */ + + public function deleteUnusedThumbnails() { + foreach($this->getUnusedThumbnailsArray() as $file) { + unlink("../assets/" . $file); + } + echo "statusMessage('All unused thumbnails has been deleted','good')"; + } + + /** + * Looks for files used in system and create where clause which contains all ID's of files. + * + * @returns String where clause which will work as filter. + */ + + private function getUsedFilesList() { + $result = DB::query("SELECT DISTINCT FileID FROM SiteTree_ImageTracking"); + $usedFiles = array(); + $where = ""; + if($result->numRecords() > 0) { + while($nextResult = $result->next()){ + $where .= $nextResult['FileID'] . ','; + } + } + $classes = ClassInfo::subclassesFor('SiteTree'); + foreach($classes as $className) { + $sng = singleton($className); + $objects = DataObject::get($className); + if($objects !== NULL) { + foreach($sng->has_one() as $fieldName => $joinClass) { + if($joinClass == 'Image' || $joinClass == 'File') { + foreach($objects as $object) { + if($object->$fieldName != NULL) $usedFiles[] = $object->$fieldName; + } + } elseif($joinClass == 'Folder') { + /*foreach($objects as $object) { + var_dump($object->$fieldName); + }*/ + } + } + } + } + foreach($usedFiles as $file) { + $where .= $file->ID . ','; + } + if($where == "") return "(ClassName = 'File' OR ClassName = 'Image')"; + $where = substr($where,0,strlen($where)-1); + $where = "ID NOT IN (" . $where . ") AND (ClassName = 'File' OR ClassName = 'Image')"; + return $where; + } + + /** + * Creates table for displaying unused files. + * + * @returns AssetTableField + */ + + private function getAssetList() { + $where = $this->getUsedFilesList(); + $assetList = new AssetTableField( + $this, + "AssetList", + "File", + array("Title" => "Title", "LinkedURL" => "Filename"), + "", + $where + ); + $assetList->setPopupCaption("View Asset"); + $assetList->setPermissions(array("show","delete")); + $assetList->Markable = false; + return $assetList; + + } + + /** + * Creates array containg all unused thumbnails. + * Array is created in three steps: + * 1.Scan assets folder and retrieve all thumbnails + * 2.Scan all HTMLField in system and retrieve thumbnails from them. + * 3.Count difference between two sets (array_diff) + * + * @returns Array + */ + + private function getUnusedThumbnailsArray() { + $allThumbnails = array(); + $dirIterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('../assets')); + foreach ($dirIterator as $file) { + if($file->isFile()) { + if(strpos($file->getPathname(),"_resampled") !== false) { + $pathInfo = pathinfo($file->getPathname()); + if(in_array(strtolower($pathInfo['extension']),array('jpeg','jpg','jpe','png','gif'))) { + $path = str_replace('\\','/',$file->getPathname()); + $allThumbnails[] = substr($path,strpos($path,'/assets/')+8); + } + } + } + } + $classes = ClassInfo::subclassesFor('SiteTree'); + $usedThumbnails = array(); + foreach($classes as $className) { + $sng = singleton($className); + $objects = DataObject::get($className); + if($objects !== NULL) { + foreach($objects as $object) { + foreach($sng->db() as $fieldName => $fieldType) { + if($fieldType == 'HTMLText') { + $url1 = HTTP::findByTagAndAttribute($object->$fieldName,array("img" => "src")); + if($url1 != NULL) $usedThumbnails[] = substr($url1[0],strpos($url1[0],'/assets/')+8); + if($object->latestPublished > 0) { + $object = Versioned::get_latest_version($className, $object->ID); + $url2 = HTTP::findByTagAndAttribute($object->$fieldName,array("img" => "src")); + if($url2 != NULL) $usedThumbnails[] = substr($url2[0],strpos($url2[0],'/assets/')+8); + } + } + } + } + } + } + return array_diff($allThumbnails,$usedThumbnails); + } } \ No newline at end of file diff --git a/code/AssetTableField.php b/code/AssetTableField.php index 578793a3..b7619581 100755 --- a/code/AssetTableField.php +++ b/code/AssetTableField.php @@ -5,6 +5,11 @@ class AssetTableField extends ComplexTableField { protected $template = "AssetTableField"; + protected $permissions = array( + "edit", + "delete", + //"export", + ); function __construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter = "", $sourceSort = "", $sourceJoin = "") { parent::__construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin); @@ -25,7 +30,7 @@ class AssetTableField extends ComplexTableField { } function sourceID() { - return $this->folder->ID; + if($this->folder) return $this->folder->ID; } function DetailForm() { @@ -160,4 +165,4 @@ class AssetTableField extends ComplexTableField { } } -?> \ No newline at end of file +?> diff --git a/javascript/AssetAdmin.js b/javascript/AssetAdmin.js index 31297403..56a8844a 100755 --- a/javascript/AssetAdmin.js +++ b/javascript/AssetAdmin.js @@ -470,4 +470,19 @@ appendLoader(function () { $('deletepage').getElementsByTagName('button')[0].onclick = function() { return false; }; $('deletepage_options').onsubmit = deletefolder.form_submit; } +}); + +Behaviour.register({ + '#UnusedThumbnails': { + onclick : function(event) { + Event.stop(event); + var options = { + method: 'get', + onSuccess: function(t) { + eval(t.responseText); + } + }; + new Ajax.Request('admin/assets/deleteUnusedThumbnails',options); + } + } }); \ No newline at end of file diff --git a/templates/Includes/AssetTableField.ss b/templates/Includes/AssetTableField.ss index cd166941..91af35a2 100755 --- a/templates/Includes/AssetTableField.ss +++ b/templates/Includes/AssetTableField.ss @@ -18,10 +18,17 @@ <% control Fields %> $Value <% end_control %> - - edit - - <% if Can(delete) %> + <% if Can(show) %> + + show + + <% end_if %> + <% if Can(edit) %> + + edit + + <% end_if %> + <% if Can(delete) %> delete