mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
API CHANGE Moved Widget API to new module (https://github.com/silverstripe/silverstripe-widgets), incl. WidgetArea and WidgetAreaEditor classes
This commit is contained in:
parent
4fd757341a
commit
8a72b32e95
@ -1,232 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Widgets let CMS authors drag and drop small pieces of functionality into
|
|
||||||
* defined areas of their websites.
|
|
||||||
*
|
|
||||||
* ## Forms
|
|
||||||
* You can use forms in widgets by implementing a {@link Widget_Controller}.
|
|
||||||
* See {@link Widget_Controller} for more information.
|
|
||||||
*
|
|
||||||
* @package cms
|
|
||||||
* @subpackage widgets
|
|
||||||
*/
|
|
||||||
class Widget extends DataObject {
|
|
||||||
static $db = array(
|
|
||||||
"Sort" => "Int",
|
|
||||||
"Enabled" => "Boolean"
|
|
||||||
);
|
|
||||||
|
|
||||||
static $defaults = array(
|
|
||||||
'Enabled' => true
|
|
||||||
);
|
|
||||||
|
|
||||||
static $has_one = array(
|
|
||||||
"Parent" => "WidgetArea",
|
|
||||||
);
|
|
||||||
|
|
||||||
static $has_many = array();
|
|
||||||
static $many_many = array();
|
|
||||||
static $belongs_many_many = array();
|
|
||||||
|
|
||||||
static $default_sort = "\"Sort\"";
|
|
||||||
|
|
||||||
static $title = "Widget Title";
|
|
||||||
static $cmsTitle = "Name of this widget";
|
|
||||||
static $description = "Description of what this widget does.";
|
|
||||||
|
|
||||||
function getCMSFields() {
|
|
||||||
$fields = new FieldList();
|
|
||||||
$this->extend('updateCMSFields', $fields);
|
|
||||||
return $fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Note: Overloaded in {@link Widget_Controller}.
|
|
||||||
*
|
|
||||||
* @return string HTML
|
|
||||||
*/
|
|
||||||
function WidgetHolder() {
|
|
||||||
return $this->renderWith("WidgetHolder");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the widget content in a custom template with the same name as the current class.
|
|
||||||
* This should be the main point of output customization.
|
|
||||||
*
|
|
||||||
* Invoked from within WidgetHolder.ss, which contains
|
|
||||||
* the "framing" around the custom content, like a title.
|
|
||||||
*
|
|
||||||
* Note: Overloaded in {@link Widget_Controller}.
|
|
||||||
*
|
|
||||||
* @return string HTML
|
|
||||||
*/
|
|
||||||
function Content() {
|
|
||||||
return $this->renderWith(array_reverse(ClassInfo::ancestry($this->class)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function Title() {
|
|
||||||
return Object::get_static($this->class, 'title');
|
|
||||||
}
|
|
||||||
|
|
||||||
function CMSTitle() {
|
|
||||||
return Object::get_static($this->class, 'cmsTitle');
|
|
||||||
}
|
|
||||||
|
|
||||||
function Description() {
|
|
||||||
return Object::get_static($this->class, 'description');
|
|
||||||
}
|
|
||||||
|
|
||||||
function DescriptionSegment() {
|
|
||||||
return $this->renderWith('WidgetDescription');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Widget_Controller->editablesegment()
|
|
||||||
*/
|
|
||||||
function EditableSegment() {
|
|
||||||
return $this->renderWith('WidgetEditor');
|
|
||||||
}
|
|
||||||
|
|
||||||
function CMSEditor() {
|
|
||||||
$output = '';
|
|
||||||
$fields = $this->getCMSFields();
|
|
||||||
foreach($fields as $field) {
|
|
||||||
$name = $field->Name();
|
|
||||||
$field->setValue($this->getField($name));
|
|
||||||
$renderedField = $field->FieldHolder();
|
|
||||||
$renderedField = preg_replace("/name=\"([A-Za-z0-9\-_]+)\"/", "name=\"Widget[" . $this->ID . "][\\1]\"", $renderedField);
|
|
||||||
$renderedField = preg_replace("/id=\"([A-Za-z0-9\-_]+)\"/", "id=\"Widget[" . $this->ID . "][\\1]\"", $renderedField);
|
|
||||||
$output .= $renderedField;
|
|
||||||
}
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ClassName() {
|
|
||||||
return $this->class;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Name() {
|
|
||||||
return "Widget[".$this->ID."]";
|
|
||||||
}
|
|
||||||
|
|
||||||
function populateFromPostData($data) {
|
|
||||||
foreach($data as $name => $value) {
|
|
||||||
if($name != "Type") {
|
|
||||||
$this->setField($name, $value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->write();
|
|
||||||
|
|
||||||
// The field must be written to ensure a unique ID.
|
|
||||||
$this->Name = $this->class.$this->ID;
|
|
||||||
$this->write();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional controller for every widget which has its own logic,
|
|
||||||
* e.g. in forms. It always handles a single widget, usually passed
|
|
||||||
* in as a database identifier through the controller URL.
|
|
||||||
* Needs to be constructed as a nested controller
|
|
||||||
* within a {@link ContentController}.
|
|
||||||
*
|
|
||||||
* ## Forms
|
|
||||||
* You can add forms like in any other SilverStripe controller.
|
|
||||||
* If you need access to the widget from within a form,
|
|
||||||
* you can use `$this->controller->getWidget()` inside the form logic.
|
|
||||||
* Note: Widget controllers currently only work on {@link Page} objects,
|
|
||||||
* because the logic is implemented in {@link ContentController->handleWidget()}.
|
|
||||||
* Copy this logic and the URL rules to enable it for other controllers.
|
|
||||||
*
|
|
||||||
* @package cms
|
|
||||||
* @subpackage widgets
|
|
||||||
*/
|
|
||||||
class Widget_Controller extends Controller {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Widget
|
|
||||||
*/
|
|
||||||
protected $widget;
|
|
||||||
|
|
||||||
static $allowed_actions = array(
|
|
||||||
'editablesegment'
|
|
||||||
);
|
|
||||||
|
|
||||||
function __construct($widget = null) {
|
|
||||||
// TODO This shouldn't be optional, is only necessary for editablesegment()
|
|
||||||
if($widget) {
|
|
||||||
$this->widget = $widget;
|
|
||||||
$this->failover = $widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Link($action = null) {
|
|
||||||
$segment = Controller::join_links('widget', ($this->widget ? $this->widget->ID : null), $action);
|
|
||||||
|
|
||||||
if(Director::get_current_page()) {
|
|
||||||
return Director::get_current_page()->Link($segment);
|
|
||||||
} else {
|
|
||||||
return Controller::curr()->Link($segment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Widget
|
|
||||||
*/
|
|
||||||
function getWidget() {
|
|
||||||
return $this->widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overloaded from {@link Widget->Content()}
|
|
||||||
* to allow for controller/form linking.
|
|
||||||
*
|
|
||||||
* @return string HTML
|
|
||||||
*/
|
|
||||||
function Content() {
|
|
||||||
return $this->renderWith(array_reverse(ClassInfo::ancestry($this->widget->class)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overloaded from {@link Widget->WidgetHolder()}
|
|
||||||
* to allow for controller/form linking.
|
|
||||||
*
|
|
||||||
* @return string HTML
|
|
||||||
*/
|
|
||||||
function WidgetHolder() {
|
|
||||||
return $this->renderWith("WidgetHolder");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uses the `WidgetEditor.ss` template and {@link Widget->editablesegment()}
|
|
||||||
* to render a administrator-view of the widget. It is assumed that this
|
|
||||||
* view contains form elements which are submitted and saved through {@link WidgetAreaEditor}
|
|
||||||
* within the CMS interface.
|
|
||||||
*
|
|
||||||
* @return string HTML
|
|
||||||
*/
|
|
||||||
function editablesegment() {
|
|
||||||
$className = $this->urlParams['ID'];
|
|
||||||
if(class_exists($className) && is_subclass_of($className, 'Widget')) {
|
|
||||||
$obj = new $className();
|
|
||||||
return $obj->EditableSegment();
|
|
||||||
} else {
|
|
||||||
user_error("Bad widget class: $className", E_USER_WARNING);
|
|
||||||
return "Bad widget class name given";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package cms
|
|
||||||
* @subpackage widgets
|
|
||||||
*/
|
|
||||||
class Widget_TreeDropdownField extends TreeDropdownField {
|
|
||||||
function FieldHolder($properties = array()) {}
|
|
||||||
function Field($properties = array()) {}
|
|
||||||
}
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Represents a set of widgets shown on a page.
|
|
||||||
* @package cms
|
|
||||||
* @subpackage widgets
|
|
||||||
*/
|
|
||||||
class WidgetArea extends DataObject {
|
|
||||||
|
|
||||||
static $db = array();
|
|
||||||
|
|
||||||
static $has_one = array();
|
|
||||||
|
|
||||||
static $has_many = array(
|
|
||||||
"Widgets" => "Widget"
|
|
||||||
);
|
|
||||||
|
|
||||||
static $many_many = array();
|
|
||||||
|
|
||||||
static $belongs_many_many = array();
|
|
||||||
|
|
||||||
public $template = __CLASS__;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used in template instead of {@link Widgets()}
|
|
||||||
* to wrap each widget in its controller, making
|
|
||||||
* it easier to access and process form logic
|
|
||||||
* and actions stored in {@link Widget_Controller}.
|
|
||||||
*
|
|
||||||
* @return SS_List Collection of {@link Widget_Controller}
|
|
||||||
*/
|
|
||||||
function WidgetControllers() {
|
|
||||||
$controllers = new ArrayList();
|
|
||||||
|
|
||||||
foreach($this->ItemsToRender() as $widget) {
|
|
||||||
// find controller
|
|
||||||
$controllerClass = '';
|
|
||||||
foreach(array_reverse(ClassInfo::ancestry($widget->class)) as $widgetClass) {
|
|
||||||
$controllerClass = "{$widgetClass}_Controller";
|
|
||||||
if(class_exists($controllerClass)) break;
|
|
||||||
}
|
|
||||||
$controller = new $controllerClass($widget);
|
|
||||||
$controller->init();
|
|
||||||
$controllers->push($controller);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $controllers;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Items() {
|
|
||||||
return $this->getComponents('Widgets');
|
|
||||||
}
|
|
||||||
|
|
||||||
function ItemsToRender() {
|
|
||||||
return $this->getComponents('Widgets', "\"Widget\".\"Enabled\" = 1");
|
|
||||||
}
|
|
||||||
|
|
||||||
function forTemplate() {
|
|
||||||
return $this->renderWith($this->template);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTemplate($template) {
|
|
||||||
$this->template = $template;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onBeforeDelete() {
|
|
||||||
parent::onBeforeDelete();
|
|
||||||
foreach($this->Widgets() as $widget) {
|
|
||||||
$widget->delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,142 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Special field type for selecting and configuring widgets on a page.
|
|
||||||
* @package cms
|
|
||||||
* @subpackage content
|
|
||||||
*/
|
|
||||||
class WidgetAreaEditor extends FormField {
|
|
||||||
/**
|
|
||||||
* 3 variables to hold titles for the template
|
|
||||||
*/
|
|
||||||
public $InUseTitle;
|
|
||||||
public $AvailableTitle;
|
|
||||||
public $ToAddTitle;
|
|
||||||
|
|
||||||
function __construct($name, $widgetClasses = array('Widget'), $maxWidgets = 0) {
|
|
||||||
$this->MaxWidgets = $maxWidgets;
|
|
||||||
$this->widgetClasses = $widgetClasses;
|
|
||||||
|
|
||||||
parent::__construct($name);
|
|
||||||
}
|
|
||||||
|
|
||||||
function FieldHolder($properties = array()) {
|
|
||||||
Requirements::css(CMS_DIR . '/css/WidgetAreaEditor.css');
|
|
||||||
Requirements::javascript(THIRDPARTY_DIR . "/prototype/prototype.js");
|
|
||||||
Requirements::javascript(THIRDPARTY_DIR . '/behaviour/behaviour.js');
|
|
||||||
Requirements::javascript(CMS_DIR . '/javascript/WidgetAreaEditor.js');
|
|
||||||
|
|
||||||
return $this->renderWith("WidgetAreaEditor");
|
|
||||||
}
|
|
||||||
|
|
||||||
function AvailableWidgets() {
|
|
||||||
|
|
||||||
$widgets= new ArrayList();
|
|
||||||
|
|
||||||
foreach($this->widgetClasses as $widgetClass) {
|
|
||||||
$classes = ClassInfo::subclassesFor($widgetClass);
|
|
||||||
array_shift($classes);
|
|
||||||
foreach($classes as $class) {
|
|
||||||
$widgets->push(singleton($class));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $widgets;
|
|
||||||
}
|
|
||||||
|
|
||||||
function UsedWidgets() {
|
|
||||||
// Call class_exists() to load Widget.php earlier and avoid a segfault
|
|
||||||
class_exists('Widget');
|
|
||||||
|
|
||||||
$relationName = $this->name;
|
|
||||||
$widgets = $this->form->getRecord()->getComponent($relationName)->Items();
|
|
||||||
return $widgets;
|
|
||||||
}
|
|
||||||
|
|
||||||
function IdxField() {
|
|
||||||
return $this->id() . 'ID';
|
|
||||||
}
|
|
||||||
|
|
||||||
function Value() {
|
|
||||||
$relationName = $this->name;
|
|
||||||
return $this->form->getRecord()->getComponent($relationName)->ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveInto(DataObjectInterface $record) {
|
|
||||||
$name = $this->name;
|
|
||||||
$idName = $name . "ID";
|
|
||||||
|
|
||||||
$widgetarea = $record->getComponent($name);
|
|
||||||
$widgetarea->write();
|
|
||||||
|
|
||||||
$record->$idName = $widgetarea->ID;
|
|
||||||
|
|
||||||
$widgets = $widgetarea->Items();
|
|
||||||
|
|
||||||
// store the field IDs and delete the missing fields
|
|
||||||
// alternatively, we could delete all the fields and re add them
|
|
||||||
$missingWidgets = array();
|
|
||||||
|
|
||||||
if($widgets) {
|
|
||||||
foreach($widgets as $existingWidget) {
|
|
||||||
$missingWidgets[$existingWidget->ID] = $existingWidget;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($_REQUEST['Widget'])) {
|
|
||||||
foreach(array_keys($_REQUEST['Widget']) as $widgetAreaName) {
|
|
||||||
if ($widgetAreaName !== $this->name) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(array_keys($_REQUEST['Widget'][$widgetAreaName]) as $newWidgetID) {
|
|
||||||
$newWidgetData = $_REQUEST['Widget'][$widgetAreaName][$newWidgetID];
|
|
||||||
|
|
||||||
// Sometimes the id is "new-1" or similar, ensure this doesn't get into the query
|
|
||||||
if(!is_numeric($newWidgetID)) {
|
|
||||||
$newWidgetID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// \"ParentID\" = '0' is for the new page
|
|
||||||
$widget = DataObject::get_one(
|
|
||||||
'Widget',
|
|
||||||
"(\"ParentID\" = '{$record->$name()->ID}' OR \"ParentID\" = '0') AND \"Widget\".\"ID\" = '$newWidgetID'"
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// check if we are updating an existing widget
|
|
||||||
if($widget && isset($missingWidgets[$widget->ID])) {
|
|
||||||
unset($missingWidgets[$widget->ID]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a new object
|
|
||||||
if(!$widget && !empty($newWidgetData['Type']) && class_exists($newWidgetData['Type'])) {
|
|
||||||
$widget = new $newWidgetData['Type']();
|
|
||||||
$widget->ID = 0;
|
|
||||||
$widget->ParentID = $record->$name()->ID;
|
|
||||||
|
|
||||||
if(!is_subclass_of($widget, 'Widget')) {
|
|
||||||
$widget = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($widget) {
|
|
||||||
if($widget->ParentID == 0) {
|
|
||||||
$widget->ParentID = $record->$name()->ID;
|
|
||||||
}
|
|
||||||
// echo "Saving $widget->ID into $name/$widget->ParentID\n<br/>";
|
|
||||||
$widget->populateFromPostData($newWidgetData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove the fields not saved
|
|
||||||
if($missingWidgets) {
|
|
||||||
foreach($missingWidgets as $removedWidget) {
|
|
||||||
if(isset($removedWidget) && is_numeric($removedWidget->ID)) {
|
|
||||||
$removedWidget->delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,282 +0,0 @@
|
|||||||
// Shortcut-function (until we update to Prototye v1.5)
|
|
||||||
if(typeof $$ != "Function") $$ = document.getElementsBySelector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File: WidgetAreaEditor.js
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class: WidgetAreaEditorClass
|
|
||||||
*/
|
|
||||||
WidgetAreaEditorClass = Class.create();
|
|
||||||
WidgetAreaEditorClass.prototype = {
|
|
||||||
initialize: function() {
|
|
||||||
this.name = this.getAttribute('name');
|
|
||||||
this.rewriteWidgetAreaAttributes();
|
|
||||||
UsedWidget.applyToChildren(document.getElementById('usedWidgets-'+this.name), 'div.Widget');
|
|
||||||
|
|
||||||
var availableWidgets = document.getElementById('availableWidgets-'+this.name).childNodes;
|
|
||||||
|
|
||||||
for(var i = 0; i < availableWidgets.length; i++) {
|
|
||||||
var widget = availableWidgets[i];
|
|
||||||
// Don't run on comments, whitespace, etc
|
|
||||||
if (widget.nodeType == 1) {
|
|
||||||
// Gotta change their ID's because otherwise we get clashes between two tabs
|
|
||||||
widget.id = widget.id + '-'+this.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Create dummy sortable to prevent javascript errors
|
|
||||||
Sortable.create('availableWidgets-'+this.name, {
|
|
||||||
tag: 'li',
|
|
||||||
handle: 'handle',
|
|
||||||
containment: []
|
|
||||||
});
|
|
||||||
|
|
||||||
// Used widgets are sortable
|
|
||||||
Sortable.create('usedWidgets-'+this.name, {
|
|
||||||
tag: 'div',
|
|
||||||
handle: 'handle',
|
|
||||||
containment: ['availableWidgets-'+this.name, 'usedWidgets-'+this.name],
|
|
||||||
onUpdate: this.updateWidgets
|
|
||||||
});
|
|
||||||
|
|
||||||
// Figure out maxid, this is used when creating new widgets
|
|
||||||
this.maxid = 0;
|
|
||||||
|
|
||||||
var usedWidgets = document.getElementById('usedWidgets-'+this.name).childNodes;
|
|
||||||
for(var i = 0; i < usedWidgets.length; i++) {
|
|
||||||
var widget = usedWidgets[i];
|
|
||||||
if(widget.id) {
|
|
||||||
widgetid = widget.id.match(/\Widget\[(.+?)\]\[([0-9]+)\]/i);
|
|
||||||
if(widgetid && parseInt(widgetid[2]) > this.maxid) {
|
|
||||||
this.maxid = parseInt(widgetid[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure correct sort values are written when page is saved
|
|
||||||
// TODO Adjust to new event listeners
|
|
||||||
jQuery('.cms-edit-form').bind('ajaxsubmit', this.beforeSave.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
rewriteWidgetAreaAttributes: function() {
|
|
||||||
this.name = this.getAttribute('name');
|
|
||||||
|
|
||||||
var monkeyWith = function(widgets, name) {
|
|
||||||
if (!widgets) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for(var i = 0; i < widgets.length; i++) {
|
|
||||||
widget = widgets[i];
|
|
||||||
if (!widget.getAttribute('rewritten') && (widget.id || widget.name)) {
|
|
||||||
if (widget.id && widget.id.indexOf('Widget[') === 0) {
|
|
||||||
var newValue = widget.id.replace(/Widget\[/, 'Widget['+name+'][');
|
|
||||||
//console.log('Renaming '+widget.tagName+' ID '+widget.id+' to '+newValue);
|
|
||||||
widget.id = newValue;
|
|
||||||
}
|
|
||||||
if (widget.name && widget.name.indexOf('Widget[') === 0) {
|
|
||||||
var newValue = widget.name.replace(/Widget\[/, 'Widget['+name+'][');
|
|
||||||
//console.log('Renaming '+widget.tagName+' Name '+widget.name+' to '+newValue);
|
|
||||||
widget.name = newValue;
|
|
||||||
}
|
|
||||||
widget.setAttribute('rewritten', 'yes');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//console.log('Skipping '+(widget.id ? widget.id : (widget.name ? widget.name : 'unknown '+widget.tagName)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
monkeyWith($$('#WidgetAreaEditor-'+this.name+' .Widget'), this.name);
|
|
||||||
monkeyWith($$('#WidgetAreaEditor-'+this.name+' .Widget *'), this.name);
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeSave: function() {
|
|
||||||
// Ensure correct sort values are written when page is saved
|
|
||||||
var usedWidgets = document.getElementById('usedWidgets-'+this.name);
|
|
||||||
|
|
||||||
if(usedWidgets) {
|
|
||||||
this.sortWidgets();
|
|
||||||
|
|
||||||
var children = usedWidgets.childNodes;
|
|
||||||
|
|
||||||
for( var i = 0; i < children.length; ++i ) {
|
|
||||||
var child = children[i];
|
|
||||||
|
|
||||||
if(child.beforeSave) {
|
|
||||||
child.beforeSave();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
addWidget: function(className, holder) {
|
|
||||||
|
|
||||||
if (document.getElementById('WidgetAreaEditor-'+holder).getAttribute('maxwidgets')) {
|
|
||||||
var maxCount = document.getElementById('WidgetAreaEditor-'+holder).getAttribute('maxwidgets');
|
|
||||||
var count = $$('#usedWidgets-'+holder+' .Widget').length;
|
|
||||||
if (count+1 > maxCount) {
|
|
||||||
alert(ss.i18n._t('WidgetAreaEditor.TOOMANY'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.name = holder;
|
|
||||||
jQuery.ajax({
|
|
||||||
'url': 'Widget_Controller/EditableSegment/' + className,
|
|
||||||
'success' : document.getElementById('usedWidgets-'+holder).parentNode.parentNode.insertWidgetEditor.bind(this)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
updateWidgets: function() {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// Gotta get the name of the current dohickey based off the ID
|
|
||||||
this.name = this.element.id.split('-').pop();
|
|
||||||
|
|
||||||
// alert(this.name);
|
|
||||||
|
|
||||||
// Gotta get the name of the current dohickey based off the ID
|
|
||||||
this.name = this.element.id.split('-').pop();
|
|
||||||
|
|
||||||
|
|
||||||
// This is called when an available widgets is dragged over to used widgets.
|
|
||||||
// It inserts the editor form into the new used widget
|
|
||||||
|
|
||||||
var usedWidgets = document.getElementById('usedWidgets-'+this.name).childNodes;
|
|
||||||
for(var i = 0; i < usedWidgets.length; i++) {
|
|
||||||
var widget = usedWidgets[i];
|
|
||||||
if(widget.id && (widget.id.indexOf("Widget[") != 0) && (widget.id != 'NoWidgets-'+this.name)) {
|
|
||||||
// Need to remove the -$Name part.
|
|
||||||
var wIdArray = widget.id.split('-');
|
|
||||||
wIdArray.pop();
|
|
||||||
|
|
||||||
jQuery.ajax({
|
|
||||||
'url': 'Widget_Controller/EditableSegment/' + wIdArray.join('-'),
|
|
||||||
'success' : function() {
|
|
||||||
document.getElementById('usedWidgets-'+self.name).parentNode.parentNode.insertWidgetEditor();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
insertWidgetEditor: function(response) {
|
|
||||||
// Remove placeholder text
|
|
||||||
if(document.getElementById('NoWidgets-'+this.name)) {
|
|
||||||
document.getElementById('usedWidgets-'+this.name).removeChild(document.getElementById('NoWidgets-'+this.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
var usedWidgets = document.getElementById('usedWidgets-'+this.name).childNodes;
|
|
||||||
|
|
||||||
// Give the widget a unique id
|
|
||||||
widgetContent = response.responseText.replace(/Widget\[0\]/gi, "Widget[new-" + (++document.getElementById('usedWidgets-'+this.name).parentNode.parentNode.maxid) + "]");
|
|
||||||
new Insertion.Top(document.getElementById('usedWidgets-'+this.name), widgetContent);
|
|
||||||
|
|
||||||
document.getElementById('usedWidgets-'+this.name).parentNode.parentNode.rewriteWidgetAreaAttributes();
|
|
||||||
UsedWidget.applyToChildren(document.getElementById('usedWidgets-'+this.name), 'div.Widget');
|
|
||||||
|
|
||||||
// Repply some common form controls
|
|
||||||
WidgetTreeDropdownField.applyTo('div.usedWidgets .TreeDropdownField');
|
|
||||||
|
|
||||||
Sortable.create('usedWidgets-'+this.name, {
|
|
||||||
tag: 'div',
|
|
||||||
handle: 'handle',
|
|
||||||
containment: ['availableWidgets-'+this.name, 'usedWidgets-'+this.name],
|
|
||||||
onUpdate: document.getElementById('usedWidgets-'+this.name).parentNode.parentNode.updateWidgets
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
sortWidgets: function() {
|
|
||||||
// Order the sort by the order the widgets are in the list
|
|
||||||
var usedWidgets = document.getElementById('usedWidgets-'+this.name);
|
|
||||||
|
|
||||||
if(usedWidgets) {
|
|
||||||
widgets = usedWidgets.childNodes;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
deleteWidget: function(widgetToRemove) {
|
|
||||||
// Remove a widget from the used widgets column
|
|
||||||
document.getElementById('usedWidgets-'+this.name).removeChild(widgetToRemove);
|
|
||||||
// TODO ... re-create NoWidgets div?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class: UsedWidget
|
|
||||||
*/
|
|
||||||
UsedWidget = Class.create();
|
|
||||||
UsedWidget.prototype = {
|
|
||||||
initialize: function() {
|
|
||||||
// Call deleteWidget when delete button is pushed
|
|
||||||
this.deleteButton = this.findDescendant('span', 'widgetDelete');
|
|
||||||
if(this.deleteButton)
|
|
||||||
this.deleteButton.onclick = this.deleteWidget.bind(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Taken from FieldEditor
|
|
||||||
findDescendant: function(tag, clsName, element) {
|
|
||||||
if(!element)
|
|
||||||
element = this;
|
|
||||||
|
|
||||||
var descendants = element.getElementsByTagName(tag);
|
|
||||||
|
|
||||||
for(var i = 0; i < descendants.length; i++) {
|
|
||||||
var el = descendants[i];
|
|
||||||
|
|
||||||
if(tag.toUpperCase() == el.tagName && el.className.indexOf( clsName ) != -1)
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
deleteWidget: function() {
|
|
||||||
this.parentNode.parentNode.parentNode.deleteWidget(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class: AvailableWidgetHeader
|
|
||||||
*/
|
|
||||||
AvailableWidgetHeader = Class.create();
|
|
||||||
AvailableWidgetHeader.prototype = {
|
|
||||||
onclick: function(event) {
|
|
||||||
parts = this.parentNode.id.split('-');
|
|
||||||
var widgetArea = parts.pop();
|
|
||||||
var className = parts.pop();
|
|
||||||
document.getElementById('WidgetAreaEditor-'+widgetArea).addWidget(className, widgetArea);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AvailableWidgetHeader.applyTo('div.availableWidgets .Widget h3');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class: WidgetTreeDropdownField
|
|
||||||
*/
|
|
||||||
WidgetTreeDropdownField = Class.extend('TreeDropdownField');
|
|
||||||
WidgetTreeDropdownField.prototype = {
|
|
||||||
getName: function() {
|
|
||||||
return 'Widget_TDF_Endpoint';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WidgetTreeDropdownField.applyTo('div.usedWidgets .TreeDropdownField');
|
|
||||||
WidgetAreaEditorClass.applyTo('.WidgetAreaEditor');
|
|
@ -1,3 +0,0 @@
|
|||||||
<% control WidgetControllers %>
|
|
||||||
$WidgetHolder
|
|
||||||
<% end_control %>
|
|
@ -1,32 +0,0 @@
|
|||||||
<div class="WidgetAreaEditor" id="WidgetAreaEditor-$Name" name="$Name"<% if MaxWidgets %> maxwidgets="$MaxWidgets"<% end_if %>>
|
|
||||||
<input type="hidden" id="$Name" name="$IdxField" value="$Value" />
|
|
||||||
<div class="availableWidgetsHolder">
|
|
||||||
<h2><% _t('AVAILABLE', 'Available Widgets') %></h2>
|
|
||||||
<p><% _t('AVAILWIDGETS', 'Click a widget title below to use it on this page.') %></p>
|
|
||||||
<div class="availableWidgets" id="availableWidgets-$Name">
|
|
||||||
<% if AvailableWidgets %>
|
|
||||||
<% control AvailableWidgets %>
|
|
||||||
$DescriptionSegment
|
|
||||||
<% end_control %>
|
|
||||||
<% else %>
|
|
||||||
<div class="NoWidgets" id="NoWidgets-$Name">
|
|
||||||
<p><% _t('NOAVAIL', 'There are currently no widgets available.') %></p>
|
|
||||||
</div>
|
|
||||||
<% end_if %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="usedWidgetsHolder">
|
|
||||||
<h2><% _t('INUSE', 'Widgets currently used') %></h2>
|
|
||||||
<p><% _t('TOSORT', 'To sort currently used widgets on this page, drag them up and down.') %></p>
|
|
||||||
|
|
||||||
<div class="usedWidgets" id="usedWidgets-$Name">
|
|
||||||
<% if UsedWidgets %>
|
|
||||||
<% control UsedWidgets %>
|
|
||||||
$EditableSegment
|
|
||||||
<% end_control %>
|
|
||||||
<% else %>
|
|
||||||
<div class="NoWidgets" id="NoWidgets-$Name"></div>
|
|
||||||
<% end_if %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,6 +0,0 @@
|
|||||||
<div class="Widget" id="$ClassName">
|
|
||||||
<h3 title="<% _t('CLICKTOADDWIDGET', 'Click to add this widget') %>">$CMSTitle</h3>
|
|
||||||
<div class="widgetDescription">
|
|
||||||
<p>$Description</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,12 +0,0 @@
|
|||||||
<div class="$ClassName Widget" id="$Name">
|
|
||||||
<h3 class="handle">$CMSTitle</h3>
|
|
||||||
<div class="widgetDescription">
|
|
||||||
<p>$Description</p>
|
|
||||||
</div>
|
|
||||||
<div class="widgetFields">
|
|
||||||
$CMSEditor
|
|
||||||
<input type="hidden" name="$Name[Type]" value="$ClassName" />
|
|
||||||
<input type="hidden" name="$Name[Sort]" value="$Sort" />
|
|
||||||
</div>
|
|
||||||
<p class="deleteWidget"><span class="widgetDelete"><% _t('DELETE', 'Delete') %></span></p>
|
|
||||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||||||
<div class="WidgetHolder $ClassName<% if FirstLast %> $FirstLast<% end_if %>">
|
|
||||||
<% if Title %><h3>$Title</h3><% end_if %>
|
|
||||||
$Content
|
|
||||||
</div>
|
|
@ -1,471 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @package cms
|
|
||||||
* @subpackage tests
|
|
||||||
*/
|
|
||||||
class WidgetAreaEditorTest extends SapphireTest {
|
|
||||||
/**
|
|
||||||
* This is the widget you want to use for your unit tests.
|
|
||||||
*/
|
|
||||||
protected $widgetToTest = 'WidgetAreaEditorTest_TestWidget';
|
|
||||||
|
|
||||||
protected $extraDataObjects = array(
|
|
||||||
'WidgetAreaEditorTest_FakePage',
|
|
||||||
'WidgetAreaEditorTest_TestWidget',
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $usesDatabase = true;
|
|
||||||
|
|
||||||
function testFillingOneArea() {
|
|
||||||
$oldRequest = $_REQUEST;
|
|
||||||
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'BottomBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidget',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$editorSide = new WidgetAreaEditor('SideBar');
|
|
||||||
$editorBott = new WidgetAreaEditor('BottomBar');
|
|
||||||
$page = new WidgetAreaEditorTest_FakePage();
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
|
|
||||||
$this->assertEquals($page->BottomBar()->Widgets()->Count(), 1);
|
|
||||||
$this->assertEquals($page->SideBar()->Widgets()->Count(), 0);
|
|
||||||
|
|
||||||
$_REQUEST = $oldRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFillingTwoAreas() {
|
|
||||||
$oldRequest = $_REQUEST;
|
|
||||||
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'SideBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetSide',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'BottomBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetBottom',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$editorSide = new WidgetAreaEditor('SideBar');
|
|
||||||
$editorBott = new WidgetAreaEditor('BottomBar');
|
|
||||||
$page = new WidgetAreaEditorTest_FakePage();
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
|
|
||||||
// Make sure they both got saved
|
|
||||||
$this->assertEquals($page->BottomBar()->Widgets()->Count(), 1);
|
|
||||||
$this->assertEquals($page->SideBar()->Widgets()->Count(), 1);
|
|
||||||
|
|
||||||
$sideWidgets = $page->SideBar()->Widgets()->toArray();
|
|
||||||
$bottWidgets = $page->BottomBar()->Widgets()->toArray();
|
|
||||||
$this->assertEquals($sideWidgets[0]->Title(), 'MyTestWidgetSide');
|
|
||||||
$this->assertEquals($bottWidgets[0]->Title(), 'MyTestWidgetBottom');
|
|
||||||
|
|
||||||
$_REQUEST = $oldRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
function testDeletingOneWidgetFromOneArea() {
|
|
||||||
$oldRequest = $_REQUEST;
|
|
||||||
|
|
||||||
// First get some widgets in there
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'SideBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetSide',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'BottomBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetBottom',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$editorSide = new WidgetAreaEditor('SideBar');
|
|
||||||
$editorBott = new WidgetAreaEditor('BottomBar');
|
|
||||||
$page = new WidgetAreaEditorTest_FakePage();
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
$sideWidgets = $page->SideBar()->Widgets()->toArray();
|
|
||||||
$bottWidgets = $page->BottomBar()->Widgets()->toArray();
|
|
||||||
|
|
||||||
// Save again (after removing the SideBar's widget)
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'SideBar' => array(
|
|
||||||
),
|
|
||||||
'BottomBar' => array(
|
|
||||||
$bottWidgets[0]->ID => array(
|
|
||||||
'Title' => 'MyTestWidgetBottom',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
$sideWidgets = $page->SideBar()->Widgets()->toArray();
|
|
||||||
$bottWidgets = $page->BottomBar()->Widgets()->toArray();
|
|
||||||
|
|
||||||
$this->assertEquals($page->BottomBar()->Widgets()->Count(), 1);
|
|
||||||
$this->assertEquals($bottWidgets[0]->Title(), 'MyTestWidgetBottom');
|
|
||||||
$this->assertEquals($page->SideBar()->Widgets()->Count(), 0);
|
|
||||||
|
|
||||||
$_REQUEST = $oldRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
function testDeletingAWidgetFromEachArea() {
|
|
||||||
$oldRequest = $_REQUEST;
|
|
||||||
|
|
||||||
// First get some widgets in there
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'SideBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetSide',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'BottomBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetBottom',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$editorSide = new WidgetAreaEditor('SideBar');
|
|
||||||
$editorBott = new WidgetAreaEditor('BottomBar');
|
|
||||||
$page = new WidgetAreaEditorTest_FakePage();
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
$sideWidgets = $page->SideBar()->Widgets()->toArray();
|
|
||||||
$bottWidgets = $page->BottomBar()->Widgets()->toArray();
|
|
||||||
|
|
||||||
// Save again (after removing the SideBar's widget)
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'SideBar' => array(
|
|
||||||
),
|
|
||||||
'BottomBar' => array(
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
$sideWidgets = $page->SideBar()->Widgets()->toArray();
|
|
||||||
$bottWidgets = $page->BottomBar()->Widgets()->toArray();
|
|
||||||
|
|
||||||
$this->assertEquals($page->BottomBar()->Widgets()->Count(), 0);
|
|
||||||
$this->assertEquals($page->SideBar()->Widgets()->Count(), 0);
|
|
||||||
|
|
||||||
$_REQUEST = $oldRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
function testEditingOneWidget() {
|
|
||||||
$oldRequest = $_REQUEST;
|
|
||||||
|
|
||||||
// First get some widgets in there
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'SideBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetSide',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'BottomBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetBottom',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$editorSide = new WidgetAreaEditor('SideBar');
|
|
||||||
$editorBott = new WidgetAreaEditor('BottomBar');
|
|
||||||
$page = new WidgetAreaEditorTest_FakePage();
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
$sideWidgets = $page->SideBar()->Widgets()->toArray();
|
|
||||||
$bottWidgets = $page->BottomBar()->Widgets()->toArray();
|
|
||||||
|
|
||||||
// Save again (after removing the SideBar's widget)
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'SideBar' => array(
|
|
||||||
$sideWidgets[0]->ID => array(
|
|
||||||
'Title' => 'MyTestWidgetSide-edited',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'BottomBar' => array(
|
|
||||||
$bottWidgets[0]->ID => array(
|
|
||||||
'Title' => 'MyTestWidgetBottom',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
$sideWidgets = $page->SideBar()->Widgets()->toArray();
|
|
||||||
$bottWidgets = $page->BottomBar()->Widgets()->toArray();
|
|
||||||
|
|
||||||
$this->assertEquals($page->BottomBar()->Widgets()->Count(), 1);
|
|
||||||
$this->assertEquals($page->SideBar()->Widgets()->Count(), 1);
|
|
||||||
$this->assertEquals($bottWidgets[0]->Title(), 'MyTestWidgetBottom');
|
|
||||||
$this->assertEquals($sideWidgets[0]->Title(), 'MyTestWidgetSide-edited');
|
|
||||||
|
|
||||||
|
|
||||||
$_REQUEST = $oldRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
function testEditingAWidgetFromEachArea() {
|
|
||||||
$oldRequest = $_REQUEST;
|
|
||||||
|
|
||||||
// First get some widgets in there
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'SideBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetSide',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'BottomBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetBottom',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$editorSide = new WidgetAreaEditor('SideBar');
|
|
||||||
$editorBott = new WidgetAreaEditor('BottomBar');
|
|
||||||
$page = new WidgetAreaEditorTest_FakePage();
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
$sideWidgets = $page->SideBar()->Widgets()->toArray();
|
|
||||||
$bottWidgets = $page->BottomBar()->Widgets()->toArray();
|
|
||||||
|
|
||||||
// Save again (after removing the SideBar's widget)
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'SideBar' => array(
|
|
||||||
$sideWidgets[0]->ID => array(
|
|
||||||
'Title' => 'MyTestWidgetSide-edited',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'BottomBar' => array(
|
|
||||||
$bottWidgets[0]->ID => array(
|
|
||||||
'Title' => 'MyTestWidgetBottom-edited',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
$sideWidgets = $page->SideBar()->Widgets()->toArray();
|
|
||||||
$bottWidgets = $page->BottomBar()->Widgets()->toArray();
|
|
||||||
|
|
||||||
$this->assertEquals($page->BottomBar()->Widgets()->Count(), 1);
|
|
||||||
$this->assertEquals($page->SideBar()->Widgets()->Count(), 1);
|
|
||||||
$this->assertEquals($bottWidgets[0]->Title(), 'MyTestWidgetBottom-edited');
|
|
||||||
$this->assertEquals($sideWidgets[0]->Title(), 'MyTestWidgetSide-edited');
|
|
||||||
|
|
||||||
|
|
||||||
$_REQUEST = $oldRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
function testEditAWidgetFromOneAreaAndDeleteAWidgetFromAnotherArea() {
|
|
||||||
$oldRequest = $_REQUEST;
|
|
||||||
|
|
||||||
// First get some widgets in there
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'SideBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetSide',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'BottomBar' => array(
|
|
||||||
'new-1' => array(
|
|
||||||
'Title' => 'MyTestWidgetBottom',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$editorSide = new WidgetAreaEditor('SideBar');
|
|
||||||
$editorBott = new WidgetAreaEditor('BottomBar');
|
|
||||||
$page = new WidgetAreaEditorTest_FakePage();
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
$sideWidgets = $page->SideBar()->Widgets()->toArray();
|
|
||||||
$bottWidgets = $page->BottomBar()->Widgets()->toArray();
|
|
||||||
|
|
||||||
// Save again (after removing the SideBar's widget)
|
|
||||||
$_REQUEST = array(
|
|
||||||
'Widget' => array(
|
|
||||||
'SideBar' => array(
|
|
||||||
$sideWidgets[0]->ID => array(
|
|
||||||
'Title' => 'MyTestWidgetSide-edited',
|
|
||||||
'Type' => $this->widgetToTest,
|
|
||||||
'Sort' => 0
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'BottomBar' => array(
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
$editorSide->saveInto($page);
|
|
||||||
$editorBott->saveInto($page);
|
|
||||||
|
|
||||||
$page->write();
|
|
||||||
$page->flushCache();
|
|
||||||
$page->BottomBar()->flushCache();
|
|
||||||
$page->SideBar()->flushCache();
|
|
||||||
$sideWidgets = $page->SideBar()->Widgets()->toArray();
|
|
||||||
$bottWidgets = $page->BottomBar()->Widgets()->toArray();
|
|
||||||
|
|
||||||
$this->assertEquals($page->BottomBar()->Widgets()->Count(), 0);
|
|
||||||
$this->assertEquals($page->SideBar()->Widgets()->Count(), 1);
|
|
||||||
$this->assertEquals($sideWidgets[0]->Title(), 'MyTestWidgetSide-edited');
|
|
||||||
|
|
||||||
|
|
||||||
$_REQUEST = $oldRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WidgetAreaEditorTest_FakePage extends Page implements TestOnly {
|
|
||||||
public static $has_one = array(
|
|
||||||
"SideBar" => "WidgetArea",
|
|
||||||
"BottomBar" => "WidgetArea",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class WidgetAreaEditorTest_TestWidget extends Widget implements TestOnly {
|
|
||||||
static $cmsTitle = "Test widget";
|
|
||||||
static $title = "Test widget";
|
|
||||||
static $description = "Test widget";
|
|
||||||
static $db = array(
|
|
||||||
'Title' => 'Varchar'
|
|
||||||
);
|
|
||||||
public function getCMSFields() {
|
|
||||||
$fields = new FieldList();
|
|
||||||
$fields->push(new TextField('Title'));
|
|
||||||
return $fields;
|
|
||||||
}
|
|
||||||
function Title() {
|
|
||||||
return $this->Title ? $this->Title : self::$title;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @package cms
|
|
||||||
* @subpackage tests
|
|
||||||
*/
|
|
||||||
class WidgetControllerTest extends FunctionalTest {
|
|
||||||
static $fixture_file = 'WidgetControllerTest.yml';
|
|
||||||
|
|
||||||
protected $extraDataObjects = array(
|
|
||||||
'WidgetControllerTestPage',
|
|
||||||
'WidgetControllerTest_Widget',
|
|
||||||
);
|
|
||||||
|
|
||||||
function testWidgetFormRendering() {
|
|
||||||
$page = $this->objFromFixture('WidgetControllerTestPage', 'page1');
|
|
||||||
$page->publish('Stage', 'Live');
|
|
||||||
|
|
||||||
$widget = $this->objFromFixture('WidgetControllerTest_Widget', 'widget1');
|
|
||||||
|
|
||||||
$response = $this->get($page->URLSegment);
|
|
||||||
|
|
||||||
$formAction = sprintf('%s/widget/%d/Form', $page->URLSegment, $widget->ID);
|
|
||||||
$this->assertContains(
|
|
||||||
$formAction,
|
|
||||||
$response->getBody(),
|
|
||||||
"Widget forms are rendered through WidgetArea templates"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testWidgetFormSubmission() {
|
|
||||||
$page = $this->objFromFixture('WidgetControllerTestPage', 'page1');
|
|
||||||
$page->publish('Stage', 'Live');
|
|
||||||
|
|
||||||
$widget = $this->objFromFixture('WidgetControllerTest_Widget', 'widget1');
|
|
||||||
|
|
||||||
$this->get($page->URLSegment);
|
|
||||||
$response = $this->submitForm('Form_Form', null, array('TestValue'=>'Updated'));
|
|
||||||
|
|
||||||
$this->assertContains(
|
|
||||||
'TestValue: Updated',
|
|
||||||
$response->getBody(),
|
|
||||||
"Form values are submitted to correct widget form"
|
|
||||||
);
|
|
||||||
$this->assertContains(
|
|
||||||
sprintf('Widget ID: %d', $widget->ID),
|
|
||||||
$response->getBody(),
|
|
||||||
"Widget form acts on correct widget, as identified in the URL"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package cms
|
|
||||||
* @subpackage tests
|
|
||||||
*/
|
|
||||||
class WidgetControllerTest_Widget extends Widget implements TestOnly {
|
|
||||||
static $db = array(
|
|
||||||
'TestValue' => 'Text'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package cms
|
|
||||||
* @subpackage tests
|
|
||||||
*/
|
|
||||||
class WidgetControllerTest_Widget_Controller extends Widget_Controller implements TestOnly {
|
|
||||||
function Form() {
|
|
||||||
$widgetform = new Form(
|
|
||||||
$this,
|
|
||||||
'Form',
|
|
||||||
new FieldList(
|
|
||||||
new TextField('TestValue')
|
|
||||||
),
|
|
||||||
new FieldList(
|
|
||||||
new FormAction('doAction')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return $widgetform;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doAction($data, $form) {
|
|
||||||
return sprintf('TestValue: %s\nWidget ID: %d',
|
|
||||||
$data['TestValue'],
|
|
||||||
$this->widget->ID
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
WidgetControllerTest_Widget:
|
|
||||||
widget1:
|
|
||||||
Title: Widget 1
|
|
||||||
WidgetArea:
|
|
||||||
area1:
|
|
||||||
Widgets: =>WidgetControllerTest_Widget.widget1
|
|
||||||
WidgetControllerTestPage:
|
|
||||||
page1:
|
|
||||||
Title: Page1
|
|
||||||
WidgetControllerTestSidebar: =>WidgetArea.area1
|
|
@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @package cms
|
|
||||||
* @subpackage tests
|
|
||||||
*/
|
|
||||||
class WidgetControllerTestPage extends Page implements TestOnly {
|
|
||||||
static $has_one = array(
|
|
||||||
'WidgetControllerTestSidebar' => 'WidgetArea'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package cms
|
|
||||||
* @subpackage tests
|
|
||||||
*/
|
|
||||||
class WidgetControllerTestPage_Controller extends Page_Controller implements TestOnly {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Template selection doesnt work in test folders,
|
|
||||||
* so we enforce a template name.
|
|
||||||
*/
|
|
||||||
function getViewer($action) {
|
|
||||||
$templates = array('WidgetControllerTestPage');
|
|
||||||
|
|
||||||
return new SSViewer($templates);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
$WidgetControllerTestSidebar
|
|
@ -1 +0,0 @@
|
|||||||
$Form
|
|
Loading…
Reference in New Issue
Block a user