mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
367 lines
10 KiB
PHP
367 lines
10 KiB
PHP
<?php
|
|
/**
|
|
* A special kind of complex table field for manipulating assets.
|
|
*
|
|
* @package cms
|
|
* @subpackage assets
|
|
*/
|
|
class AssetTableField extends ComplexTableField {
|
|
|
|
protected $folder;
|
|
|
|
protected $template = "AssetTableField";
|
|
|
|
protected $permissions = array(
|
|
"edit",
|
|
"delete",
|
|
//"export",
|
|
);
|
|
|
|
/**
|
|
* Indicates whether a search is being executed on this object
|
|
*/
|
|
protected $searchingFor = null;
|
|
|
|
function __construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter = "", $sourceSort = "", $sourceJoin = "") {
|
|
parent::__construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin);
|
|
|
|
$SNG_file = singleton('File');
|
|
|
|
// If search was request, filter the results here
|
|
$SQL_search = (!empty($_REQUEST['FileSearch'])) ? Convert::raw2sql($_REQUEST['FileSearch']) : null;
|
|
if($SQL_search) {
|
|
$searchFilters = array();
|
|
foreach($SNG_file->searchableFields() as $fieldName => $fieldSpec) {
|
|
if(strpos($fieldName, '.') === false) $searchFilters[] = "\"$fieldName\" LIKE '%{$SQL_search}%'";
|
|
}
|
|
$this->sourceFilter = '(' . implode(' OR ', $searchFilters) . ')';
|
|
$this->searchingFor = $_REQUEST['FileSearch'];
|
|
|
|
// @todo Integrate search form more closely and don't rely on deprecated
|
|
// $extraLinkParams.
|
|
$this->extraLinkParams = array(
|
|
'FileSearch' => $SQL_search
|
|
);
|
|
}
|
|
|
|
$this->sourceSort = 'Title';
|
|
$this->Markable = true;
|
|
}
|
|
|
|
/**
|
|
* Creates the link to this form, including the search pattern
|
|
*
|
|
* @return string
|
|
*/
|
|
function CurrentLink() {
|
|
$link = parent::CurrentLink();
|
|
|
|
if(isset($_REQUEST['FileSearch']) ) {
|
|
if ( strpos($link, '?')!==false )
|
|
$link .= "&";
|
|
else
|
|
$link .= "/?";
|
|
|
|
$link .= "FileSearch=".urlencode($_REQUEST['FileSearch']);
|
|
}
|
|
|
|
return $link;
|
|
}
|
|
|
|
function FieldHolder() {
|
|
$ret = parent::FieldHolder();
|
|
|
|
Requirements::javascript(CMS_DIR . '/javascript/AssetTableField.js');
|
|
|
|
return $ret;
|
|
}
|
|
|
|
function FirstLink() {
|
|
$link = parent::FirstLink();
|
|
if($link && isset($_REQUEST['FileSearch'])) {
|
|
return $link . '&FileSearch=' . $_REQUEST['FileSearch'];
|
|
}
|
|
return $link;
|
|
}
|
|
|
|
function PrevLink() {
|
|
$link = parent::PrevLink();
|
|
if($link && isset($_REQUEST['FileSearch'])) {
|
|
return $link . '&FileSearch=' . $_REQUEST['FileSearch'];
|
|
}
|
|
return $link;
|
|
}
|
|
|
|
function NextLink() {
|
|
$link = parent::NextLink();
|
|
if($link && isset($_REQUEST['FileSearch'])) {
|
|
return $link . '&FileSearch=' . $_REQUEST['FileSearch'];
|
|
}
|
|
return $link;
|
|
}
|
|
|
|
function LastLink() {
|
|
$link = parent::LastLink();
|
|
if($link && isset($_REQUEST['FileSearch'])) {
|
|
return $link . '&FileSearch=' . $_REQUEST['FileSearch'];
|
|
}
|
|
return $link;
|
|
}
|
|
|
|
function setFolder($folder) {
|
|
$this->folder = $folder;
|
|
$this->sourceFilter .= ($this->sourceFilter) ? " AND " : "";
|
|
|
|
// If you are searching for files then show all those from subfolders
|
|
if($this->searchingFor) {
|
|
$folderIDs = $nextIDSet = array($folder->ID);
|
|
$folderClasses = "'" . implode("','", ClassInfo::subclassesFor("Folder")) . "'";
|
|
|
|
while($nextIDSet) {
|
|
// TO DO: In 2.4 this should be refactored to use the new data mapper.
|
|
$nextIDSet = DB::query("SELECT \"ID\" FROM \"File\" WHERE \"ParentID\" IN ("
|
|
. implode(", " , $nextIDSet) . ") AND \"ClassName\" IN ($folderClasses)")->column();
|
|
if($nextIDSet) $folderIDs = array_merge($folderIDs, $nextIDSet);
|
|
}
|
|
|
|
$this->sourceFilter .= " \"ParentID\" IN (" . implode(", ", $folderIDs) . ") AND \"ClassName\" <> 'Folder'";
|
|
|
|
// Otherwise just show the direct contents
|
|
} else {
|
|
$this->sourceFilter .= " \"ParentID\" = '" . $folder->ID . "' AND \"ClassName\" <> 'Folder'";
|
|
}
|
|
}
|
|
|
|
function Folder() {
|
|
return $this->folder;
|
|
}
|
|
|
|
function sourceID() {
|
|
if($this->folder) return $this->folder->ID;
|
|
}
|
|
|
|
/**
|
|
* Get the pop-up fields for the given record.
|
|
*/
|
|
function getCustomFieldsFor($childData) {
|
|
if(!$childData) {
|
|
user_error("AssetTableField::DetailForm No record found");
|
|
return null;
|
|
}
|
|
|
|
if(!$childData instanceof File) {
|
|
throw new InvalidArgumentException(sprintf('$childData is of class "%s", subclass of "File" expected', get_class($childData)));
|
|
}
|
|
|
|
if($childData->ParentID) {
|
|
$folder = DataObject::get_by_id('File', $childData->ParentID );
|
|
} else {
|
|
$folder = singleton('Folder');
|
|
}
|
|
|
|
$urlLink = "<div class='field readonly'>";
|
|
$urlLink .= "<label class='left'>"._t('AssetTableField.URL','URL')."</label>";
|
|
$urlLink .= "<span class='readonly'><a href='{$childData->Link()}'>{$childData->RelativeLink()}</a></span>";
|
|
$urlLink .= "</div>";
|
|
|
|
$detailFormFields = new FieldList(
|
|
new TabSet("BottomRoot",
|
|
$mainTab = new Tab('Main',
|
|
new TextField("Title", _t('AssetTableField.TITLE','Title')),
|
|
new TextField("Name", _t('AssetTableField.FILENAME','Filename')),
|
|
new LiteralField("AbsoluteURL", $urlLink),
|
|
new ReadonlyField("FileType", _t('AssetTableField.TYPE','Type')),
|
|
new ReadonlyField("Size", _t('AssetTableField.SIZE','Size'), $childData->getSize()),
|
|
new DropdownField("OwnerID", _t('AssetTableField.OWNER','Owner'), Member::mapInCMSGroups()),
|
|
new DateField_Disabled("Created", _t('AssetTableField.CREATED','First uploaded')),
|
|
new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT','Last changed'))
|
|
)
|
|
)
|
|
);
|
|
$mainTab->setTitle(_t('AssetTableField.MAIN', 'Main'));
|
|
|
|
if(is_a($childData, 'Image')) {
|
|
$tab = $detailFormFields->findOrMakeTab("BottomRoot.Image", _t('AssetTableField.IMAGE', 'Image'));
|
|
|
|
$big = $childData->URL;
|
|
$formattedImage = $childData->getFormattedImage('AssetLibraryPreview');
|
|
$thumbnail = $formattedImage ? $formattedImage->URL : '';
|
|
|
|
// Hmm this required the translated string to be appended to BottomRoot to add this to the Main tab
|
|
$detailFormFields->addFieldToTab('BottomRoot.Main',
|
|
new ReadonlyField("Dimensions", _t('AssetTableField.DIM','Dimensions'))
|
|
);
|
|
|
|
$tab->push(
|
|
new LiteralField("ImageFull",
|
|
"<img id='thumbnailImage' src='{$thumbnail}?r=" . rand(1,100000) . "' alt='{$childData->Name}' />"
|
|
)
|
|
);
|
|
}
|
|
|
|
if(!($childData instanceof Folder)) {
|
|
$mainTab->addFieldToTab(
|
|
'BottomRoot.Main',
|
|
new CheckboxField("ShowInSearch", $childData->fieldLabel('ShowInSearch'))
|
|
);
|
|
}
|
|
|
|
if($childData && $childData->hasMethod('BackLinkTracking')) {
|
|
if(class_exists('Subsite')) Subsite::disable_subsite_filter(true);
|
|
$links = $childData->BackLinkTracking();
|
|
if(class_exists('Subsite')) Subsite::disable_subsite_filter(false);
|
|
|
|
$linkArray = array();
|
|
if($links && $links->exists()) {
|
|
$backlinks = array();
|
|
foreach($links as $link) {
|
|
// Avoid duplicates
|
|
if (!in_array($link->ID, $linkArray)) {
|
|
$backlinks[] = "<li><a href=\"admin/show/$link->ID\">" . $link->Breadcrumbs(null,true). "</a></li>";
|
|
$linkArray[] = $link->ID;
|
|
}
|
|
}
|
|
$backlinks = "<div style=\"clear:left\">". _t('AssetTableField.PAGESLINKING','The following pages link to this file:') ."<ul>" . implode("",$backlinks) . "</ul></div>";
|
|
}
|
|
if(!isset($backlinks)) $backlinks = "<p>". _t('AssetTableField.NOLINKS',"This file hasn't been linked to from any pages.") ."</p>";
|
|
$detailFormFields->addFieldToTab("BottomRoot.Links", new LiteralField("Backlinks", $backlinks));
|
|
}
|
|
|
|
// the ID field confuses the Controller-logic in finding the right view for ReferencedField
|
|
$detailFormFields->removeByName('ID');
|
|
|
|
if($childData) $childData->extend('updateCMSFields', $detailFormFields);
|
|
|
|
return $detailFormFields;
|
|
}
|
|
|
|
/**
|
|
* Provide some HTML for a search form, to be
|
|
* added above the AssetTable field, allowing
|
|
* a user to filter the current table's files
|
|
* by their filename.
|
|
*
|
|
* @return string HTML for search form
|
|
*/
|
|
function SearchForm() {
|
|
$fieldContainer = new FieldGroup(
|
|
new FieldGroup(
|
|
new TextField(
|
|
'FileSearch',
|
|
_t('MemberTableField.SEARCH', 'Search'),
|
|
$this->searchingFor
|
|
)
|
|
),
|
|
new FieldGroup(
|
|
$btnFilter = new InlineFormAction(
|
|
'FileFilterButton',
|
|
_t('MemberTableField.FILTER', 'Filter')
|
|
),
|
|
$btnClear = new InlineFormAction(
|
|
'FileFilterClearButton',
|
|
_t('AssetTableField.CLEAR', 'Clear')
|
|
)
|
|
)
|
|
);
|
|
$btnFilter->includeDefaultJS(false);
|
|
$btnClear->includeDefaultJS(false);
|
|
|
|
return $fieldContainer->FieldHolder();
|
|
}
|
|
|
|
/**
|
|
* @return FormField|null
|
|
*/
|
|
function DeleteMarkedButton() {
|
|
if(!$this->isReadonly() ) {
|
|
$deleteButton = new InlineFormAction(
|
|
'deletemarked',
|
|
_t('Folder.DELSELECTED','Delete selected files'),
|
|
'delete'
|
|
);
|
|
$deleteButton->includeDefaultJS(false);
|
|
return $deleteButton;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return string HTML
|
|
*/
|
|
public function deletemarked($request) {
|
|
$fileIDs = $request->requestVar($this->Name());
|
|
$numFiles = 0;
|
|
$brokenPageList = '';
|
|
|
|
if($fileIDs && count($fileIDs)) {
|
|
$files = DataObject::get(
|
|
"File",
|
|
sprintf("\"File\".\"ID\" IN (%s)", Convert::raw2sql(implode(',', $fileIDs)))
|
|
);
|
|
if($files) {
|
|
$brokenPages = array();
|
|
foreach($files as $file) {
|
|
$brokenPages = array_merge($brokenPages, $file->BackLinkTracking()->toArray());
|
|
$file->delete();
|
|
$numFiles++;
|
|
}
|
|
if($brokenPages) {
|
|
$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>';
|
|
}
|
|
$brokenPageList .= '</ul>';
|
|
Notifications::notifyByEmail("BrokenLink", "Page_BrokenLinkEmail");
|
|
} else {
|
|
$brokenPageList = '';
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
$response = $this->form->Controller()->getResponse();
|
|
$response->addHeader(
|
|
'X-Status',
|
|
sprintf(
|
|
_t('AssetAdmin.DELETEDX',"Deleted %s file(s) %s"),
|
|
$numFiles,
|
|
$brokenPageList
|
|
)
|
|
);
|
|
}
|
|
|
|
public function movemarked($request) {
|
|
$fileIDs = $request->requestVar($this->Name());
|
|
$folderId = $request->requestVar('DestFolderID');
|
|
$numFiles = 0;
|
|
|
|
if($folderId && (is_numeric($folderId) || ($folderId) == 'root')) {
|
|
if($folderId == 'root') $folderId = 0;
|
|
|
|
if($fileIDs && count($fileIDs)) {
|
|
$files = DataObject::get(
|
|
"File",
|
|
sprintf("\"File\".\"ID\" IN (%s)", Convert::raw2sql(implode(',', $fileIDs)))
|
|
);
|
|
if($files) {
|
|
foreach($files as $file) {
|
|
$file->ParentID = $folderId;
|
|
$file->write();
|
|
$numFiles++;
|
|
}
|
|
}
|
|
}
|
|
|
|
$response = $this->form->Controller()->getResponse();
|
|
$response->addHeader(
|
|
'X-Status',
|
|
sprintf(
|
|
sprintf(_t('AssetAdmin.MOVEDX','Moved %s files'),$numFiles),
|
|
$numFiles
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
?>
|