Version: current

      1 <?php
      2 /**
      3  * This formfield represents many-many joins using a tree selector shown in a dropdown styled element
      4  * which can be added to any form usually in the CMS.
      5  *
      6  * @package forms
      7  * @subpackage fields-relational
      8  */
      9 class TreeMultiselectField extends TreeDropdownField {
     10     function __construct($name, $title, $sourceObject = "Group", $keyField = "ID", $labelField = "Title") {
     11         parent::__construct($name, $title, $sourceObject, $keyField, $labelField);
     12         $this->value = 'unchanged';
     13     }
     14
     15     /**
     16      * Return this field's linked items
     17      */
     18     function getItems() {
     19         // If the value has been set, use that
     20         if($this->value != 'unchanged' && is_array($this->sourceObject)) {
     21             $items = array();
     22             $values = is_array($this->value) ? $this->value : preg_split('/ *, */', trim($this->value));
     23             foreach($values as $value) {
     24                 $item = new stdClass;
     25                 $item->ID = $value;
     26                 $item->Title = $this->sourceObject[$value];
     27                 $items[] = $item;
     28             }
     29             return $items;
     30
     31         // Otherwise, look data up from the linked relation
     32         } if($this->value != 'unchanged' && is_string($this->value)) {
     33             $items = new DataObjectSet();
     34             $ids = explode(',', $this->value);
     35             foreach($ids as $id) {
     36                 if(!is_numeric($id)) continue;
     37                 $item = DataObject::get_by_id($this->sourceObject, $id);
     38                 if($item) $items->push($item);
     39             }
     40             return $items;
     41         } else if($this->form) {
     42             $fieldName = $this->name;
     43             $record = $this->form->getRecord();
     44             if(is_object($record) && $record->hasMethod($fieldName))
     45                 return $record->$fieldName();
     46         }
     47     }
     48     /**
     49      * We overwrite the field attribute to add our hidden fields, as this
     50      * formfield can contain multiple values.
     51      */
     52     function Field() {
     53         $value = '';
     54         $itemList = '';
     55
     56         Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
     57
     58         Requirements::javascript(SAPPHIRE_DIR . '/thirdparty/prototype/prototype.js');
     59         Requirements::javascript(SAPPHIRE_DIR . '/thirdparty/behaviour/behaviour.js');
     60         Requirements::javascript(SAPPHIRE_DIR . '/javascript/tree/tree.js');
     61         // needed for errorMessage()
     62         Requirements::javascript(SAPPHIRE_DIR . '/javascript/LeftAndMain.js');
     63         Requirements::javascript(SAPPHIRE_DIR . '/javascript/TreeSelectorField.js');
     64
     65         Requirements::css(SAPPHIRE_DIR . '/javascript/tree/tree.css');
     66         Requirements::css(SAPPHIRE_DIR . '/css/TreeDropdownField.css');
     67
     68
     69         $items = $this->getItems();
     70
     71         if($items && count($items)) {
     72             foreach($items as $id => $item) {
     73                 $titleArray[] = $item->Title;
     74                 $idArray[] = $item->ID;
     75             }
     76
     77             if(isset($titleArray)) {
     78                 $itemList = implode(", ", $titleArray);
     79                 $value = implode(",", $idArray);
     80             }
     81         }
     82
     83         $id = $this->id();
     84
     85         return <<<HTML
     86             <div class="TreeDropdownField multiple" href="{$this->Link()}"><input id="$id" type="hidden" name="$this->name" value="$value" /><span class="items">$itemList</span><a href="#" title="open" class="editLink">&nbsp;</a></div>
     87 HTML;
     88     }
     89
     90     /**
     91      * Save the results into the form
     92      * Calls function $record->onChange($items) before saving to the assummed
     93      * Component set.
     94      */
     95     function saveInto(DataObject $record) {
     96         // Detect whether this field has actually been updated
     97         if($this->value !== 'unchanged') {
     98             $items = array();
     99
    100             $fieldName = $this->name;
    101             $saveDest = $record->$fieldName();
    102             if(!$saveDest) user_error("TreeMultiselectField::saveInto() Field '$fieldName' not found on $record->class.$record->ID", E_USER_ERROR);
    103
    104             if($this->value) {
    105                 $items = preg_split("/ *, */", trim($this->value));
    106             }
    107
    108             // Allows you to modify the items on your object before save
    109             $funcName = "onChange$fieldName";
    110             if($record->hasMethod($funcName)){
    111                 $result = $record->$funcName($items);
    112                 if(!$result){
    113                     return;
    114                 }
    115             }
    116
    117             $saveDest->setByIDList($items);
    118         }
    119     }
    120
    121     /**
    122      * Changes this field to the readonly field.
    123      */
    124     function performReadonlyTransformation() {
    125         $field = new TreeMultiselectField_Readonly($this->name, $this->title, $this->sourceObject, $this->keyField, $this->labelField);
    126         $field->addExtraClass($this->extraClass());
    127         $field->setForm($this->form);
    128         $field->setValue($this->value);
    129         return $field;
    130     }
    131 }
    132
    133 /**
    134  * @package forms
    135  * @subpackage fields-relational
    136  */
    137 class TreeMultiselectField_Readonly extends TreeMultiselectField {
    138
    139     protected $readonly = true;
    140
    141     function Field() {
    142         $titleArray = $itemIDs = array();
    143         $titleList = $itemIDsList = "";
    144         if($items = $this->getItems()) {
    145             foreach($items as $item) $titleArray[] = $item->Title;
    146             foreach($items as $item) $itemIDs[] = $item->ID;
    147             if($titleArray) $titleList = implode(", ", $titleArray);
    148             if($itemIDs) $itemIDsList = implode(",", $itemIDs);
    149         }
    150
    151         $field = new ReadonlyField($this->name.'_ReadonlyValue', $this->title);
    152         $field->setValue($titleList);
    153         $field->setForm($this->form);
    154
    155         $valueField = new HiddenField($this->name);
    156         $valueField->setValue($itemIDsList);
    157         $valueField->setForm($this->form);
    158
    159         return $field->Field().$valueField->Field();
    160     }
    161 }

[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. -