PluginProbe ʕ •ᴥ•ʔ
Admin Columns / 2.4.4
Admin Columns v2.4.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 review_notice.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
1380 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 ":"" and "'", 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 $options['label'] = str_replace( "'", '', $options['label'] );
438 }
439 }
440
441 // used by child classes for additional sanitizing
442 $options = $this->sanitize_options( $options );
443
444 return $options;
445 }
446
447 /**
448 * @since 2.0
449 */
450 public function get_label() {
451
452 /**
453 * Filter the column instance label
454 *
455 * @since 2.0
456 *
457 * @param string $label Column instance label
458 * @param CPAC_Column $column_instance Column class instance
459 */
460 return apply_filters( 'cac/column/settings_label', stripslashes( str_replace( '[cpac_site_url]', site_url(), $this->options->label ) ), $this );
461 }
462
463 /**
464 * Sanitizes label using intern wordpress function esc_url so it matches the label sorting url.
465 *
466 * @since 1.0
467 * @param string $string
468 * @return string Sanitized string
469 */
470 public function get_sanitized_label() {
471 $string = esc_url( $this->options->label );
472 $string = str_replace( 'http://', '', $string );
473 $string = str_replace( 'https://', '', $string );
474
475 return $string;
476 }
477
478 /**
479 * @since 1.3.1
480 */
481 protected function get_shorten_url( $url = '' ) {
482 if ( ! $url ) {
483 return false;
484 }
485
486 return "<a title='{$url}' href='{$url}'>" . url_shorten( $url ) . "</a>";
487 }
488
489 /**
490 * @since 1.3
491 */
492 protected function strip_trim( $string ) {
493 return trim( strip_tags( $string ) );
494 }
495
496 /**
497 * @since 2.2.1
498 */
499 protected function get_term_field( $field, $term_id, $taxonomy ) {
500 $term_field = get_term_field( $field, $term_id, $taxonomy, 'display' );
501 if ( is_wp_error( $term_field ) ) {
502 return false;
503 }
504 return $term_field;
505 }
506
507 /**
508 * @since 1.0
509 * @param int $post_id Post ID
510 * @return string Post Excerpt.
511 */
512 protected function get_post_excerpt( $post_id, $words ) {
513 global $post;
514
515 $save_post = $post;
516 $post = get_post( $post_id );
517
518 setup_postdata( $post );
519
520 $excerpt = get_the_excerpt();
521 $post = $save_post;
522
523 if ( $post ) {
524 setup_postdata( $post );
525 }
526
527 $output = $this->get_shortened_string( $excerpt, $words );
528
529 return $output;
530 }
531
532 /**
533 * @see wp_trim_words();
534 * @since 1.0
535 * @return string Trimmed text.
536 */
537 protected function get_shortened_string( $text = '', $num_words = 30, $more = null ) {
538 if ( ! $text ) {
539 return false;
540 }
541
542 return wp_trim_words( $text, $num_words, $more );
543 }
544
545 /**
546 * @since 1.3.1
547 * @param string $name
548 * @param string $title
549 * @return string HTML img element
550 */
551 public function get_asset_image( $name = '', $title = '' ) {
552
553 if ( ! $name ) {
554 return false;
555 }
556 return sprintf( "<img alt='' src='%s' title='%s'/>", CPAC_URL . "assets/images/{$name}", esc_attr( $title ) );
557 }
558
559 /**
560 * @since 3.4.4
561 */
562 public function get_user_postcount( $user_id, $post_type ) {
563 global $wpdb;
564 $sql = "
565 SELECT COUNT(ID)
566 FROM {$wpdb->posts}
567 WHERE post_status = 'publish'
568 AND post_author = %d
569 AND post_type = %s
570 ";
571 return $wpdb->get_var( $wpdb->prepare( $sql, $user_id, $post_type ) );
572 }
573
574 /**
575 * @since 1.2.0
576 * @param string $url
577 * @return bool
578 */
579 protected function is_image_url( $url ) {
580
581 if ( ! is_string( $url ) ) {
582 return false;
583 }
584
585 $validExt = array('.jpg', '.jpeg', '.gif', '.png', '.bmp');
586 $ext = strrchr( $url, '.' );
587
588 return in_array( $ext, $validExt );
589 }
590
591 /**
592 * @since 1.0
593 * @return array Image Sizes.
594 */
595 public function get_all_image_sizes() {
596 $image_sizes = array(
597 'thumbnail' => __( "Thumbnail", 'cpac' ),
598 'medium' => __( "Medium", 'cpac' ),
599 'large' => __( "Large", 'cpac' ),
600 'full' => __( "Full", 'cpac' )
601 );
602
603 foreach( get_intermediate_image_sizes() as $size ) {
604 if ( ! isset( $image_sizes[$size] ) ) {
605 $image_sizes[$size] = ucwords( str_replace( '-', ' ', $size) );
606 }
607 }
608
609 return $image_sizes;
610 }
611
612 /**
613 * @since 2.2.6
614 */
615 public function get_terms_for_display( $term_ids, $taxonomy ) {
616 if ( empty( $term_ids ) ) {
617 return false;
618 }
619
620 $values = array();
621 $term_ids = (array) $term_ids;
622 if ( $term_ids && ! is_wp_error( $term_ids ) ) {
623 $post_type = $this->get_post_type();
624 foreach ( $term_ids as $term_id ) {
625 $term = get_term( $term_id, $taxonomy );
626 $title = esc_html( sanitize_term_field( 'name', $term->name, $term->term_id, $term->taxonomy, 'edit' ) );
627
628 $filter_key = $term->taxonomy;
629 if ( 'category' === $term->taxonomy ) {
630 $filter_key = 'category_name';
631 }
632
633 $link = "<a href='edit.php?post_type={$post_type}&{$filter_key}={$term->slug}'>{$title}</a>";
634 if ( $post_type == 'attachment' ) {
635 $link = "<a href='upload.php?taxonomy={$filter_key}&term={$term->slug}'>{$title}</a>";
636 }
637
638 $values[] = $link;
639 }
640 }
641 if ( ! $values ) {
642 return false;
643 }
644
645 return implode( ', ', $values );
646 }
647
648 /**
649 * @since 2.0
650 * @param string $name
651 * @return array Image Sizes
652 */
653 public function get_image_size_by_name( $name = '' ) {
654
655 if ( ! $name || is_array( $name ) ) {
656 return false;
657 }
658
659 global $_wp_additional_image_sizes;
660
661 if ( ! isset( $_wp_additional_image_sizes[ $name ] ) ) {
662 return false;
663 }
664
665 return $_wp_additional_image_sizes[ $name ];
666 }
667
668 /**
669 * @see image_resize()
670 * @since 2.0
671 * @return string Image URL
672 */
673 public function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) {
674 $resized = false;
675 $editor = wp_get_image_editor( $file );
676
677 if ( is_wp_error( $editor ) )
678 return false;
679
680 $editor->set_quality( $jpeg_quality );
681
682 $resized = $editor->resize( $max_w, $max_h, $crop );
683 if ( is_wp_error( $resized ) )
684 return false;
685
686 $dest_file = $editor->generate_filename( $suffix, $dest_path );
687
688 $saved = $editor->save( $dest_file );
689
690 if ( is_wp_error( $saved ) )
691 return false;
692
693 $resized = $dest_file;
694
695 return $resized;
696 }
697
698 /**
699 * @since: 2.2.6
700 *
701 */
702 public function get_color_for_display( $color_hex ) {
703 if ( ! $color_hex ) {
704 return false;
705 }
706 $text_color = $this->get_text_color( $color_hex );
707 return "<div class='cpac-color'><span style='background-color:{$color_hex};color:{$text_color}'>{$color_hex}</span></div>";
708 }
709
710 /**
711 * Determines text color absed on bakground coloring.
712 *
713 * @since 1.0
714 */
715 public function get_text_color( $bg_color ) {
716
717 $rgb = $this->hex2rgb( $bg_color );
718
719 return $rgb && ( ( $rgb[0]*0.299 + $rgb[1]*0.587 + $rgb[2]*0.114 ) < 186 ) ? '#ffffff' : '#333333';
720 }
721
722 /**
723 * Convert hex to rgb
724 *
725 * @since 1.0
726 */
727 public function hex2rgb( $hex ) {
728 $hex = str_replace( "#", "", $hex );
729
730 if(strlen($hex) == 3) {
731 $r = hexdec(substr($hex,0,1).substr($hex,0,1));
732 $g = hexdec(substr($hex,1,1).substr($hex,1,1));
733 $b = hexdec(substr($hex,2,1).substr($hex,2,1));
734 } else {
735 $r = hexdec(substr($hex,0,2));
736 $g = hexdec(substr($hex,2,2));
737 $b = hexdec(substr($hex,4,2));
738 }
739 $rgb = array($r, $g, $b);
740
741 return $rgb;
742 }
743
744 /**
745 * Count the number of words in a string (multibyte-compatible)
746 *
747 * @since 2.3
748 *
749 * @param string $input Input string
750 * @return int Number of words
751 */
752 public function str_count_words( $input ) {
753
754 $patterns = array(
755 'strip' => '/<[a-zA-Z\/][^<>]*>/',
756 'clean' => '/[0-9.(),;:!?%#$¿\'"_+=\\/-]+/',
757 'w' => '/\S\s+/',
758 'c' => '/\S/'
759 );
760
761 $type = 'w';
762
763 $input = preg_replace( $patterns['strip'], ' ', $input );
764 $input = preg_replace( '/&nbsp;|&#160;/i', ' ', $input );
765 $input = preg_replace( $patterns['clean'], '', $input );
766
767 if ( ! strlen( preg_replace( '/\s/', '', $input ) ) ) {
768 return 0;
769 }
770
771 return preg_match_all( $patterns[ $type ], $input, $matches ) + 1;
772 }
773
774 /**
775 * @since 1.0
776 * @param mixed $meta Image files or Image ID's
777 * @param array $args
778 * @return array HTML img elements
779 */
780 public function get_thumbnails( $images, $args = array() ) {
781
782 if ( empty( $images ) || 'false' == $images ) {
783 return array();
784 }
785
786 // turn string to array
787 if ( is_string( $images ) || is_numeric( $images ) ) {
788 if ( strpos( $images, ',' ) !== false ) {
789 $images = array_filter( explode( ',', $this->strip_trim( str_replace( ' ', '', $images ) ) ) );
790 }
791 else {
792 $images = array( $images );
793 }
794 }
795
796 // Image size
797 $defaults = array(
798 'image_size' => 'cpac-custom',
799 'image_size_w' => 80,
800 'image_size_h' => 80,
801 );
802 $args = wp_parse_args( $args, $defaults );
803
804 extract( $args );
805
806 $thumbnails = array();
807 foreach( $images as $value ) {
808
809 if ( $this->is_image_url( $value ) ) {
810
811 // get dimensions from image_size
812 if ( $sizes = $this->get_image_size_by_name( $image_size ) ) {
813 $image_size_w = $sizes['width'];
814 $image_size_h = $sizes['height'];
815 }
816
817 $image_path = str_replace( WP_CONTENT_URL, WP_CONTENT_DIR, $value );
818
819 if ( is_file( $image_path ) ) {
820
821 // try to resize image
822 if ( $resized = $this->image_resize( $image_path, $image_size_w, $image_size_h, true ) ) {
823 $thumbnails[] = "<img src='" . str_replace( WP_CONTENT_DIR, WP_CONTENT_URL, $resized ) . "' alt='' width='{$image_size_w}' height='{$image_size_h}' />";
824 }
825
826 // return full image with maxed dimensions
827 else {
828 $thumbnails[] = "<img src='{$value}' alt='' style='max-width:{$image_size_w}px;max-height:{$image_size_h}px' />";
829 }
830 }
831 }
832
833 // Media Attachment
834 elseif ( is_numeric( $value ) && wp_get_attachment_url( $value ) ) {
835
836 $src = '';
837 $width = '';
838 $height = '';
839
840 if ( ! $image_size || 'cpac-custom' == $image_size ) {
841 $width = $image_size_w;
842 $height = $image_size_h;
843
844 // to make sure wp_get_attachment_image_src() get the image with matching dimensions.
845 $image_size = array( $width, $height );
846 }
847
848 // Is Image
849 if ( $attributes = wp_get_attachment_image_src( $value, $image_size ) ) {
850 $src = $attributes[0];
851 $width = $attributes[1];
852 $height = $attributes[2];
853
854 // image size by name
855 if ( $sizes = $this->get_image_size_by_name( $image_size ) ) {
856 $width = $sizes['width'];
857 $height = $sizes['height'];
858 }
859 }
860
861 // Is File, use icon
862 elseif ( $attributes = wp_get_attachment_image_src( $value, $image_size, true ) ) {
863 $src = $attributes[0];
864
865 if ( $sizes = $this->get_image_size_by_name( $image_size ) ) {
866 $width = $sizes['width'];
867 $height = $sizes['height'];
868 }
869 }
870
871 // maximum dimensions
872 $max = max( array( $width, $height ) );
873
874 $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>";
875 }
876 }
877
878 return $thumbnails;
879 }
880
881 /**
882 * Implode for multi dimensional array
883 *
884 * @since 1.0
885 * @param string $glue
886 * @param array $pieces
887 * @return string Imploded array
888 */
889 public function recursive_implode( $glue, $pieces ) {
890 foreach( $pieces as $r_pieces ) {
891 if ( is_array( $r_pieces ) ) {
892 $retVal[] = $this->recursive_implode( $glue, $r_pieces );
893 }
894 else {
895 $retVal[] = $r_pieces;
896 }
897 }
898 if ( isset($retVal) && is_array( $retVal ) ) {
899 return implode( $glue, $retVal );
900 }
901
902 return false;
903 }
904
905 /**
906 * Get timestamp
907 *
908 * @since 2.0
909 * @param string $date
910 * @return string Formatted date
911 */
912 public function get_timestamp( $date ) {
913
914 if ( empty( $date ) || in_array( $date, array( '0000-00-00 00:00:00', '0000-00-00', '00:00:00' ) ) ) {
915 return false;
916 }
917
918 // some plugins store dates in a jquery timestamp format, format is in ms since The Epoch.
919 // See http://api.jqueryui.com/datepicker/#utility-formatDate
920 // credits: nmarks
921 if ( is_numeric( $date ) ) {
922 $length = strlen( trim( $date ) );
923
924 // Dates before / around September 8th, 2001 are saved as 9 numbers * 1000 resulting in 12 numbers to store the time.
925 // Dates after September 8th are saved as 10 numbers * 1000, resulting in 13 numbers.
926 // For example the ACF Date and Time Picker uses this format.
927 // credits: Ben C
928 if ( 12 === $length || 13 === $length ) {
929 $date = round( $date / 1000 ); // remove the ms
930 }
931
932 // Date format: yyyymmdd ( often used by ACF ) must start with 19xx or 20xx and is 8 long
933 // @todo: in theory a numeric string of 8 can also be a unixtimestamp; no conversion would be needed
934 if ( 8 === $length && ( strpos( $date, '20' ) === 0 || strpos( $date, '19' ) === 0 ) ) {
935 $date = strtotime( $date );
936 }
937 }
938
939 // Parse with strtotime if it's not numeric
940 else {
941 $date = strtotime( $date );
942 }
943
944 return $date;
945 }
946
947 /**
948 * @since 1.3.1
949 * @param string $date
950 * @return string Formatted date
951 */
952 public function get_date( $date, $format = '' ) {
953
954 if ( ! $date = $this->get_timestamp( $date ) ) {
955 return false;
956 }
957 if ( ! $format ) {
958 $format = get_option( 'date_format' );
959 }
960
961 return date_i18n( $format, $date );
962 }
963
964 /**
965 * @since 1.3.1
966 * @param string $date
967 * @return string Formatted time
968 */
969 protected function get_time( $date, $format = '' ) {
970
971 if ( ! $date = $this->get_timestamp( $date ) ) {
972 return false;
973 }
974 if ( ! $format ) {
975 $format = get_option( 'time_format' );
976 }
977
978 return date_i18n( $format, $date );
979 }
980
981 /**
982 * Get display name.
983 *
984 * Can also be used by addons.
985 *
986 * @since 2.0
987 */
988 public function get_display_name( $user_id ) {
989
990 if ( ! $userdata = get_userdata( $user_id ) ) {
991 return false;
992 }
993
994 $name = '';
995
996 if ( ! empty( $this->options->display_author_as ) ) {
997
998 $display_as = $this->options->display_author_as;
999
1000 if ( 'first_last_name' == $display_as ) {
1001 $first = ! empty( $userdata->first_name ) ? $userdata->first_name : '';
1002 $last = ! empty( $userdata->last_name ) ? " {$userdata->last_name}" : '';
1003 $name = $first.$last;
1004 }
1005
1006 elseif ( ! empty( $userdata->{$display_as} ) ) {
1007 $name = $userdata->{$display_as};
1008 }
1009 }
1010
1011 // default to display_name
1012 if ( ! $name ) {
1013 $name = $userdata->display_name;
1014 }
1015
1016 return $name;
1017 }
1018
1019 /**
1020 * @since 2.0
1021 * @param string $field_key
1022 * @return string Attribute Name
1023 */
1024 public function label_view( $label, $description = '', $pointer = '' ) {
1025 ?>
1026 <td class="label">
1027 <label for="<?php $this->attr_id( $pointer ); ?>">
1028 <?php echo stripslashes( $label ); ?>
1029 <?php if( $description ) : ?><p class="description"><?php echo $description; ?></p><?php endif; ?>
1030 </label>
1031 </td>
1032 <?php
1033 }
1034
1035 /**
1036 * @since 2.0
1037 */
1038 public function display_field_date_format() {
1039
1040 $field_key = 'date_format';
1041 $label = __( 'Date Format', 'cpac' );
1042 $description = __( 'This will determine how the date will be displayed.', 'cpac' );
1043
1044 ?>
1045 <tr class="column_<?php echo $field_key; ?>">
1046 <?php $this->label_view( $label, $description, $field_key ); ?>
1047 <td class="input">
1048 <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"/>
1049 <p class="description">
1050 <?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' ); ?>
1051 <a target='_blank' href='http://codex.wordpress.org/Formatting_Date_and_Time'><?php _e( 'Documentation on date and time formatting.', 'cpac' ); ?></a>
1052 </p>
1053 </td>
1054 </tr>
1055
1056 <?php
1057 }
1058
1059 /**
1060 * @since 2.0
1061 */
1062 public function display_field_excerpt_length() {
1063
1064 $field_key = 'excerpt_length';
1065 $label = __( 'Excerpt length', 'cpac' );
1066 $description = __( 'Number of words', 'cpac' );
1067
1068 ?>
1069 <tr class="column_<?php echo $field_key; ?>">
1070 <?php $this->label_view( $label, $description, $field_key ); ?>
1071 <td class="input">
1072 <input type="text" name="<?php $this->attr_name( $field_key ); ?>" id="<?php $this->attr_id( $field_key ); ?>" value="<?php echo $this->options->excerpt_length; ?>"/>
1073 </td>
1074 </tr>
1075 <?php
1076 }
1077
1078 /**
1079 * @since 2.0
1080 */
1081 public function display_field_preview_size() {
1082
1083 $field_key = 'image_size';
1084 $label = __( 'Preview size', 'cpac' );
1085
1086 ?>
1087 <tr class="column_<?php echo $field_key; ?>">
1088
1089 <?php $this->label_view( $label, '', $field_key ); ?>
1090
1091 <td class="input">
1092 <?php foreach ( $sizes = $this->get_all_image_sizes() as $id => $image_label ) : ?>
1093 <label for="<?php $this->attr_id( $field_key ); ?>-<?php echo $id ?>" class="custom-size">
1094 <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 ); ?>>
1095 <?php echo $image_label; ?>
1096 </label>
1097 <?php endforeach; ?>
1098
1099 <div class="custom_image_size">
1100 <label for="<?php $this->attr_id( $field_key ); ?>-custom" class="custom-size image-size-custom" >
1101 <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' ); ?>
1102 </label>
1103 <label for="<?php $this->attr_id( $field_key ); ?>-w" class="custom-size-w<?php echo $this->options->image_size != 'cpac-custom' ? ' hidden' : ''; ?>">
1104 <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' ); ?>
1105 </label>
1106 <label for="<?php $this->attr_id( $field_key ); ?>-h" class="custom-size-h<?php echo $this->options->image_size != 'cpac-custom' ? ' hidden' : ''; ?>">
1107 <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' ); ?>
1108 </label>
1109 </div>
1110 </td>
1111 </tr>
1112 <?php
1113 }
1114
1115 /**
1116 * @since 2.1.1
1117 */
1118 public function display_field_before_after() {
1119 $this->display_field_text( 'before', __( "Before", 'cpac' ), __( 'This text will appear before the custom field value.', 'cpac' ) );
1120 $this->display_field_text( 'after', __( "After", 'cpac' ), __( 'This text will appear after the custom field value.', 'cpac' ) );
1121 }
1122
1123 /**
1124 * @since 2.3.2
1125 */
1126 public function display_field_user_format() {
1127
1128 $nametypes = array(
1129 'display_name' => __( 'Display Name', 'cpac' ),
1130 'first_name' => __( 'First Name', 'cpac' ),
1131 'last_name' => __( 'Last Name', 'cpac' ),
1132 'nickname' => __( 'Nickname', 'cpac' ),
1133 'user_login' => __( 'User Login', 'cpac' ),
1134 'user_email' => __( 'User Email', 'cpac' ),
1135 'ID' => __( 'User ID', 'cpac' ),
1136 'first_last_name' => __( 'First and Last Name', 'cpac' ),
1137 );
1138
1139 $this->display_field_select( 'display_author_as', __( 'Display format', 'cpac' ), $nametypes, __( 'This is the format of the author name.', 'cpac' ) );
1140 }
1141
1142 /**
1143 * @since 2.3.4
1144 * @param string $name Name of the column option
1145 * @return string $label Label
1146 * @return array $options Select options
1147 * @return strong $description (optional) Description below the label
1148 */
1149 public function display_field_select( $name, $label, $options = array(), $description = '' ) {
1150 $current = $this->get_option( $name );
1151 ?>
1152 <tr class="column-<?php echo $name; ?>">
1153 <?php $this->label_view( $label, $description, $name ); ?>
1154 <td class="input">
1155 <select name="<?php $this->attr_name( $name ); ?>" id="<?php $this->attr_id( $name ); ?>">
1156 <?php foreach ( $options as $key => $label ) : ?>
1157 <option value="<?php echo $key; ?>"<?php selected( $key, $current ); ?>><?php echo $label; ?></option>
1158 <?php endforeach; ?>
1159 </select>
1160 </td>
1161 </tr>
1162 <?php
1163 }
1164
1165 /**
1166 * @since 2.3.4
1167 * @param string $name Name of the column option
1168 * @return string $label Label
1169 * @return array $options Select options
1170 * @return strong $description (optional) Description below the label
1171 */
1172 public function display_field_text( $name, $label, $description = '' ) {
1173 ?>
1174 <tr class="column-<?php echo $name; ?>">
1175 <?php $this->label_view( $label, $description, $name ); ?>
1176 <td class="input">
1177 <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 ) ) ); ?>"/>
1178 </td>
1179 </tr>
1180 <?php
1181 }
1182
1183 /**
1184 * @since 2.0
1185 * @param array Column Objects
1186 * @return string HTML List
1187 */
1188 public function get_column_list( $columns = array(), $label = '' ) {
1189
1190 if ( empty( $columns ) ) {
1191 return false;
1192 }
1193
1194 $list = '';
1195
1196 // sort by alphabet
1197 $_columns = array();
1198
1199 foreach ( $columns as $column ) {
1200 if ( $column->properties->hidden ) {
1201 continue;
1202 }
1203
1204 $_columns[ $column->properties->type ] = ( 0 === strlen( strip_tags( $column->properties->label ) ) ) ? ucfirst( $column->properties->type ) : $column->properties->label;
1205 }
1206
1207 asort( $_columns );
1208
1209 $list = "<optgroup label='{$label}'>";
1210 foreach ( $_columns as $type => $label ) {
1211 $selected = selected( $this->properties->type, $type, false );
1212 $list .= "<option value='{$type}'{$selected}>{$label}</option>";
1213 }
1214 $list .= "</optgroup>";
1215
1216 return $list;
1217 }
1218
1219 /**
1220 * @since 2.0
1221 */
1222 public function display() {
1223
1224 $classes = implode( ' ', array_filter( array ( "cpac-box-{$this->properties->type}", $this->properties->classes ) ) );
1225
1226 // column list
1227 $column_list = '';
1228
1229 $groups = $this->storage_model->get_column_type_groups();
1230 foreach ( $groups as $group => $label ) {
1231 $column_list .= $this->get_column_list( $this->storage_model->column_types[ $group ], $label );
1232 }
1233
1234 // clone attribute
1235 $data_clone = $this->properties->is_cloneable ? " data-clone='{$this->properties->clone}'" : '';
1236
1237 ?>
1238 <div class="cpac-column <?php echo $classes; ?>" data-type="<?php echo $this->properties->type; ?>"<?php echo $data_clone; ?>>
1239 <input type="hidden" class="column-name" name="<?php echo $this->attr_name( 'column-name' ); ?>" value="<?php echo esc_attr( $this->properties->name ); ?>" />
1240 <input type="hidden" class="type" name="<?php echo $this->attr_name( 'type' ); ?>" value="<?php echo $this->properties->type; ?>" />
1241 <input type="hidden" class="clone" name="<?php echo $this->attr_name( 'clone' ); ?>" value="<?php echo $this->properties->clone; ?>" />
1242 <div class="column-meta">
1243 <table class="widefat">
1244 <tbody>
1245 <tr>
1246 <td class="column_sort"></td>
1247 <td class="column_label">
1248 <div class="inner">
1249 <div class="meta">
1250
1251 <span title="<?php echo esc_attr( __( 'width', 'cpac' ) ); ?>" class="width" data-indicator-id="">
1252 <?php echo ! empty( $this->options->width ) ? $this->options->width . $this->options->width_unit : ''; ?>
1253 </span>
1254
1255 <?php
1256 /**
1257 * Fires in the meta-element for column options, which is displayed right after the column label
1258 *
1259 * @since 2.0
1260 *
1261 * @param CPAC_Column $column_instance Column class instance
1262 */
1263 do_action( 'cac/column/settings_meta', $this );
1264
1265 /**
1266 * @deprecated 2.2 Use cac/column/settings_meta instead
1267 */
1268 do_action( 'cac/column/label', $this );
1269 ?>
1270
1271 </div>
1272 <a class="toggle" href="javascript:;"><?php echo stripslashes( $this->get_label() ); ?></a>
1273 <a class="edit-button" href="javascript:;"><?php _e( 'Edit', 'cpac' ); ?></a>
1274 <?php if ( $this->properties->is_cloneable ) : ?>
1275 <a class="clone-button" href="#"><?php _e( 'Clone', 'cpac' ); ?></a>
1276 <?php endif; ?>
1277 <a class="remove-button" href="javascript:;"><?php _e( 'Remove', 'cpac' ); ?></a>
1278 </div>
1279 </td>
1280 <td class="column_type">
1281 <div class="inner">
1282 <a href="#"><?php echo stripslashes( $this->properties->label ); ?></a>
1283 </div>
1284 </td>
1285 <td class="column_edit"></td>
1286 </tr>
1287 </tbody>
1288 </table>
1289 </div><!--.column-meta-->
1290
1291 <div class="column-form">
1292 <table class="widefat">
1293 <tbody>
1294 <tr class="column_type">
1295 <?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' ); ?>
1296 <td class="input">
1297 <select name="<?php $this->attr_name( 'type' ); ?>" id="<?php $this->attr_id( 'type' ); ?>">
1298 <?php echo $column_list; ?>
1299 </select>
1300 <div class="msg"></div>
1301 </td>
1302 </tr><!--.column_label-->
1303
1304 <tr class="column_label<?php echo $this->properties->hide_label ? ' hidden' : ''; ?>">
1305 <?php $this->label_view( __( 'Label', 'cpac' ), __( 'This is the name which will appear as the column header.', 'cpac' ), 'label' ); ?>
1306 <td class="input">
1307 <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 ); ?>" />
1308 </td>
1309 </tr><!--.column_label-->
1310
1311 <tr class="column_width">
1312 <?php $this->label_view( __( 'Width', 'cpac' ), '', 'width' ); ?>
1313 <td class="input">
1314 <div class="description" title="<?php _e( 'default', 'cpac' ); ?>">
1315 <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; ?>" />
1316 <span class="unit"><?php echo $this->options->width_unit; ?></span>
1317 </div>
1318 <div class="width-slider"></div>
1319
1320 <div class="unit-select">
1321 <label for="<?php $this->attr_id( 'width_unit_px' ); ?>">
1322 <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' ); ?>/>
1323 px
1324 </label>
1325 <label for="<?php $this->attr_id( 'width_unit_perc' ); ?>">
1326 <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, '%' ); ?>/>
1327 %
1328 </label>
1329 </div>
1330
1331 </td>
1332 </tr><!--.column_width-->
1333
1334 <?php
1335 /**
1336 * Fires directly before the custom options for a column are displayed in the column form
1337 *
1338 * @since 2.0
1339 * @param CPAC_Column $column_instance Column class instance
1340 */
1341 do_action( 'cac/column/settings_before', $this );
1342 ?>
1343
1344 <?php
1345 /**
1346 * Load specific column settings.
1347 *
1348 */
1349 $this->display_settings();
1350
1351 ?>
1352
1353 <?php
1354 /**
1355 * Fires directly after the custom options for a column are displayed in the column form
1356 *
1357 * @since 2.0
1358 * @param CPAC_Column $column_instance Column class instance
1359 */
1360 do_action( 'cac/column/settings_after', $this );
1361 ?>
1362
1363 <tr class="column_action">
1364 <td colspan="2">
1365 <p>
1366 <?php if ( $this->properties->is_cloneable ) : ?>
1367 <a class="clone-button" href="#"><?php _e( 'Clone', 'cpac' ); ?></a>
1368 <?php endif; ?>
1369 <a href="javascript:;" class="remove-button"><?php _e( 'Remove' );?></a>
1370 </p>
1371 </td>
1372 </tr>
1373
1374 </tbody>
1375 </table>
1376 </div>
1377 </div>
1378 <?php
1379 }
1380 }