Version: current

      1 <?php
      2 /**
      3  * Displays a set of checkboxes as a logical group.
      4  *
      5  * ASSUMPTION -> IF you pass your source as an array, you pass values as an array too.
      6  *              Likewise objects are handled the same.
      7  *
      8  * @todo Document the different source data that can be used
      9  * with this form field - e.g ComponentSet, DataObjectSet,
     10  * array. Is it also appropriate to accept so many different
     11  * types of data when just using an array would be appropriate?
     12  *
     13  * @todo Make use of FormField->createTag() to generate the
     14  * HTML tag(s) for this field.
     15  *
     16  * @package forms
     17  * @subpackage fields-basic
     18  */
     19 class CheckboxSetField extends OptionsetField {
     20
     21     /**
     22      * @var Array
     23      */
     24     protected $defaultItems = array();
     25
     26     /**
     27      * @todo Explain different source data that can be used with this field,
     28      * e.g. SQLMap, DataObjectSet or an array.
     29      *
     30      * @todo Should use CheckboxField FieldHolder rather than constructing own markup.
     31      */
     32     function Field() {
     33         Requirements::css(SAPPHIRE_DIR . '/css/CheckboxSetField.css');
     34
     35         $source = $this->source;
     36         $values = $this->value;
     37
     38         // Get values from the join, if available
     39         if(is_object($this->form)) {
     40             $record = $this->form->getRecord();
     41             if(!$values && $record && $record->hasMethod($this->name)) {
     42                 $funcName = $this->name;
     43                 $join = $record->$funcName();
     44                 if($join) {
     45                     foreach($join as $joinItem) {
     46                         $values[] = $joinItem->ID;
     47                     }
     48                 }
     49             }
     50         }
     51
     52         // Source is not an array
     53         if(!is_array($source) && !is_a($source, 'SQLMap')) {
     54             if(is_array($values)) {
     55                 $items = $values;
     56             } else {
     57                 // Source and values are DataObject sets.
     58                 if($values && is_a($values, 'DataObjectSet')) {
     59                     foreach($values as $object) {
     60                         if(is_a($object, 'DataObject')) {
     61                             $items[] = $object->ID;
     62                         }
     63                    }
     64                 } elseif($values && is_string($values)) {
     65                     $items = explode(',', $values);
     66                     $items = str_replace('{comma}', ',', $items);
     67                 }
     68             }
     69         } else {
     70             // Sometimes we pass a singluar default value thats ! an array && !DataObjectSet
     71             if(is_a($values, 'DataObjectSet') || is_array($values)) {
     72                 $items = $values;
     73             } else {
     74                 $items = explode(',', $values);
     75                 $items = str_replace('{comma}', ',', $items);
     76             }
     77         }
     78
     79         if(is_array($source)) {
     80             unset($source['']);
     81         }
     82
     83         $odd = 0;
     84         $options = array();
     85
     86         if($source) foreach($source as $index => $item) {
     87             if(is_a($item, 'DataObject')) {
     88                 $value = $item->ID;
     89                 $title = $item->Title;
     90             } else {
     91                 $value = $index;
     92                 $title = $item;
     93             }
     94
     95             $odd = ($odd + 1) % 2;
     96             $value_lat = Convert::rus2lat($value);
     97                         $extraClass = $odd ? 'odd' : 'even';
     98             $extraClass .= ' val' . str_replace(' ', '', $value_lat);
     99             $itemID = $this->id() . '_' . ereg_replace('[^a-zA-Z0-9]+', '', $value_lat);
    100             $checked = '';
    101
    102             if(isset($items)) {
    103                 $checked = (in_array($value, $items) || in_array($value, $this->defaultItems)) ? 1 : 0;
    104             }
    105             $disabled = ($this->disabled || in_array($value, $this->disabledItems)) ? 1 : 0;
    106
    107             $options[] = new ArrayData(array(
    108                 'ID' => $itemID,
    109                 'Class' => $extraClass,
    110                 'Name' => "{$this->name}[{$value_lat}]",
    111                 'Value' => $value,
    112                 'Title' => $title,
    113                 'isChecked' => $checked,
    114                 'isDisabled' => $disabled,
    115             ));
    116         }
    117
    118         $attributes = array(
    119             'class' => "optionset checkboxsetfield {$this->extraClass()}",
    120             'id' => $this->id(),
    121         );
    122         return $this->createTag('input', $attributes, new DataObjectSet($options));
    123     }
    124
    125     /**
    126      * Default selections, regardless of the {@link setValue()} settings.
    127      * Note: Items marked as disabled through {@link setDisabledItems()} can still be
    128      * selected by default through this method.
    129      *
    130      * @param Array $items Collection of array keys, as defined in the $source array
    131      */
    132     function setDefaultItems($items) {
    133         $this->defaultItems = $items;
    134     }
    135
    136     /**
    137      * @return Array
    138      */
    139     function getDefaultItems() {
    140         return $this->defaultItems;
    141     }
    142
    143     /**
    144      * Load a value into this CheckboxSetField
    145      */
    146     function setValue($value, $obj = null) {
    147         // If we're not passed a value directly, we can look for it in a relation method on the object passed as a second arg
    148         if(!$value && $obj && $obj instanceof DataObject && $obj->hasMethod($this->name)) {
    149             $funcName = $this->name;
    150             $selected = $obj->$funcName();
    151             if ($selected && is_object($selected) ) {
    152                 $value = $selected->toDropdownMap('ID', 'ID');
    153             }
    154         }
    155
    156         parent::setValue($value, $obj);
    157     }
    158
    159     /**
    160      * Save the current value of this CheckboxSetField into a DataObject.
    161      * If the field it is saving to is a has_many or many_many relationship,
    162      * it is saved by setByIDList(), otherwise it creates a comma separated
    163      * list for a standard DB text/varchar field.
    164      *
    165      * @param DataObject $record The record to save into
    166      */
    167     function saveInto(DataObject $record) {
    168         $fieldname = $this->name ;
    169         if($fieldname && $record && ($record->has_many($fieldname) || $record->many_many($fieldname))) {
    170             $idList = array();
    171             if($this->value) foreach($this->value as $id => $bool) {
    172                if($bool) {
    173                     $idList[] = $id;
    174                 }
    175             }
    176             $record->$fieldname()->setByIDList($idList);
    177         } elseif($fieldname && $record) {
    178             if($this->value) {
    179                 $this->value = str_replace(',', '{comma}', $this->value);
    180                 $record->$fieldname = implode(",", $this->value);
    181             } else {
    182                 $record->$fieldname = '';
    183             }
    184         }
    185     }
    186
    187     /**
    188      * Return the CheckboxSetField value as an array
    189      * selected item keys.
    190      *
    191      * @return string
    192      */
    193     function dataValue() {
    194         if($this->value && is_array($this->value)) {
    195             $filtered = array();
    196             foreach($this->value as $item) {
    197                 if($item) {
    198                     $filtered[] = str_replace(",", "{comma}", $item);
    199                 }
    200             }
    201             return implode(',', $filtered);
    202         }
    203         return '';
    204     }
    205
    206     function performDisabledTransformation() {
    207         $clone = clone $this;
    208         $clone->setDisabled(true);
    209
    210         return $clone;
    211     }
    212
    213     /**
    214      * Transforms the source data for this CheckboxSetField
    215      * into a comma separated list of values.
    216      *
    217      * @return ReadonlyField
    218      */
    219     function performReadonlyTransformation() {
    220         $values = '';
    221         $data = array();
    222
    223         $items = $this->value;
    224         if($this->source) {
    225             foreach($this->source as $source) {
    226                 if(is_object($source)) {
    227                     $sourceTitles[$source->ID] = $source->Title;
    228                 }
    229             }
    230         }
    231
    232         if($items) {
    233             // Items is a DO Set
    234             if(is_a($items, 'DataObjectSet')) {
    235                 foreach($items as $item) {
    236                     $data[] = $item->Title;
    237                 }
    238                 if($data) $values = implode(', ', $data);
    239
    240             // Items is an array or single piece of string (including comma seperated string)
    241             } else {
    242                 if(!is_array($items)) {
    243                     $items = preg_split('/ *, */', trim($items));
    244                 }
    245                 foreach($items as $item) {
    246                     if(is_array($item)) {
    247                         $data[] = $item['Title'];
    248                     } elseif(is_array($this->source) && !empty($this->source[$item])) {
    249                         $data[] = $this->source[$item];
    250                     } elseif(is_a($this->source, 'DataObjectSet')) {
    251                         $data[] = $sourceTitles[$item];
    252                     } else {
    253                         $data[] = $item;
    254                     }
    255                 }
    256                 $values = implode(', ', $data);
    257             }
    258         }
    259         $title = ($this->title) ? $this->title : '';
    260         $field = new ReadonlyField($this->name, $title, $values);
    261         $field->setForm($this->form);
    262
    263         return $field;
    264     }
    265
    266     function ExtraOptions() {
    267         return FormField::ExtraOptions();
    268     }
    269
    270 }
    271 ?>

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