PluginProbe ʕ •ᴥ•ʔ
Admin Columns / 2.4
Admin Columns v2.4
7.0.19 2.3.5 2.4 2.4.1 2.4.10 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.6.1 2.5.6.2 2.5.6.3 2.5.6.4 3.0 3.0.1 3.0.2 3.0.3 3.0.5 3.0.7 3.1 3.1.1 3.1.10 3.1.2 3.1.3 3.1.5 3.2.3 3.2.7 3.3.1 3.4.1 3.4.6 3.4.8 4.0.1 4.0.3 4.1.6 4.2.2 4.2.5 4.3 4.3.2 4.4.1 4.4.4 4.4.5 4.5.5 4.6.1 4.7.18 4.7.19 4.7.20 4.7.7 7.0.13 7.0.14 7.0.16 trunk 1.0 1.1 1.1.3 1.2 1.2.1 1.3 1.3.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.5.1 1.4.6 1.4.6.1 1.4.6.2 1.4.6.3 1.4.6.4 1.4.7 1.4.8 1.4.9 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2 2.2.1 2.2.1.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.5.1 2.2.6 2.2.6.1 2.2.6.2 2.2.6.3 2.2.6.4 2.2.7 2.2.8 2.2.8.1 2.2.9 2.3.1 2.3.2 2.3.3
codepress-admin-columns / classes / column.php
codepress-admin-columns / classes Last commit date
column 11 years ago storage_model 11 years ago addons.php 11 years ago column.php 11 years ago settings.php 11 years ago storage_model.php 11 years ago third_party.php 11 years ago upgrade.php 11 years ago utility.php 11 years ago
column.php
1365 lines
1 <?php
2 /**
3 * CPAC_Column class
4 *
5 * @since 2.0
6 *
7 * @param object $storage_model CPAC_Storage_Model
8 */
9 class CPAC_Column {
10
11 /**
12 * A Storage Model can be a Posttype, User, Comment, Link or Media storage type.
13 *
14 * @since 2.0
15 * @var CPAC_Storage_Model $storage_model contains a CPAC_Storage_Model object which the column belongs too.
16 */
17 public $storage_model;
18
19 /**
20 * @since 2.0
21 * @var array $options contains the user set options for the CPAC_Column object.
22 */
23 public $options = array();
24
25 /**
26 * @since 2.0
27 * @var object $options_default contains the options for the CPAC_Column object before they are populated with user input.
28 */
29 protected $options_default;
30
31 /**
32 * @since 2.0
33 * @var array $properties describes the fixed properties for the CPAC_Column object.
34 */
35 public $properties = array();
36
37 /**
38 * @since 2.0
39 *
40 * @param int $id ID
41 * @return string Value
42 */
43 public function get_value( $id ) {}
44
45 /**
46 * Get the raw, underlying value for the column
47 * Not suitable for direct display, use get_value() for that
48 *
49 * @since 2.0.3
50 *
51 * @param int $id ID
52 * @return mixed Value
53 */
54 public function get_raw_value( $id ) {}
55
56 /**
57 * @since 2.0
58 */
59 protected function display_settings() {}
60
61 /**
62 * Get the sorting value. This value will be used to sort the column.
63 *
64 * @since 2.3.2
65 * @param int $id Object ID
66 * @return string Value for sorting
67 */
68 public function get_sorting_value( $id ) {}
69
70 /**
71 * Overwrite this function in child class to sanitize
72 * user submitted values.
73 *
74 * @since 2.0
75 *
76 * @param $options array User submitted column options
77 * @return array Options
78 */
79 protected function sanitize_options( $options ) {
80
81 if ( isset( $options['date_format'] ) ) {
82 $options['date_format'] = trim( $options['date_format'] );
83 }
84
85 if ( isset( $options['width'] ) ) {
86 $options['width'] = trim( $options['width'] );
87 if ( ! is_numeric( $options['width'] ) ) {
88 $options['width'] = '';
89 }
90 }
91
92 return $options;
93 }
94
95 /**
96 * Overwrite this function in child class.
97 * Determine whether this column type should be available
98 *
99 * @since 2.2
100 *
101 * @return bool Whether the column type should be available
102 */
103 public function apply_conditional() {
104
105 return true;
106 }
107
108 /**
109 * Overwrite this function in child class.
110 * Adds (optional) scripts to the listings screen.
111 *
112 * @since 2.3.4
113 */
114 public function scripts() {}
115
116 /**
117 * An object copy (clone) is created for creating multiple column instances.
118 *
119 * @since 2.0
120 */
121 public function __clone() {
122
123 // Force a copy of this->object, otherwise it will point to same object.
124 $this->options = clone $this->options;
125 $this->properties = clone $this->properties;
126 }
127
128 /**
129 * @since 2.0
130 *
131 * @param object $storage_model CPAC_Storage_Model
132 */
133 public function __construct( CPAC_Storage_Model $storage_model ) {
134
135 $this->storage_model = $storage_model;
136
137 $this->init();
138 $this->after_setup();
139 }
140
141 /**
142 * @since 2.2
143 */
144 public function init() {
145
146 // Default properties
147 $default_properties = array(
148 'clone' => null, // Unique clone ID
149 'type' => null, // Unique type
150 'name' => null, // Unique name
151 'label' => null, // Label which describes this column.
152 'classes' => null, // Custom CSS classes for this column.
153 'hide_label' => false, // Should the Label be hidden?
154 'is_registered' => true, // Should the column be registered based on conditional logic, example usage see: 'post/page-template.php'
155 'is_cloneable' => true, // Should the column be cloneable
156 'default' => false, // Is this a WP default column,
157 'group' => 'custom',
158 'hidden' => false
159 );
160
161 foreach ( $default_properties as $property => $value ) {
162 $this->properties[ $property ] = $value;
163 }
164
165 // Default options
166 $default_options = array(
167 'before' => '', // Before field
168 'after' => '', // After field
169 'width' => null, // Width for this column.
170 'width_unit'=> '%', // Unit for width; pecentage (%) or pixels (px).
171 'state' => 'off' // Active state for this column.
172 );
173
174 /**
175 * Filter the default options for a column instance, such as label and width
176 *
177 * @since 2.2
178 * @param array $default_options Default column options
179 * @param CPAC_Storage_Model $storage_model Storage Model class instance
180 */
181 $default_options = apply_filters( 'cac/column/default_options', $default_options ); // do not pass $this because object is not ready
182
183 foreach ( $default_options as $option => $value ) {
184 $this->options[ $option ] = $value;
185 }
186 }
187
188 /**
189 * After Setup
190 *
191 */
192 public function after_setup() {
193
194 // Column name defaults to column type
195 if ( ! isset( $this->properties['name'] ) ) {
196 $this->properties['name'] = $this->properties['type'];
197 }
198
199 // Check whether the column should be available
200 $this->properties['is_registered'] = $this->apply_conditional();
201
202 /**
203 * Filter the properties of a column type, such as type and is_cloneable
204 * Property $column_instance added in Admin Columns 2.2
205 *
206 * @since 2.0
207 * @param array $properties Column properties
208 * @param CPAC_Storage_Model $storage_model Storage Model class instance
209 */
210 $this->properties = apply_filters( 'cac/column/properties', $this->properties ); // do not pass $this because object is not ready
211
212 /**
213 * Filter the properties of a column type for a specific storage model
214 * Property $column_instance added in Admin Columns 2.2
215 *
216 * @since 2.0
217 * @see Filter cac/column/properties
218 */
219 $this->properties = apply_filters( "cac/column/properties/storage_key={$this->storage_model->key}", $this->properties ); // do not pass $this because object is not ready
220
221 // Column label defaults to column type label
222 if ( ! isset( $this->options['label'] ) ) {
223 $this->options['label'] = $this->properties['label'];
224 }
225
226 // Convert properties and options arrays to object
227 $this->options = (object) $this->options;
228 $this->properties = (object) $this->properties;
229
230 // Read options from database
231 $this->populate_options();
232
233 $this->sanitize_label();
234 }
235
236 /**
237 * Populate Options
238 * Added $options parameter in 2.2
239 *
240 * @since 2.0
241 * @param array $options Optional. Options to populate the storage model with. Defaults to options from database.
242 */
243 public function populate_options( $options = NULL ) {
244 $this->options = (object) array_merge( (array) $this->options, is_array( $options ) ? $options : $this->read() );
245 }
246
247 /**
248 * @param string $property
249 * @return mixed $value
250 */
251 public function set_properties( $property, $value ) {
252 $this->properties->{$property} = $value;
253
254 return $this;
255 }
256
257 /**
258 * @param string $option
259 * @return mixed $value
260 */
261 public function set_options( $option, $value ) {
262 $this->options->{$option} = $value;
263
264 return $this;
265 }
266
267 /**
268 * @param int $id
269 * @return object
270 */
271 public function set_clone( $id = null ) {
272
273 if ( $id !== null && $id > 0 ) {
274 $this->properties->name = "{$this->properties->type}-{$id}";
275 $this->properties->clone = $id;
276 }
277
278 return $this;
279 }
280
281 /**
282 * @since 1.0
283 */
284 public function get_before() {
285 return stripslashes( $this->options->before );
286 }
287
288 /**
289 * @since 1.0
290 */
291 public function get_after() {
292 return stripslashes( $this->options->after );
293 }
294
295 /**
296 * Get the type of the column.
297 *
298 * @since 2.3.4
299 */
300 public function get_type() {
301 return $this->properties->type;
302 }
303
304 /**
305 * Get the name of the column.
306 *
307 * @since 2.3.4
308 */
309 public function get_name() {
310 return $this->properties->name;
311 }
312
313 /**
314 * Get the column options set by the user
315 *
316 * @since 2.3.4
317 * @return object Column options set by user
318 */
319 public function get_options() {
320 return $this->options;
321 }
322
323 /**
324 * Get a single column option
325 *
326 * @since 2.3.4
327 * @return array Column options set by user
328 */
329 public function get_option( $name ) {
330 return isset( $this->options->{$name} ) ? $this->options->{$name} : false;
331 }
332
333 /**
334 * Checks column type
335 *
336 * @since 2.3.4
337 * @param string $type Column type. Also work without the 'column-' prefix. Example 'column-meta' or 'meta'.
338 * @return bool Matches column type
339 */
340 public function is_type( $type ) {
341 return ( $type === $this->get_type() ) || ( 'column-' . $type === $this->get_type() );
342 }
343
344 /**
345 * @since 2.1.1
346 */
347 public function get_post_type() {
348 return $this->storage_model->get_post_type();
349 }
350
351 /**
352 * @since 2.3.4
353 */
354 public function get_storage_model() {
355 return $this->storage_model;
356 }
357
358 /**
359 * @since 2.3.4
360 */
361 public function get_storage_model_type() {
362 return $this->storage_model->get_type();
363 }
364
365 /**
366 * @since 2.3.4
367 */
368 public function get_storage_model_meta_type() {
369 return $this->storage_model->get_meta_type();
370 }
371
372 /**
373 * @param string $field_key
374 * @return void
375 */
376 public function attr_name( $field_name ) {
377 echo "{$this->storage_model->key}[{$this->properties->name}][{$field_name}]";
378 }
379
380 /**
381 * @param string $field_key
382 * @return string Attribute Name
383 */
384 public function attr_id( $field_name ) {
385 echo "cpac-{$this->storage_model->key}-{$this->properties->name}-{$field_name}";
386 }
387
388 /**
389 * @since 2.0
390 * @return array Column options
391 */
392 public function read() {
393 $options = (array) $this->storage_model->get_database_columns();
394
395 if ( empty( $options[ $this->properties->name ] ) ) {
396 return array();
397 }
398
399 return $options[ $this->properties->name ];
400 }
401
402 /**
403 * @since 2.0
404 */
405 public function sanitize_label() {
406 // check if original label has changed. Example WPML adds a language column, the column heading will have to display the added flag.
407 if ( $this->properties->hide_label && $this->properties->label !== $this->options->label ) {
408 $this->options->label = $this->properties->label;
409 }
410
411 // replace urls, so export will not have to deal with them
412 $this->options->label = stripslashes( str_replace( '[cpac_site_url]', site_url(), $this->options->label ) );
413 }
414
415 /**
416 * @since 2.0
417 * @param $options array User submitted column options
418 * @return array Options
419 */
420 public function sanitize_storage( $options ) {
421
422 // excerpt length must be numeric, else we will return it's default
423 if ( isset( $options['excerpt_length'] ) ) {
424 $options['excerpt_length'] = trim( $options['excerpt_length'] );
425 if ( empty( $options['excerpt_length'] ) || ! is_numeric( $options['excerpt_length'] ) ) {
426 $options['excerpt_length'] = $this->options_default->excerpt_length;
427 }
428 }
429
430 if ( ! empty( $options['label'] ) ) {
431
432 // Label can not contains the character ':', because
433 // CPAC_Column::get_sanitized_label() will return an empty string
434 // and make an exception for site_url()
435 if ( false === strpos( $options['label'], site_url() ) ) {
436 $options['label'] = str_replace( ':', '', $options['label'] );
437 }
438 }
439
440 // used by child classes for additional sanitizing
441 $options = $this->sanitize_options( $options );
442
443 return $options;
444 }
445
446 /**
447 * @since 2.0
448 */
449 public function get_label() {
450
451 /**
452 * Filter the column instance label
453 *
454 * @since 2.0
455 *
456 * @param string $label Column instance label
457 * @param CPAC_Column $column_instance Column class instance
458 */
459 return apply_filters( 'cac/column/settings_label', stripslashes( str_replace( '[cpac_site_url]', site_url(), $this->options->label ) ), $this );
460 }
461
462 /**
463 * Sanitizes label using intern wordpress function esc_url so it matches the label sorting url.
464 *
465 * @since 1.0
466 * @param string $string
467 * @return string Sanitized string
468 */
469 public function get_sanitized_label() {
470 $string = esc_url( $this->options->label );
471 $string = str_replace( 'http://', '', $string );
472 $string = str_replace( 'https://', '', $string );
473
474 return $string;
475 }
476
477 /**
478 * @since 1.3.1
479 */
480 protected function get_shorten_url( $url = '' ) {
481 if ( ! $url ) {
482 return false;
483 }
484
485 return "<a title='{$url}' href='{$url}'>" . url_shorten( $url ) . "</a>";
486 }
487
488 /**
489 * @since 1.3
490 */
491 protected function strip_trim( $string ) {
492 return trim( strip_tags( $string ) );
493 }
494
495 /**
496 * @since 2.2.1
497 */
498 protected function get_term_field( $field, $term_id, $taxonomy ) {
499 $term_field = get_term_field( $field, $term_id, $taxonomy, 'display' );
500 if ( is_wp_error( $term_field ) ) {
501 return false;
502 }
503 return $term_field;
504 }
505
506 /**
507 * @since 1.0
508 * @param int $post_id Post ID
509 * @return string Post Excerpt.
510 */
511 protected function get_post_excerpt( $post_id, $words ) {
512 global $post;
513
514 $save_post = $post;
515 $post = get_post( $post_id );
516
517 setup_postdata( $post );
518
519 $excerpt = get_the_excerpt();
520 $post = $save_post;
521
522 if ( $post ) {
523 setup_postdata( $post );
524 }
525
526 $output = $this->get_shortened_string( $excerpt, $words );
527
528 return $output;
529 }
530
531 /**
532 * @see wp_trim_words();
533 * @since 1.0
534 * @return string Trimmed text.
535 */
536 protected function get_shortened_string( $text = '', $num_words = 30, $more = null ) {
537 if ( ! $text ) {
538 return false;
539 }
540
541 return wp_trim_words( $text, $num_words, $more );
542 }
543
544 /**
545 * @since 1.3.1
546 * @param string $name
547 * @param string $title
548 * @return string HTML img element
549 */
550 public function get_asset_image( $name = '', $title = '' ) {
551
552 if ( ! $name ) {
553 return false;
554 }
555
556 return sprintf( "<img alt='' src='%s' title='%s'/>", CPAC_URL . "assets/images/{$name}", esc_attr( $title ) );
557 }
558
559 /**
560 * @since 1.2.0
561 * @param string $url
562 * @return bool
563 */
564 protected function is_image_url( $url ) {
565
566 if ( ! is_string( $url ) ) {
567 return false;
568 }
569
570 $validExt = array('.jpg', '.jpeg', '.gif', '.png', '.bmp');
571 $ext = strrchr( $url, '.' );
572
573 return in_array( $ext, $validExt );
574 }
575
576 /**
577 * @since 1.0
578 * @return array Image Sizes.
579 */
580 public function get_all_image_sizes() {
581 $image_sizes = array(
582 'thumbnail' => __( "Thumbnail", 'cpac' ),
583 'medium' => __( "Medium", 'cpac' ),
584 'large' => __( "Large", 'cpac' ),
585 'full' => __( "Full", 'cpac' )
586 );
587
588 foreach( get_intermediate_image_sizes() as $size ) {
589 if ( ! isset( $image_sizes[$size] ) ) {
590 $image_sizes[$size] = ucwords( str_replace( '-', ' ', $size) );
591 }
592 }
593
594 return $image_sizes;
595 }
596
597 /**
598 * @since 2.2.6
599 */
600 public function get_terms_for_display( $term_ids, $taxonomy ) {
601 if ( empty( $term_ids ) ) {
602 return false;
603 }
604
605 $values = array();
606 $term_ids = (array) $term_ids;
607 if ( $term_ids && ! is_wp_error( $term_ids ) ) {
608 $post_type = $this->get_post_type();
609 foreach ( $term_ids as $term_id ) {
610 $term = get_term( $term_id, $taxonomy );
611 $title = esc_html( sanitize_term_field( 'name', $term->name, $term->term_id, $term->taxonomy, 'edit' ) );
612
613 $filter_key = $term->taxonomy;
614 if ( 'category' === $term->taxonomy ) {
615 $filter_key = 'category_name';
616 }
617
618 $link = "<a href='edit.php?post_type={$post_type}&{$filter_key}={$term->slug}'>{$title}</a>";
619 if ( $post_type == 'attachment' ) {
620 $link = "<a href='upload.php?taxonomy={$filter_key}&term={$term->slug}'>{$title}</a>";
621 }
622
623 $values[] = $link;
624 }
625 }
626 if ( ! $values ) {
627 return false;
628 }
629
630 return implode( ', ', $values );
631 }
632
633 /**
634 * @since 2.0
635 * @param string $name
636 * @return array Image Sizes
637 */
638 public function get_image_size_by_name( $name = '' ) {
639
640 if ( ! $name || is_array( $name ) ) {
641 return false;
642 }
643
644 global $_wp_additional_image_sizes;
645
646 if ( ! isset( $_wp_additional_image_sizes[ $name ] ) ) {
647 return false;
648 }
649
650 return $_wp_additional_image_sizes[ $name ];
651 }
652
653 /**
654 * @see image_resize()
655 * @since 2.0
656 * @return string Image URL
657 */
658 public function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) {
659 $resized = false;
660 $editor = wp_get_image_editor( $file );
661
662 if ( is_wp_error( $editor ) )
663 return false;
664
665 $editor->set_quality( $jpeg_quality );
666
667 $resized = $editor->resize( $max_w, $max_h, $crop );
668 if ( is_wp_error( $resized ) )
669 return false;
670
671 $dest_file = $editor->generate_filename( $suffix, $dest_path );
672
673 $saved = $editor->save( $dest_file );
674
675 if ( is_wp_error( $saved ) )
676 return false;
677
678 $resized = $dest_file;
679
680 return $resized;
681 }
682
683 /**
684 * @since: 2.2.6
685 *
686 */
687 public function get_color_for_display( $color_hex ) {
688 if ( ! $color_hex ) {
689 return false;
690 }
691 $text_color = $this->get_text_color( $color_hex );
692 return "<div class='cpac-color'><span style='background-color:{$color_hex};color:{$text_color}'>{$color_hex}</span></div>";
693 }
694
695 /**
696 * Determines text color absed on bakground coloring.
697 *
698 * @since 1.0
699 */
700 public function get_text_color( $bg_color ) {
701
702 $rgb = $this->hex2rgb( $bg_color );
703
704 return $rgb && ( ( $rgb[0]*0.299 + $rgb[1]*0.587 + $rgb[2]*0.114 ) < 186 ) ? '#ffffff' : '#333333';
705 }
706
707 /**
708 * Convert hex to rgb
709 *
710 * @since 1.0
711 */
712 public function hex2rgb( $hex ) {
713 $hex = str_replace( "#", "", $hex );
714
715 if(strlen($hex) == 3) {
716 $r = hexdec(substr($hex,0,1).substr($hex,0,1));
717 $g = hexdec(substr($hex,1,1).substr($hex,1,1));
718 $b = hexdec(substr($hex,2,1).substr($hex,2,1));
719 } else {
720 $r = hexdec(substr($hex,0,2));
721 $g = hexdec(substr($hex,2,2));
722 $b = hexdec(substr($hex,4,2));
723 }
724 $rgb = array($r, $g, $b);
725
726 return $rgb;
727 }
728
729 /**
730 * Count the number of words in a string (multibyte-compatible)
731 *
732 * @since 2.3
733 *
734 * @param string $input Input string
735 * @return int Number of words
736 */
737 public function str_count_words( $input ) {
738
739 $patterns = array(
740 'strip' => '/<[a-zA-Z\/][^<>]*>/',
741 'clean' => '/[0-9.(),;:!?%#$¿\'"_+=\\/-]+/',
742 'w' => '/\S\s+/',
743 'c' => '/\S/'
744 );
745
746 $type = 'w';
747
748 $input = preg_replace( $patterns['strip'], ' ', $input );
749 $input = preg_replace( '/&nbsp;|&#160;/i', ' ', $input );
750 $input = preg_replace( $patterns['clean'], '', $input );
751
752 if ( ! strlen( preg_replace( '/\s/', '', $input ) ) ) {
753 return 0;
754 }
755
756 return preg_match_all( $patterns[ $type ], $input, $matches ) + 1;
757 }
758
759 /**
760 * @since 1.0
761 * @param mixed $meta Image files or Image ID's
762 * @param array $args
763 * @return array HTML img elements
764 */
765 public function get_thumbnails( $images, $args = array() ) {
766
767 if ( empty( $images ) || 'false' == $images ) {
768 return array();
769 }
770
771 // turn string to array
772 if ( is_string( $images ) || is_numeric( $images ) ) {
773 if ( strpos( $images, ',' ) !== false ) {
774 $images = array_filter( explode( ',', $this->strip_trim( str_replace( ' ', '', $images ) ) ) );
775 }
776 else {
777 $images = array( $images );
778 }
779 }
780
781 // Image size
782 $defaults = array(
783 'image_size' => 'cpac-custom',
784 'image_size_w' => 80,
785 'image_size_h' => 80,
786 );
787 $args = wp_parse_args( $args, $defaults );
788
789 extract( $args );
790
791 $thumbnails = array();
792 foreach( $images as $value ) {
793
794 if ( $this->is_image_url( $value ) ) {
795
796 // get dimensions from image_size
797 if ( $sizes = $this->get_image_size_by_name( $image_size ) ) {
798 $image_size_w = $sizes['width'];
799 $image_size_h = $sizes['height'];
800 }
801
802 $image_path = str_replace( WP_CONTENT_URL, WP_CONTENT_DIR, $value );
803
804 if ( is_file( $image_path ) ) {
805
806 // try to resize image
807 if ( $resized = $this->image_resize( $image_path, $image_size_w, $image_size_h, true ) ) {
808 $thumbnails[] = "<img src='" . str_replace( WP_CONTENT_DIR, WP_CONTENT_URL, $resized ) . "' alt='' width='{$image_size_w}' height='{$image_size_h}' />";
809 }
810
811 // return full image with maxed dimensions
812 else {
813 $thumbnails[] = "<img src='{$value}' alt='' style='max-width:{$image_size_w}px;max-height:{$image_size_h}px' />";
814 }
815 }
816 }
817
818 // Media Attachment
819 elseif ( is_numeric( $value ) && wp_get_attachment_url( $value ) ) {
820
821 $src = '';
822 $width = '';
823 $height = '';
824
825 if ( ! $image_size || 'cpac-custom' == $image_size ) {
826 $width = $image_size_w;
827 $height = $image_size_h;
828
829 // to make sure wp_get_attachment_image_src() get the image with matching dimensions.
830 $image_size = array( $width, $height );
831 }
832
833 // Is Image
834 if ( $attributes = wp_get_attachment_image_src( $value, $image_size ) ) {
835 $src = $attributes[0];
836 $width = $attributes[1];
837 $height = $attributes[2];
838
839 // image size by name
840 if ( $sizes = $this->get_image_size_by_name( $image_size ) ) {
841 $width = $sizes['width'];
842 $height = $sizes['height'];
843 }
844 }
845
846 // Is File, use icon
847 elseif ( $attributes = wp_get_attachment_image_src( $value, $image_size, true ) ) {
848 $src = $attributes[0];
849
850 if ( $sizes = $this->get_image_size_by_name( $image_size ) ) {
851 $width = $sizes['width'];
852 $height = $sizes['height'];
853 }
854 }
855
856 // maximum dimensions
857 $max = max( array( $width, $height ) );
858
859 $thumbnails[] = "<span class='cpac-column-value-image' style='width:{$width}px;height:{$height}px;'><img style='max-width:{$max}px;max-height:{$max}px;' src='{$src}' alt=''/></span>";
860 }
861 }
862
863 return $thumbnails;
864 }
865
866 /**
867 * Implode for multi dimensional array
868 *
869 * @since 1.0
870 * @param string $glue
871 * @param array $pieces
872 * @return string Imploded array
873 */
874 public function recursive_implode( $glue, $pieces ) {
875 foreach( $pieces as $r_pieces ) {
876 if ( is_array( $r_pieces ) ) {
877 $retVal[] = $this->recursive_implode( $glue, $r_pieces );
878 }
879 else {
880 $retVal[] = $r_pieces;
881 }
882 }
883 if ( isset($retVal) && is_array( $retVal ) ) {
884 return implode( $glue, $retVal );
885 }
886
887 return false;
888 }
889
890 /**
891 * Get timestamp
892 *
893 * @since 2.0
894 * @param string $date
895 * @return string Formatted date
896 */
897 public function get_timestamp( $date ) {
898
899 if ( empty( $date ) || in_array( $date, array( '0000-00-00 00:00:00', '0000-00-00', '00:00:00' ) ) ) {
900 return false;
901 }
902
903 // some plugins store dates in a jquery timestamp format, format is in ms since The Epoch.
904 // See http://api.jqueryui.com/datepicker/#utility-formatDate
905 // credits: nmarks
906 if ( is_numeric( $date ) ) {
907 $length = strlen( trim( $date ) );
908
909 // Dates before / around September 8th, 2001 are saved as 9 numbers * 1000 resulting in 12 numbers to store the time.
910 // Dates after September 8th are saved as 10 numbers * 1000, resulting in 13 numbers.
911 // For example the ACF Date and Time Picker uses this format.
912 // credits: Ben C
913 if ( 12 === $length || 13 === $length ) {
914 $date = round( $date / 1000 ); // remove the ms
915 }
916
917 // Date format: yyyymmdd ( often used by ACF ) must start with 19xx or 20xx and is 8 long
918 // @todo: in theory a numeric string of 8 can also be a unixtimestamp; no conversion would be needed
919 if ( 8 === $length && ( strpos( $date, '20' ) === 0 || strpos( $date, '19' ) === 0 ) ) {
920 $date = strtotime( $date );
921 }
922 }
923
924 // Parse with strtotime if it's not numeric
925 else {
926 $date = strtotime( $date );
927 }
928
929 return $date;
930 }
931
932 /**
933 * @since 1.3.1
934 * @param string $date
935 * @return string Formatted date
936 */
937 protected function get_date( $date, $format = '' ) {
938
939 if ( ! $date = $this->get_timestamp( $date ) ) {
940 return false;
941 }
942 if ( ! $format ) {
943 $format = get_option( 'date_format' );
944 }
945
946 return date_i18n( $format, $date );
947 }
948
949 /**
950 * @since 1.3.1
951 * @param string $date
952 * @return string Formatted time
953 */
954 protected function get_time( $date, $format = '' ) {
955
956 if ( ! $date = $this->get_timestamp( $date ) ) {
957 return false;
958 }
959 if ( ! $format ) {
960 $format = get_option( 'time_format' );
961 }
962
963 return date_i18n( $format, $date );
964 }
965
966 /**
967 * Get display name.
968 *
969 * Can also be used by addons.
970 *
971 * @since 2.0
972 */
973 public function get_display_name( $user_id ) {
974
975 if ( ! $userdata = get_userdata( $user_id ) ) {
976 return false;
977 }
978
979 $name = '';
980
981 if ( ! empty( $this->options->display_author_as ) ) {
982
983 $display_as = $this->options->display_author_as;
984
985 if ( 'first_last_name' == $display_as ) {
986 $first = ! empty( $userdata->first_name ) ? $userdata->first_name : '';
987 $last = ! empty( $userdata->last_name ) ? " {$userdata->last_name}" : '';
988 $name = $first.$last;
989 }
990
991 elseif ( ! empty( $userdata->{$display_as} ) ) {
992 $name = $userdata->{$display_as};
993 }
994 }
995
996 // default to display_name
997 if ( ! $name ) {
998 $name = $userdata->display_name;
999 }
1000
1001 return $name;
1002 }
1003
1004 /**
1005 * @since 2.0
1006 * @param string $field_key
1007 * @return string Attribute Name
1008 */
1009 public function label_view( $label, $description = '', $pointer = '' ) {
1010 ?>
1011 <td class="label">
1012 <label for="<?php $this->attr_id( $pointer ); ?>">
1013 <?php echo stripslashes( $label ); ?>
1014 <?php if( $description ) : ?><p class="description"><?php echo $description; ?></p><?php endif; ?>
1015 </label>
1016 </td>
1017 <?php
1018 }
1019
1020 /**
1021 * @since 2.0
1022 */
1023 public function display_field_date_format() {
1024
1025 $field_key = 'date_format';
1026 $label = __( 'Date Format', 'cpac' );
1027 $description = __( 'This will determine how the date will be displayed.', 'cpac' );
1028
1029 ?>
1030 <tr class="column_<?php echo $field_key; ?>">
1031 <?php $this->label_view( $label, $description, $field_key ); ?>
1032 <td class="input">
1033 <input type="text" name="<?php $this->attr_name( $field_key ); ?>" id="<?php $this->attr_id( $field_key ); ?>" value="<?php echo $this->options->date_format; ?>" placeholder="<?php _e( 'Example:', 'cpac' ); ?> d M Y H:i"/>
1034 <p class="description">
1035 <?php printf( __( 'Leave empty for WordPress date format, change your <a href="%s">default date format here</a>.' , 'cpac' ), admin_url( 'options-general.php' ) . '#date_format_custom_radio' ); ?>
1036 <a target='_blank' href='http://codex.wordpress.org/Formatting_Date_and_Time'><?php _e( 'Documentation on date and time formatting.', 'cpac' ); ?></a>
1037 </p>
1038 </td>
1039 </tr>
1040
1041 <?php
1042 }
1043
1044 /**
1045 * @since 2.0
1046 */
1047 public function display_field_excerpt_length() {
1048
1049 $field_key = 'excerpt_length';
1050 $label = __( 'Excerpt length', 'cpac' );
1051 $description = __( 'Number of words', 'cpac' );
1052
1053 ?>
1054 <tr class="column_<?php echo $field_key; ?>">
1055 <?php $this->label_view( $label, $description, $field_key ); ?>
1056 <td class="input">
1057 <input type="text" name="<?php $this->attr_name( $field_key ); ?>" id="<?php $this->attr_id( $field_key ); ?>" value="<?php echo $this->options->excerpt_length; ?>"/>
1058 </td>
1059 </tr>
1060 <?php
1061 }
1062
1063 /**
1064 * @since 2.0
1065 */
1066 public function display_field_preview_size() {
1067
1068 $field_key = 'image_size';
1069 $label = __( 'Preview size', 'cpac' );
1070
1071 ?>
1072 <tr class="column_<?php echo $field_key; ?>">
1073
1074 <?php $this->label_view( $label, '', $field_key ); ?>
1075
1076 <td class="input">
1077 <?php foreach ( $sizes = $this->get_all_image_sizes() as $id => $image_label ) : ?>
1078 <label for="<?php $this->attr_id( $field_key ); ?>-<?php echo $id ?>" class="custom-size">
1079 <input type="radio" value="<?php echo $id; ?>" name="<?php $this->attr_name( $field_key ); ?>" id="<?php $this->attr_id( $field_key ); ?>-<?php echo $id ?>"<?php checked( $this->options->image_size, $id ); ?>>
1080 <?php echo $image_label; ?>
1081 </label>
1082 <?php endforeach; ?>
1083
1084 <div class="custom_image_size">
1085 <label for="<?php $this->attr_id( $field_key ); ?>-custom" class="custom-size image-size-custom" >
1086 <input type="radio" value="cpac-custom" name="<?php $this->attr_name( $field_key ); ?>" id="<?php $this->attr_id( $field_key ); ?>-custom"<?php checked( $this->options->image_size, 'cpac-custom' ); ?>><?php _e( 'Custom', 'cpac' ); ?>
1087 </label>
1088 <label for="<?php $this->attr_id( $field_key ); ?>-w" class="custom-size-w<?php echo $this->options->image_size != 'cpac-custom' ? ' hidden' : ''; ?>">
1089 <input type="text" name="<?php $this->attr_name( 'image_size_w' ); ?>" id="<?php $this->attr_id( $field_key ); ?>-w" value="<?php echo $this->options->image_size_w; ?>" /><?php _e( 'width', 'cpac' ); ?>
1090 </label>
1091 <label for="<?php $this->attr_id( $field_key ); ?>-h" class="custom-size-h<?php echo $this->options->image_size != 'cpac-custom' ? ' hidden' : ''; ?>">
1092 <input type="text" name="<?php $this->attr_name( 'image_size_h' ); ?>" id="<?php $this->attr_id( $field_key ); ?>-h" value="<?php echo $this->options->image_size_h; ?>" /><?php _e( 'height', 'cpac' ); ?>
1093 </label>
1094 </div>
1095 </td>
1096 </tr>
1097 <?php
1098 }
1099
1100 /**
1101 * @since 2.1.1
1102 */
1103 public function display_field_before_after() {
1104 $this->display_field_text( 'before', __( "Before", 'cpac' ), __( 'This text will appear before the custom field value.', 'cpac' ) );
1105 $this->display_field_text( 'after', __( "After", 'cpac' ), __( 'This text will appear after the custom field value.', 'cpac' ) );
1106 }
1107
1108 /**
1109 * @since 2.3.2
1110 */
1111 public function display_field_user_format() {
1112
1113 $nametypes = array(
1114 'display_name' => __( 'Display Name', 'cpac' ),
1115 'first_name' => __( 'First Name', 'cpac' ),
1116 'last_name' => __( 'Last Name', 'cpac' ),
1117 'nickname' => __( 'Nickname', 'cpac' ),
1118 'user_login' => __( 'User Login', 'cpac' ),
1119 'user_email' => __( 'User Email', 'cpac' ),
1120 'ID' => __( 'User ID', 'cpac' ),
1121 'first_last_name' => __( 'First and Last Name', 'cpac' ),
1122 );
1123
1124 $this->display_field_select( 'display_author_as', __( 'Display format', 'cpac' ), $nametypes, __( 'This is the format of the author name.', 'cpac' ) );
1125 }
1126
1127 /**
1128 * @since 2.3.4
1129 * @param string $name Name of the column option
1130 * @return string $label Label
1131 * @return array $options Select options
1132 * @return strong $description (optional) Description below the label
1133 */
1134 public function display_field_select( $name, $label, $options = array(), $description = '' ) {
1135 $current = $this->get_option( $name );
1136 ?>
1137 <tr class="column-<?php echo $name; ?>">
1138 <?php $this->label_view( $label, $description, $name ); ?>
1139 <td class="input">
1140 <select name="<?php $this->attr_name( $name ); ?>" id="<?php $this->attr_id( $name ); ?>">
1141 <?php foreach ( $options as $key => $label ) : ?>
1142 <option value="<?php echo $key; ?>"<?php selected( $key, $current ); ?>><?php echo $label; ?></option>
1143 <?php endforeach; ?>
1144 </select>
1145 </td>
1146 </tr>
1147 <?php
1148 }
1149
1150 /**
1151 * @since 2.3.4
1152 * @param string $name Name of the column option
1153 * @return string $label Label
1154 * @return array $options Select options
1155 * @return strong $description (optional) Description below the label
1156 */
1157 public function display_field_text( $name, $label, $description = '' ) {
1158 ?>
1159 <tr class="column-<?php echo $name; ?>">
1160 <?php $this->label_view( $label, $description, $name ); ?>
1161 <td class="input">
1162 <input type="text" name="<?php $this->attr_name( $name ); ?>" id="<?php $this->attr_id( $name ); ?>" value="<?php echo esc_attr( stripslashes( $this->get_option( $name ) ) ); ?>"/>
1163 </td>
1164 </tr>
1165 <?php
1166 }
1167
1168 /**
1169 * @since 2.0
1170 * @param array Column Objects
1171 * @return string HTML List
1172 */
1173 public function get_column_list( $columns = array(), $label = '' ) {
1174
1175 if ( empty( $columns ) ) {
1176 return false;
1177 }
1178
1179 $list = '';
1180
1181 // sort by alphabet
1182 $_columns = array();
1183
1184 foreach ( $columns as $column ) {
1185 if ( $column->properties->hidden ) {
1186 continue;
1187 }
1188
1189 $_columns[ $column->properties->type ] = ( 0 === strlen( strip_tags( $column->properties->label ) ) ) ? ucfirst( $column->properties->type ) : $column->properties->label;
1190 }
1191
1192 asort( $_columns );
1193
1194 $list = "<optgroup label='{$label}'>";
1195 foreach ( $_columns as $type => $label ) {
1196 $selected = selected( $this->properties->type, $type, false );
1197 $list .= "<option value='{$type}'{$selected}>{$label}</option>";
1198 }
1199 $list .= "</optgroup>";
1200
1201 return $list;
1202 }
1203
1204 /**
1205 * @since 2.0
1206 */
1207 public function display() {
1208
1209 $classes = implode( ' ', array_filter( array ( "cpac-box-{$this->properties->type}", $this->properties->classes ) ) );
1210
1211 // column list
1212 $column_list = '';
1213
1214 $groups = $this->storage_model->get_column_type_groups();
1215 foreach ( $groups as $group => $label ) {
1216 $column_list .= $this->get_column_list( $this->storage_model->column_types[ $group ], $label );
1217 }
1218
1219 // clone attribute
1220 $data_clone = $this->properties->is_cloneable ? " data-clone='{$this->properties->clone}'" : '';
1221
1222 ?>
1223 <div class="cpac-column <?php echo $classes; ?>" data-type="<?php echo $this->properties->type; ?>"<?php echo $data_clone; ?>>
1224 <input type="hidden" class="column-name" name="<?php echo $this->attr_name( 'column-name' ); ?>" value="<?php echo esc_attr( $this->properties->name ); ?>" />
1225 <input type="hidden" class="type" name="<?php echo $this->attr_name( 'type' ); ?>" value="<?php echo $this->properties->type; ?>" />
1226 <input type="hidden" class="clone" name="<?php echo $this->attr_name( 'clone' ); ?>" value="<?php echo $this->properties->clone; ?>" />
1227 <div class="column-meta">
1228 <table class="widefat">
1229 <tbody>
1230 <tr>
1231 <td class="column_sort"></td>
1232 <td class="column_label">
1233 <div class="inner">
1234 <div class="meta">
1235
1236 <span title="<?php echo esc_attr( __( 'width', 'cpac' ) ); ?>" class="width" data-indicator-id="">
1237 <?php echo ! empty( $this->options->width ) ? $this->options->width . $this->options->width_unit : ''; ?>
1238 </span>
1239
1240 <?php
1241 /**
1242 * Fires in the meta-element for column options, which is displayed right after the column label
1243 *
1244 * @since 2.0
1245 *
1246 * @param CPAC_Column $column_instance Column class instance
1247 */
1248 do_action( 'cac/column/settings_meta', $this );
1249
1250 /**
1251 * @deprecated 2.2 Use cac/column/settings_meta instead
1252 */
1253 do_action( 'cac/column/label', $this );
1254 ?>
1255
1256 </div>
1257 <a class="toggle" href="javascript:;"><?php echo stripslashes( $this->get_label() ); ?></a>
1258 <a class="edit-button" href="javascript:;"><?php _e( 'Edit', 'cpac' ); ?></a>
1259 <?php if ( $this->properties->is_cloneable ) : ?>
1260 <a class="clone-button" href="#"><?php _e( 'Clone', 'cpac' ); ?></a>
1261 <?php endif; ?>
1262 <a class="remove-button" href="javascript:;"><?php _e( 'Remove', 'cpac' ); ?></a>
1263 </div>
1264 </td>
1265 <td class="column_type">
1266 <div class="inner">
1267 <a href="#"><?php echo stripslashes( $this->properties->label ); ?></a>
1268 </div>
1269 </td>
1270 <td class="column_edit"></td>
1271 </tr>
1272 </tbody>
1273 </table>
1274 </div><!--.column-meta-->
1275
1276 <div class="column-form">
1277 <table class="widefat">
1278 <tbody>
1279 <tr class="column_type">
1280 <?php $this->label_view( __( 'Type', 'cpac' ), __( 'Choose a column type.', 'cpac' ) . '<em>' . __( 'Type', 'cpac' ) . ': ' . $this->properties->type . '</em><em>' . __( 'Name', 'cpac' ) . ': ' . $this->properties->name . '</em>', 'type' ); ?>
1281 <td class="input">
1282 <select name="<?php $this->attr_name( 'type' ); ?>" id="<?php $this->attr_id( 'type' ); ?>">
1283 <?php echo $column_list; ?>
1284 </select>
1285 <div class="msg"></div>
1286 </td>
1287 </tr><!--.column_label-->
1288
1289 <tr class="column_label<?php echo $this->properties->hide_label ? ' hidden' : ''; ?>">
1290 <?php $this->label_view( __( 'Label', 'cpac' ), __( 'This is the name which will appear as the column header.', 'cpac' ), 'label' ); ?>
1291 <td class="input">
1292 <input class="text" type="text" name="<?php $this->attr_name( 'label' ); ?>" id="<?php $this->attr_id( 'label' ); ?>" value="<?php echo esc_attr( $this->options->label ); //echo sanitize_text_field( $this->options->label ); ?>" />
1293 </td>
1294 </tr><!--.column_label-->
1295
1296 <tr class="column_width">
1297 <?php $this->label_view( __( 'Width', 'cpac' ), '', 'width' ); ?>
1298 <td class="input">
1299 <div class="description" title="<?php _e( 'default', 'cpac' ); ?>">
1300 <input class="width" type="text" placeholder="<?php _e( 'auto', 'cpac' ); ?>" name="<?php $this->attr_name( 'width' ); ?>" id="<?php $this->attr_id( 'width' ); ?>" value="<?php echo $this->options->width; ?>" />
1301 <span class="unit"><?php echo $this->options->width_unit; ?></span>
1302 </div>
1303 <div class="width-slider"></div>
1304
1305 <div class="unit-select">
1306 <label for="<?php $this->attr_id( 'width_unit_px' ); ?>">
1307 <input type="radio" class="unit" name="<?php $this->attr_name( 'width_unit' ); ?>" id="<?php $this->attr_id( 'width_unit_px' ); ?>" value="px"<?php checked( $this->options->width_unit, 'px' ); ?>/>
1308 px
1309 </label>
1310 <label for="<?php $this->attr_id( 'width_unit_perc' ); ?>">
1311 <input type="radio" class="unit" name="<?php $this->attr_name( 'width_unit' ); ?>" id="<?php $this->attr_id( 'width_unit_perc' ); ?>" value="%"<?php checked( $this->options->width_unit, '%' ); ?>/>
1312 %
1313 </label>
1314 </div>
1315
1316 </td>
1317 </tr><!--.column_width-->
1318
1319 <?php
1320 /**
1321 * Fires directly before the custom options for a column are displayed in the column form
1322 *
1323 * @since 2.0
1324 * @param CPAC_Column $column_instance Column class instance
1325 */
1326 do_action( 'cac/column/settings_before', $this );
1327 ?>
1328
1329 <?php
1330 /**
1331 * Load specific column settings.
1332 *
1333 */
1334 $this->display_settings();
1335
1336 ?>
1337
1338 <?php
1339 /**
1340 * Fires directly after the custom options for a column are displayed in the column form
1341 *
1342 * @since 2.0
1343 * @param CPAC_Column $column_instance Column class instance
1344 */
1345 do_action( 'cac/column/settings_after', $this );
1346 ?>
1347
1348 <tr class="column_action">
1349 <td colspan="2">
1350 <p>
1351 <?php if ( $this->properties->is_cloneable ) : ?>
1352 <a class="clone-button" href="#"><?php _e( 'Clone', 'cpac' ); ?></a>
1353 <?php endif; ?>
1354 <a href="javascript:;" class="remove-button"><?php _e( 'Remove' );?></a>
1355 </p>
1356 </td>
1357 </tr>
1358
1359 </tbody>
1360 </table>
1361 </div>
1362 </div>
1363 <?php
1364 }
1365 }