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 to populate autocomplete and option fields with WordPress Users.
  5  *
  6  * @package Fieldmanager_Datasource
  7  */
  8 class Fieldmanager_Datasource_User extends Fieldmanager_Datasource {
  9 
 10     /**
 11      * Supply a function which returns a list of users; takes one argument,
 12      * a possible fragment
 13      */
 14     public $query_callback = Null;
 15 
 16     /**
 17      * Arguments to get_users(), which uses WP's defaults.
 18      * @see http://codex.wordpress.org/Template_Tags/get_users
 19      */
 20     public $query_args = array();
 21 
 22     /**
 23      * @var boolean
 24      * Allow AJAX. If set to false, Autocomplete will pre-load get_items() with no fragment,
 25      * so False could cause performance problems.
 26      */
 27     public $use_ajax = True;
 28 
 29     /**
 30      * @var string
 31      * Display property. Defaults to display_name, but can also be 'user_login', 'user_email',
 32      * or 'user_nicename'
 33      */
 34     public $display_property = 'display_name';
 35 
 36     /**
 37      * @var array
 38      * Allowed display properties for validation.
 39      */
 40     protected $allowed_display_properties = array( 'display_name', 'user_login', 'user_email', 'user_nicename' );
 41 
 42     /**
 43      * @var string
 44      * Store property. Defaults to ID, but can also be 'user_login', 'user_email',
 45      * or 'user_nicename'.
 46      */
 47     public $store_property = 'ID';
 48 
 49     /**
 50      * @var array
 51      * Allowed store properties for validation.
 52      */
 53     protected $allowed_store_properties = array( 'ID', 'user_login', 'user_email', 'user_nicename' );
 54 
 55     /**
 56      * @var string
 57      * Capability required to refer to a user via this datasource.
 58      * @see http://codex.wordpress.org/Roles_and_Capabilities
 59      */
 60     public $capability = 'list_users';
 61 
 62     /**
 63      * @var string|Null
 64      * If not empty, set this object's ID as a value on the user. This is used to
 65      * establish two-way relationships.
 66      */
 67     public $reciprocal = Null;
 68 
 69     /**
 70      * Constructor. Used for validation.
 71      */
 72     public function __construct( $options = array() ) {
 73         parent::__construct( $options );
 74 
 75         // Validate improper usage of store property
 76         if ( ! in_array( $this->store_property, $this->allowed_store_properties ) ) {
 77             throw new FM_Developer_Exception( sprintf(
 78                 __( 'Store property %s is invalid. Must be one of %s.', 'fieldmanager' ),
 79                 $this->store_property,
 80                 implode( ', ', $this->allowed_store_properties )
 81             ) );
 82         }
 83 
 84         if ( ! empty( $this->reciprocal ) && 'ID' != $this->store_property ) {
 85             throw new FM_Developer_Exception( __( 'You cannot use reciprocal relationships with FM_Datasource_User if store_property is not set to ID.', 'fieldmanager' ) );
 86         }
 87 
 88         // Validate improper usage of display property
 89         if ( ! in_array( $this->display_property, $this->allowed_display_properties ) ) {
 90             throw new FM_Developer_Exception( sprintf(
 91                 __( 'Display property %s is invalid. Must be one of %s.', 'fieldmanager' ),
 92                 $this->display_property,
 93                 implode( ', ', $this->allowed_display_properties )
 94             ) );
 95         }
 96     }
 97 
 98     /**
 99      * Get a user by the specified field.
100      * @param int $value post_id
101      * @return int|string
102      */
103     public function get_value( $value ) {
104         switch ( $this->store_property ) {
105             case 'ID':
106                 $field = 'id';
107                 break;
108             case 'user_nicename':
109                 $field = 'slug';
110                 break;
111             case 'user_email':
112                 $field = 'email';
113                 break;
114             case 'user_login':
115                 $field = 'login';
116                 break;
117         }
118 
119         // Sanitize the value
120         $value = $this->sanitize_value( $value );
121 
122         $user = get_user_by( $field, $value );
123         return $user ? $user->{$this->display_property} : '';
124     }
125 
126     /**
127      * Get users which match this datasource, optionally filtered by
128      * a search fragment, e.g. for Autocomplete.
129      * @param string $fragment
130      * @return array post_id => post_title for display or AJAX
131      */
132     public function get_items( $fragment = Null ) {
133         if ( is_callable( $this->query_callback ) ) {
134             return call_user_func( $this->query_callback, $fragment );
135         }
136 
137         $default_args = array();
138         $user_args = array_merge( $default_args, $this->query_args );
139         $ret = array();
140 
141         if ( $fragment ) {
142             $user_args['search'] = '*' . $fragment . '*';
143         }
144 
145         $users = get_users( $user_args );
146         foreach ( $users as $u ) {
147             $ret[ $u->{$this->store_property} ] = $u->{$this->display_property};
148         }
149 
150         return $ret;
151     }
152 
153     /**
154      * Get an action to register by hashing (non cryptographically for speed)
155      * the options that make this datasource unique.
156      * @return string ajax action
157      */
158     public function get_ajax_action() {
159         if ( !empty( $this->ajax_action ) ) return $this->ajax_action;
160         $unique_key = json_encode( $this->query_args );
161         $unique_key .= $this->display_property;
162         $unique_key .= (string) $this->query_callback;
163         return 'fm_datasource_post' . crc32( $unique_key );
164     }
165 
166     /**
167      * Delete reciprocal user metadata prior to saving (presave will re-add).
168      * Reciprocal relationships are not possible if we are not storing by ID.
169      * @param array $values new post values
170      * @param array $current_values existing post values
171      */
172     public function presave_alter_values( Fieldmanager_Field $field, $values, $current_values ) {
173         if ( $field->data_type != 'post' || ! $this->reciprocal || 'ID' != $this->store_property ) {
174             return $values;
175         }
176 
177         if ( ! empty( $current_values ) ) {
178             foreach ( $current_values as $user_id ) {
179                 delete_user_meta( $user_id, $this->reciprocal, $field->data_id );
180             }
181         }
182 
183         return $values;
184     }
185 
186     /**
187      * Handle reciprocal usermeta.
188      * Reciprocal relationships are not possible if we are not storing by ID.
189      * @param int $value
190      * @return string
191      */
192     public function presave( Fieldmanager_Field $field, $value, $current_value ) {
193         if ( empty( $value ) ) {
194             return;
195         }
196 
197         $return_single = False;
198         if ( !is_array( $value ) ) {
199             $return_single = True;
200             $value = array( $value );
201         }
202 
203         foreach ( $value as $i => $v ) {
204             $value[$i] = $this->sanitize_value( $v );
205             if( ! current_user_can( $this->capability, $v ) ) {
206                 wp_die( esc_html( sprintf( __( 'Tried to refer to user "%s" which current user cannot edit.', 'fieldmanager' ), $v ) ) );
207             }
208             if ( $this->reciprocal && 'ID' == $this->store_property ) {
209                 add_user_meta( $v, $this->reciprocal, $field->data_id );
210             }
211         }
212 
213         return $return_single ? $value[0] : $value;
214     }
215 
216     /**
217      * Get view link for a user.
218      * @param int $value
219      * @return string
220      */
221     public function get_view_link( $value ) {
222         return '';
223     }
224 
225     /**
226      * Get edit link for a user.
227      * @param int $value
228      * @return string
229      */
230     public function get_edit_link( $value ) {
231         return sprintf(
232             ' <a target="_new" class="fm-autocomplete-edit-link %s" href="%s">%s</a>',
233             empty( $value ) ? 'fm-hidden' : '',
234             empty( $value ) ? '#' : esc_url( get_edit_user_link( $value ) ),
235             esc_html__( 'Edit', 'fieldmanager' )
236         );
237     }
238 
239     /**
240      * Sanitize the value based on store_property.
241      * @param int|string $value
242      * @return int|string
243      */
244     protected function sanitize_value( $value ) {
245         switch ( $this->store_property ) {
246         case 'ID':
247             $value = intval( $value );
248             break;
249         case 'user_email':
250             $value = sanitize_email( $value );
251             break;
252         default:
253             $value = sanitize_text_field( $value );
254             break;
255         }
256 
257         return $value;
258     }
259 }
260 
Fieldmanager API documentation generated by ApiGen 2.8.0