mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
MINOR Moved Widget, WidgetArea and related files from 'sapphire' to 'cms' module
This commit is contained in:
parent
6d18e38278
commit
764c5a842b
@ -1,3 +0,0 @@
|
|||||||
<% control WidgetControllers %>
|
|
||||||
$WidgetHolder
|
|
||||||
<% end_control %>
|
|
@ -1,4 +0,0 @@
|
|||||||
<div class="WidgetHolder $ClassName<% if FirstLast %> $FirstLast<% end_if %>">
|
|
||||||
<% if Title %><h3>$Title</h3><% end_if %>
|
|
||||||
$Content
|
|
||||||
</div>
|
|
@ -1,89 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @package sapphire
|
|
||||||
* @subpackage tests
|
|
||||||
*/
|
|
||||||
class WidgetControllerTest extends FunctionalTest {
|
|
||||||
static $fixture_file = 'sapphire/tests/widgets/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 sapphire
|
|
||||||
* @subpackage tests
|
|
||||||
*/
|
|
||||||
class WidgetControllerTest_Widget extends Widget implements TestOnly {
|
|
||||||
static $db = array(
|
|
||||||
'TestValue' => 'Text'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package sapphire
|
|
||||||
* @subpackage tests
|
|
||||||
*/
|
|
||||||
class WidgetControllerTest_Widget_Controller extends Widget_Controller implements TestOnly {
|
|
||||||
function Form() {
|
|
||||||
$widgetform = new Form(
|
|
||||||
$this,
|
|
||||||
'Form',
|
|
||||||
new FieldSet(
|
|
||||||
new TextField('TestValue')
|
|
||||||
),
|
|
||||||
new FieldSet(
|
|
||||||
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 sapphire
|
|
||||||
* @subpackage tests
|
|
||||||
*/
|
|
||||||
class WidgetControllerTestPage extends Page implements TestOnly {
|
|
||||||
static $has_one = array(
|
|
||||||
'WidgetControllerTestSidebar' => 'WidgetArea'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @package sapphire
|
|
||||||
* @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
|
|
@ -1,233 +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 sapphire
|
|
||||||
* @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 FieldSet();
|
|
||||||
$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 = ereg_replace("name=\"([A-Za-z0-9\-_]+)\"", "name=\"Widget[" . $this->ID . "][\\1]\"", $renderedField);
|
|
||||||
$renderedField = ereg_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 sapphire 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 sapphire
|
|
||||||
* @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 sapphire
|
|
||||||
* @subpackage widgets
|
|
||||||
*/
|
|
||||||
class Widget_TreeDropdownField extends TreeDropdownField {
|
|
||||||
function FieldHolder() {}
|
|
||||||
function Field() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@ -1,73 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Represents a set of widgets shown on a page.
|
|
||||||
* @package sapphire
|
|
||||||
* @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 DataObjectSet Collection of {@link Widget_Controller}
|
|
||||||
*/
|
|
||||||
function WidgetControllers() {
|
|
||||||
$controllers = new DataObjectSet();
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
Loading…
Reference in New Issue
Block a user