mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
Merged from branches/2.3
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@76846 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
5b0ee9678f
commit
b1018f5864
@ -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 "<img src=\"$url\" alt=\"$title\" />";
|
||||
}
|
||||
}
|
||||
|
@ -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');
|
||||
@ -1534,6 +1534,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
|
||||
* to the database.
|
||||
|
@ -358,6 +358,10 @@ class Folder extends File {
|
||||
new HiddenField("ID")
|
||||
);
|
||||
|
||||
if(!$this->canEdit()) {
|
||||
$fields->removeFieldFromTab("Root", "Upload");
|
||||
}
|
||||
|
||||
$this->extend('updateCMSFields', $fields);
|
||||
|
||||
return $fields;
|
||||
|
249
forms/HtmlEditorConfig.php
Normal file
249
forms/HtmlEditorConfig.php
Normal file
@ -0,0 +1,249 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A PHP version of TinyMCE's configuration, to allow various parameters to be configured on a site or section basis
|
||||
*
|
||||
* There can be multiple HtmlEditorConfig's, which should always be created / accessed using HtmlEditorConfig::get. You can then set
|
||||
* the currently active config using set_active. Whichever config is active when HtmlEditorField#Field is called wins.
|
||||
*
|
||||
* @author "Hamish Friedlander" <hamish@silverstripe.com>
|
||||
*/
|
||||
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) . ");
|
||||
}";
|
||||
}
|
||||
}
|
@ -20,13 +20,12 @@ class HtmlEditorField extends TextareaField {
|
||||
$this->extraClass = 'typography';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the a <textarea> field with tinymce="true" set on it
|
||||
*/
|
||||
function Field() {
|
||||
Requirements::javascript(MCE_ROOT . "tiny_mce_src.js");
|
||||
Requirements::javascript(SAPPHIRE_DIR . '/javascript/HtmlEditorField.js');
|
||||
Requirements::customScript(HtmlEditorConfig::get_active()->generateJS(), 'htmlEditorConfig');
|
||||
|
||||
// Don't allow unclosed tags - they will break the whole application ;-)
|
||||
$cleanVal = $this->value;
|
||||
|
@ -936,24 +936,21 @@ JS
|
||||
$items = $this->customSourceItems;
|
||||
} else {
|
||||
$dataQuery = $this->getCsvQuery();
|
||||
$records = $dataQuery->execute();
|
||||
$sourceClass = $this->sourceClass;
|
||||
$dataobject = new $sourceClass();
|
||||
$items = $dataobject->buildDataObjectSet($records, 'DataObjectSet');
|
||||
}
|
||||
|
||||
if($items && $items->count()) foreach($items as $item) {
|
||||
// create a TableListField_Item to support resolving of
|
||||
// relation-fields in dot notation via TableListField_Item->Fields()
|
||||
if($item) $fieldItems->push(new TableListField_Item($item, $this));
|
||||
$items = $dataQuery->execute();
|
||||
}
|
||||
|
||||
// temporary override to adjust TableListField_Item behaviour
|
||||
$this->setFieldFormatting(array());
|
||||
$this->fieldList = $csvColumns;
|
||||
|
||||
if($fieldItems) {
|
||||
foreach($fieldItems as $fieldItem) {
|
||||
if($items) {
|
||||
foreach($items as $item) {
|
||||
if(is_array($item)) {
|
||||
$className = isset($item['RecordClassName']) ? $item['RecordClassName'] : $item['ClassName'];
|
||||
$item = new $className($item);
|
||||
}
|
||||
$fieldItem = new TableListField_Item($item, $this);
|
||||
|
||||
$fields = $fieldItem->Fields();
|
||||
$columnData = array();
|
||||
if($fields) foreach($fields as $field) {
|
||||
@ -973,6 +970,10 @@ JS
|
||||
}
|
||||
$fileData .= implode($separator, $columnData);
|
||||
$fileData .= "\n";
|
||||
|
||||
$item->destroy();
|
||||
unset($item);
|
||||
unset($fieldItem);
|
||||
}
|
||||
|
||||
$numColumns = count($columnData);
|
||||
|
@ -13,6 +13,7 @@ class VersionedTest extends SapphireTest {
|
||||
// Get all items, ignoring deleted
|
||||
$remainingPages = DataObject::get("SiteTree", "ParentID = 0");
|
||||
// Check that page 3 has gone
|
||||
$this->assertNotNull($remainingPages);
|
||||
$this->assertEquals(array("Page 1", "Page 2"), $remainingPages->column('Title'));
|
||||
|
||||
// Get all including deleted
|
||||
|
@ -10,6 +10,7 @@ class VirtualPageTest extends SapphireTest {
|
||||
function testEditingSourcePageUpdatesVirtualPages() {
|
||||
$master = $this->objFromFixture('Page', 'master');
|
||||
$master->Title = "New title";
|
||||
$master->MenuTitle = "New menutitle";
|
||||
$master->Content = "<p>New content</p>";
|
||||
$master->write();
|
||||
|
||||
@ -18,6 +19,8 @@ class VirtualPageTest extends SapphireTest {
|
||||
|
||||
$this->assertEquals("New title", $vp1->Title);
|
||||
$this->assertEquals("New title", $vp2->Title);
|
||||
$this->assertEquals("New menutitle", $vp1->MenuTitle);
|
||||
$this->assertEquals("New menutitle", $vp2->MenuTitle);
|
||||
$this->assertEquals("<p>New content</p>", $vp1->Content);
|
||||
$this->assertEquals("<p>New content</p>", $vp2->Content);
|
||||
}
|
||||
@ -29,6 +32,7 @@ class VirtualPageTest extends SapphireTest {
|
||||
function testPublishingSourcePagePublishesVirtualPages() {
|
||||
$master = $this->objFromFixture('Page', 'master');
|
||||
$master->Title = "New title";
|
||||
$master->MenuTitle = "New menutitle";
|
||||
$master->Content = "<p>New content</p>";
|
||||
$master->write();
|
||||
$master->doPublish();
|
||||
@ -42,9 +46,31 @@ class VirtualPageTest extends SapphireTest {
|
||||
|
||||
$this->assertEquals("New title", $vp1->Title);
|
||||
$this->assertEquals("New title", $vp2->Title);
|
||||
$this->assertEquals("New menutitle", $vp1->MenuTitle);
|
||||
$this->assertEquals("New menutitle", $vp2->MenuTitle);
|
||||
$this->assertEquals("<p>New content</p>", $vp1->Content);
|
||||
$this->assertEquals("<p>New content</p>", $vp2->Content);
|
||||
Versioned::reading_stage("Stage");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that virtual pages get the content from the master page when they are created.
|
||||
*/
|
||||
function testNewVirtualPagesGrabTheContentFromTheirMaster() {
|
||||
$vp = new VirtualPage();
|
||||
$vp->write();
|
||||
|
||||
$vp->CopyContentFromID = $this->idFromFixture('Page', 'master');
|
||||
$vp->write();
|
||||
|
||||
$this->assertEquals("My Page", $vp->Title);
|
||||
$this->assertEquals("My Page Nav", $vp->MenuTitle);
|
||||
|
||||
$vp->CopyContentFromID = $this->idFromFixture('Page', 'master2');
|
||||
$vp->write();
|
||||
|
||||
$this->assertEquals("My Other Page", $vp->Title);
|
||||
$this->assertEquals("My Other Page Nav", $vp->MenuTitle);
|
||||
}
|
||||
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
Page:
|
||||
master:
|
||||
Title: My Page
|
||||
MenuTitle: My Page Nav
|
||||
master2:
|
||||
Title: My Other Page
|
||||
MenuTitle: My Other Page Nav
|
||||
holder:
|
||||
Title: Sub-pages
|
||||
VirtualPage:
|
||||
|
Loading…
x
Reference in New Issue
Block a user