MINOR merged branches/2.3 into trunk

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@67466 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2008-12-04 22:38:58 +00:00
parent e79dd5558b
commit 3c8e45f65a
22 changed files with 373 additions and 443 deletions

View File

@ -20,65 +20,6 @@ Director::addRules(50, array(
CMSMenu::populate_menu();
// Javascript combined files
Requirements::combine_files(
'assets/base.js',
array(
'jsparty/prototype.js',
'jsparty/behaviour.js',
'jsparty/prototype_improvements.js',
'jsparty/jquery/jquery.js',
'jsparty/jquery/plugins/livequery/jquery.livequery.js',
'jsparty/jquery/plugins/effen/jquery.fn.js',
'sapphire/javascript/core/jquery.ondemand.js',
'jsparty/jquery/jquery_improvements.js',
'jsparty/firebug/firebugx.js',
'sapphire/javascript/i18n.js',
)
);
Requirements::combine_files(
'assets/leftandmain.js',
array(
'jsparty/loader.js',
'jsparty/hover.js',
'jsparty/layout_helpers.js',
'jsparty/scriptaculous/effects.js',
'jsparty/scriptaculous/dragdrop.js',
'jsparty/scriptaculous/controls.js',
'jsparty/greybox/AmiJS.js',
'jsparty/greybox/greybox.js',
'cms/javascript/LeftAndMain.js',
'cms/javascript/LeftAndMain_left.js',
'cms/javascript/LeftAndMain_right.js',
//'jsparty/tiny_mce2/tiny_mce_src.js',
'jsparty/tree/tree.js',
'jsparty/tabstrip/tabstrip.js',
'cms/javascript/TinyMCEImageEnhancement.js',
'jsparty/SWFUpload/SWFUpload.js',
'cms/javascript/Upload.js',
'sapphire/javascript/TreeSelectorField.js',
'cms/javascript/ThumbnailStripField.js',
)
);
Requirements::combine_files(
'assets/cmsmain.js',
array(
'cms/javascript/CMSMain.js',
'cms/javascript/CMSMain_left.js',
'cms/javascript/CMSMain_right.js',
'cms/javascript/SideTabs.js',
'cms/javascript/TaskList.js',
'cms/javascript/SideReports.js',
'cms/javascript/LangSelector.js',
'cms/javascript/TranslationTab.js',
'jsparty/calendar/calendar.js',
'jsparty/calendar/lang/calendar-en.js',
'jsparty/calendar/calendar-setup.js',
)
);
CMSMenu::add_link(
'Help',
_t('LeftAndMain.HELP', 'Help', PR_HIGH, 'Menu title'),

View File

@ -14,7 +14,7 @@ class AssetAdmin extends LeftAndMain {
static $menu_title = 'Files & Images';
public static $tree_class = "File";
public static $tree_class = 'File';
/**
* @see Upload->allowedMaxFileSize
@ -164,7 +164,6 @@ JS
$form->disableSecurityToken();
return $form;
}
/**
@ -232,7 +231,6 @@ JS
$status = "";
}
$fileIDs = array();
$fileNames = array();
foreach($newFiles as $newFile) {
@ -258,11 +256,6 @@ JS
HTML;
}
/**
* Needs to be overridden to make sure an ID with value "0" is still valid (rootfolder)
*/
/**
* Return the form that displays the details of a folder, including a file list and fields for editing the folder name.
*/
@ -275,11 +268,10 @@ HTML;
if($record) {
$fields = $record->getCMSFields();
$actions = new FieldSet();
// Only show save button if not 'assets' folder
if( $record->canEdit() && $id != "root") {
if($record->canEdit() && $id != 'root') {
$actions = new FieldSet(
new FormAction('save',_t('AssetAdmin.SAVEFOLDERNAME','Save folder name'))
);
@ -295,11 +287,11 @@ HTML;
));
}
if( !$record->canEdit() )
if(!$record->canEdit()) {
$form->makeReadonly();
}
return $form;
}
}
@ -318,8 +310,8 @@ HTML;
if($files) {
foreach($files as $file) {
if($file instanceof Image) {
$file->deleteFormattedImages();
}
$file->deleteFormattedImages();
}
$file->ParentID = $destFolderID;
$file->write();
$numFiles++;
@ -330,11 +322,13 @@ HTML;
}
$message = sprintf(_t('AssetAdmin.MOVEDX','Moved %s files'),$numFiles);
FormResponse::status_message($message, "good");
FormResponse::add("$('Form_EditForm').getPageFromServer($('Form_EditForm_ID').value)");
return FormResponse::respond();
} else {
user_error("Bad data: $_REQUEST[DestFolderID]", E_USER_ERROR);
user_error('Bad data:' . $_REQUEST['DestFolderID'], E_USER_ERROR);
}
}
@ -343,54 +337,53 @@ HTML;
* Called and returns in same way as 'save' function
*/
public function deletemarked($urlParams, $form) {
$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();
}
if( !$folderID )
$folderID = $file->ParentID;
// $deleteList .= "\$('Form_EditForm_Files').removeById($file->ID);\n";
$file->delete();
$numFiles++;
$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();
}
if($brokenPages = Notifications::getItems("BrokenLink")) {
$brokenPageList = " ". _t('AssetAdmin.NOWBROKEN',"These pages now have broken links:")."</ul>";
foreach($brokenPages as $brokenPage) {
$brokenPageList .= "<li style=&quot;font-size: 65%&quot;>" . $brokenPage->Breadcrumbs(3, true) . "</li>";
}
$brokenPageList .= "</ul>";
Notifications::notifyByEmail("BrokenLink", "Page_BrokenLinkEmail");
} else {
$brokenPageList = '';
if(!$folderID) {
$folderID = $file->ParentID;
}
$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');";
}
} else {
user_error("No files in $fileList could be found!", E_USER_ERROR);
$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=&quot;font-size: 65%&quot;>" . $brokenPage->Breadcrumbs(3, true) . '</li>';
}
$brokenPageList .= '</ul>';
Notifications::notifyByEmail("BrokenLink", "Page_BrokenLinkEmail");
} else {
$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');";
}
} else {
user_error("No files in $fileList could be found!", E_USER_ERROR);
}
$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();
}
$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();
}
@ -532,7 +525,7 @@ JS;
*/
public function returnItemToUser($p) {
if(!empty($_REQUEST['ajax'])) {
$parentID = (int)$p->ParentID;
$parentID = (int) $p->ParentID;
return <<<JS
tree = $('sitetree');
var newNode = tree.createTreeNode($p->ID, "$p->Title", "$p->class");
@ -555,17 +548,24 @@ JS;
if(!$ids) return false;
foreach($ids as $id) {
$record = DataObject::get_by_id($this->stat('tree_class'), (int) $id);
if($record) {
if(is_numeric($id)) {
$record = DataObject::get_by_id($this->stat('tree_class'), $id);
if(!$record) {
Debug::message( "Record appears to be null" );
}
$record->delete();
$record->destroy();
$script .= $this->deleteTreeNodeJS($record);
}
}
$size = sizeof($ids);
if($size > 1) $message = $size . ' ' . _t('AssetAdmin.FOLDERSDELETED', 'folders deleted.');
else $message = $size . ' ' . _t('AssetAdmin.FOLDERDELETED', 'folder deleted.');
if($size > 1) {
$message = $size.' '._t('AssetAdmin.FOLDERSDELETED', 'folders deleted.');
} else {
$message = $size.' '._t('AssetAdmin.FOLDERDELETED', 'folder deleted.');
}
if(isset($brokenPageList)) {
$message .= ' '._t('AssetAdmin.NOWBROKEN', 'The following pages now have broken links:').'<ul>'.addslashes($brokenPageList).'</ul>'.
@ -577,7 +577,7 @@ JS;
}
public function removefile(){
if($fileID = $this->urlParams['ID']){
if($fileID = $this->urlParams['ID']) {
$file = DataObject::get_by_id('File', $fileID);
// Delete the temp verions of this file in assets/_resampled
if($file instanceof Image) {
@ -591,10 +591,10 @@ JS;
$('Form_EditForm_Files').removeFile($fileID);
statusMessage('removed file', 'good');
JS;
}else{
} else {
Director::redirectBack();
}
}else{
} else {
user_error("AssetAdmin::removefile: Bad parameters: File=$fileID", E_USER_ERROR);
}
}
@ -602,11 +602,10 @@ JS;
public function save($urlParams, $form) {
// Don't save the root folder - there's no database record
if($_REQUEST['ID'] == 'root') {
FormResponse::status_message("Saved", "good");
FormResponse::status_message('Saved', 'good');
return FormResponse::respond();
}
$form->dataFieldByName('Title')->value = $form->dataFieldByName('Name')->value;
return parent::save($urlParams, $form);
@ -619,11 +618,8 @@ JS;
*/
/**
* Removes all unused thumbnails, and echos status message to user.
*
* @returns null
*/
* Removes all unused thumbnails, and echos status message to user.
*/
public function deleteUnusedThumbnails() {
foreach($this->getUnusedThumbnailsArray() as $file) {
unlink(ASSETS_PATH . "/" . $file);
@ -632,50 +628,57 @@ JS;
}
/**
* 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_PATH));
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);
}
* 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)
*
* @return array
*/
private function getUnusedThumbnailsArray() {
$allThumbnails = array();
$usedThumbnails = array();
$dirIterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(ASSETS_PATH));
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');
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);
}
}
?>

View File

@ -193,4 +193,5 @@ class AssetTableField extends ComplexTableField {
}
}
?>
?>

View File

@ -51,10 +51,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
'sidereport',
'submit',
'switchlanguage',
'tasklist',
'unpublish',
'versions',
'waitingon',
'EditForm',
'AddPageOptionsForm',
'SiteTreeAsUL',
@ -412,26 +410,13 @@ JS;
if($record->hasMethod('getAllCMSActions')) {
$actions = $record->getAllCMSActions();
} else {
$actions = new FieldSet();
if($record->DeletedFromStage) {
if($record->can('CMSEdit')) {
$actions->push(new FormAction('revert',_t('CMSMain.RESTORE','Restore')));
$actions->push(new FormAction('deletefromlive',_t('CMSMain.DELETEFP','Delete from the published site')));
}
} else {
if($record->canEdit()) {
$actions->push($deleteAction = new FormAction('delete',_t('CMSMain.DELETE','Delete from the draft site')));
$deleteAction->addExtraClass('delete');
}
if($record->hasMethod('getCMSActions')) {
$extraActions = $record->getCMSActions();
if($extraActions) foreach($extraActions as $action) $actions->push($action);
}
$actions = $record->getCMSActions();
// add default actions if none are defined
if(!$actions || !$actions->Count()) {
if($record->canEdit()) {
$actions->push(new FormAction('save',_t('CMSMain.SAVE','Save')));
$actions->push($deleteAction = new FormAction('delete',_t('CMSMain.DELETE','Delete from the draft site')));
$deleteAction->addExtraClass('delete');
}
}
}
@ -579,6 +564,8 @@ JS;
public function revert($urlParams, $form) {
$id = $_REQUEST['ID'];
$record = DataObject::get_by_id("SiteTree", $id);
// if the user can't publish, he shouldn't be able to revert a page (and hence copy the last stored revision to the live site)
if(isset($record) && $record && !$record->canEdit()) return Security::permissionFailure($this);
$record->doRevertToLive();

View File

@ -20,18 +20,18 @@ class ImageEditor extends Controller {
Requirements::clear();
Requirements::javascript(THIRDPARTY_DIR . '/prototype.js');
Requirements::javascript(THIRDPARTY_DIR . '/scriptaculous/scriptaculous.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Utils.js');
//Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/ImageHistory.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Image.js');
//Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/ImageTransformation.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Resizeable.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Effects.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Environment.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Crop.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Resize.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/ImageBox.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/ImageEditor.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/DocumentBody.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Utils.js');
//Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/ImageHistory.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Image.js');
//Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/ImageTransformation.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Resizeable.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Effects.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Environment.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Crop.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/Resize.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/ImageBox.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/ImageEditor.js');
Requirements::javascript(CMS_DIR . '/javascript/ImageEditor/DocumentBody.js');
Requirements::javascript(THIRDPARTY_DIR . '/loader.js');
Requirements::javascript(THIRDPARTY_DIR . '/behaviour.js');
@ -257,3 +257,5 @@ class ImageEditor extends Controller {
return $path['filename'] . "." . substr($path['extension'],0,strpos($path['extension'],'?'));
}
}
?>

View File

@ -22,7 +22,7 @@ class LeftAndMain extends Controller {
static $url_segment;
static $url_rule;
static $url_rule = '/$Action/$ID/$OtherID';
static $menu_title;
@ -137,6 +137,7 @@ class LeftAndMain extends Controller {
Requirements::javascript(THIRDPARTY_DIR . '/prototype.js');
Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery_improvements.js');
Requirements::javascript(THIRDPARTY_DIR . '/behaviour.js');
Requirements::javascript(THIRDPARTY_DIR . '/jquery/plugins/livequery/jquery.livequery.js');
Requirements::javascript(SAPPHIRE_DIR . '/javascript/core/jquery.ondemand.js');
@ -182,6 +183,64 @@ class LeftAndMain extends Controller {
Requirements::customScript('Behaviour.addLoader(hideLoading);');
// Javascript combined files
Requirements::combine_files(
'assets/base.js',
array(
'jsparty/prototype.js',
'jsparty/behaviour.js',
'jsparty/prototype_improvements.js',
'jsparty/jquery/jquery.js',
'jsparty/jquery/plugins/livequery/jquery.livequery.js',
'jsparty/jquery/plugins/effen/jquery.fn.js',
'sapphire/javascript/core/jquery.ondemand.js',
'jsparty/jquery/jquery_improvements.js',
'jsparty/firebug/firebugx.js',
'sapphire/javascript/i18n.js',
)
);
Requirements::combine_files(
'assets/leftandmain.js',
array(
'jsparty/loader.js',
'jsparty/hover.js',
'jsparty/layout_helpers.js',
'jsparty/scriptaculous/effects.js',
'jsparty/scriptaculous/dragdrop.js',
'jsparty/scriptaculous/controls.js',
'jsparty/greybox/AmiJS.js',
'jsparty/greybox/greybox.js',
'cms/javascript/LeftAndMain.js',
'cms/javascript/LeftAndMain_left.js',
'cms/javascript/LeftAndMain_right.js',
//'jsparty/tiny_mce2/tiny_mce_src.js',
'jsparty/tree/tree.js',
'jsparty/tabstrip/tabstrip.js',
'cms/javascript/TinyMCEImageEnhancement.js',
'jsparty/SWFUpload/SWFUpload.js',
'cms/javascript/Upload.js',
'sapphire/javascript/TreeSelectorField.js',
'cms/javascript/ThumbnailStripField.js',
)
);
Requirements::combine_files(
'assets/cmsmain.js',
array(
'cms/javascript/CMSMain.js',
'cms/javascript/CMSMain_left.js',
'cms/javascript/CMSMain_right.js',
'cms/javascript/SideTabs.js',
'cms/javascript/SideReports.js',
'cms/javascript/LangSelector.js',
'cms/javascript/TranslationTab.js',
'jsparty/calendar/calendar.js',
'jsparty/calendar/lang/calendar-en.js',
'jsparty/calendar/calendar-setup.js',
)
);
// DEPRECATED 2.3: Use init()
$dummy = null;
$this->extend('augmentInit', $dummy);
@ -273,7 +332,7 @@ class LeftAndMain extends Controller {
*/
public function MainMenu() {
// Don't accidentally return a menu if you're not logged in - it's used to determine access.
if(!Member::currentUserID()) return new DataObjectSet();
if(!Member::currentUser()) return new DataObjectSet();
// Encode into DO set
$menu = new DataObjectSet();
@ -342,15 +401,10 @@ class LeftAndMain extends Controller {
public function Left() {
return $this->renderWith($this->getTemplatesWithSuffix('_left'));
}
public function Right() {
return $this->renderWith($this->getTemplatesWithSuffix('_right'));
}
public function RightBottom() {
if(SSViewer::hasTemplate($this->getTemplatesWithSuffix('_rightbottom'))) {
return $this->renderWith($this->getTemplatesWithSuffix('_rightbottom'));
}
}
public function getRecord($id, $className = null) {
if(!$className) $className = $this->stat('tree_class');

View File

@ -82,6 +82,8 @@ abstract class ModelAdmin extends LeftAndMain {
* a subclass of {@link BulkLoader} (mostly CSV data).
* By default {@link CsvBulkLoader} is used, assuming a standard mapping
* of column names to {@link DataObject} properties/relations.
*
* e.g. "BlogEntry" => "BlogEntryCsvBulkLoader"
*
* @var array
*/
@ -94,6 +96,19 @@ abstract class ModelAdmin extends LeftAndMain {
*/
protected static $page_length = 30;
/**
* Class name of the form field used for the results list. Overloading this in subclasses
* can let you customise the results table field.
*/
protected $resultsTableClassName = 'TableListField';
/**
* Return {@link $this->resultsTableClassName}
*/
public function resultsTableClassName() {
return $this->resultsTableClassName;
}
/**
* Initialize the model admin interface. Sets up embedded jquery libraries and requisite plugins.
*
@ -351,10 +366,8 @@ class ModelAdmin_CollectionController extends Controller {
*/
public function ImportForm() {
$modelName = $this->modelClass;
$importers = $this->parentController->getModelImporters();
if(!$importers) return false;
if(!$importers || !isset($importers[$modelName])) return false;
$fields = new FieldSet(
new HiddenField('ClassName', _t('ModelAdmin.CLASSTYPE'), $modelName),
@ -374,7 +387,7 @@ class ModelAdmin_CollectionController extends Controller {
$specRelations->push(new ArrayData(array('Name' => $name, 'Description' => $desc)));
}
$specHTML = $this->customise(array(
'ModelName' => singleton($modelName)->i18n_singular_name(),
'ModelName' => Convert::raw2att($modelName),
'Fields' => $specFields,
'Relations' => $specRelations,
))->renderWith('ModelAdmin_ImportSpec');
@ -401,16 +414,24 @@ class ModelAdmin_CollectionController extends Controller {
*
* @todo Figure out ajax submission of files via jQuery.form plugin
*
* @param unknown_type $data
* @param unknown_type $form
* @param unknown_type $request
* @param array $data
* @param Form $form
* @param HTTPRequest $request
*/
function import($data, $form, $request) {
$modelName = singleton($data['ClassName'])->i18n_singular_name();
$modelName = $data['ClassName'];
$importers = $this->parentController->getModelImporters();
$importerClass = $importers[$modelName];
$loader = new $importerClass($data['ClassName']);
// File wasn't properly uploaded, show a reminder to the user
if(empty($_FILES['_CsvFile']['tmp_name'])) {
$form->sessionMessage(_t('ModelAdmin.NOCSVFILE', 'Please browse for a CSV file to import'), 'good');
Director::redirectBack();
return false;
}
$results = $loader->load($_FILES['_CsvFile']['tmp_name']);
$message = '';
@ -428,17 +449,21 @@ class ModelAdmin_CollectionController extends Controller {
);
if(!$results->CreatedCount() && !$results->UpdatedCount()) $message .= _t('ModelAdmin.NOIMPORT', "Nothing to import");
Session::setFormMessage('Form_ImportForm', $message, 'good');
Director::redirect($_SERVER['HTTP_REFERER'] . '#Form_ImportForm_holder');
$form->sessionMessage($message, 'good');
Director::redirectBack();
}
/**
* Give the flexibilility to show variouse combination of columns in the search result table
* @param $columnsAvailable array The columns that should be made available for selecting. Should be a map. Keys are dot-syntax
* field names, and values are titles. By default the $summary_fields from your model will be used.
*/
public function ColumnSelectionField() {
public function ColumnSelectionField($columnsAvailable = null) {
$model = singleton($this->modelClass);
$source = $model->summaryFields();
$source = $columnsAvailable ? $columnsAvailable : $model->summaryFields();
// select all fields by default
$value = array();
if($source) foreach ($source as $fieldName => $label){
$value[] = $fieldName;
@ -535,18 +560,30 @@ class ModelAdmin_CollectionController extends Controller {
return $context->getQuery($searchCriteria);
}
function getResultColumns($searchCriteria) {
/**
* Returns all columns used for tabular search results display.
* Defaults to all fields specified in {@link DataObject->summaryFields()}.
*
* @param array $searchCriteria Limit fields by populating the 'ResultsAssembly' key
* @param boolean $selectedOnly Limit by 'ResultsAssempty
*/
function getResultColumns($searchCriteria, $selectedOnly = true) {
$model = singleton($this->modelClass);
$summaryFields = $model->summaryFields();
$resultAssembly = $searchCriteria['ResultAssembly'];
if(!is_array($resultAssembly)) {
$explodedAssembly = split(' *, *', $resultAssembly);
$resultAssembly = array();
foreach($explodedAssembly as $item) $resultAssembly[$item] = true;
}
$summaryFields = $this->ColumnSelectionField()->Children->dataFieldByName('ResultAssembly')->Source;
return array_intersect_key($summaryFields, $resultAssembly);
if($selectedOnly) {
$resultAssembly = $searchCriteria['ResultAssembly'];
if(!is_array($resultAssembly)) {
$explodedAssembly = split(' *, *', $resultAssembly);
$resultAssembly = array();
foreach($explodedAssembly as $item) $resultAssembly[$item] = true;
}
return array_intersect_key($summaryFields, $resultAssembly);
} else {
return $summaryFields;
}
}
/**
@ -558,7 +595,8 @@ class ModelAdmin_CollectionController extends Controller {
if($searchCriteria instanceof HTTPRequest) $searchCriteria = $searchCriteria->getVars();
$summaryFields = $this->getResultColumns($searchCriteria);
$tf = new TableListField(
$className = $this->parentController->resultsTableClassName();
$tf = new $className(
$this->modelClass,
$this->modelClass,
$summaryFields
@ -569,6 +607,10 @@ class ModelAdmin_CollectionController extends Controller {
// @todo Remove records that can't be viewed by the current user
$tf->setPermissions(array_merge(array('view','export'), TableListField::permissions_for_object($this->modelClass)));
// csv export settings (select all columns regardless of user checkbox settings in 'ResultsAssembly')
$exportFields = $this->getResultColumns($searchCriteria, false);
$tf->setFieldListCsv($exportFields);
$url = '<a href=\"' . $this->Link() . '/$ID/edit\">$value</a>';
$tf->setFieldFormatting(array_combine(array_keys($summaryFields), array_fill(0,count($summaryFields), $url)));
@ -593,7 +635,7 @@ class ModelAdmin_CollectionController extends Controller {
unset($filteredCriteria['url']);
unset($filteredCriteria['action_search']);
if(isset($filteredCriteria['Investors__PEFirm__IsPECMember']) && !$filteredCriteria['Investors__PEFirm__IsPECMember']) unset($filteredCriteria['Investors__PEFirm__IsPECMember']);
$form->setFormAction($this->Link() . '/ResultsForm?' . http_build_query($filteredCriteria));
return $form;
}
@ -719,9 +761,8 @@ class ModelAdmin_RecordController extends Controller {
$validator = ($this->currentRecord->hasMethod('getCMSValidator')) ? $this->currentRecord->getCMSValidator() : null;
$actions = new FieldSet(
new FormAction("doSave", _t('ModelAdmin.SAVE', "Save"))
);
$actions = $this->currentRecord->getCMSActions();
$actions->push(new FormAction("doSave", _t('ModelAdmin.SAVE', "Save")));
if($this->currentRecord->canDelete(Member::currentUser())) {
$actions->insertFirst($deleteAction = new FormAction('doDelete', _t('ModelAdmin.DELETE', 'Delete')));

View File

@ -20,8 +20,6 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
'addgroup',
'addmember',
'autocomplete',
'getmember',
'newmember',
'removememberfromgroup',
'savemember',
'AddRecordForm',
@ -84,8 +82,11 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
$fieldName = $this->urlParams['ID'];
$fieldVal = $_REQUEST[$fieldName];
$result = '';
// Make sure we only autocomplete on keys that actually exist, and that we don't autocomplete on password
if(!array_key_exists($fieldName, singleton($this->stat('subitem_class'))->stat('db')) || $fieldName == 'Password') return;
$matches = DataObject::get($this->stat('subitem_class'),"\"$fieldName\" LIKE '" . addslashes($fieldVal) . "%'");
$matches = DataObject::get($this->stat('subitem_class'),"\"$fieldName\" LIKE '" . Convert::raw2sql($fieldVal) . "%'");
if($matches) {
$result .= "<ul>";
foreach($matches as $match) {
@ -93,7 +94,6 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
$data = $match->FirstName;
$data .= ",$match->Surname";
$data .= ",$match->Email";
$data .= ",$match->Password";
$result .= "<li>" . $match->$fieldName . "<span class=\"informal\">($match->FirstName $match->Surname, $match->Email)</span><span class=\"informal data\">$data</span></li>";
}
$result .= "</ul>";
@ -101,15 +101,6 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
}
}
public function getmember() {
Session::set('currentMember', $_REQUEST['ID']);
SSViewer::setOption('rewriteHashlinks', false);
$result = $this->renderWith("LeftAndMain_rightbottom");
$parts = split('</?form[^>]*>', $result);
echo $parts[1];
}
public function MemberForm() {
$id = $_REQUEST['ID'] ? $_REQUEST['ID'] : Session::get('currentMember');
if($id)
@ -235,24 +226,6 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
return $this->returnItemToUser($newGroup);
}
public function newmember() {
Session::clear('currentMember');
$newMemberForm = array(
"MemberForm" => $this->getMemberForm('new'),
);
// This should be using FormResponse ;-)
if(Director::is_ajax()) {
SSViewer::setOption('rewriteHashlinks', false);
$customised = $this->customise($newMemberForm);
$result = $customised->renderWith($this->class . "_rightbottom");
$parts = split('</?form[^>]*>', $result);
return $parts[1];
} else {
return $newMemberForm;
}
}
public function EditedMember() {
if(Session::get('currentMember'))
return DataObject::get_by_id("Member", Session::get('currentMember'));

View File

@ -3,6 +3,12 @@
* This class lets you export a static copy of your site.
* It creates a huge number of folders each containing an index.html file.
* This preserves the URL naming format.
*
* Requirements: Unix Filesystem supporting symlinking.
* Doesn't work on Windows.
*
* @see StaticPublisher
*
* @package cms
* @subpackage export
*/
@ -41,63 +47,60 @@ class StaticExporter extends Controller {
}
function export() {
if($_REQUEST['baseurl']) {
// specify custom baseurl for publishing to other webroot
if(isset($_REQUEST['baseurl'])) {
$base = $_REQUEST['baseurl'];
if(substr($base,-1) != '/') $base .= '/';
Director::setBaseURL($base);
}
$folder = '/tmp/static-export/' . project();
if(!project()) $folder .= 'site';
if(!file_exists($folder)) mkdir($folder, Filesystem::$folder_create_mask, true);
// setup temporary folders
$tmpBaseFolder = TEMP_FOLDER . '/static-export';
$tmpFolder = (project()) ? "$tmpBaseFolder/" . project() : "$tmpBaseFolder/site";
if(!file_exists($tmpFolder)) Filesystem::makeFolder($tmpFolder);
$baseFolderName = basename($tmpFolder);
// symlink /assets
$f1 = ASSETS_PATH;
$f2 = Director::baseFolder() . '/' . project();
`cd $folder; ln -s $f1; ln -s $f2`;
`cd $tmpFolder; ln -s $f1; ln -s $f2`;
$baseFolder = basename($folder);
if($folder && file_exists($folder)) {
$pages = DataObject::get("SiteTree");
foreach($pages as $page) {
$subfolder = "$folder/$page->URLSegment";
$contentfile = "$folder/$page->URLSegment/index.html";
// Make the folder
if(!file_exists($subfolder)) {
mkdir($subfolder, Filesystem::$folder_create_mask);
}
// Run the page
Requirements::clear();
$controllerClass = "{$page->class}_Controller";
if(class_exists($controllerClass)) {
$controller = new $controllerClass($page);
$pageContent = $controller->handleRequest(new HTTPRequest('GET',''))->getBody();
// Write to file
if($fh = fopen($contentfile, 'w')) {
fwrite($fh, $pageContent->getBody());
fclose($fh);
}
}
// iterate through all instances of SiteTree
$pages = DataObject::get("SiteTree");
foreach($pages as $page) {
$subfolder = "$tmpFolder/$page->URLSegment";
$contentfile = "$tmpFolder/$page->URLSegment/index.html";
// Make the folder
if(!file_exists($subfolder)) {
Filesystem::makeFolder($subfolder);
}
copy("$folder/home/index.html", "$folder/index.html");
// Run the page
Requirements::clear();
$link = Director::makeRelative($page->Link());
$response = Director::test($link);
`cd /tmp/static-export; tar -czhf $baseFolder.tar.gz $baseFolder`;
$content = file_get_contents("/tmp/static-export/$baseFolder.tar.gz");
Filesystem::removeFolder('/tmp/static-export');
return HTTPRequest::send_file($content, "$baseFolder.tar.gz");
} else {
echo _t('StaticExporter.ONETHATEXISTS',"Please specify a folder that exists");
// Write to file
if($fh = fopen($contentfile, 'w')) {
fwrite($fh, $response->getBody());
fclose($fh);
}
}
// copy homepage (URLSegment: "home") to webroot
copy("$tmpFolder/home/index.html", "$tmpFolder/index.html");
// archive all generated files
`cd $tmpBaseFolder; tar -czhf $baseFolderName.tar.gz $baseFolderName`;
$archiveContent = file_get_contents("$tmpBaseFolder/$baseFolderName.tar.gz");
// remove temporary files and folder
Filesystem::removeFolder($tmpBaseFolder);
// return as download to the client
$response = HTTPRequest::send_file($archiveContent, "$baseFolderName.tar.gz", 'application/x-tar-gz');
echo $response->output();
}
}

View File

@ -114,3 +114,5 @@ class FilesystemPublisher extends StaticPublisher {
}
}
}
?>

View File

@ -75,3 +75,5 @@ abstract class StaticPublisher extends DataObjectDecorator {
return $urls;
}
}
?>

View File

@ -193,62 +193,6 @@
clear: left;
}
/**
* Bottom-right
*/
#rightbottom {
border: none;
margin-top: 4px;
margin-left: 1px;
border: 1px solid #808080;
}
#rightbottom form {
margin: 1em;
}
#rightbottom form div {
margin-top: 3px;
}
#rightbottom form div.field {
clear: both;
margin-left: 10em;
font-size: 12px;
border: none;
}
#rightbottom form label.left {
float: left;
width: 10em;
margin-left: -10em;
}
#rightbottom form input,
#rightbottom form select,
#rightbottom form textarea {
width: 90%;
}
#rightbottom form input.checkbox,
#rightbottom form .optionset input,
#rightbottom form .htmleditor select,
#rightbottom form input.action {
width: auto;
}
#rightbottom form .optionset li {
list-style: none;
}
#rightbottom form h2 {
clear: both;
}
#rightbottom form .fieldgroup input,
#rightbottom form .fieldgroup select {
width: auto;
}
/**
* RHS Action Parameters boxes
*/

View File

@ -119,7 +119,7 @@ body.stillLoading select {
border: 1px solid #acbbcc;
background: #fff;
}
#right, #rightbottom {
#right {
position: absolute;
left: 208px;
top: 45px;
@ -132,10 +132,6 @@ body.stillLoading select {
margin-right: 3px;
}
#rightbottom {
height: 30%;
}
#separator {
position: absolute;
top: 51px;
@ -161,17 +157,13 @@ body.stillLoading select {
}
#left div.title, #right div.title, #rightbottom div.title {
#left div.title, #right div.title {
border-top: 1px solid #77BBEE;
height: 22px !important;
background: #0075C9 url(../images/texture/obar.gif) repeat-x 0 0;
}
#rightbottom div.light {
background-image: url(../images/textures/obar-light.png) !important;
}
#left div.title div, #right div.title div, #rightbottom div.title div {
#left div.title div, #right div.title div {
font-size: 14px;
font-weight: bold;
color: #fff;

View File

@ -1,5 +1,15 @@
var _AJAX_LOADING = false;
// Resize the tabs once the document is properly loaded
// @todo most of this file needs to be tidied up using jQuery
if(typeof(jQuery) != 'undefined') {
(function($) {
$(document).ready(function() {
window.onresize(true);
});
})(jQuery);
}
/**
* Code for the separator bar between the two panes
*/
@ -33,8 +43,7 @@ DraggableSeparator.prototype = {
}
function fixRightWidth() {
if( !$('right') )
return;
if(!$('right')) return;
// Absolutely position all the elements
var sep = getDimension($('left'),'width') + getDimension($('left'),'left');
@ -53,14 +62,7 @@ function fixRightWidth() {
$('contentPanel').style.left = leftWidth + sepWidth + rightWidth + sepWidth + 23 + 'px';
}
if( rightWidth >= 0 )
$('right').style.width = rightWidth + 'px';
var rb;
if(rb = $('rightbottom')) {
rb.style.left = $('right').style.left;
rb.style.width = $('right').style.width;
}
if(rightWidth >= 0) $('right').style.width = rightWidth + 'px';
}
Behaviour.register({
@ -140,7 +142,7 @@ window.ontabschanged = function() {
fitToParent(divs[i], 3);
}
}*/
if(typeof _TAB_DIVS_ON_PAGE != 'undefined') {
for(i = 0; i < _TAB_DIVS_ON_PAGE.length; i++ ) {
fitToParent(_TAB_DIVS_ON_PAGE[i], 30);
@ -150,8 +152,6 @@ window.ontabschanged = function() {
window.onresize = function(init) {
var right = $('right');
var rightbottom = $('rightbottom');
if(rightbottom) rightbottom.style.display = 'none';
if(typeof fitToParent == 'function') {
fitToParent('right', 12);
@ -171,14 +171,6 @@ window.onresize = function(init) {
$('left').style.height = $('separator').style.height = rightH + 'px';
}
if(rightbottom) {
var newHeight = rightH / 3;
right.style.height = (newHeight*2) + 'px';
rightbottom.style.height = newHeight + 'px';
rightbottom.style.display = '';
rightbottom.style.top = getDimension(right,'top') + (newHeight*2) + 'px';
}
if(typeof fitToParent == 'function') {
fitToParent('Form_EditForm');
if($('Form_EditorToolbarImageForm') && $('Form_EditorToolbarImageForm').style.display == "block") {

View File

@ -317,7 +317,7 @@ CMSRightForm.prototype = {
}*/
}
CMSForm.applyTo('#Form_SubForm', 'rightbottom');
CMSForm.applyTo('#Form_SubForm');
CMSRightForm.applyTo('#Form_EditForm', 'right');
function action_save_right() {

View File

@ -111,7 +111,7 @@ $(document).ready(function() {
* Clear search button
*/
$('#SearchForm_holder button[name=action_clearsearch]').click(function(e) {
$(this.form).clearForm();
$(this.form).resetForm();
return false;
});

View File

@ -103,16 +103,22 @@ WidgetAreaEditor.prototype = {
// Order the sort by the order the widgets are in the list
var usedWidgets = $('WidgetAreaEditor_usedWidgets');
if (usedWidgets) {
if(usedWidgets) {
widgets = usedWidgets.childNodes;
for( i = 0; div = widgets[i]; i++ ) {
var fields = div.getElementsByTagName('input');
for( j = 0; field = fields.item(j); j++ ) {
if( field.name == div.id + '[Sort]' ) {
field.value = i;
for(i = 0; i < widgets.length; i++) {
var div = widgets[i];
if(div.nodeName != '#comment') {
var fields = div.getElementsByTagName('input');
for(j = 0; field = fields.item(j); j++) {
if(field.name == div.id + '[Sort]') {
field.value = i;
}
}
}
}
}
},

View File

@ -26,9 +26,10 @@ if((typeof tinyMCE != 'undefined')) {
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_toolbar_parent : "right",
plugins : "template,contextmenu,table,emotions,paste,../../tinymce_ssbuttons,../../tinymce_advcode,spellchecker",
plugins : "blockquote,template,contextmenu,table,emotions,paste,../../tinymce_ssbuttons,../../tinymce_advcode,spellchecker",
blockquote_clear_tag : "p",
table_inline_editing : true,
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect,separator,bullist,numlist,outdent,indent,hr,charmap",
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect,separator,bullist,numlist,outdent,indent,blockquote,hr,charmap",
theme_advanced_buttons2 : "undo,redo,separator,cut,copy,paste,pastetext,pasteword,spellchecker,separator,ssimage,ssflash,sslink,unlink,anchor,separator,template,advcode,separator,search,replace,selectall,visualaid,separator,tablecontrols",
theme_advanced_buttons3 : "",
spellchecker_languages : "$SpellcheckLangs",
@ -39,9 +40,7 @@ if((typeof tinyMCE != 'undefined')) {
safari_warning : false,
relative_urls : true,
verify_html : true,
valid_elements : "+a[id|rel|rev|dir|tabindex|accesskey|type|name|href|target|title|class],-strong/-b[class],-em/-i[class],-strike[class],-u[class],#p[id|dir|class|align],-ol[class],-ul[class],-li[class],br,img[id|dir|longdesc|usemap|class|src|border|alt=|title|width|height|align],-sub[class],-sup[class],-blockquote[dir|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|dir|id|style],-tr[id|dir|class|rowspan|width|height|align|valign|bgcolor|background|bordercolor|style],tbody[id|class|style],thead[id|class|style],tfoot[id|class|style],-td[id|dir|class|colspan|rowspan|width|height|align|valign|scope|style],-th[id|dir|class|colspan|rowspan|width|height|align|valign|scope|style],caption[id|dir|class],-div[id|dir|class|align],-span[class|align],-pre[class|align],address[class|align],-h1[id|dir|class|align],-h2[id|dir|class|align],-h3[id|dir|class|align],-h4[id|dir|class|align],-h5[id|dir|class|align],-h6[id|dir|class|align],hr[class],dd[id|class|title|dir],dl[id|class|title|dir],dt[id|class|title|dir],iframe[align<bottom?left?middle?right?top|class|frameborder|height|id|longdesc|marginheight|marginwidth|name|scrolling<auto?no?yes|src|style|title|width]",
extended_valid_elements : "img[class|src|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],script[src|type],object[width|height|type|data],param[value|name]"
verify_html : true
});
}
@ -54,4 +53,4 @@ Behaviour.register({
}
}
}
})
})

View File

@ -17,6 +17,7 @@
</tr>
</thead>
<tfoot>
<% if can(add) %>
<tr class="addtogrouprow">
<% if Markable %><td width="18">&nbsp;</dh><% end_if %>
$AddRecordForm.CellFields
@ -31,6 +32,7 @@
<% if Can(edit) %><td width="18">&nbsp;</td><% end_if %>
<% if Can(delete) %><td width="18">&nbsp;</td><% end_if %>
</tr>
<% end_if %>
</tfoot>
<tbody>
<% if Items %>

View File

@ -31,10 +31,13 @@
<h3><% _t('SEARCHLISTINGS','Search') %></h3>
$SearchForm
<h3><% _t('IMPORT_TAB_HEADER', 'Import') %></h3>
$ImportForm
</div>
<% if ImportForm %>
<h3><% _t('IMPORT_TAB_HEADER', 'Import') %></h3>
$ImportForm
<% end_if %>
</div>
<% end_control %>
</div>
</div>

View File

@ -24,13 +24,6 @@
$Right
</div>
<% if RightBottom %>
<div class="right" id="rightbottom">
$RightBottom
<div id="statusMessage" style="display:none;"></div>
</div>
<% end_if %>
<div id="contentPanel" style="display:none;">
<% control EditorToolbar %>
$ImageForm

View File

@ -1,10 +0,0 @@
<p>$Message</p>
<ul id="TaskList">
<% control Tasks %>
<li class="$EvenOdd">
<a href="admin/show/$ID">$Title</a>
<div class="extra"><% _t('BY','by') %> $RequestedBy.FirstName&nbsp;$RequestedBy.Surname.Initial, $Created.Ago</div>
</li>
<% end_control %>
</ul>