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

Packages

  • auth
  • Booking
  • cart
    • shipping
    • steppedcheckout
  • Catalog
  • 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         return $this->FieldHolder();
 61     }
 62     
 63     /**
 64      * Accessor method for $this->children
 65      * @return FieldSet
 66      */
 67     public function getChildren() {
 68         return $this->children;
 69     }
 70     
 71     /**
 72      * @param FieldSet $children
 73      */
 74     public function setChildren($children) {
 75         $this->children = $children;
 76     }
 77 
 78     /**
 79      * Returns the fields nested inside another DIV
 80      */
 81     function FieldHolder() {
 82         $fs = $this->FieldSet();
 83         $idAtt = isset($this->id) ? " id=\"{$this->id}\"" : '';
 84         $className = ($this->columnCount) ? "field {$this->class} {$this->extraClass()} multicolumn" : "field {$this->class} {$this->extraClass()}";
 85         $content = "<div class=\"$className\"$idAtt>\n";
 86         
 87         foreach($fs as $subfield) {
 88             if($this->columnCount) {
 89                 $className = "column{$this->columnCount}";
 90                 if(!next($fs)) $className .= " lastcolumn";
 91                 $content .= "\n<div class=\"{$className}\">\n" . $subfield->FieldHolder() . "\n</div>\n";
 92             } else if($subfield){
 93                 $content .= "\n" . $subfield->FieldHolder() . "\n";
 94             }
 95         }
 96         $content .= "</div>\n";
 97                 
 98         return $content;
 99     }
