From b1018f5864d0b23395af445f28e6866978ff3cc9 Mon Sep 17 00:00:00 2001 From: Sean Harvey Date: Thu, 14 May 2009 05:26:47 +0000 Subject: [PATCH] Merged from branches/2.3 git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@76846 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- core/model/Image.php | 6 - core/model/SiteTree.php | 15 +- filesystem/Folder.php | 4 + forms/HtmlEditorConfig.php | 249 ++++++++++++++++++++++++++++++++ forms/HtmlEditorField.php | 3 +- forms/TableListField.php | 25 ++-- tests/model/VersionedTest.php | 1 + tests/model/VirtualPageTest.php | 26 ++++ tests/model/VirtualPageTest.yml | 2 + 9 files changed, 307 insertions(+), 24 deletions(-) create mode 100644 forms/HtmlEditorConfig.php diff --git a/core/model/Image.php b/core/model/Image.php index 87df32c5e..d30f221b6 100755 --- a/core/model/Image.php +++ b/core/model/Image.php @@ -102,12 +102,6 @@ class Image extends File { $url = $this->URL(); $title = ($this->Title) ? $this->Title : $this->Filename; - // remove file path and extension - // that accessware.co.nz complains about this - if (preg_match("/([^\/.]*)\..{1,6}$/", $title, $matches)) { - $title = $matches[1]; - } - return "\"$title\""; } } diff --git a/core/model/SiteTree.php b/core/model/SiteTree.php index 47871e2c4..dc57e89ee 100644 --- a/core/model/SiteTree.php +++ b/core/model/SiteTree.php @@ -696,12 +696,12 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid // if page can't be edited, don't grant delete permissions if(!$this->canEdit($member)) return false; - + $children = $this->AllChildren(); if($children) foreach($children as $child) { if(!$child->canDelete($member)) return false; } - + return $this->stat('can_create') != false; } @@ -1337,8 +1337,8 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid $labels['ShowInMenus'] =_t('SiteTree.SHOWINMENUS', "Show in menus?"); $labels['ShowInSearch'] = _t('SiteTree.SHOWINSEARCH', "Show in search?"); $labels['ProvideComments'] = _t('SiteTree.ALLOWCOMMENTS', "Allow comments on this page?"); - $labels['ViewersGroup'] = _t('SiteTree.GROUP', "Group"); - $labels['EditorsGroup'] = _t('SiteTree.GROUP'); + $labels['ViewerGroups'] = _t('SiteTree.VIEWERGROUPS', "Viewer Groups"); + $labels['EditorGroups'] = _t('SiteTree.EDITORGROUPS', "Editor Groups"); $labels['URLSegment'] = _t('SiteTree.URLSegment', 'URL Segment', PR_MEDIUM, 'URL for this page'); $labels['Content'] = _t('SiteTree.Content', 'Content', PR_MEDIUM, 'Main HTML Content for a page'); $labels['HomepageForDomain'] = _t('SiteTree.HomepageForDomain', 'Hompage for this domain'); @@ -1533,6 +1533,13 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid return $result; } + + function doDeleteFromLive() { + $origStage = Versioned::current_stage(); + Versioned::reading_stage('Live'); + $this->delete(); + Versioned::reading_stage($origStage); + } /** * Check if this page is new - that is, if it has yet to have been written diff --git a/filesystem/Folder.php b/filesystem/Folder.php index 385351da6..71f62351b 100755 --- a/filesystem/Folder.php +++ b/filesystem/Folder.php @@ -357,6 +357,10 @@ class Folder extends File { ), new HiddenField("ID") ); + + if(!$this->canEdit()) { + $fields->removeFieldFromTab("Root", "Upload"); + } $this->extend('updateCMSFields', $fields); diff --git a/forms/HtmlEditorConfig.php b/forms/HtmlEditorConfig.php new file mode 100644 index 000000000..1029d61ad --- /dev/null +++ b/forms/HtmlEditorConfig.php @@ -0,0 +1,249 @@ + + */ +class HtmlEditorConfig { + + static $configs = array(); + static $current = null; + + /** + * Get the HtmlEditorConfig object for the given identifier. This is a correct way to get an HtmlEditorConfig instance - do not call 'new' + * @param $identifier string - the identifier for the config set + * @return HtmlEditorConfig - the configuration object. This will be created if it does not yet exist for that identifier + */ + static function get($identifier = 'default') { + if (!array_key_exists($identifier, self::$configs)) self::$configs[$identifier] = new HtmlEditorConfig(); + return self::$configs[$identifier]; + } + + /** + * Set the currently active configuration object + * @param $identifier string - the identifier for the config set + * @return null + */ + static function set_active($identifier = null) { + self::$current = $identifier; + } + + /** + * Get the currently active configuration object + * @return HtmlEditorConfig - the active configuration object + */ + static function get_active() { + $identifier = self::$current ? self::$current : 'default'; + return self::get($identifier); + } + + /** + * Holder for all TinyMCE settings _except_ plugins and buttons + */ + protected $settings = array( + 'mode' => "specific_textareas", + 'editor_selector' => "htmleditor", + 'width' => "100%", + 'auto_resize' => false, + 'theme' => "advanced", + + 'theme_advanced_layout_manager' => "SimpleLayout", + 'theme_advanced_toolbar_location' => "top", + 'theme_advanced_toolbar_align' => "left", + 'theme_advanced_toolbar_parent' => "right", + + 'blockquote_clear_tag' => "p", + 'table_inline_editing' => true, + + 'safari_warning' => false, + 'relative_urls' => true, + 'verify_html' => true + ); + + /** + * Holder list of enabled plugins + */ + protected $plugins = array( + 'blockquote', 'contextmenu', 'table', 'emotions', 'paste', '../../tinymce_advcode', 'spellchecker' + ); + + /** + * Holder list of buttons, organised by line + */ + protected $buttons = array( + 1 => array('bold','italic','underline','strikethrough','separator','justifyleft','justifycenter','justifyright','justifyfull','formatselect','separator','bullist','numlist','outdent','indent','blockquote','hr','charmap'), + 2 => array('undo','redo','separator','cut','copy','paste','pastetext','pasteword','spellchecker','separator','advcode','search','replace','selectall','visualaid','separator','tablecontrols'), + 3 => array() + ); + + /** + * Get the current value of an option + * @param $k string - The key of the option to get + * @return mixed - The value of the specified option + */ + function getOption($k) { + return $this->settings[$k]; + } + + /** + * Set the value of one option + * @param $k string - The key of the option to set + * @param $v mixed - The value of the option to set + * @return mixed - $v returned for chaining + */ + function setOption($k,$v) { + return $this->settings[$k] = $v; + } + + /** + * Set multiple options + * @param $a array - The options to set, as keys and values of the array + * @return null + */ + function setOptions($a) { + foreach ($a as $k=>$v) { + $this->settings[$k] = $v; + } + } + + /** + * Enable one or several plugins. Will maintain unique list if already enabled plugin is re-passed + * @param[0..] a string, or several strings, or a single array of strings - The plugins to enable + * @return null + */ + function enablePlugins() { + $plugins = func_get_args(); + if (is_array($plugins[0])) $plugins = $plugins[0]; + + foreach ($plugins as $plugin) { + if (!in_array($plugin, $this->plugins)) $this->plugins[] = $plugin; + } + } + + /** + * Enable one or several plugins. Will properly handle being passed a plugin that is already disabled + * @param[0..] a string, or several strings, or a single array of strings - The plugins to disable + * @return null + */ + function disablePlugins() { + $plugins = func_get_args(); + if (is_array($plugins[0])) $plugins = $plugins[0]; + + foreach ($plugins as $plugin) { + if (($idx = array_search($plugin, $this->plugins)) !== false) { + array_splice($this->plugins, $idx, 1); + continue; + } + } + } + + /** + * Totally re-set the buttons on a given line + * @param[0] integer from 1..3 - The line number to redefine + * @param[1..] a string or several strings, or a single array of strings - The button names to make this line contain + * @return null + */ + function setButtonsForLine() { + if (func_num_args() == 2) { + list($line, $buttons) = func_get_args(); + } + else { + $buttons = func_get_args(); + $line = array_shift($buttons); + } + $this->buttons[$line] = is_array($buttons) ? $buttons : array($buttons); + } + + /** + * Add buttons to the end of a line + * @param[0] integer from 1..3 + * @param[1..] a string, or several strings, or a single array of strings - The button names to add to the end of this line + * @return null + */ + function addButtonsToLine() { + $inserts = func_get_args(); + $line = array_shift($inserts); + if (is_array($inserts[0])) $inserts = $inserts[0]; + + foreach ($inserts as $button) { + $this->buttons[$line][] = $button; + } + } + + /** + * Internal function for adding and removing buttons related to another button + * @param $name string - the name of the button to modify + * @param $offset integer - the offset relative to that button to perform an array_splice at - 0 for before $name, 1 for after + * @param $del integer - the number of buttons to remove at the position given by index(string) + offset + * @param $add mixed - an array or single item to insert at the position given by index(string) + offset, or null for no insertion + * @return boolean - true if $name matched a button, false otherwise + */ + protected function modifyButtons($name, $offset, $del=0, $add=null) { + foreach ($this->buttons as &$buttons) { + if (($idx = array_search($name, $buttons)) !== false) { + if ($add) array_splice($buttons, $idx+$offset, $del, $add); + else array_splice($buttons, $idx+$offset, $del, $add); + return true; + } + } + return false; + } + + /** + * Insert buttons before the first occurance of another button + * @param[0] string - the name of the button to insert other buttons before + * @param[1..] a string, or several strings, or a single array of strings - the button names to insert before that button + * @return boolean - true if insertion occured, false if it did not (because the given button name was not found) + */ + function insertButtonsBefore() { + $inserts = func_get_args(); + $before = array_shift($inserts); + return $this->modifyButtons($before, 0, 0, $inserts); + } + + /** + * Insert buttons after the first occurance of another button + * @param[0] string - the name of the button to insert other buttons after + * @param[1..] a string, or several strings, or a single array of strings - the button names to insert after that button + * @return boolean - true if insertion occured, false if it did not (because the given button name was not found) + */ + function insertButtonsAfter() { + $inserts = func_get_args(); + $after = array_shift($inserts); + return $this->modifyButtons($after, 1, 0, $inserts); + } + + /** + * Remove the first occurance of buttons + * @param[0..] string - the name of the buttons to remove + * @return null + */ + function removeButtons() { + $removes = func_get_args(); + foreach ($removes as $button) { + $this->modifyButtons($button, 0, 1); + } + } + + /** + * Generate the javascript that will set tinyMCE's configuration to that of the current settings of this object + * @return string - the javascript + */ + function generateJS() { + $config = $this->settings; + $config['plugins'] = implode(',', $this->plugins); + + foreach ($this->buttons as $i=>$buttons) { + $config['theme_advanced_buttons'.$i] = implode(',', $buttons); + } + + return " +if((typeof tinyMCE != 'undefined')) { + tinyMCE.init(" . Convert::raw2json($config) . "); +}"; + } +} diff --git a/forms/HtmlEditorField.php b/forms/HtmlEditorField.php index 593b8e6a7..21e04e794 100755 --- a/forms/HtmlEditorField.php +++ b/forms/HtmlEditorField.php @@ -20,13 +20,12 @@ class HtmlEditorField extends TextareaField { $this->extraClass = 'typography'; } - /** * Returns the a