1 <?php
2
3 4 5 6 7
8 class Fieldmanager_Datasource_Term extends Fieldmanager_Datasource {
9
10 11 12 13
14 public $taxonomy = null;
15
16 17 18 19
20 public $taxonomy_args = array();
21
22 23 24 25
26 public $taxonomy_hierarchical = false;
27
28 29 30 31
32 public $taxonomy_hierarchical_depth = 0;
33
34 35 36 37
38 public $append_taxonomy = False;
39
40 41 42 43
44 public $taxonomy_save_to_terms = True;
45
46 47 48 49
50 public $only_save_to_taxonomy = False;
51
52 53 54 55
56 public $store_term_taxonomy_id = False;
57
58 59 60 61
62 public $use_ajax = True;
63
64 65 66
67 public function __construct( $options = array() ) {
68 global $wp_taxonomies;
69
70
71
72 if ( !isset( $options['taxonomy_args']['hide_empty'] ) ) {
73 $options['taxonomy_args']['hide_empty'] = False;
74 }
75
76 parent::__construct( $options );
77
78
79 if ( $this->only_save_to_taxonomy ) {
80 $this->taxonomy_save_to_terms = true;
81 }
82
83 if ( $this->taxonomy_save_to_terms ) {
84
85 foreach ( $this->get_taxonomies() as $taxonomy ) {
86 if ( ! empty( $wp_taxonomies[ $taxonomy ] ) ) {
87 $wp_taxonomies[ $taxonomy ]->sort = true;
88 }
89 }
90 }
91 }
92
93 94 95 96
97 public function get_taxonomies() {
98 return is_array( $this->taxonomy ) ? $this->taxonomy : array( $this->taxonomy );
99 }
100
101 102 103 104 105
106 public function get_ajax_action() {
107 if ( !empty( $this->ajax_action ) ) return $this->ajax_action;
108 $unique_key = json_encode( $this->taxonomy_args );
109 $unique_key .= json_encode( $this->get_taxonomies() );
110 $unique_key .= (string) $this->taxonomy_hierarchical;
111 $unique_key .= (string) $this->taxonomy_hierarchical_depth;
112 return 'fm_datasource_term_' . crc32( $unique_key );
113 }
114
115 116 117 118 119 120 121
122 public function preload_alter_values( Fieldmanager_Field $field, $values ) {
123 if ( $this->only_save_to_taxonomy ) {
124 $taxonomies = $this->get_taxonomies();
125 $terms = wp_get_object_terms( $field->data_id, $taxonomies[0], array( 'orderby' => 'term_order' ) );
126
127 if ( count( $terms ) > 0 ) {
128 if ( $field->limit == 1 && empty( $field->multiple ) ) {
129 return $terms[0]->term_id;
130 } else {
131 $ret = array();
132 foreach ( $terms as $term ) {
133 $ret[] = $term->term_id;
134 }
135 return $ret;
136 }
137 }
138 }
139 return $values;
140 }
141
142 143 144 145 146 147
148 public function presave_alter_values( Fieldmanager_Field $field, $values, $current_values ) {
149 if ( !is_array( $values ) ) {
150 $values = array( $values );
151 }
152
153
154 if ( get_class( $field ) == 'Fieldmanager_Autocomplete' && !$field->exact_match && isset( $this->taxonomy ) ) {
155 foreach( $values as $i => $value ) {
156
157 if ( is_numeric( $value ) ) {
158 continue;
159 }
160
161
162 if ( '=' === substr( $value, 0, 1 ) ) {
163 $value = sanitize_text_field( substr( $value, 1 ) );
164 }
165
166
167 $term_by = function_exists( 'wpcom_vip_get_term_by' ) ? 'wpcom_vip_get_term_by' : 'get_term_by';
168 $term = call_user_func( $term_by, 'name', $value, $this->taxonomy );
169
170 if ( !$term ) {
171 $term = wp_insert_term( $value, $this->taxonomy );
172 if ( is_wp_error( $term ) ) {
173 unset( $value );
174 continue;
175 }
176 $term = (object) $term;
177 }
178 $values[$i] = $term->term_id;
179 }
180 }
181
182
183 if ( $this->taxonomy_save_to_terms && isset( $this->taxonomy ) && !empty( $values ) ) {
184 $tax_values = array();
185 foreach ( $values as $value ) {
186 if ( !empty( $value ) ) {
187 if( is_numeric( $value ) )
188 $tax_values[] = $value;
189 else if( is_array( $value ) )
190 $tax_values = $value;
191 }
192 }
193 $this->pre_save_taxonomy( $tax_values, $field );
194 }
195 if ( $this->only_save_to_taxonomy ) {
196 if ( empty( $values ) && ! ( $this->append_taxonomy ) ) {
197 $this->pre_save_taxonomy( array(), $field );
198 }
199 return array();
200 }
201 return $values;
202 }
203
204 205 206
207 public function presave( Fieldmanager_Field $field, $value, $current_value ) {
208 return empty( $value ) ? $value : intval( $value );
209 }
210
211 212 213 214 215
216 public function pre_save_taxonomy( $tax_values, $field ) {
217
218 $tax_values = array_map( 'intval', $tax_values );
219 $tax_values = array_unique( $tax_values );
220 $taxonomies = $this->get_taxonomies();
221
222 $tree = $field->get_form_tree();
223 $oldest_parent = array_shift( $tree );
224
225 foreach( $taxonomies as $taxonomy ) {
226 if ( ! isset( $oldest_parent->current_context->taxonomies_to_save[ $taxonomy ] ) ) {
227 $oldest_parent->current_context->taxonomies_to_save[ $taxonomy ] = array(
228 'term_ids' => array(),
229 'append' => $this->append_taxonomy,
230 );
231 } else {
232
233 $oldest_parent->current_context->taxonomies_to_save[ $taxonomy ]['append'] = $oldest_parent->current_context->taxonomies_to_save[ $taxonomy ]['append'] && $this->append_taxonomy;
234 }
235 }
236
237
238 if ( count( $taxonomies ) > 1 ) {
239
240 $taxonomies_to_save = array();
241 foreach ( $tax_values as $term_id ) {
242 $term = $this->get_term( $term_id );
243 $oldest_parent->current_context->taxonomies_to_save[ $term->taxonomy ]['term_ids'][] = $term_id;
244 }
245 } else {
246 $oldest_parent->current_context->taxonomies_to_save[ $taxonomies[0] ]['term_ids'] = array_merge( $oldest_parent->current_context->taxonomies_to_save[ $taxonomies[0] ]['term_ids'], $tax_values );
247 }
248 }
249
250 251 252 253 254
255 public function get_items( $fragment = Null ) {
256
257
258 if ( $this->taxonomy_hierarchical ) {
259 $tax_args = $this->taxonomy_args;
260 $tax_args['parent'] = 0;
261 $parent_terms = get_terms( $this->get_taxonomies(), $tax_args );
262 return $this->build_hierarchical_term_data( $parent_terms, $this->taxonomy_args, 0, $fragment );
263 }
264
265 $tax_args = $this->taxonomy_args;
266 if ( !empty( $fragment ) ) $tax_args['search'] = $fragment;
267 $terms = get_terms( $this->get_taxonomies(), $tax_args );
268
269
270
271
272
273 if ( count( $this->get_taxonomies() ) > 1 && $this->grouped && $this->allow_optgroups ) {
274
275 $term_groups = array();
276 foreach ( $this->get_taxonomies() as $tax ) {
277 $term_groups[$tax] = array();
278 }
279 foreach ( $terms as $term ) {
280 $term_groups[$term->taxonomy][ $term->term_id ] = $term->name;
281 }
282 return $term_groups;
283 }
284
285
286 $stack = array();
287 foreach ( $terms as $term ) {
288
289 $key = $this->store_term_taxonomy_id ? $term->term_taxonomy_id : $term->term_id;
290 $stack[ $key ] = $term->name;
291 }
292 return apply_filters( 'fm_datasource_term_get_items', $stack, $terms, $this, $fragment );
293 }
294
295 296 297 298 299 300 301 302
303 protected function build_hierarchical_term_data( $parent_terms, $tax_args, $depth, $stack = array(), $pattern = '' ) {
304
305
306 foreach ( $parent_terms as $term ) {
307 $taxonomy_data = get_taxonomy( $term->taxonomy );
308 $prefix = '';
309
310
311 for ( $i = 0; $i < $depth; $i++ ) {
312 $prefix .= '--';
313 }
314
315 $key = $this->store_term_taxonomy_id ? $term->term_taxonomy_id : $term->term_id;
316 $stack[ $key ] = $prefix . ' ' . $term->name;
317
318
319 $tax_args['parent'] = $term->term_id;
320 if ( !empty( $pattern ) ) $tax_args['search'] = $fragment;
321 $child_terms = get_terms( $this->get_taxonomies(), $tax_args );
322 if ( $this->taxonomy_hierarchical_depth == 0 || $depth + 1 < $this->taxonomy_hierarchical_depth ) {
323 if ( !empty( $child_terms ) ) {
324 $stack = $this->build_hierarchical_term_data( $child_terms, $this->taxonomy_args, $depth + 1, $stack );
325 }
326 }
327 }
328 return $stack;
329 }
330
331 332 333 334 335
336 public function get_value( $value ) {
337 $id = intval( $value );
338 if ( ! $id )
339 return null;
340
341 $term = $this->get_term( $id );
342 $value = is_object( $term ) ? $term->name : '';
343 return apply_filters( 'fm_datasource_term_get_value', $value, $term, $this );
344 }
345
346 347 348 349 350
351 private function get_term( $term_id ) {
352 if ( $this->store_term_taxonomy_id ) {
353 global $wpdb;
354 return $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.term_taxonomy_id = %d LIMIT 1", $term_id ) );
355 } else {
356 $terms = get_terms( $this->get_taxonomies(), array( 'hide_empty' => false, 'include' => array( $term_id ), 'number' => 1 ) );
357 return !empty( $terms[0] ) ? $terms[0] : Null;
358 }
359 }
360
361 362 363 364 365
366 public function get_view_link( $value ) {
367 return sprintf(
368 ' <a target="_new" class="fm-autocomplete-view-link %s" href="%s">%s</a>',
369 empty( $value ) ? 'fm-hidden' : '',
370 empty( $value ) ? '#' : esc_url( get_term_link( $this->get_term( $value ) ) ),
371 esc_html__( 'View', 'fieldmanager' )
372 );
373 }
374
375 376 377 378 379
380 public function get_edit_link( $value ) {
381 $term = $this->get_term( $value );
382 return sprintf(
383 '<a target="_new" class="fm-autocomplete-edit-link %s" href="%s">%s</a>',
384 empty( $value ) ? 'fm-hidden' : '',
385 empty( $value ) ? '#' : esc_url( get_edit_term_link( $term->term_id, $term->taxonomy ) ),
386 esc_html__( 'Edit', 'fieldmanager' )
387 );
388 }
389
390 }
391