Fieldmanager
  • Package
  • Class
  • Tree
  • Todo

Packages

  • Fieldmanager
    • Context
    • Datasource
    • Field
    • Util
  • None

Classes

  • Fieldmanager_Autocomplete
  • Fieldmanager_Checkbox
  • Fieldmanager_Checkboxes
  • Fieldmanager_Colorpicker
  • Fieldmanager_Datepicker
  • Fieldmanager_DraggablePost
  • Fieldmanager_Field
  • Fieldmanager_Grid
  • Fieldmanager_Group
  • Fieldmanager_Hidden
  • Fieldmanager_Link
  • Fieldmanager_Media
  • Fieldmanager_Options
  • Fieldmanager_Password
  • Fieldmanager_Radios
  • Fieldmanager_RichTextArea
  • Fieldmanager_Select
  • Fieldmanager_TextArea
  • Fieldmanager_TextField
  1 <?php
  2 
  3 /**
  4  * Abstract base class for handling option fields, like select elements,
  5  * checkboxes or radios.
  6  *
  7  * @package Fieldmanager_Field
  8  */
  9 abstract class Fieldmanager_Options extends Fieldmanager_Field {
 10 
 11     /**
 12      * @var array
 13      * Full option data, allows grouping
 14      */
 15     public $data = array();
 16 
 17     /**
 18      * @var array
 19      * Shortcut to data which allows a simple associative array
 20      */
 21     public $options = array();
 22 
 23     /**
 24      * @var boolean
 25      * Is the data grouped?
 26      * E.g. should we use <optgroup>
 27      */
 28     public $grouped = false;
 29 
 30     /**
 31      * @var array
 32      * Always prepend this element to the $data
 33      */
 34     public $first_element = array();
 35 
 36     /**
 37      * @var boolean
 38      * Allow multiple selections?
 39      */
 40     public $multiple = False;
 41 
 42     /**
 43      * @var string
 44      * Path to an options template to load.
 45      */
 46     public $options_template = '';
 47 
 48     /**
 49      * @var boolean
 50      * Ensure that the datasource only runs once.
 51      */
 52     private $has_built_data = False;
 53 
 54     /**
 55      * Add CSS, construct parent
 56      * @param string $label
 57      * @param mixed $options
 58      */
 59     public function __construct( $label = '', $options = array() ) {
 60         $this->sanitize = array( $this, 'sanitize' );
 61         parent::__construct( $label, $options );
 62 
 63         if ( !empty( $this->options ) ) {
 64             $this->add_options( $this->options );
 65         }
 66 
 67         // Add the options CSS
 68         fm_add_style( 'fm_options_css', 'css/fieldmanager-options.css' );
 69     }
 70 
 71     /**
 72      * Sanitize function that can handle arrays as well as string values.
 73      * @param array|string $value
 74      * @return array|string Sanitized $value
 75      */
 76     public function sanitize( $value ) {
 77         if ( isset( $value ) && is_array( $value ) && ! empty( $value ) ) {
 78             return array_map( 'sanitize_text_field', $value );
 79         } else {
 80             return sanitize_text_field( $value );
 81         }
 82     }
 83 
 84     /**
 85      * Add options
 86      * @param array $options
 87      * @return void
 88      */
 89     public function add_options( $options ) {
 90         $values = array_values( $options );
 91         if ( isset( $values[0] ) && is_array( $values[0] ) ) {
 92             foreach ( $options as $group => $data ) {
 93                 foreach ( $data as $value => $label ) {
 94                     $this->add_option_data( $value, $label, $group, $group );
 95                 }
 96             }
 97         } else {
 98             $keys = array_keys( $options );
 99             $use_name_as_value = ( array_keys( $keys ) === $keys );
100             foreach ( $options as $k => $v ) {
101                 $this->add_option_data( $v, ( $use_name_as_value ? $v : $k ) );
102             }
103         }
104     }
105 
106     /**
107      * Generate form elements.
108      * @param mixed $value
109      * @return string HTML
110      */
111     public function form_data_elements( $value ) {
112 
113         if ( !$this->has_built_data ) {
114             if ( $this->datasource ) {
115                 $this->add_options( $this->datasource->get_items() );
116             }
117 
118             // Add the first element to the data array. This is useful for database-based data sets that require a first element.
119             if ( !empty( $this->first_element ) ) array_unshift( $this->data, $this->first_element );
120             $this->has_built_data = True;
121         }
122 
123         // If the value is not in an array, put it in one since sometimes there will be multiple selects
124         if ( !is_array( $value ) && isset( $value ) ) {
125             $value = array( $value );
126         }
127 
128         // Output the data for the form. Child classes will handle the output format appropriate for them.
129         $form_data_elements_html = '';
130 
131         if ( !empty( $this->data ) ) {
132 
133             $current_group = '';
134 
135             foreach( $this->data as $data_element ) {
136 
137                 // If grouped display is desired, check where to add the start and end points
138                 // Note we are assuming the data has come pre-sorted into groups
139                 if( $this->grouped && ( $current_group != $data_element['group'] ) ) {
140 
141                     // Append the end for the previous group unless this is the first group
142                     if ( $current_group != '' ) $form_data_elements_html .= $this->form_data_end_group();
143 
144                     // Append the start of the group
145                     $form_data_elements_html .= $this->form_data_start_group( $data_element['group'] );
146 
147                     // Set the current group
148                     $current_group = $data_element['group'];
149                 }
150 
151                 // Get the current element
152                 $form_data_elements_html .= $this->form_data_element( $data_element, $value );
153             }
154 
155             // If this was grouped display, close the final group
156             if( $this->grouped || ( isset( $this->datasource ) && $this->datasource->grouped ) ) $form_data_elements_html .= $this->form_data_end_group();
157         }
158 
159         return $form_data_elements_html;
160 
161     }
162 
163     /**
164      * A single element for a single bit of data, e.g. '<option>'
165      * @param mixed $value
166      */
167     public function form_data_element( $data_row, $value ) {
168         if ( !$this->options_template ) {
169             $tpl_slug = 'options-' . strtolower( str_replace( 'Fieldmanager_', '', get_class( $this ) ));
170             $this->options_template = fieldmanager_get_template( $tpl_slug );
171         }
172         ob_start();
173         include $this->options_template;
174         return ob_get_clean();
175     }
176 
177     /**
178      * Helper for output functions to toggle a selected options
179      * @param string $current_option this option
180      * @param array $options all valid options
181      * @param string $attribute
182      * @return string $attribute on match, empty on failure.
183      */
184     public function option_selected( $current_option, $options, $attribute ) {
185         if ( ( $options != null && !empty( $options ) ) && in_array( $current_option, $options ) ) return $attribute;
186         else return '';
187     }
188 
189     /**
190      * Override presave_all to handle special cases associated with multiple options fields.
191      * @input mixed[] $values
192      * @return mixed[] sanitized values
193      */
194     public function presave_all( $values, $current_values ) {
195         // Multiple select and radio fields with no values chosen are left out of
196         // the post request altogether, requiring special case handling.
197         if ( 1 !== $this->limit && '' === $values ) {
198             $values = null;
199         }
200 
201         return parent::presave_all( $values, $current_values );
202     }
203 
204     /**
205      * Presave function, which handles sanitization and validation
206      * @param mixed $value If a single field expects to manage an array, it must override presave()
207      * @return sanitized values.
208      */
209     public function presave( $value, $current_value = array() ) {
210         if ( !empty( $this->datasource ) ) {
211             return $this->datasource->presave( $this, $value, $current_value );
212         }
213         foreach ( $this->validate as $func ) {
214             if ( !call_user_func( $func, $value ) ) {
215                 $this->_failed_validation( sprintf(
216                     __( 'Input "%1$s" is not valid for field "%2$s" ', 'fieldmanager' ),
217                     (string) $value,
218                     $this->label
219                 ) );
220             }
221         }
222         return call_user_func( $this->sanitize, $value );
223     }
224 
225     /**
226      * Alter values before rendering
227      * @param array $values
228      */
229     public function preload_alter_values( $values ) {
230         if ( $this->datasource ) return $this->datasource->preload_alter_values( $this, $values );
231         return $values;
232     }
233 
234     /**
235      * Presave hook to set taxonomy data, maybe
236      * @param int[] $values
237      * @param int[] $current_values
238      * @return int[] $values
239      */
240     public function presave_alter_values( $values, $current_values = array() ) {
241         if ( !empty( $this->datasource ) ) {
242             if ( ! empty( $this->datasource->only_save_to_taxonomy ) ) {
243                 $this->skip_save = true;
244             } elseif ( ! empty( $this->datasource->only_save_to_post_parent ) ) {
245                 $this->skip_save = true;
246             }
247             return $this->datasource->presave_alter_values( $this, $values, $current_values );
248         }
249         return $values;
250     }
251 
252 
253     /**
254      * Add option data to the data attribute of this object
255      * @param string $name
256      * @param mixed $value
257      * @param string $group
258      * @param string|int $group_id
259      * @return void
260      */
261     protected function add_option_data( $name, $value, $group=null, $group_id=null ) {
262         $data = array(
263             'name' => $name,
264             'value' => $value
265         );
266         if( isset( $group ) ) $data['group'] = $group;
267         if( isset( $group_id ) ) $data['group_id'] = $group_id;
268 
269         $this->data[] = $data;
270     }
271 
272     /**
273      * Helper function to get the list of default meta boxes to remove.
274      * If $remove_default_meta_boxes is true and the datasource is Fieldmanager_Datasource_Term,
275      * this will return a list of all default meta boxes for the specified taxonomies.
276      * We only need to return id and context since the page will be handled by the list of post types provided to add_meta_box.
277      * Otherwise, this will just return an empty array.
278      * @param array current list of meta boxes to remove
279      * @return array list of meta boxes to remove
280      */
281     protected function add_meta_boxes_to_remove( &$meta_boxes_to_remove ) {
282         if ( $this->remove_default_meta_boxes && get_class( $this->datasource ) == 'Fieldmanager_Datasource_Term' ) {
283             // Iterate over the list and build the list of meta boxes
284             $meta_boxes = array();
285             foreach( $this->datasource->get_taxonomies() as $taxonomy ) {
286                 // The ID differs if this is a hierarchical taxonomy or not. Get the taxonomy object.
287                 $taxonomy_obj = get_taxonomy( $taxonomy );
288                 if ( false !== $taxonomy_obj ) {
289                     if ( $taxonomy_obj->hierarchical )
290                         $id = $taxonomy . "div";
291                     else
292                         $id = 'tagsdiv-' . $taxonomy;
293 
294                     $meta_boxes[$id] = array(
295                         'id' => $id,
296                         'context' => 'side'
297                     );
298                 }
299             }
300 
301             // Merge in the new meta boxes to remove
302             $meta_boxes_to_remove = array_merge( $meta_boxes_to_remove, $meta_boxes );
303         }
304     }
305 }
306 
307 require_once( dirname( __FILE__ ) . '/class-fieldmanager-select.php' );
308 
309 require_once( dirname( __FILE__ ) . '/class-fieldmanager-radios.php' );
310 
311 require_once( dirname( __FILE__ ) . '/class-fieldmanager-checkboxes.php' );
312 
Fieldmanager API documentation generated by ApiGen 2.8.0