100         
101     /**
102      * Returns the fields in the restricted field holder inside a DIV.
103      */
104     function SmallFieldHolder() {//return $this->FieldHolder();
105         $fs = $this->FieldSet();
106         $idAtt = isset($this->id) ? " id=\"{$this->id}\"" : '';
107         $className = ($this->columnCount) ? "field CompositeField {$this->extraClass()} multicolumn" : "field CompositeField {$this->extraClass()}";
108         $content = "<div class=\"$className\"$idAtt>";
109         
110         foreach($fs as $subfield) {//echo ' subf'.$subfield->Name();
111             if($this->columnCount) {
112                 $className = "column{$this->columnCount}";
113                 if(!next($fs)) $className .= " lastcolumn";
114                 $content .= "<div class=\"{$className}\">" . $subfield->FieldHolder() . "</div>";
115             } else if($subfield){
116                 $content .= $subfield->SmallFieldHolder() . " ";
117             }
118         }   
119         $content .= "</div>";
120     
121         return $content;
122     }   
123     /**
124      * Add all of the non-composite fields contained within this field to the list.
125      * Sequentialisation is used when connecting the form to its data source
126      */
127     public function collateDataFields(&$list, $saveableOnly = false) {
128         foreach($this->children as $field) {
129             if(is_object($field)) {
130                 if($field->isComposite()) $field->collateDataFields($list, $saveableOnly);
131                 if($saveableOnly) {
132                     $isIncluded =  ($field->hasData() && !$field->isReadonly() && !$field->isDisabled());
133                 } else {
134                     $isIncluded =  ($field->hasData());
135                 }
136                 if($isIncluded) {
137                     $name = $field->Name();
138                     if($name) {
139                         $formName = (isset($this->form)) ? $this->form->FormName() : '(unknown form)';
140                         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);
141                         $list[$name] = $field;
142                     }
143                 }
144             }
145         }
146     }
147 
148     function setForm($form) {
149         foreach($this->children as $f) if(is_object($f)) $f->setForm($form);
150         parent::setForm($form);
151     }
152     
153     function setColumnCount($columnCount) {
154         $this->columnCount = $columnCount;
155     }
156     
157     function isComposite() { return true; }
158     function hasData() { return false; }
159 
160     public function fieldByName($name) {
161         return $this->children->fieldByName($name);
162     }
163     /**
164      * Add a new child field to the end of the set.
165      */
166     public function push(FormField $field) {
167         $this->children->push($field);
168     }
169     
170     /**
171      * @uses FieldSet->insertBefore()
172      */
173     public function insertBefore($field, $insertBefore) {
174         $ret = $this->children->insertBefore($field, $insertBefore);
175         $this->sequentialSet = null;
176         return $ret;
177     }
178 
179     public function insertAfter($field, $insertAfter) {
180         $ret = $this->children->insertAfter($field, $insertAfter);
181         $this->sequentialSet = null;
182         return $ret;
183     }
184 
185     /**
186      * Remove a field from this CompositeField by Name.
187      * The field could also be inside a CompositeField.
188      * 
189      * @param string $fieldName The name of the field
190      * @param boolean $dataFieldOnly If this is true, then a field will only
191      * be removed if it's a data field.  Dataless fields, such as tabs, will
192      * be left as-is.
193      */
194     public function removeByName($fieldName, $dataFieldOnly = false) {
195         $this->children->removeByName($fieldName, $dataFieldOnly);
196     }
197 
198     public function replaceField($fieldName, $newField) {
199         return $this->children->replaceField($fieldName, $newField);
200     }
201 
202     function rootFieldSet() {
203         if(is_object($this->containerFieldSet)) return $this->containerFieldSet->rootFieldSet();
204         else return $this->children;
205     }
206     
207     /**
208      * Return a readonly version of this field.  Keeps the composition but returns readonly
209      * versions of all the children
210      */
211     public function performReadonlyTransformation() {
212         $newChildren = new FieldSet();
213         $clone = clone $this;
214         foreach($clone->getChildren() as $idx => $child) {
215             if(is_object($child)) $child = $child->transform(new ReadonlyTransformation());
216             $newChildren->push($child, $idx);
217         }
218 
219         $clone->children = $newChildren;
220         $clone->readonly = true;
221         return $clone;
222     }
223 
224     /**
225      * Return a readonly version of this field.  Keeps the composition but returns readonly
226      * versions of all the children
227      */
228     public function performDisabledTransformation($trans) {
229         $newChildren = new FieldSet();
230         $clone = clone $this;
231         if($clone->getChildren()) foreach($clone->getChildren() as $idx => $child) {
232             if(is_object($child)) {
233                 $child = $child->transform($trans);
234             }
235             $newChildren->push($child, $idx);
236         }
237 
238         $clone->children = $newChildren;
239         $clone->readonly = true;
240         
241         return $clone;
242     }
243 
244     function IsReadonly() {
245         return $this->readonly;
246     }
247     
248     /**
249      * Find the numerical position of a field within
250      * the children collection. Doesn't work recursively.
251      * 
252      * @param string|FormField
253      * @return Position in children collection (first position starts with 0). Returns FALSE if the field can't be found.
254      */
255     function fieldPosition($field) {
256         if(is_string($field)) $field = $this->fieldByName($field);
257         if(!$field) return false;
258         
259         $i = 0;
260         foreach($this->children as $child) {
261             if($child->Name() == $field->Name()) return $i;
262             $i++;
263         }
264         
265         return false;
266     }
267     
268     /**
269      * Transform the named field into a readonly feld.
270      * 
271      * @param string|FormField
272      */
273     function makeFieldReadonly($field) {
274         $fieldName = ($field instanceof FormField) ? $field->Name() : $field;
275         
276         // Iterate on items, looking for the applicable field
277         foreach($this->children as $i => $item) {
278             if($item->isComposite()) {
279                 $item->makeFieldReadonly($fieldName);
280             } else {
281                 // Once it's found, use FormField::transform to turn the field into a readonly version of itself.
282                 if($item->Name() == $fieldName) {
283                     $this->children->replaceField($fieldName, $item->transform(new ReadonlyTransformation()));
284 
285                     // Clear an internal cache
286                     $this->sequentialSet = null;
287 
288                     // A true results indicates that the field was foudn
289                     return true;
290                 }
291             }
292         }
293         return false;
294     }
295 
296     function debug() {
297         $result = "$this->class ($this->name) <ul>";
298         foreach($this->children as $child) {
299             $result .= "<li>" . Debug::text($child) . "&nbsp;</li>";
300         }
301         $result .= "</ul>";
302         return $result;
303     }
304     
305     function validate($validator){
306         
307         $valid = true;
308         foreach($this->children as $idx => $child){
309             $valid = ($child && $child->validate($validator) && $valid);
310         }
311         
312         return $valid;
313     }
314 }
315 
316 ?>
[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.1 API Docs API documentation generated by ApiGen 2.8.0