diff --git a/code/widgets/Widget.php b/code/widgets/Widget.php
deleted file mode 100644
index 8ef5b7af..00000000
--- a/code/widgets/Widget.php
+++ /dev/null
@@ -1,232 +0,0 @@
- "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()) {}
-}
-
diff --git a/code/widgets/WidgetArea.php b/code/widgets/WidgetArea.php
deleted file mode 100644
index a3f1d9ea..00000000
--- a/code/widgets/WidgetArea.php
+++ /dev/null
@@ -1,72 +0,0 @@
- "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();
- }
- }
-}
-
diff --git a/code/widgets/WidgetAreaEditor.php b/code/widgets/WidgetAreaEditor.php
deleted file mode 100644
index 9c5dcd11..00000000
--- a/code/widgets/WidgetAreaEditor.php
+++ /dev/null
@@ -1,142 +0,0 @@
-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
";
- $widget->populateFromPostData($newWidgetData);
- }
- }
- }
- }
-
- // remove the fields not saved
- if($missingWidgets) {
- foreach($missingWidgets as $removedWidget) {
- if(isset($removedWidget) && is_numeric($removedWidget->ID)) {
- $removedWidget->delete();
- }
- }
- }
- }
-}
diff --git a/javascript/WidgetAreaEditor.js b/javascript/WidgetAreaEditor.js
deleted file mode 100644
index ac2f156b..00000000
--- a/javascript/WidgetAreaEditor.js
+++ /dev/null
@@ -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');
\ No newline at end of file
diff --git a/templates/WidgetArea.ss b/templates/WidgetArea.ss
deleted file mode 100644
index b5279962..00000000
--- a/templates/WidgetArea.ss
+++ /dev/null
@@ -1,3 +0,0 @@
-<% control WidgetControllers %>
- $WidgetHolder
-<% end_control %>
\ No newline at end of file
diff --git a/templates/WidgetAreaEditor.ss b/templates/WidgetAreaEditor.ss
deleted file mode 100644
index 6e3854e7..00000000
--- a/templates/WidgetAreaEditor.ss
+++ /dev/null
@@ -1,32 +0,0 @@
-
<% _t('AVAILWIDGETS', 'Click a widget title below to use it on this page.') %>
-<% _t('NOAVAIL', 'There are currently no widgets available.') %>
-<% _t('TOSORT', 'To sort currently used widgets on this page, drag them up and down.') %>
- --