2007-07-19 12:40:05 +02:00
< ? php
/**
* AssetAdmin is the 'file store' section of the CMS .
* It provides an interface for maniupating the File and Folder objects in the system .
2008-04-06 10:20:13 +02:00
*
2008-02-25 03:10:37 +01:00
* @ package cms
* @ subpackage assets
2007-07-19 12:40:05 +02:00
*/
class AssetAdmin extends LeftAndMain {
2008-04-06 10:20:13 +02:00
2008-11-02 22:27:55 +01:00
static $url_segment = 'assets' ;
static $url_rule = '/$Action/$ID' ;
static $menu_title = 'Files & Images' ;
2008-12-04 23:38:58 +01:00
public static $tree_class = 'File' ;
2008-04-06 10:20:13 +02:00
/**
2008-10-02 02:34:41 +02:00
* @ see Upload -> allowedMaxFileSize
2008-04-06 10:20:13 +02:00
* @ var int
*/
public static $allowed_max_file_size ;
/**
2008-10-02 02:34:41 +02:00
* @ see Upload -> allowedExtensions
2008-04-06 10:20:13 +02:00
* @ var array
*/
public static $allowed_extensions = array ();
2008-02-25 03:10:37 +01:00
2009-08-11 03:08:29 +02:00
/**
* If this is true , then restrictions set in $allowed_max_file_size and
* $allowed_extensions will be applied to users with admin privileges as
* well .
*/
public static $apply_restrictions_to_admin = false ;
2008-02-25 03:10:37 +01:00
static $allowed_actions = array (
2009-11-21 04:19:05 +01:00
'doAdd' ,
'AddForm' ,
2008-02-25 03:10:37 +01:00
'deletemarked' ,
2009-01-06 03:18:33 +01:00
'DeleteItemsForm' ,
2008-02-25 03:10:37 +01:00
'deleteUnusedThumbnails' ,
'doUpload' ,
'getfile' ,
'getsubtree' ,
'movemarked' ,
'removefile' ,
'save' ,
'savefile' ,
'uploadiframe' ,
2008-08-09 07:57:44 +02:00
'UploadForm' ,
2009-11-21 04:19:05 +01:00
'deleteUnusedThumbnails' => 'ADMIN' ,
'batchactions' ,
'BatchActionsForm'
2008-02-25 03:10:37 +01:00
);
2007-07-19 12:40:05 +02:00
/**
* Return fake - ID " root " if no ID is found ( needed to upload files into the root - folder )
*/
public function currentPageID () {
if ( isset ( $_REQUEST [ 'ID' ]) && is_numeric ( $_REQUEST [ 'ID' ])) {
return $_REQUEST [ 'ID' ];
} elseif ( is_numeric ( $this -> urlParams [ 'ID' ])) {
return $this -> urlParams [ 'ID' ];
} elseif ( is_numeric ( Session :: get ( " { $this -> class } .currentPage " ))) {
return Session :: get ( " { $this -> class } .currentPage " );
} else {
return " root " ;
}
}
/**
* Set up the controller , in particular , re - sync the File database with the assets folder ./
*/
function init () {
parent :: init ();
2007-10-29 03:10:59 +01:00
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
if ( ! file_exists ( ASSETS_PATH )) {
mkdir ( ASSETS_PATH );
2007-10-29 03:10:59 +01:00
}
2007-07-19 12:40:05 +02:00
// needed for MemberTableField (Requirements not determined before Ajax-Call)
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
Requirements :: css ( SAPPHIRE_DIR . " /css/ComplexTableField.css " );
2009-11-21 04:18:55 +01:00
Requirements :: javascript ( CMS_DIR . '/javascript/LeftAndMain.BatchActions.js' );
2009-11-21 04:18:25 +01:00
Requirements :: javascript ( CMS_DIR . " /javascript/AssetAdmin.DragDrop.js " );
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
Requirements :: javascript ( CMS_DIR . " /javascript/AssetAdmin.js " );
Requirements :: javascript ( CMS_DIR . " /javascript/CMSMain_upload.js " );
Requirements :: javascript ( CMS_DIR . " /javascript/Upload.js " );
2009-11-21 03:36:54 +01:00
Requirements :: javascript ( CMS_DIR . " /thirdparty/swfupload/swfupload.js " );
2007-07-19 12:40:05 +02:00
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
Requirements :: javascript ( THIRDPARTY_DIR . " /greybox/AmiJS.js " );
Requirements :: javascript ( THIRDPARTY_DIR . " /greybox/greybox.js " );
Requirements :: css ( THIRDPARTY_DIR . " /greybox/greybox.css " );
2007-09-27 22:56:55 +02:00
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
Requirements :: css ( CMS_DIR . " /css/AssetAdmin.css " );
2008-11-22 04:47:56 +01:00
Requirements :: customScript ( <<< JS
_TREE_ICONS = {};
_TREE_ICONS [ 'Folder' ] = {
2009-11-21 04:16:54 +01:00
fileIcon : 'sapphire/javascript/tree/images/page-closedfolder.gif' ,
openFolderIcon : 'sapphire/javascript/tree/images/page-openfolder.gif' ,
closedFolderIcon : 'sapphire/javascript/tree/images/page-closedfolder.gif'
2008-11-22 04:47:56 +01:00
};
JS
);
2009-11-21 04:19:05 +01:00
CMSBatchActionHandler :: register ( 'delete' , 'AssetAdmin_DeleteBatchAction' , 'Folder' );
2007-07-19 12:40:05 +02:00
}
/**
* Show the content of the upload iframe . The form is specified by a template .
*/
function uploadiframe () {
Requirements :: clear ();
2009-11-21 03:36:38 +01:00
Requirements :: javascript ( SAPPHIRE_DIR . " /thirdparty/prototype/prototype.js " );
Requirements :: javascript ( SAPPHIRE_DIR . " /thirdparty/behaviour/behaviour.js " );
Requirements :: javascript ( SAPPHIRE_DIR . " /javascript/prototype_improvements.js " );
2009-11-21 04:18:15 +01:00
//Requirements::javascript(CMS_DIR . "/javascript/LeftAndMain.js");
Requirements :: javascript ( CMS_DIR . " /thirdparty/multifile/multifile.js " );
2009-11-21 04:19:35 +01:00
Requirements :: css ( CMS_DIR . " /thirdparty/multifile/multifile.css " );
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
Requirements :: css ( CMS_DIR . " /css/typography.css " );
Requirements :: css ( CMS_DIR . " /css/layout.css " );
Requirements :: css ( CMS_DIR . " /css/cms_left.css " );
Requirements :: css ( CMS_DIR . " /css/cms_right.css " );
2007-07-19 12:40:05 +02:00
if ( isset ( $data [ 'ID' ]) && $data [ 'ID' ] != 'root' ) $folder = DataObject :: get_by_id ( " Folder " , $data [ 'ID' ]);
else $folder = singleton ( 'Folder' );
2009-07-02 09:23:29 +02:00
// Don't modify the output of the template, or it will become invalid
ContentNegotiator :: disable ();
2008-11-07 13:21:41 +01:00
return array ( 'CanUpload' => $folder -> canEdit ());
2007-07-19 12:40:05 +02:00
}
/**
* Return the form object shown in the uploadiframe .
*/
function UploadForm () {
2009-01-05 07:17:59 +01:00
// disabled flash upload javascript (CMSMain_upload()) below,
// see r54952 (originally committed in r42014)
2008-04-26 08:39:23 +02:00
$form = new Form ( $this , 'UploadForm' , new FieldSet (
2007-07-19 12:40:05 +02:00
new HiddenField ( " ID " , " " , $this -> currentPageID ()),
2009-11-21 03:01:06 +01:00
new HiddenField ( " FolderID " , " " , $this -> currentPageID ()),
2007-07-19 12:40:05 +02:00
// needed because the button-action is triggered outside the iframe
new HiddenField ( " action_doUpload " , " " , " 1 " ),
2009-02-03 04:46:15 +01:00
new FileField ( " Files[0] " , _t ( 'AssetAdmin.CHOOSEFILE' , 'Choose file: ' )),
2007-07-19 12:40:05 +02:00
new LiteralField ( 'UploadButton' , "
2009-07-02 09:23:29 +02:00
< input type = \ " submit \" value= \" " . _t ( 'AssetAdmin.UPLOAD' , 'Upload Files Listed Below' ) . " \" name= \" action_upload \" id= \" Form_UploadForm_action_upload \" class= \" action \" />
2007-07-19 12:40:05 +02:00
" ),
new LiteralField ( 'MultifileCode' , "
2007-09-16 18:33:05 +02:00
< p > " . _t('AssetAdmin.FILESREADY','Files ready to upload:') . " </ p >
2009-07-02 09:23:29 +02:00
< div id = \ " Form_UploadForm_FilesList \" ></div>
2007-07-19 12:40:05 +02:00
" )
), new FieldSet (
));
2008-04-26 08:39:23 +02:00
// Makes ajax easier
$form -> disableSecurityToken ();
return $form ;
2007-07-19 12:40:05 +02:00
}
/**
* This method processes the results of the UploadForm .
* It will save the uploaded files to / assets / and create new File objects as required .
*/
function doUpload ( $data , $form ) {
2009-11-12 23:06:37 +01:00
$processedFiles = array ();
if ( ! isset ( $data [ 'Files' ])) return Director :: set_status_code ( " 404 " );
if ( is_array ( $data [ 'Files' ])) {
foreach ( $data [ 'Files' ] as $param => $files ) {
if ( ! is_array ( $files )) $files = array ( $files );
foreach ( $files as $key => $value ) {
$processedFiles [ $key ][ $param ] = $value ;
}
2007-07-19 12:40:05 +02:00
}
}
2009-11-12 23:06:37 +01:00
else {
$proccessedFiles [] = $data [ 'Files' ];
}
// get the folder to upload to.
if ( isset ( $data [ 'FolderID' ]) && $data [ 'FolderID' ] != " root " ) {
$folder = DataObject :: get_by_id ( 'Folder' , $data [ 'FolderID' ]);
}
else {
$folder = DataObject :: get_one ( 'Folder' );
}
2007-07-19 12:40:05 +02:00
2007-08-21 04:32:20 +02:00
$newFiles = array ();
2007-07-19 12:40:05 +02:00
$fileSizeWarnings = '' ;
2009-11-21 04:19:35 +01:00
$errorsArr = '' ;
2009-01-05 07:17:59 +01:00
$status = '' ;
$statusMessage = '' ;
2009-11-12 23:06:37 +01:00
2008-04-06 10:20:13 +02:00
foreach ( $processedFiles as $tmpFile ) {
if ( $tmpFile [ 'error' ] == UPLOAD_ERR_NO_TMP_DIR ) {
2009-11-21 04:19:35 +01:00
$errorsArr [] = _t ( 'AssetAdmin.NOTEMP' , 'There is no temporary folder for uploads. Please set upload_tmp_dir in php.ini.' );
2007-08-21 04:32:20 +02:00
break ;
}
2008-04-06 10:20:13 +02:00
if ( $tmpFile [ 'tmp_name' ]) {
2007-08-21 04:32:20 +02:00
// Workaround open_basedir problems
if ( ini_get ( " open_basedir " )) {
2008-04-06 10:20:13 +02:00
$newtmp = TEMP_FOLDER . '/' . $tmpFile [ 'name' ];
move_uploaded_file ( $tmpFile [ 'tmp_name' ], $newtmp );
$tmpFile [ 'tmp_name' ] = $newtmp ;
2007-08-21 04:32:20 +02:00
}
2007-07-19 12:40:05 +02:00
2008-04-06 10:20:13 +02:00
// validate files (only if not logged in as admin)
2009-08-11 03:08:29 +02:00
if ( ! self :: $apply_restrictions_to_admin && Permission :: check ( 'ADMIN' )) {
2008-04-06 10:20:13 +02:00
$valid = true ;
2007-07-19 12:40:05 +02:00
} else {
2008-04-06 10:20:13 +02:00
$upload = new Upload ();
2009-11-21 04:19:35 +01:00
$upload -> setAllowedExtensions ( array ( 'gif' ));
2008-04-06 10:20:13 +02:00
$upload -> setAllowedMaxFileSize ( self :: $allowed_max_file_size );
$valid = $upload -> validate ( $tmpFile );
if ( ! $valid ) {
2009-11-21 04:19:35 +01:00
$errorsArr = $upload -> getErrors ();
2008-04-06 10:20:13 +02:00
}
2007-07-19 12:40:05 +02:00
}
2008-04-06 10:20:13 +02:00
// move file to given folder
if ( $valid ) $newFiles [] = $folder -> addUploadToFolder ( $tmpFile );
2007-07-19 12:40:05 +02:00
}
}
2009-11-21 04:19:35 +01:00
2007-07-19 12:40:05 +02:00
if ( $newFiles ) {
$numFiles = sizeof ( $newFiles );
2007-09-16 18:33:05 +02:00
$statusMessage = sprintf ( _t ( 'AssetAdmin.UPLOADEDX' , " Uploaded %s files " ), $numFiles ) ;
2007-07-19 12:40:05 +02:00
$status = " good " ;
2009-11-21 04:19:35 +01:00
} else if ( $errorsArr ) {
$statusMessage = implode ( '\n' , $errorsArr );
$status = 'bad' ;
} else {
2007-09-16 18:33:05 +02:00
$statusMessage = _t ( 'AssetAdmin.NOTHINGTOUPLOAD' , 'There was nothing to upload' );
2007-07-19 12:40:05 +02:00
$status = " " ;
}
2009-11-12 23:06:37 +01:00
2008-02-25 03:10:37 +01:00
$fileIDs = array ();
$fileNames = array ();
foreach ( $newFiles as $newFile ) {
$fileIDs [] = $newFile ;
2008-11-24 10:30:41 +01:00
$fileObj = DataObject :: get_one ( 'File' , " \" File \" . \" ID \" = $newFile " );
2009-04-29 03:44:28 +02:00
// notify file object after uploading
if ( method_exists ( $fileObj , 'onAfterUpload' )) $fileObj -> onAfterUpload ();
2008-02-25 03:10:37 +01:00
$fileNames [] = $fileObj -> Name ;
}
2009-11-21 04:19:35 +01:00
// TODO Replace with clientside logic which doesn't have assumptions in the response
2007-07-19 12:40:05 +02:00
echo <<< HTML
< script type = " text/javascript " >
2009-11-21 04:19:35 +01:00
var url = parent . document . getElementById ( 'sitetree' ) . getTreeNodeByIdx ( " { $folder -> ID } " ) . getElementsByTagName ( 'a' )[ 0 ] . href ;
parent . jQuery ( '#Form_EditForm' ) . concrete ( 'ss' ) . loadForm ( url );
2007-07-19 12:40:05 +02:00
parent . statusMessage ( " { $statusMessage } " , " { $status } " );
</ script >
HTML ;
}
2009-04-29 03:44:28 +02:00
/**
* Custom currentPage () method to handle opening the 'root' folder
*/
public function currentPage () {
$id = $this -> currentPageID ();
if ( $id && is_numeric ( $id )) {
return DataObject :: get_by_id ( $this -> stat ( 'tree_class' ), $id );
} else if ( $id == 'root' ) {
return singleton ( $this -> stat ( 'tree_class' ));
}
}
2007-07-19 12:40:05 +02:00
2009-11-21 04:17:16 +01:00
/**
* @ return Form
*/
function EditForm ( $request = null ) {
return $this -> getEditForm ();
}
2007-07-19 12:40:05 +02:00
/**
* Return the form that displays the details of a folder , including a file list and fields for editing the folder name .
*/
2009-11-21 04:15:13 +01:00
function getEditForm ( $id = null ) {
2009-11-21 04:17:16 +01:00
if ( ! $id ) $id = $this -> currentPageID ();
2009-11-21 04:18:19 +01:00
$record = ( $id && $id != " root " ) ? DataObject :: get_by_id ( " File " , $id ) : null ;
2009-11-21 04:15:13 +01:00
if ( $record && ! $record -> canView ()) return Security :: permissionFailure ( $this );
2009-07-02 00:28:06 +02:00
2008-02-25 03:10:37 +01:00
if ( $record ) {
$fields = $record -> getCMSFields ();
2009-11-21 04:19:29 +01:00
// Required for file tree setup
if ( ! $fields -> dataFieldByName ( 'ParentID' )) $fields -> push ( new HiddenField ( 'ParentID' ));
2007-07-19 12:40:05 +02:00
$actions = new FieldSet ();
2007-09-15 22:47:35 +02:00
// Only show save button if not 'assets' folder
2008-12-04 23:38:58 +01:00
if ( $record -> canEdit () && $id != 'root' ) {
2007-07-19 12:40:05 +02:00
$actions = new FieldSet (
2007-09-16 18:33:05 +02:00
new FormAction ( 'save' , _t ( 'AssetAdmin.SAVEFOLDERNAME' , 'Save folder name' ))
2007-07-19 12:40:05 +02:00
);
}
$form = new Form ( $this , " EditForm " , $fields , $actions );
if ( $record -> ID ) {
$form -> loadDataFrom ( $record );
} else {
$form -> loadDataFrom ( array (
" ID " => " root " ,
" URL " => Director :: absoluteBaseURL () . 'assets/' ,
));
}
2008-12-04 23:38:58 +01:00
if ( ! $record -> canEdit ()) {
2007-07-19 12:40:05 +02:00
$form -> makeReadonly ();
2008-12-04 23:38:58 +01:00
}
2009-11-21 04:15:00 +01:00
} else {
2009-11-21 04:15:13 +01:00
$form = $this -> EmptyForm ();
2007-07-19 12:40:05 +02:00
}
2009-11-21 04:15:00 +01:00
return $form ;
2007-07-19 12:40:05 +02:00
}
/**
* Perform the " move marked " action .
2007-09-15 22:47:35 +02:00
* Called and returns in same way as 'save' function
2007-07-19 12:40:05 +02:00
*/
2007-09-15 22:47:35 +02:00
public function movemarked ( $urlParams , $form ) {
2009-02-03 03:50:25 +01:00
if ( $_REQUEST [ 'DestFolderID' ] && ( is_numeric ( $_REQUEST [ 'DestFolderID' ]) || ( $_REQUEST [ 'DestFolderID' ]) == 'root' )) {
$destFolderID = ( $_REQUEST [ 'DestFolderID' ] == 'root' ) ? 0 : $_REQUEST [ 'DestFolderID' ];
2007-07-19 12:40:05 +02:00
$fileList = " ' " . ereg_replace ( ' *, *' , " ',' " , trim ( addslashes ( $_REQUEST [ 'FileIDs' ]))) . " ' " ;
$numFiles = 0 ;
if ( $fileList != " '' " ) {
2008-11-24 10:30:41 +01:00
$files = DataObject :: get ( " File " , " \" File \" . \" ID \" IN ( $fileList ) " );
2007-07-19 12:40:05 +02:00
if ( $files ) {
foreach ( $files as $file ) {
2007-09-15 22:30:54 +02:00
if ( $file instanceof Image ) {
2008-12-04 23:38:58 +01:00
$file -> deleteFormattedImages ();
}
2007-07-19 12:40:05 +02:00
$file -> ParentID = $destFolderID ;
$file -> write ();
$numFiles ++ ;
}
} else {
user_error ( " No files in $fileList could be found! " , E_USER_ERROR );
}
}
2007-09-15 22:47:35 +02:00
2007-09-16 18:33:05 +02:00
$message = sprintf ( _t ( 'AssetAdmin.MOVEDX' , 'Moved %s files' ), $numFiles );
2008-12-04 23:38:58 +01:00
2007-09-15 22:47:35 +02:00
FormResponse :: status_message ( $message , " good " );
2009-10-21 06:39:50 +02:00
FormResponse :: add ( " $ ('Form_EditForm_Files').refresh(); " );
2008-12-04 23:38:58 +01:00
2009-10-21 06:35:25 +02:00
return FormResponse :: respond ();
2007-07-19 12:40:05 +02:00
}
}
/**
* Perform the " delete marked " action .
2007-09-15 22:47:35 +02:00
* Called and returns in same way as 'save' function
2007-07-19 12:40:05 +02:00
*/
2007-09-15 22:47:35 +02:00
public function deletemarked ( $urlParams , $form ) {
2008-12-04 23:38:58 +01:00
$fileList = " ' " . ereg_replace ( ' *, *' , " ',' " , trim ( addslashes ( $_REQUEST [ 'FileIDs' ]))) . " ' " ;
$numFiles = 0 ;
$folderID = 0 ;
$deleteList = '' ;
$brokenPageList = '' ;
if ( $fileList != " '' " ) {
$files = DataObject :: get ( " File " , " \" File \" . \" ID \" IN ( $fileList ) " );
if ( $files ) {
foreach ( $files as $file ) {
if ( $file instanceof Image ) {
$file -> deleteFormattedImages ();
2007-07-19 12:40:05 +02:00
}
2008-12-04 23:38:58 +01:00
if ( ! $folderID ) {
$folderID = $file -> ParentID ;
2007-07-19 12:40:05 +02:00
}
2008-12-04 23:38:58 +01:00
$file -> delete ();
$numFiles ++ ;
}
if ( $brokenPages = Notifications :: getItems ( 'BrokenLink' )) {
$brokenPageList = " " . _t ( 'AssetAdmin.NOWBROKEN' , 'These pages now have broken links:' ) . '</ul>' ;
foreach ( $brokenPages as $brokenPage ) {
$brokenPageList .= " <li style="font-size: 65%"> " . $brokenPage -> Breadcrumbs ( 3 , true ) . '</li>' ;
2007-07-19 12:40:05 +02:00
}
2008-12-04 23:38:58 +01:00
$brokenPageList .= '</ul>' ;
Notifications :: notifyByEmail ( " BrokenLink " , " Page_BrokenLinkEmail " );
2007-07-19 12:40:05 +02:00
} else {
2008-12-04 23:38:58 +01:00
$brokenPageList = '' ;
}
$deleteList = '' ;
if ( $folderID ) {
$remaining = DB :: query ( " SELECT COUNT(*) FROM \" File \" WHERE \" ParentID \" = $folderID " ) -> value ();
if ( ! $remaining ) $deleteList .= " Element.removeClassName( \$ ('sitetree').getTreeNodeByIdx(' $folderID ').getElementsByTagName('a')[0],'contents'); " ;
2007-07-19 12:40:05 +02:00
}
2008-12-04 23:38:58 +01:00
} else {
user_error ( " No files in $fileList could be found! " , E_USER_ERROR );
2007-07-19 12:40:05 +02:00
}
2008-12-04 23:38:58 +01:00
}
$message = sprintf ( _t ( 'AssetAdmin.DELETEDX' , " Deleted %s files.%s " ), $numFiles , $brokenPageList ) ;
FormResponse :: add ( $deleteList );
FormResponse :: status_message ( $message , " good " );
FormResponse :: add ( " $ ('Form_EditForm').getPageFromServer( $ ('Form_EditForm_ID').value) " );
return FormResponse :: respond ();
2007-07-19 12:40:05 +02:00
}
/**
* Returns the content to be placed in Form_SubForm when editing a file .
* Called using ajax .
*/
public function getfile () {
SSViewer :: setOption ( 'rewriteHashlinks' , false );
// bdc: only try to return something if user clicked on an object
if ( is_object ( $this -> getSubForm ( $this -> urlParams [ 'ID' ]))) {
return $this -> getSubForm ( $this -> urlParams [ 'ID' ]) -> formHtmlContent ();
}
else return null ;
}
/**
* Action handler for the save button on the file subform .
* Saves the file
*/
public function savefile ( $data , $form ) {
$record = DataObject :: get_by_id ( " File " , $data [ 'ID' ]);
$form -> saveInto ( $record );
$record -> write ();
$title = Convert :: raw2js ( $record -> Title );
$name = Convert :: raw2js ( $record -> Name );
2007-09-16 18:33:05 +02:00
$saved = sprintf ( _t ( 'AssetAdmin.SAVEDFILE' , 'Saved file %s' ), " # $data[ID] " );
2007-07-19 12:40:05 +02:00
echo <<< JS
2007-09-16 18:33:05 +02:00
statusMessage ( '$saved' );
2007-07-19 12:40:05 +02:00
$ ( 'record-$data[ID]' ) . getElementsByTagName ( 'td' )[ 1 ] . innerHTML = " $title " ;
$ ( 'record-$data[ID]' ) . getElementsByTagName ( 'td' )[ 2 ] . innerHTML = " $name " ;
JS ;
}
/**
2008-11-06 23:56:24 +01:00
* Return the entire site tree as a nested UL .
* @ return string HTML for site tree
2008-02-25 03:10:37 +01:00
*/
2007-07-19 12:40:05 +02:00
public function SiteTreeAsUL () {
$obj = singleton ( 'Folder' );
2009-03-10 22:59:19 +01:00
$obj -> setMarkingFilter ( 'ClassName' , ClassInfo :: subclassesFor ( 'Folder' ));
2009-07-02 00:28:06 +02:00
$obj -> markPartialTree ( 30 , null , " ChildFolders " );
2007-07-19 12:40:05 +02:00
if ( $p = $this -> currentPage ()) $obj -> markToExpose ( $p );
// getChildrenAsUL is a flexible and complex way of traversing the tree
2008-11-06 23:56:24 +01:00
$siteTreeList = $obj -> getChildrenAsUL (
'' ,
'"<li id=\"record-$child->ID\" class=\"$child->class" . $child->markingClasses() . ($extraArg->isCurrentPage($child) ? " current" : "") . "\">" . ' .
2009-11-21 03:38:59 +01:00
'"<a href=\"" . Director::link(substr($extraArg->Link(),0,-1), "show", $child->ID) . "\" class=\"" . ($child->hasChildFolders() ? " contents" : "") . "\" >" . $child->TreeTitle . "</a>" ' ,
2008-11-06 23:56:24 +01:00
$this ,
2009-07-02 00:28:06 +02:00
true ,
" ChildFolders "
2008-11-06 23:56:24 +01:00
);
// Wrap the root if needs be
2007-07-19 12:40:05 +02:00
$rootLink = $this -> Link () . 'show/root' ;
2009-01-05 07:17:59 +01:00
$baseUrl = Director :: absoluteBaseURL () . " assets " ;
2008-11-06 23:56:24 +01:00
if ( ! isset ( $rootID )) {
2009-01-05 07:17:59 +01:00
$siteTree = " <ul id= \" sitetree \" class= \" tree unformatted \" ><li id= \" record-root \" class= \" Root \" ><a href= \" $rootLink\ " >< strong > { $baseUrl } </ strong ></ a > "
2008-11-06 23:56:24 +01:00
. $siteTreeList . " </li></ul> " ;
}
2007-07-19 12:40:05 +02:00
return $siteTree ;
}
/**
* Returns a subtree of items underneat the given folder .
*/
public function getsubtree () {
2008-11-07 00:47:28 +01:00
$obj = DataObject :: get_by_id ( 'Folder' , $_REQUEST [ 'ID' ]);
2009-03-10 22:59:19 +01:00
$obj -> setMarkingFilter ( 'ClassName' , ClassInfo :: subclassesFor ( 'Folder' ));
2007-07-19 12:40:05 +02:00
$obj -> markPartialTree ();
2008-11-07 00:47:28 +01:00
$results = $obj -> getChildrenAsUL (
'' ,
'"<li id=\"record-$child->ID\" class=\"$child->class" . $child->markingClasses() . ($extraArg->isCurrentPage($child) ? " current" : "") . "\">" . ' .
2009-11-21 03:38:59 +01:00
'"<a href=\"" . Director::link(substr($extraArg->Link(),0,-1), "show", $child->ID) . "\" >" . $child->TreeTitle . "</a>" ' ,
2008-11-07 00:47:28 +01:00
$this ,
true
);
2007-07-19 12:40:05 +02:00
2008-11-07 00:47:28 +01:00
return substr ( trim ( $results ), 4 , - 5 );
2007-07-19 12:40:05 +02:00
}
//------------------------------------------------------------------------------------------//
// Data saving handlers
2009-11-21 04:19:05 +01:00
/**
* @ return Form
*/
function AddForm () {
$typeMap = array ( 'Folder' => singleton ( 'Folder' ) -> i18n_singular_name ());
$typeField = new DropdownField ( 'Type' , false , $typeMap , 'Folder' );
$form = new Form (
$this ,
'AddForm' ,
new FieldSet (
new HiddenField ( 'ParentID' ),
$typeField -> performReadonlyTransformation ()
),
new FieldSet (
new FormAction ( 'doAdd' , _t ( 'AssetAdmin_left.ss.GO' , 'Go' ))
)
);
$form -> setValidator ( null );
$form -> addExtraClass ( 'actionparams' );
return $form ;
}
2007-07-19 12:40:05 +02:00
/**
* Add a new folder and return its details suitable for ajax .
*/
2009-11-21 04:19:29 +01:00
public function doAdd ( $data , $form ) {
$parentID = ( isset ( $data [ 'ParentID' ]) && is_numeric ( $data [ 'ParentID' ])) ? ( int ) $data [ 'ParentID' ] : 0 ;
$name = ( isset ( $data [ 'Name' ])) ? basename ( $data [ 'Name' ]) : _t ( 'AssetAdmin.NEWFOLDER' , " NewFolder " );
2007-07-19 12:40:05 +02:00
2009-11-21 04:19:29 +01:00
if ( $parentID ) {
$parentObj = DataObject :: get_by_id ( 'File' , $parentID );
if ( ! $parentObj || ! $parentObj -> ID ) $parentID = 0 ;
2007-07-19 12:40:05 +02:00
}
// Get the folder to be created
2009-04-29 03:44:28 +02:00
if ( isset ( $parentObj -> ID )) $filename = $parentObj -> FullPath . $name ;
else $filename = ASSETS_PATH . '/' . $name ;
2007-07-19 12:40:05 +02:00
// Actually create
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
if ( ! file_exists ( ASSETS_PATH )) {
mkdir ( ASSETS_PATH );
2007-10-29 03:10:59 +01:00
}
2009-10-31 02:25:32 +01:00
2009-04-29 03:44:28 +02:00
$p = new Folder ();
2009-11-21 04:19:29 +01:00
$p -> ParentID = $parentID ;
$p -> Name = $p -> Title = basename ( $filename );
2007-07-19 12:40:05 +02:00
$p -> write ();
2009-11-21 04:18:19 +01:00
// Used in TinyMCE inline folder creation
2009-11-21 04:19:29 +01:00
if ( isset ( $data [ 'returnID' ])) {
2007-11-12 22:47:45 +01:00
return $p -> ID ;
} else {
2009-11-21 04:18:19 +01:00
$form = $this -> getEditForm ( $p -> ID );
return $form -> formHtmlContent ();
2007-11-12 22:47:45 +01:00
}
2009-10-31 02:25:32 +01:00
2007-07-19 12:40:05 +02:00
}
2009-11-21 04:19:05 +01:00
/**
* Batch Actions Handler
*/
function batchactions () {
return new CMSBatchActionHandler ( $this , 'batchactions' , 'Folder' );
}
2009-01-06 03:18:33 +01:00
/**
* @ return Form
*/
2009-11-21 04:19:05 +01:00
function BatchActionsForm () {
$actions = $this -> batchactions () -> batchActionList ();
$actionsMap = array ();
foreach ( $actions as $action ) $actionsMap [ $action -> Link ] = $action -> Title ;
2009-01-06 03:18:33 +01:00
$form = new Form (
$this ,
2009-11-21 04:19:05 +01:00
'BatchActionsForm' ,
2009-01-06 03:18:33 +01:00
new FieldSet (
2009-11-21 04:19:05 +01:00
new LiteralField (
'Intro' ,
sprintf ( '<p><small>%s</small></p>' ,
_t (
'CMSMain_left.ss.SELECTPAGESACTIONS' ,
'Select the pages that you want to change & then click an action:'
)
)
2009-01-06 03:18:33 +01:00
),
2009-11-21 04:19:05 +01:00
new HiddenField ( 'csvIDs' ),
new DropdownField (
'Action' ,
false ,
$actionsMap
)
2009-01-06 03:18:33 +01:00
),
new FieldSet (
2009-11-21 04:19:05 +01:00
// TODO i18n
new FormAction ( 'submit' , " Go " )
2009-01-06 03:18:33 +01:00
)
);
$form -> addExtraClass ( 'actionparams' );
2009-11-21 04:19:05 +01:00
$form -> unsetValidator ();
2009-01-06 03:18:33 +01:00
return $form ;
}
2008-02-25 03:10:37 +01:00
2007-07-19 12:40:05 +02:00
public function removefile (){
2008-12-04 23:38:58 +01:00
if ( $fileID = $this -> urlParams [ 'ID' ]) {
2007-07-19 12:40:05 +02:00
$file = DataObject :: get_by_id ( 'File' , $fileID );
2007-09-15 23:57:11 +02:00
// Delete the temp verions of this file in assets/_resampled
if ( $file instanceof Image ) {
$file -> deleteFormattedImages ();
}
2007-07-19 12:40:05 +02:00
$file -> delete ();
$file -> destroy ();
if ( Director :: is_ajax ()) {
echo <<< JS
$ ( 'Form_EditForm_Files' ) . removeFile ( $fileID );
statusMessage ( 'removed file' , 'good' );
JS ;
2008-12-04 23:38:58 +01:00
} else {
2007-07-19 12:40:05 +02:00
Director :: redirectBack ();
}
2008-12-04 23:38:58 +01:00
} else {
2007-07-19 12:40:05 +02:00
user_error ( " AssetAdmin::removefile: Bad parameters: File= $fileID " , E_USER_ERROR );
}
}
2009-11-21 04:19:02 +01:00
/**
* @ return Form
*/
function SyncForm () {
$form = new Form (
$this ,
'SyncForm' ,
new FieldSet (),
new FieldSet (
$btn = new FormAction ( 'doSync' , _t ( 'FILESYSTEMSYNC' , 'Look for new files' ))
)
);
$form -> addExtraClass ( 'actionparams' );
$form -> setFormMethod ( 'GET' );
$form -> setFormAction ( 'dev/tasks/FilesystemSyncTask' );
$btn -> describe ( _t ( 'AssetAdmin_left.ss.FILESYSTEMSYNC_DESC' , 'SilverStripe maintains its own database of the files & images stored in your assets/ folder. Click this button to update that database, if files are added to the assets/ folder from outside SilverStripe, for example, if you have uploaded files via FTP.' ));
return $form ;
}
2007-07-19 12:40:05 +02:00
public function save ( $urlParams , $form ) {
// Don't save the root folder - there's no database record
if ( $_REQUEST [ 'ID' ] == 'root' ) {
2008-12-04 23:38:58 +01:00
FormResponse :: status_message ( 'Saved' , 'good' );
2007-07-19 12:40:05 +02:00
return FormResponse :: respond ();
}
$form -> dataFieldByName ( 'Title' ) -> value = $form -> dataFieldByName ( 'Name' ) -> value ;
return parent :: save ( $urlParams , $form );
}
2007-10-02 23:34:57 +02:00
/**
* #################################
* Garbage collection .
* #################################
*/
/**
2009-02-03 04:46:15 +01:00
* Removes all unused thumbnails from the file store
* and returns the status of the process to the user .
2008-12-04 23:38:58 +01:00
*/
2009-02-03 04:46:15 +01:00
public function deleteunusedthumbnails () {
$count = 0 ;
$thumbnails = $this -> getUnusedThumbnails ();
if ( $thumbnails ) {
foreach ( $thumbnails as $thumbnail ) {
unlink ( ASSETS_PATH . " / " . $thumbnail );
$count ++ ;
}
}
$message = sprintf ( _t ( 'AssetAdmin.THUMBSDELETED' , '%s unused thumbnails have been deleted' ), $count );
FormResponse :: status_message ( $message , 'good' );
echo FormResponse :: respond ();
2007-10-02 23:34:57 +02:00
}
/**
2008-12-04 23:38:58 +01:00
* Creates array containg all unused thumbnails .
*
* Array is created in three steps :
2009-02-03 04:46:15 +01:00
* 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 )
2008-12-04 23:38:58 +01:00
*
* @ return array
*/
2009-02-03 04:46:15 +01:00
private function getUnusedThumbnails () {
2008-12-04 23:38:58 +01:00
$allThumbnails = array ();
$usedThumbnails = array ();
$dirIterator = new RecursiveIteratorIterator ( new RecursiveDirectoryIterator ( ASSETS_PATH ));
2009-02-03 04:46:15 +01:00
$classes = ClassInfo :: subclassesFor ( 'SiteTree' );
2008-12-04 23:38:58 +01:00
2009-02-03 04:46:15 +01:00
if ( $dirIterator ) {
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 );
}
2008-12-04 23:38:58 +01:00
}
}
}
}
2009-02-03 04:46:15 +01:00
if ( $classes ) {
foreach ( $classes as $className ) {
$SNG_class = singleton ( $className );
$objects = DataObject :: get ( $className );
if ( $objects !== NULL ) {
foreach ( $objects as $object ) {
foreach ( $SNG_class -> 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 );
}
}
2008-12-04 23:38:58 +01:00
}
}
}
}
}
}
2009-02-03 04:46:15 +01:00
return array_diff ( $allThumbnails , $usedThumbnails );
2008-12-04 23:38:58 +01:00
}
2009-02-03 04:46:15 +01:00
2007-11-01 21:58:28 +01:00
}
2009-11-21 04:19:05 +01:00
/**
* Delete multiple { @ link Folder } records ( and the associated filesystem nodes ) .
* Usually used through the { @ link AssetAdmin } interface .
*
* @ package cms
* @ subpackage batchactions
*/
class AssetAdmin_DeleteBatchAction extends CMSBatchAction {
function getActionTitle () {
// _t('AssetAdmin_left.ss.SELECTTODEL','Select the folders that you want to delete and then click the button below')
return _t ( 'AssetAdmin_DeleteBatchAction.TITLE' , 'Delete folders' );
}
function run ( DataObjectSet $records ) {
$status = array (
'modified' => array (),
'deleted' => array ()
);
foreach ( $records as $record ) {
$id = $record -> ID ;
// Perform the action
if ( $record -> canDelete ()) $record -> delete ();
$status [ 'deleted' ][ $id ] = array ();
$record -> destroy ();
unset ( $record );
}
return Convert :: raw2json ( $status );
}
}
2009-04-29 03:44:28 +02:00
?>