Fieldmanager
  • Package
  • Class
  • Tree
  • Todo

Packages

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

Classes

  • Fieldmanager_Datasource
  • Fieldmanager_Datasource_Post
  • Fieldmanager_Datasource_Term
  • Fieldmanager_Datasource_User
  1 <?php
  2 
  3 /**
  4  * Datasource base class to populate autocomplete and option fields.
  5  *
  6  * Datasources provide data to populate autocomplete and option fields.
  7  *
  8  * This class can be used as an arbitrary data source for static options, or it
  9  * can be extended to provide custom data sources.
 10  *
 11  * @package Fieldmanager_Datasource
 12  */
 13 class Fieldmanager_Datasource {
 14 
 15     /**
 16      * @var array
 17      */
 18     public $options = array();
 19 
 20     /**
 21      * @var boolean
 22      */
 23     public $options_callback = Null;
 24 
 25     /**
 26      * @var boolean
 27      */
 28     public $use_ajax = False;
 29 
 30     /**
 31      * @var boolean
 32      */
 33     public $allow_optgroups = True;
 34 
 35     /**
 36      * @var string
 37      */
 38     public $ajax_action = '';
 39 
 40     /**
 41      * @var int
 42      * Counter to create uniquely named AJAX actions.
 43      */
 44     public static $counter = 0;
 45 
 46     /**
 47      * @var boolean
 48      * If true, group elements
 49      */
 50     public $grouped = False;
 51 
 52     /**
 53      * Constructor
 54      */
 55     public function __construct( $options = array() ) {
 56 
 57         foreach ( $options as $k => $v ) {
 58             try {
 59                 $reflection = new ReflectionProperty( $this, $k ); // Would throw a ReflectionException if item doesn't exist (developer error)
 60                 if ( $reflection->isPublic() ) $this->$k = $v;
 61                 else throw new FM_Developer_Exception; // If the property isn't public, don't set it (rare)
 62             } catch ( Exception $e ) {
 63                 $message = sprintf(
 64                     __( 'You attempted to set a property "%1$s" that is nonexistant or invalid for an instance of "%2$s" named "%3$s".', 'fieldmanager' ),
 65                     $k, __CLASS__, !empty( $options['name'] ) ? $options['name'] : 'NULL'
 66                 );
 67                 $title = esc_html__( 'Nonexistant or invalid option' );
 68                 if ( !Fieldmanager_Field::$debug ) {
 69                     wp_die( esc_html( $message ), $title );
 70                 } else {
 71                     throw new FM_Developer_Exception( esc_html( $message ) );
 72                 }
 73             }
 74         }
 75 
 76         if ( get_class( $this ) == __CLASS__ && empty( $options ) ) {
 77             $message = esc_html__( 'Invalid options for Datasource; must use the options parameter to supply an array.', 'fieldmanager' );
 78             if ( Fieldmanager_Field::$debug ) {
 79                 throw new FM_Developer_Exception( $message );
 80             } else {
 81                 wp_die( $message, esc_html__( 'Invalid Datasource Options', 'fieldmanager' ) );
 82             }
 83         }
 84 
 85         if ( !empty( $this->options ) ) {
 86             $keys = array_keys( $this->options );
 87             if ( ( array_keys( $keys ) === $keys ) ) {
 88                 foreach ( $this->options as $k => $v ) {
 89                     $this->options[$v] = $v;
 90                     unset( $this->options[$k] );
 91                 }
 92             }
 93         }
 94 
 95         if ( $this->use_ajax ) {
 96             add_action( 'wp_ajax_' . $this->get_ajax_action(), array( $this, 'autocomplete_search' ) );
 97         }
 98     }
 99 
100     /**
101      * Get the value of an item; most clearly used by Post and Term, which
102      * take database IDs and return user-friendly titles.
103      * @param int $id
104      * @return string value
105      */
106     public function get_value( $id ) {
107         return isset( $this->options[ $id ] ) ? $this->options[ $id ] : '';
108     }
109 
110     /**
111      * Get available options, optionally filtering by a fragment (e.g. for Autocomplete)
112      * @param string $fragment optional fragment to filter by
113      * @return array, key => value of available options
114      */
115     public function get_items( $fragment = Null ) {
116         if ( !$fragment ) {
117             return $this->options;
118         }
119         $ret = array();
120         foreach ( $this->options as $k => $v ) {
121             if ( strpos( $v, $fragment ) !== False ) $ret[$k] = $v;
122         }
123         return $ret;
124     }
125 
126     /**
127      * Get an action to register by hashing (non cryptographically for speed)
128      * the options that make this datasource unique.
129      * @return string ajax action
130      */
131     public function get_ajax_action() {
132         if ( !empty( $this->ajax_action ) ) return $this->ajax_action;
133         return 'fm_datasource_' . crc32( 'base' . json_encode( $this->options ) . $this->options_callback );
134     }
135 
136     /**
137      * Format items for use in AJAX.
138      *
139      * @param string|null $fragment to search
140      */
141     public function get_items_for_ajax( $fragment = null ) {
142         $items = $this->get_items( $fragment );
143         $return = array();
144 
145         foreach ( $items as $id => $label ) {
146             $return[] = array( 'label' => $label, 'value' => $id );
147         }
148 
149         return $return;
150     }
151 
152     /**
153      * AJAX callback to find posts
154      * @return void, causes process to exit.
155      */
156     public function autocomplete_search() {
157         // Check the nonce before we do anything
158         check_ajax_referer( 'fm_search_nonce', 'fm_search_nonce' );
159         $items = $this->get_items_for_ajax( sanitize_text_field( $_POST['fm_autocomplete_search'] ) );
160 
161         // See if any results were returned and return them as an array
162         if ( ! empty( $items ) ) {
163             wp_send_json( $items );
164         } else {
165             wp_send_json( 0 );
166         }
167     }
168 
169     /**
170      * Trigger to handle actions needed before saving data
171      * @param Fieldmanager_Field $field
172      * @param string|int $value
173      * @param string|int|null $current_value
174      * @return string cleaned value
175      */
176     public function presave_alter_values( Fieldmanager_Field $field, $values, $current_values ) {
177         // nothing here, but some child classes need this method.
178         return $values;
179     }
180 
181     /**
182      * Modify values before rendering editor
183      * @param Fieldmanager_Field $field
184      * @param array $values
185      * @return array $values loaded up, if applicable.
186      */
187     public function preload_alter_values( Fieldmanager_Field $field, $values ) {
188         return $values;
189     }
190 
191     /**
192      * Datasource handles sanitization and validation
193      * @param Fieldmanager_Field $field
194      * @param string|int $value
195      * @param string|int|null $current_value
196      * @return string cleaned value
197      */
198     public function presave( Fieldmanager_Field $field, $value, $current_value ) {
199         if ( is_array( $value ) ) {
200             return array_map( 'sanitize_text_field', $value );
201         }
202         return sanitize_text_field( $value );
203     }
204 
205     /**
206      * Get view link, not used here but meant for override
207      * @param int|string $value
208      * @return string
209      */
210     public function get_view_link( $value ) {
211         return '';
212     }
213 
214     /**
215      * Get edit link, not used here but meant for override
216      * @param int|string $value
217      * @return string
218      */
219     public function get_edit_link( $value ) {
220         return '';
221     }
222 
223 }
224 
Fieldmanager API documentation generated by ApiGen 2.8.0