Version: current

      1 <?php
      2 /**
      3  * Widgets let CMS authors drag and drop small pieces of functionality into
      4  * defined areas of their websites.
      5  *
      6  * ## Forms
      7  * You can use forms in widgets by implementing a {@link Widget_Controller}.
      8  * See {@link Widget_Controller} for more information.
      9  *
     10  * @package sapphire
     11  * @subpackage widgets
     12  */
     13 class Widget extends DataObject {
     14     static $db = array(
     15         "Sort" => "Int",
     16         "Enabled" => "Boolean"
     17     );
     18
     19     static $defaults = array(
     20         'Enabled' => true
     21     );
     22
     23     static $has_one = array(
     24         "Parent" => "WidgetArea",
     25     );
     26
     27     static $has_many = array();
     28     static $many_many = array();
     29     static $belongs_many_many = array();
     30
     31     static $default_sort = "\"Sort\"";
     32
     33     static $title = "Widget Title";
     34     static $cmsTitle = "Name of this widget";
     35     static $description = "Description of what this widget does.";
     36
     37     function getCMSFields() {
     38         $fields = parent::getCMSFields();
     39         $fields->replaceField('Sort', new HiddenField('Sort'));
     40         $this->extend('updateCMSFields', $fields);
     41         return $fields;
     42     }
     43
     44     /**
     45      * Note: Overloaded in {@link Widget_Controller}.
     46      *
     47      * @return string HTML
     48      */
     49     function WidgetHolder() {
     50         return $this->renderWith("WidgetHolder");
     51     }
     52
     53     function Title() {
     54         return Object::get_static($this->class, 'title');
     55     }
     56
     57     function CMSTitle() {
     58         return Object::get_static($this->class, 'cmsTitle');
     59     }
     60
     61     function Description() {
     62         return Object::get_static($this->class, 'description');
     63     }
     64
     65     function DescriptionSegment() {
     66         return $this->renderWith('WidgetDescription');
     67     }
     68
     69     /**
     70      * @see Widget_Controller->editablesegment()
     71      */
     72     function EditableSegment() {
     73         return $this->renderWith('WidgetEditor');
     74     }
     75
     76     function CMSEditor() {
     77         $output = '';
     78         $fields = $this->getCMSFields();
     79         foreach($fields as $field) {
     80             $name = $field->Name();
     81             $field->setValue($this->getField($name));
     82             $renderedField = $field->FieldHolder();
     83             $renderedField = ereg_replace("name=\"([A-Za-z0-9\-_]+)\"", "name=\"Widget[" . $this->ID . "][\\1]\"", $renderedField);
     84             $renderedField = ereg_replace("id=\"([A-Za-z0-9\-_]+)\"", "id=\"Widget[" . $this->ID . "][\\1]\"", $renderedField);
     85             $output .= $renderedField;
     86         }
     87         return $output;
     88     }
     89
     90     function ClassName() {
     91         return $this->class;
     92     }
     93
     94     function Name() {
     95         return "Widget[".$this->ID."]";
     96     }
     97
     98     function EnabledTitle() {
     99         return ($this->Enabled) ? _t('Boolean.YES','YES') : _t('Boolean.NO','NO');
    100     }
    101
    102     function populateFromPostData($data) {
    103         foreach($data as $name => $value) {
    104             if($name != "Type") {
    105                 $this->setField($name, $value);
    106             }
    107         }
    108
    109         $this->write();
    110
    111         // The field must be written to ensure a unique ID.
    112         $this->Name = $this->class.$this->ID;
    113         $this->write();
    114     }
    115
    116 }
    117
    118 /**
    119  * Optional controller for every widget which has its own logic,
    120  * e.g. in forms. It always handles a single widget, usually passed
    121  * in as a database identifier through the controller URL.
    122  * Needs to be constructed as a nested controller
    123  * within a {@link ContentController}.
    124  *
    125  * ## Forms
    126  * You can add forms like in any other sapphire controller.
    127  * If you need access to the widget from within a form,
    128  * you can use `$this->controller->getWidget()` inside the form logic.
    129  * Note: Widget controllers currently only work on {@link Page} objects,
    130  * because the logic is implemented in {@link ContentController->handleWidget()}.
    131  * Copy this logic and the URL rules to enable it for other controllers.
    132  *
    133  * @package sapphire
    134  * @subpackage widgets
    135  */
    136 class Widget_Controller extends Controller {
    137
    138     /**
    139      * @var Widget
    140      */
    141     protected $widget;
    142
    143     function __construct($widget = null) {
    144         // TODO This shouldn't be optional, is only necessary for editablesegment()
    145         if($widget) {
    146             $this->widget = $widget;
    147             $this->failover = $widget;
    148         }
    149
    150         parent::__construct();
    151     }
    152
    153     public function Link($action = null) {
    154         return Controller::curr()->Link (
    155             Controller::join_links('widget', ($this->widget ? $this->widget->ID : null), $action)
    156         );
    157     }
    158
    159     /**
    160      * @return Widget
    161      */
    162     function getWidget() {
    163         return $this->widget;
    164     }
    165
    166     /**
    167      * Overloaded from {@link Widget->WidgetHolder()}
    168      * to allow for controller/form linking.
    169      *
    170      * @return string HTML
    171      */
    172     function WidgetHolder() {
    173         return $this->renderWith("WidgetHolder");
    174     }
    175
    176     /**
    177      * Uses the `WidgetEditor.ss` template and {@link Widget->editablesegment()}
    178      * to render a administrator-view of the widget. It is assumed that this
    179      * view contains form elements which are submitted and saved through {@link WidgetAreaEditor}
    180      * within the CMS interface.
    181      *
    182      * @return string HTML
    183      */
    184     function editablesegment() {
    185         $className = $this->urlParams['ID'];
    186         if(class_exists($className) && is_subclass_of($className, 'Widget')) {
    187             $obj = new $className();
    188             return $obj->EditableSegment();
    189         } else {
    190             user_error("Bad widget class: $className", E_USER_WARNING);
    191             return "Bad widget class name given";
    192         }
    193     }
    194 }
    195
    196 /**
    197  * @package sapphire
    198  * @subpackage widgets
    199  */
    200 class Widget_TreeDropdownField extends TreeDropdownField {
    201     function FieldHolder() {}
    202     function Field() {}
    203 }
    204
    205 ?>

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -