Version: current

      1 <?php
      2 /**
      3  * Lets you include a nested group of fields inside a template.
      4  * This control gives you more flexibility over form layout.
      5  *
      6  * Note: the child fields within a field group aren't rendered using FieldHolder().  Instead,
      7  * SmallFieldHolder() is called, which just prefixes $Field with a <label> tag, if the Title is set.
      8  *
      9  * <b>Usage</b>
     10  *
     11  * <code>
     12  * new FieldGroup(
     13  *  new FieldGroup(
     14  *      new HeaderField('FieldGroup 1'),
     15  *      new TextField('Firstname')
     16  *  ),
     17  *  new FieldGroup(
     18  *      new HeaderField('FieldGroup 2'),
     19  *      new TextField('Surname')
     20  *  )
     21  * )
     22  * </code>
     23  *
     24  * <b>Adding to existing FieldGroup instances</b>
     25  *
     26  * <code>
     27  * function getCMSFields() {
     28  *  $fields = parent::getCMSFields();
     29  *
     30  *  $fields->addFieldToTab(
     31  *      'Root.Content.Main',
     32  *      new FieldGroup(
     33  *          new TimeField("StartTime","What's the start time?"),
     34  *          new TimeField("EndTime","What's the end time?")
     35  *      ),
     36  *      'Content'
     37  *  );
     38  *
     39  *  return $fields;
     40  *
     41  * }
     42  * </code>
     43  *
     44  * @package forms
     45  * @subpackage fields-structural
     46  */
     47 class FieldGroup extends CompositeField {
     48     protected $zebra;
     49     public $subfieldParam = "SmallFieldHolder";
     50
     51     function __construct($arg1 = null, $arg2 = null) {
     52         if(is_array($arg1) || is_a($arg1, 'FieldSet')) {
     53             $fields = $arg1;
     54
     55         } else if(is_array($arg2) || is_a($arg2, 'FieldSet')) {
     56             $this->title = $arg1;
     57             $fields = $arg2;
     58
     59         } else {
     60             $fields = func_get_args();
     61             if(!is_object(reset($fields))) $this->title = array_shift($fields);
     62         }
     63
     64         parent::__construct($fields);
     65     }
     66
     67     /**
     68      * Returns the name (ID) for the element.
     69      * In some cases the FieldGroup doesn't have a title, but we still want
     70      * the ID / name to be set. This code, generates the ID from the nested children
     71      */
     72     function Name(){
     73         if ($this->name)
     74             return $this->name;
     75
     76         if(!$this->title) {
     77             $fs = $this->FieldSet();
     78             $compositeTitle = '';
     79             $count = 0;
     80             foreach($fs as $subfield){
     81                 $compositeTitle .= $subfield->Name();
     82                 if($subfield->Name()) $count++;
     83             }
     84             if($count == 1) $compositeTitle .= 'Group';
     85             return ereg_replace("[^a-zA-Z0-9]+","",$compositeTitle);
     86         }
     87
     88         return ereg_replace("[^a-zA-Z0-9]+","", Convert::rus2lat($this->title));
     89     }
     90
     91     /**
     92      * Returns a set of <span class="subfield"> tags, each containing a sub-field.
     93      * You can also use <% control FieldSet %>, if you'd like more control over the generated HTML
     94      *
     95      * @todo Shouldn't use SmallFieldHolder() (very difficult to style),
     96      * it is easier to overwrite the <div class="field"> behaviour in a more specific class
     97      */
     98     function Field() {
     99         $fs = $this->FieldSet();
    100         $spaceZebra = isset($this->zebra) ? " $this->zebra" : '';
    101         $idAtt = isset($this->id) ? " id=\"{$this->id}\"" : '';
    102         $content = "<div class=\"fieldgroup$spaceZebra\"$idAtt>";
    103         foreach($fs as $subfield) {
    104             $childZebra = (!isset($childZebra) || $childZebra == "odd") ? "even" : "odd";
    105             if($subfield->hasMethod('setZebra')) $subfield->setZebra($childZebra);
    106             $content .= "<div class=\"fieldgroupField\">" . $subfield->{$this->subfieldParam}() . "</div>";
    107         }
    108         $content .= "</div>";
    109         return $content;
    110     }
    111
    112     public function setID($id) {
    113         $this->id = Convert::raw2att($id);
    114     }
    115
    116     /**
    117      * Set an odd/even class
    118      */
    119     function setZebra($zebra) {
    120         if($zebra == 'odd' || $zebra == 'even') $this->zebra = $zebra;
    121         else user_error("setZebra passed '$zebra'.  It should be passed 'odd' or 'even'", E_USER_WARNING);
    122     }
    123
    124     function FieldHolder() {
    125         $Title = $this->XML_val('Title');
    126         $Message = $this->XML_val('Message');
    127         $MessageType = $this->XML_val('MessageType');
    128         $RightTitle = $this->XML_val('RightTitle');
    129         $Type = $this->XML_val('Type');
    130         $extraClass = $this->XML_val('extraClass');
    131         $Name = $this->XML_val('id');
    132         $Field = $this->XML_val('Field');
    133
    134         $titleBlock = (!empty($Title)) ? "<label class=\"left\">$Title</label>" : "";
    135         $messageBlock = (!empty($Message)) ? "<span class=\"message $MessageType\">$Message</span>" : "";
    136         $rightTitleBlock = (!empty($RightTitle)) ? "<label class=\"right\">$RightTitle</label>" : "";
    137
    138         return <<<HTML
    139 <div id="$Name" class="field $Type $extraClass">$titleBlock<div class="middleColumn">$Field</div>$rightTitleBlock$messageBlock</div>
    140 HTML;
    141     }
    142
    143     function Message() {
    144         $fs = $this->FieldSet();
    145         foreach($fs as $subfield) {
    146             if($m = $subfield->Message()) $message[] = $m;
    147         }
    148         if(isset($message)) return implode(",  ", $message) . ". ";
    149     }
    150
    151     function MessageType(){
    152         $fs = $this->FieldSet();
    153         foreach($fs as $subfield) {
    154             if($m = $subfield->MessageType()) $MessageType[$m] = 1;
    155         }
    156         if(isset($MessageType)) {
    157             return implode(" ", array_keys($MessageType));
    158         }
    159     }
    160
    161     /**
    162      * This allows fields within this fieldgroup to still allow them to get valuated.
    163      */
    164     function jsValidation(){
    165         $fs = $this->FieldSet();
    166         $validationCode = '';
    167
    168         foreach($fs as $subfield) {
    169             if($value = $subfield->jsValidation()) {
    170                 $validationCode .= $value;
    171             }
    172         }
    173         return $validationCode;
    174     }
    175
    176     function php($data){
    177         return;
    178     }
    179
    180 }
    181
    182 ?>

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