Webylon 3.2 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • 1c
    • exchange
      • catalog
  • auth
  • Booking
  • building
    • company
  • cart
    • shipping
    • steppedcheckout
  • Catalog
    • monument
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • CompositeField
  • FieldGroup
  • FieldSet
  • HiddenFieldSet
  • SelectionGroup
  • Tab
  • TabSet
  • ToggleCompositeField
  1 <?php
  2 /**
  3  * Base class for all fields that contain other fields.
  4  * Implements sequentialisation - so that when we're saving / loading data, we can populate
  5  * a tabbed form properly.  All of the children are stored in $this->children
  6  * @package forms
  7  * @subpackage fields-structural
  8  */
  9 class CompositeField extends FormField {
 10     
 11     /**
 12      * @var FieldSet
 13      */
 14     protected $children;
 15     
 16     /**
 17      * Set to true when this field is a readonly field
 18      */
 19     protected $readonly;
 20     
 21     /**
 22      * @var $columnCount int Toggle different css-rendering for multiple columns 
 23      * ("onecolumn", "twocolumns", "threecolumns"). The content is determined
 24      * by the $children-array, so wrap all items you want to have grouped in a
 25      * column inside a CompositeField.
 26      * Caution: Please make sure that this variable actually matches the 
 27      * count of your $children.
 28      */
 29     protected $columnCount = null;
 30     
 31     public function __construct($children = null) {
 32         if($children instanceof FieldSet) {
 33             $this->children = $children;
 34         } elseif(is_array($children)) {
 35             $this->children = new FieldSet($children); 
 36         } else {
 37             $children = is_array(func_get_args()) ? func_get_args() : array();
 38             $this->children = new FieldSet($children); 
 39         }
 40         $this->children->setContainerField($this);
 41         
 42         // Skipping FormField::__construct(), but we have to make sure this
 43         // doesn't count as a broken constructor
 44         $this->brokenOnConstruct = false;
 45         Object::__construct();
 46     }
 47 
 48     /**
 49      * Returns all the sub-fields, suitable for <% control FieldSet %>
 50      */
 51     public function FieldSet() {
 52         return $this->children;
 53     }
 54     
 55     public function setID($id) {
 56         $this->id = $id;
 57     }
 58     
 59     public function Field() {
 60         $attributes = array(
 61             'class' => ($this->columnCount) ? "field {$this->class} {$this->extraClass()} multicolumn" : "field {$this->class} {$this->extraClass()}",          
 62         );
 63         if (isset($this->id)) {
 64             $attributes['id'] = $this->id;
 65         }
 66         return $this->createTag('input', $attributes);
 67     }
 68     
 69     /**
 70      * Accessor method for $this->children
 71      * @return FieldSet
 72      */
 73     public function getChildren() {
 74         return $this->children;
 75     }
 76     
 77     /**
 78      * @param FieldSet $children
 79      */
 80     public function setChildren($children) {
 81         $this->children = $children;
 82     }
 83 
 84     /**
 85      * Returns the fields nested inside another DIV
 86      */
 87      /*
 88     function FieldHolder() {
 89         $fs = $this->FieldSet();
 90         $idAtt = isset($this->id) ? " id=\"{$this->id}\"" : '';
 91         $className = ($this->columnCount) ? "field {$this->class} {$this->extraClass()} multicolumn" : "field {$this->class} {$this->extraClass()}";
 92         $content = "<div class=\"$className\"$idAtt>\n";
 93         
 94         foreach($fs as $subfield) {
 95             if($this->columnCount) {
 96                 $className = "column{$this->columnCount}";
 97                 if(!next($fs)) $className .= " lastcolumn";
 98                 $content .= "\n<div class=\"{$className}\">\n" . $subfield->FieldHolder() . "\n</div>\n";
 99             } else if($subfield){
100                 $content .= "\n" . $subfield->FieldHolder() . "\n";
101             }
102         }
103         $content .= "</div>\n";
104                 
105         return $content;
106     }
107     */
108         
109     /**
110      * Returns the fields in the restricted field holder inside a DIV.
111      */
112      /*
113     function SmallFieldHolder() {//return $this->FieldHolder();
114         $fs = $this->FieldSet();
115         $idAtt = isset($this->id) ? " id=\"{$this->id}\"" : '';
116         $className = ($this->columnCount) ? "field CompositeField {$this->extraClass()} multicolumn" : "field CompositeField {$this->extraClass()}";
117         $content = "<div class=\"$className\"$idAtt>";
118         
119         foreach($fs as $subfield) {//echo ' subf'.$subfield->Name();
120             if($this->columnCount) {
121                 $className = "column{$this->columnCount}";
122                 if(!next($fs)) $className .= " lastcolumn";
123                 $content .= "<div class=\"{$className}\">" . $subfield->FieldHolder() . "</div>";
124             } else if($subfield){
125                 $content .= $subfield->SmallFieldHolder() . " ";
126             }
127         }   
128         $content .= "</div>";
129     
130         return $content;
131     }
132     */  
133     /**
134      * Add all of the non-composite fields contained within this field to the list.
135      * Sequentialisation is used when connecting the form to its data source
136      */
137     public function collateDataFields(&$list, $saveableOnly = false) {
138         foreach($this->children as $field) {
139             if(is_object($field)) {
140                 if($field->isComposite()) $field->collateDataFields($list, $saveableOnly);
141                 if($saveableOnly) {
142                     $isIncluded =  ($field->hasData() && !$field->isReadonly() && !$field->isDisabled());
143                 } else {
144                     $isIncluded =  ($field->hasData());
145                 }
146                 if($isIncluded) {
147                     $name = $field->Name();
148                     if($name) {
149                         $formName = (isset($this->form)) ? $this->form->FormName() : '(unknown form)';
150                         if(isset($list[$name])) user_error("collateDataFields() I noticed that a field called '$name' appears twice in your form: '{$formName}'.  One is a '{$field->class}' and the other is a '{$list[$name]->class}'", E_USER_ERROR);
151                         $list[$name] = $field;
152                     }
153                 }
154             }
155         }
156     }
157 
158     function setForm($form) {
159         foreach($this->children as $f) if(is_object($f)) $f->setForm($form);
160         parent::setForm($form);
161     }
162     
163     function setColumnCount($columnCount) {
164         $this->columnCount = $columnCount;
165     }
166     
167     function isComposite() { return true; }
168     function hasData() { return false; }
169 
170     public function fieldByName($name) {
171         return $this->children->fieldByName($name);
172     }
173     /**
174      * Add a new child field to the end of the set.
175      */
176     public function push(FormField $field) {
177         $this->children->push($field);
178     }
179     
180     /**
181      * @uses FieldSet->insertBefore()
182      */
183     public function insertBefore($field, $insertBefore) {
184         $ret = $this->children->insertBefore($field, $insertBefore);
185         $this->sequentialSet = null;
186         return $ret;
187     }
188 
189     public function insertAfter($field, $insertAfter) {
190         $ret = $this->children->insertAfter($field, $insertAfter);
191         $this->sequentialSet = null;
192         return $ret;
193     }
194 
195     /**
196      * Remove a field from this CompositeField by Name.
197      * The field could also be inside a CompositeField.
198      * 
199      * @param string $fieldName The name of the field
200      * @param boolean $dataFieldOnly If this is true, then a field will only
201      * be removed if it's a data field.  Dataless fields, such as tabs, will
202      * be left as-is.
203      */
204     public function removeByName($fieldName, $dataFieldOnly = false) {
205         $this->children->removeByName($fieldName, $dataFieldOnly);
206     }
207 
208     public function replaceField($fieldName, $newField) {
209         return $this->children->replaceField($fieldName, $newField);
210     }
211 
212     function rootFieldSet() {
213         if(is_object($this->containerFieldSet)) return $this->containerFieldSet->rootFieldSet();
214         else return $this->children;
215     }
216     
217     /**
218      * Return a readonly version of this field.  Keeps the composition but returns readonly
219      * versions of all the children
220      */
221     public function performReadonlyTransformation() {
222         $newChildren = new FieldSet();
223         $clone = clone $this;
224         foreach($clone->getChildren() as $idx => $child) {
225             if(is_object($child)) $child = $child->transform(new ReadonlyTransformation());
226             $newChildren->push($child, $idx);
227         }
228 
229         $clone->children = $newChildren;
230         $clone->readonly = true;
231         return $clone;
232     }
233 
234     /**
235      * Return a readonly version of this field.  Keeps the composition but returns readonly
236      * versions of all the children
237      */
238     public function performDisabledTransformation($trans) {
239         $newChildren = new FieldSet();
240         $clone = clone $this;
241         if($clone->getChildren()) foreach($clone->getChildren() as $idx => $child) {
242             if(is_object($child)) {
243                 $child = $child->transform($trans);
244             }
245             $newChildren->push($child, $idx);
246         }
247 
248         $clone->children = $newChildren;
249         $clone->readonly = true;
250         
251         return $clone;
252     }
253 
254     function IsReadonly() {
255         return $this->readonly;
256     }
257     
258     /**
259      * Find the numerical position of a field within
260      * the children collection. Doesn't work recursively.
261      * 
262      * @param string|FormField
263      * @return Position in children collection (first position starts with 0). Returns FALSE if the field can't be found.
264      */
265     function fieldPosition($field) {
266         if(is_string($field)) $field = $this->fieldByName($field);
267         if(!$field) return false;
268         
269         $i = 0;
270         foreach($this->children as $child) {
271             if($child->Name() == $field->Name()) return $i;
272             $i++;
273         }
274         
275         return false;
276     }
277     
278     /**
279      * Transform the named field into a readonly feld.
280      * 
281      * @param string|FormField
282      */
283     function makeFieldReadonly($field) {
284         $fieldName = ($field instanceof FormField) ? $field->Name() : $field;
285         
286         // Iterate on items, looking for the applicable field
287         foreach($this->children as $i => $item) {
288             if($item->isComposite()) {
289                 $item->makeFieldReadonly($fieldName);
290             } else {
291                 // Once it's found, use FormField::transform to turn the field into a readonly version of itself.
292                 if($item->Name() == $fieldName) {
293                     $this->children->replaceField($fieldName, $item->transform(new ReadonlyTransformation()));
294 
295                     // Clear an internal cache
296                     $this->sequentialSet = null;
297 
298                     // A true results indicates that the field was foudn
299                     return true;
300                 }
301             }
302         }
303         return false;
304     }
305 
306     function debug() {
307         $result = "$this->class ($this->name) <ul>";
308         foreach($this->children as $child) {
309             $result .= "<li>" . Debug::text($child) . "&nbsp;</li>";
310         }
311         $result .= "</ul>";
312         return $result;
313     }
314     
315     function validate($validator){
316         
317         $valid = true;
318         foreach($this->children as $idx => $child){
319             $valid = ($child && $child->validate($validator) && $valid);
320         }
321         
322         return $valid;
323     }
324 }
325 
326 ?>
[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. -
Webylon 3.2 API Docs API documentation generated by ApiGen 2.8.0