Code

< 40 %
40-60 %
> 60 %
1
<?php
2
/**
3
 * Plugin Name: Dynamic Featured Image
4
 * Plugin URI: http://wordpress.org/plugins/dynamic-featured-image/
5
 * Description: Dynamically adds multiple featured image or post thumbnail functionality to your posts, pages and custom post types.
6
 * Version: 3.7.0
7
 * Author: Ankit Pokhrel
8
 * Author URI: https://ankitpokhrel.com
9
 * License: GPL2 or later
10
 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 * Text Domain: dynamic-featured-image
12
 * Domain Path: /languages
13
 * GitHub Plugin URI: https://github.com/ankitpokhrel/Dynamic-Featured-Image
14
 *
15
 * @package dynamic-featured-image
16
 *
17
 * Copyright (C) 2013-2019 Ankit Pokhrel <[email protected], https://ankitpokhrel.com>
18
 *
19
 * This program is free software; you can redistribute it and/or modify
20
 * it under the terms of the GNU General Public License as published by
21
 * the Free Software Foundation; either version 3 of the License, or
22
 * (at your option) any later version.
23
 *
24
 * This program is distributed in the hope that it will be useful,
25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
 * GNU General Public License for more details.
28
 *
29
 * You should have received a copy of the GNU General Public License
30
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
31
 */
32
33
// Avoid direct calls to this file.
34
if ( ! defined( 'ABSPATH' ) ) {
35
    header( 'Status: 403 Forbidden' );
36
    header( 'HTTP/1.1 403 Forbidden' );
37
    exit();
38
}
39
40
/**
41
 * Dynamic Featured Image plugin main class.
42
 *
43
 * @author Ankit Pokhrel <[email protected]>
44
 * @version 3.7.0
45
 */
46
class Dynamic_Featured_Image {
47
    /**
48
     * Current version of the plugin.
49
     *
50
     * @since 3.0.0
51
     */
52
    const VERSION = '3.7.0';
53
54
    /**
55
     * Text domain.
56
     *
57
     * @since 3.6.0
58
     */
59
    const TEXT_DOMAIN = 'dynamic-featured-image';
60
61
    /**
62
     * Documentation Link.
63
     *
64
     * @since 3.6.0
65
     */
66
    const WIKI_LINK = 'https://github.com/ankitpokhrel/Dynamic-Featured-Image/wiki/';
67
68
    /**
69
     * Image upload directory.
70
     *
71
     * @var $upload_dir string
72
     */
73
    private $upload_dir;
74
75
    /**
76
     * Image upload URL.
77
     *
78
     * @var $upload_url string
79
     */
80
    private $upload_url;
81
82
    /**
83
     * Database object.
84
     *
85
     * @var $db wpdb
86
     */
87
    private $db;
88
89
    /**
90
     * Title for dfi metabox.
91
     *
92
     * @var $metabox_title string
93
     */
94
    protected $metabox_title;
95
96
    /**
97
     * Users post type filter for dfi metabox.
98
     *
99
     * @var $user_filter array
100
     */
101
    protected $user_filter;
102
103
    /**
104
     * Constructor. Hooks all interactions to initialize the class.
105
     *
106
     * @since 1.0.0
107
     * @access public
108
     * @global object $wpdb
109
     *
110
     * @see     add_action()
111
     */
112 1
    public function __construct() {
113
        // plugin update warning.
114 1
        add_action( 'in_plugin_update_message-' . plugin_basename( __FILE__ ), array( $this, 'update_notice' ) );
115
116 1
        add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
117 1
        add_action( 'add_meta_boxes', array( $this, 'initialize_featured_box' ) );
118 1
        add_action( 'save_post', array( $this, 'save_meta' ) );
119 1
        add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );
120
121
        // handle ajax request.
122 1
        add_action( 'wp_ajax_dfiMetaBox_callback', array( $this, 'ajax_callback' ) );
123
124
        // media uploader custom fields.
125 1
        add_filter( 'attachment_fields_to_edit', array( $this, 'media_attachment_custom_fields' ), 10, 2 );
126 1
        add_filter( 'attachment_fields_to_save', array( $this, 'media_attachment_custom_fields_save' ), 10, 2 );
127
128
        // plugin sponsors.
129 1
        new PluginSponsor();
130
131
        // get the site protocol.
132 1
        $protocol = $this->get_protocol();
133
134 1
        $this->upload_dir = wp_upload_dir();
135 1
        $this->upload_url = preg_replace( '#^https?://#', '', $this->upload_dir['baseurl'] );
136
137
        // add protocol to the upload url.
138 1
        $this->upload_url = $protocol . $this->upload_url;
139
140
        // post type filter added by user.
141 1
        $this->user_filter = array();
142
143 1
        global $wpdb;
144 1
        $this->db = $wpdb;
145 1
    }
146
147
    /**
148
     * Return site protocol.
149
     *
150
     * @since 3.5.1
151
     * @access public
152
     *
153
     * @return string
154
     */
155
    private function get_protocol() {
156
        return is_ssl() ? 'https://' : 'http://';
157
    }
158
159
    /**
160
     * Add required admin scripts.
161
     *
162
     * @since 1.0.0
163
     * @access public
164
     *
165
     * @see  wp_enqueue_style()
166
     * @see  wp_register_script()
167
     * @see  wp_enqueue_script()
168
     *
169
     * @return void
170
     */
171 1
    public function enqueue_admin_scripts() {
172
        // enqueue styles.
173 1
        wp_enqueue_style( 'style-dfi', plugins_url( '/css/style-dfi.css', __FILE__ ), array(), self::VERSION );
174
175
        // register script.
176 1
        wp_register_script( 'scripts-dfi', plugins_url( '/js/script-dfi.js', __FILE__ ), array( 'jquery' ), self::VERSION );
177
178
        // localize the script with required data.
179 1
        wp_localize_script(
180 1
            'scripts-dfi',
181 1
            'DFI_SPECIFIC',
182
            array(
183 1
                'upload_url'               => $this->upload_url,
184 1
                'metabox_title'            => __( $this->metabox_title, self::TEXT_DOMAIN ),
185 1
                'mediaSelector_title'      => __( 'Dynamic Featured Image - Media Selector', self::TEXT_DOMAIN ),
186 1
                'mediaSelector_buttonText' => __( 'Set Featured Image', self::TEXT_DOMAIN ),
187 1
                'ajax_nonce'               => wp_create_nonce( plugin_basename( __FILE__ ) ),
188
            )
189 1
        );
190
191
        // enqueue scripts.
192 1
        wp_enqueue_script( 'scripts-dfi' );
193 1
    }
194
195
    /**
196
     * Add featured meta boxes dynamically.
197
     *
198
     * @since 1.0.0
199
     * @access public
200
     * @global object $post
201
     *
202
     * @see  get_post_meta()
203
     * @see  get_post_types()
204
     * @see  add_meta_box()
205
     * @see  add_filter()
206
     *
207
     * @return void
208
     */
209
    public function initialize_featured_box() {
210
        global $post;
211
212
        // make metabox title dynamic.
213
        $this->metabox_title = apply_filters( 'dfi_set_metabox_title', __( 'Featured Image', self::TEXT_DOMAIN ) );
214
215
        $featured_data  = get_post_meta( $post->ID, 'dfiFeatured', true );
216
        $total_featured = is_array( $featured_data ) ? count( $featured_data ) : 0;
217
218
        $default_filter    = array( 'attachment', 'revision', 'nav_menu_item' );
219
        $this->user_filter = apply_filters( 'dfi_post_type_user_filter', $this->user_filter );
220
221
        $post_types = array_diff( get_post_types(), array_merge( $default_filter, $this->user_filter ) );
222
        $post_types = apply_filters( 'dfi_post_types', $post_types );
223
224
        if ( ! empty( $featured_data ) && $total_featured >= 1 ) {
225
            $i = 2;
226
            foreach ( $featured_data as $featured ) {
227
                $this->dfi_add_meta_box( $post_types, $featured, $i++ );
228
            }
229
        } else {
230
            $this->dfi_add_meta_box( $post_types );
231
        }
232
    }
233
234
    /**
235
     * Translates more than one digit number digit by digit.
236
     *
237
     * @param  int $number Integer to be translated.
238
     *
239
     * @return string Translated number
240
     */
241 3
    protected function get_number_translation( $number ) {
242 3
        if ( $number <= 9 ) {
243 2
            return __( $number, self::TEXT_DOMAIN );
244
        } else {
245 1
            $pieces = str_split( $number, 1 );
246 1
            $buffer = '';
247 1
            foreach ( $pieces as $piece ) {
248 1
                $buffer .= __( $piece, self::TEXT_DOMAIN );
249 1
            }
250
251 1
            return $buffer;
252
        }
253
    }
254
255
    /**
256
     * Adds meta boxes.
257
     *
258
     * @param  array  $post_types Post types to show featured image box.
259
     * @param  object $featured Callback arguments.
260
     * @param  int    $i Index of the featured image.
261
     *
262
     * @return void
263
     */
264
    private function dfi_add_meta_box( $post_types, $featured = null, $i = null ) {
265
        if ( ! is_null( $i ) ) {
266
            foreach ( $post_types as $type ) {
267
                add_meta_box(
268
                    'dfiFeaturedMetaBox-' . $i,
269
                    __( $this->metabox_title, self::TEXT_DOMAIN ) . ' ' . $this->get_number_translation( $i ),
270
                    array( $this, 'featured_meta_box' ),
271
                    $type,
272
                    apply_filters( 'dfi_metabox_context', 'side' ),
273
                    apply_filters( 'dfi_metabox_priority', 'low' ),
274
                    array( $featured, $i + 1 )
275
                );
276
277
                add_filter( "postbox_classes_{$type}_dfiFeaturedMetaBox-" . $i, array( $this, 'add_metabox_classes' ) );
278
            }
279
        } else {
280
            foreach ( $post_types as $type ) {
281
                add_meta_box(
282
                    'dfiFeaturedMetaBox',
283
                    __( $this->metabox_title, self::TEXT_DOMAIN ) . ' ' . __( 2, self::TEXT_DOMAIN ),
284
                    array( $this, 'featured_meta_box' ),
285
                    $type,
286
                    apply_filters( 'dfi_metabox_context', 'side' ),
287
                    apply_filters( 'dfi_metabox_priority', 'low' ),
288
                    array( null, null )
289
                );
290
291
                add_filter( "postbox_classes_{$type}_dfiFeaturedMetaBox", array( $this, 'add_metabox_classes' ) );
292
            }
293
        }
294
    }
295
296
    /**
297
     * Separate thumb and full image url from given URL string.
298
     *
299
     * @since  3.3.1
300
     *
301
     * @param  string $url_string Url string.
302
     * @param  string $state Thumb or full.
303
     *
304
     * @return string|null
305
     */
306 3
    private function separate( $url_string, $state = 'thumb' ) {
307 3
        $image_piece = explode( ',', $url_string );
308
309 3
        if ( 'thumb' === $state ) {
310 2
            return isset( $image_piece[0] ) ? $image_piece[0] : null;
311
        }
312
313 3
        return isset( $image_piece[1] ) ? $image_piece[1] : null;
314
    }
315
316
    /**
317
     * Create a nonce field.
318
     *
319
     * @since  3.5.0
320
     *
321
     * @see  wp_nonce_field()
322
     * @see  plugin_basename()
323
     *
324
     * @codeCoverageIgnore
325
     *
326
     * @param  string $key Nonce key.
327
     *
328
     * @return string
329
     */
330
    protected function nonce_field( $key ) {
331
        return wp_nonce_field( plugin_basename( __FILE__ ), $key, true, false );
332
    }
333
334
    /**
335
     * Featured meta box as seen in the admin.
336
     *
337
     * @since 1.0.0
338
     * @access public
339
     *
340
     * @param  object $post Global post object.
341
     * @param  array  $featured Array containing featured image count.
342
     *
343
     * @throws Exception Medium size image not found.
344
     * @return void
345
     */
346 3
    public function featured_meta_box( $post, $featured ) {
347 3
        $featured_img         = $featured['args'][0];
348 3
        $featured_id          = is_null( $featured['args'][1] ) ? 2 : --$featured['args'][1];
349 3
        $featured_img_full    = $featured_img;
350 3
        $featured_img_trimmed = $featured_img;
351
352 3
        if ( ! is_null( $featured_img ) ) {
353 3
            $featured_img_trimmed = $this->separate( $featured_img );
354 3
            $featured_img_full    = $this->separate( $featured_img, 'full' );
355 3
        }
356
357 3
        $thumbnail     = null;
358 3
        $attachment_id = null;
359 3 View Code Duplication
        if ( ! empty( $featured_img_full ) ) {
360 1
            $attachment_id = $this->get_image_id( $this->upload_url . $featured_img_full );
361
362 1
            $thumbnail = $this->get_image_thumb_by_attachment_id( $attachment_id, 'medium' );
363
364 1
            if ( empty( $thumbnail ) ) {
365
                // since medium sized thumbnail image is missing,
366
                // let's set full image url as thumbnail.
367
                $thumbnail = $featured_img_full;
368
            }
369 1
        }
370
371
        // Add a nonce field.
372 3
        echo $this->nonce_field( 'dfi_fimageplug-' . $featured_id ); // WPCS: XSS ok.
373 3
        echo $this->get_featured_box( $featured_img_trimmed, $featured_img, $featured_id, $thumbnail, $post->ID, $attachment_id ); // WPCS: XSS ok.
374 3
    }
375
376
    /**
377
     * Returns featured box html content.
378
     *
379
     * @since  3.1.0
380
     * @access private
381
     *
382
     * @param string $featured_img_trimmed Medium sized image.
383
     * @param string $featured_img         Full sized image.
384
     * @param string $featured_id          Featured id number for translation.
385
     * @param string $thumbnail            Thumb sized image.
386
     * @param int    $post_id              Post id.
387
     * @param int    $attachment_id        Attachment id.
388
     *
389
     * @return string Html content
390
     */
391 3
    private function get_featured_box( $featured_img_trimmed, $featured_img, $featured_id, $thumbnail, $post_id, $attachment_id ) {
392 3
        $has_featured_image = ! empty( $featured_img_trimmed ) ? ' hasFeaturedImage' : '';
393 3
        $thumbnail          = ! is_null( $thumbnail ) ? $thumbnail : '';
394 3
        $dfi_empty          = is_null( $featured_img_trimmed ) ? 'dfiImgEmpty' : '';
395
396 3
        return "<a href='javascript:void(0)' class='dfiFeaturedImage{$has_featured_image}' title='" . __( 'Set Featured Image', self::TEXT_DOMAIN ) . "' data-post-id='" . $post_id . "' data-attachment-id='" . $attachment_id . "'><span class='dashicons dashicons-camera'></span></a><br/>
397 3
            <img src='" . $thumbnail . "' class='dfiImg {$dfi_empty}'/>
398
            <div class='dfiLinks'>
399 3
                <a href='javascript:void(0)' data-id='{$featured_id}' data-id-local='" . $this->get_number_translation( $featured_id + 1 ) . "' class='dfiAddNew dashicons dashicons-plus' title='" . __( 'Add New', self::TEXT_DOMAIN ) . "'></a>
400 3
                <a href='javascript:void(0)' class='dfiRemove dashicons dashicons-minus' title='" . __( 'Remove', self::TEXT_DOMAIN ) . "'></a>
401
            </div>
402
            <div class='dfiClearFloat'></div>
403 3
            <input type='hidden' name='dfiFeatured[]' value='{$featured_img}'  class='dfiImageHolder' />";
404
    }
405
406
    /**
407
     * Load new featured meta box via ajax.
408
     *
409
     * @since 1.0.0
410
     * @access public
411
     *
412
     * @return void
413
     */
414 2
    public function ajax_callback() {
415 2
        check_ajax_referer( plugin_basename( __FILE__ ), 'security' );
416
417 1
        $featured_id = isset( $_POST['id'] ) ? intval( wp_unslash( $_POST['id'] ) ) : null;
418
419 1
        if ( ! is_numeric( $featured_id ) ) {
420
            return;
421
        }
422
423
        // @codingStandardsIgnoreStart
424 1
        echo $this->nonce_field( 'dfi_fimageplug-' . $featured_id );
425
        ?>
426
        <a href="javascript:void(0)" class="dfiFeaturedImage"
427
           title="<?php echo __( 'Set Featured Image', self::TEXT_DOMAIN ) ?>"><span
428
                    class="dashicons dashicons-camera"></span></a><br/>
429
        <img src="" class="dfiImg dfiImgEmpty"/>
430
        <div class="dfiLinks">
431
            <a href="javascript:void(0)" data-id="<?php echo $featured_id ?>"
432
               data-id-local="<?php echo $this->get_number_translation( $featured_id + 1 ) ?>"
433
               class="dfiAddNew dashicons dashicons-plus" title="<?php echo __( 'Add New', self::TEXT_DOMAIN ) ?>"></a>
434
            <a href="javascript:void(0)" class="dfiRemove dashicons dashicons-minus"
435
               title="<?php echo __( 'Remove', self::TEXT_DOMAIN ) ?>"></a>
436
        </div>
437
        <div class="dfiClearFloat"></div>
438
        <input type="hidden" name="dfiFeatured[]" value="" class="dfiImageHolder"/>
439
        <?php
440
        // @codingStandardsIgnoreEnd
441 1
        wp_die( '' );
442
    }
443
444
    /**
445
     * Add custom class 'featured-meta-box' to meta box.
446
     *
447
     * @since 1.0.0
448
     * @access public
449
     *
450
     * @see  add_metabox_classes
451
     *
452
     * @param array $classes Classes to add in the meta box.
453
     *
454
     * @return array
455
     */
456 1
    public function add_metabox_classes( $classes ) {
457 1
        array_push( $classes, 'featured-meta-box' );
458
459 1
        return $classes;
460
    }
461
462
    /**
463
     * Add custom fields in media uploader.
464
     *
465
     * @since  3.4.0
466
     *
467
     * @param array $form_fields Fields to include in media attachment form.
468
     * @param array $post Post data.
469
     *
470
     * @return array
471
     */
472 1
    public function media_attachment_custom_fields( $form_fields, $post ) {
473 1
        $form_fields['dfi-link-to-image'] = array(
474 1
            'label' => __( 'Link to Image', self::TEXT_DOMAIN ),
475 1
            'input' => 'text',
476 1
            'value' => get_post_meta( $post->ID, '_dfi_link_to_image', true ),
477
        );
478
479 1
        return $form_fields;
480
    }
481
482
    /**
483
     * Save values of media uploader custom fields.
484
     *
485
     * @since 3.4.0
486
     *
487
     * @param array $post Post data for database.
488
     * @param array $attachment Attachment fields from $_POST form.
489
     *
490
     * @return array
491
     */
492 1
    public function media_attachment_custom_fields_save( $post, $attachment ) {
493 1
        if ( isset( $attachment['dfi-link-to-image'] ) ) {
494 1
            update_post_meta( $post['ID'], '_dfi_link_to_image', $attachment['dfi-link-to-image'] );
495 1
        }
496
497 1
        return $post;
498
    }
499
500
    /**
501
     * Update featured images in the database.
502
     *
503
     * @since 1.0.0
504
     * @access public
505
     *
506
     * @see  plugin_basename()
507
     * @see  update_post_meta()
508
     * @see  current_user_can()
509
     *
510
     * @param  int $post_id Current post id.
511
     *
512
     * @return bool|null
513
     */
514 2
    public function save_meta( $post_id ) {
515
        // Check auto save.
516 2
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
517 1
            return false;
518
        }
519
520 2
        if ( ! $this->verify_nonces() ) {
521 2
            return false;
522
        }
523
524
        // Check permission before saving data.
525 1
        if ( current_user_can( 'edit_posts', $post_id ) && isset( $_POST['dfiFeatured'] ) ) { // WPCS: CSRF ok.
526 1
            $featured_images = is_array( $_POST['dfiFeatured'] ) ? $_POST['dfiFeatured'] : array(); // WPCS: sanitization ok, CSRF ok.
527
528 1
            update_post_meta( $post_id, 'dfiFeatured', $this->sanitize_array( $featured_images ) );
529 1
        }
530 1
    }
531
532
    /**
533
     * Sanitize array.
534
     *
535
     * @since 3.6.0
536
     * @access protected
537
     *
538
     * @param array $input_array Input array.
539
     *
540
     * @return array
541
     */
542 1
    protected function sanitize_array( $input_array ) {
543 1
        $sanitized = array();
544
545 1
        foreach ( $input_array as $value ) {
546 1
            $sanitized[] = sanitize_text_field( wp_unslash( $value ) );
547 1
        }
548
549 1
        return $sanitized;
550
    }
551
552
    /**
553
     * Verify metabox nonces.
554
     *
555
     * @access protected
556
     * @see  wp_verify_nonce()
557
     *
558
     * @return bool
559
     */
560
    protected function verify_nonces() {
561
        $keys = preg_grep( '/dfi_fimageplug-\d+$/', array_keys( $_POST ) ); // WPCS: CSRF ok.
562
563
        if ( empty( $keys ) ) {
564
            return false;
565
        }
566
567
        foreach ( $keys as $key ) {
568
            // Verify nonce.
569
            if ( ! isset( $_POST[ $key ] ) ||
570
                 ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST[ $key ] ) ), plugin_basename( __FILE__ ) )
571
            ) {
572
                return false;
573
            }
574
        }
575
576
        return true;
577
    }
578
579
    /**
580
     * Add update notice. Displayed in plugin update page.
581
     *
582
     * @since 2.0.0
583
     * @access public
584
     *
585
     * @return void
586
     */
587 1
    public function update_notice() {
588 1
        $info = __( 'ATTENTION! Please read the <a href="' . self::WIKI_LINK . '" target="_blank">DOCUMENTATION</a> properly before update.',
589 1
        self::TEXT_DOMAIN );
590
591 1
        echo '<span style="color: red; padding: 7px 0; display: block">' . strip_tags( $info, '<a><b><i><span>' ) . '</span>'; // WPCS: XSS ok.
592 1
    }
593
594
    /**
595
     * Execute query.
596
     *
597
     * @param string $query Query to execute.
598
     *
599
     * @return null|string
600
     */
601 6
    private function execute_query( $query ) {
602 6
        return $this->db->get_var( $query );
603
    }
604
605
    /**
606
     * Get attachment id of the image by image url.
607
     *
608
     * @since 3.1.7
609
     * @access protected
610
     * @global object $wpdb
611
     *
612
     * @param  string $image_url URL of an image.
613
     *
614
     * @return string
615
     */
616 1
    protected function get_attachment_id( $image_url ) {
617 1
        return $this->execute_query( $this->db->prepare( 'SELECT ID FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
618
    }
619
620
    /**
621
     * Get image url of the image by attachment id.
622
     *
623
     * @since 2.0.0
624
     * @access public
625
     *
626
     * @see  wp_get_attachment_image_src()
627
     *
628
     * @param  int    $attachment_id attachment id of an image.
629
     * @param  string $size size of the image to fetch (thumbnail, medium, full).
630
     *
631
     * @return string
632
     */
633 1
    public function get_image_url( $attachment_id, $size = 'full' ) {
634 1
        $image_thumb = wp_get_attachment_image_src( $attachment_id, $size );
635
636 1
        return empty( $image_thumb ) ? null : $image_thumb[0];
637
    }
638
639
    /**
640
     * Get image thumbnail url of specific size by attachment id.
641
     *
642
     * @since 3.7.0
643
     * @access public
644
     *
645
     * @see wp_get_attachment_image_src()
646
     *
647
     * @param int $attachment_id attachment id of an image.
648
     * @param string $size size of the image to fetch (thumbnail, medium, full).
649
     *
650
     * @return string|null
651
     */
652 1
    public function get_image_thumb_by_attachment_id( $attachment_id, $size = 'thumbnail' ) {
653 1
        if ( empty( $attachment_id ) ) {
654
            return null;
655
        }
656
657 1
        $image_thumb = wp_get_attachment_image_src( $attachment_id, $size );
658
659 1
        return empty( $image_thumb ) ? null : $image_thumb[0];
660
    }
661
662
    /**
663
     * Get image thumbnail url of specific size by image url.
664
     *
665
     * @since 2.0.0
666
     * @access public
667
     *
668
     * @see  get_image_id()
669
     * @see  wp_get_attachment_image_src()
670
     *
671
     * @param  string $image_url url of an image.
672
     * @param  string $size size of the image to fetch (thumbnail, medium, full).
673
     *
674
     * @return string
675
     */
676 1
    public function get_image_thumb( $image_url, $size = 'thumbnail' ) {
677 1
        $attachment_id = $this->get_image_id( $image_url );
678 1
        $image_thumb   = wp_get_attachment_image_src( $attachment_id, $size );
679
680 1
        return empty( $image_thumb ) ? null : $image_thumb[0];
681
    }
682
683
    /**
684
     * Gets attachment id from given image url.
685
     *
686
     * @param  string $image_url url of an image.
687
     *
688
     * @since  2.0.0
689
     * @access public
690
     *
691
     * @return int|null attachment id of an image
692
     */
693 5
    public function get_image_id( $image_url ) {
694 5
        $attachment_id = $this->get_attachment_id( $image_url );
695
696 5
        if ( is_null( $attachment_id ) ) {
697
            /*
698
             * Check if the image is an edited image.
699
             * and try to get the attachment id.
700
             */
701
702 4
            global $wp_version;
703
704 4
            if ( intval( $wp_version ) >= 4 ) {
705 4
                return attachment_url_to_postid( $image_url );
706
            }
707
708
            // Fallback.
709
            $image_url = str_replace( $this->upload_url . '/', '', $image_url );
710
711
            $row = $this->execute_query( $this->db->prepare( 'SELECT post_id FROM ' . $this->db->postmeta . ' WHERE meta_key = %s AND meta_value = %s', '_wp_attached_file', $image_url ) );
712
            if ( ! is_null( $row ) ) {
713
                $attachment_id = $row;
714
            }
715
        }
716
717 4
        return $attachment_id;
718
    }
719
720
    /**
721
     * Get image title.
722
     *
723
     * @since 2.0.0
724
     * @access public
725
     *
726
     * @param string $image_url URL of an image.
727
     *
728
     * @return string
729
     */
730 1
    public function get_image_title( $image_url ) {
731 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_title FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
732
    }
733
734
    /**
735
     * Get image title by id.
736
     *
737
     * @since 2.0.0
738
     * @access public
739
     *
740
     * @param  int $attachment_id Attachment id of an image.
741
     *
742
     * @return string
743
     */
744 1
    public function get_image_title_by_id( $attachment_id ) {
745 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_title FROM ' . $this->db->posts . ' WHERE ID = %d', $attachment_id ) );
746
    }
747
748
    /**
749
     * Get image caption.
750
     *
751
     * @since 2.0.0
752
     * @access public
753
     *
754
     * @param  string $image_url URL of an image.
755
     *
756
     * @return string
757
     */
758 1
    public function get_image_caption( $image_url ) {
759 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_excerpt FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
760
    }
761
762
    /**
763
     * Get image caption by id.
764
     *
765
     * @since 2.0.0
766
     * @access public
767
     *
768
     * @param  int $attachment_id Attachment id of an image.
769
     *
770
     * @return string
771
     */
772 1
    public function get_image_caption_by_id( $attachment_id ) {
773 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_excerpt FROM ' . $this->db->posts . ' WHERE ID = %d', $attachment_id ) );
774
    }
775
776
    /**
777
     * Get image alternate text.
778
     *
779
     * @since 2.0.0
780
     * @access public
781
     *
782
     * @see  get_post_meta()
783
     *
784
     * @param  string $image_url URL of an image.
785
     *
786
     * @return string
787
     */
788 1
    public function get_image_alt( $image_url ) {
789 1
        $attachment = $this->db->get_col( $this->db->prepare( 'SELECT ID FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
790
791 1
        $alt = null;
792 1
        if ( ! empty( $attachment ) ) {
793 1
            $alt = get_post_meta( $attachment[0], '_wp_attachment_image_alt' );
794 1
        }
795
796 1
        return ( is_null( $alt ) || empty( $alt ) ) ? null : $alt[0];
797
    }
798
799
    /**
800
     * Get image alternate text by attachment id.
801
     *
802
     * @since 2.0.0
803
     * @access public
804
     *
805
     * @see  get_post_meta()
806
     *
807
     * @param  int $attachment_id Attachment id of an image.
808
     *
809
     * @return string
810
     */
811 1
    public function get_image_alt_by_id( $attachment_id ) {
812 1
        $alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt' );
813
814 1
        return empty( $alt ) ? null : $alt[0];
815
    }
816
817
    /**
818
     * Get image description.
819
     *
820
     * @since 3.0.0
821
     * @access public
822
     *
823
     * @param  string $image_url URL of an image.
824
     *
825
     * @return string
826
     */
827 1
    public function get_image_description( $image_url ) {
828 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_content FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
829
    }
830
831
    /**
832
     * Get image description by id.
833
     *
834
     * @since 3.0.0
835
     * @access public
836
     *
837
     * @param  int $attachment_id attachment id of an image.
838
     *
839
     * @return string
840
     */
841 1
    public function get_image_description_by_id( $attachment_id ) {
842 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_content FROM ' . $this->db->posts . ' WHERE ID = %d', $attachment_id ) );
843
    }
844
845
    /**
846
     * Get link to image.
847
     *
848
     * @since 3.4.0
849
     * @access public
850
     *
851
     * @param  int $attachment_id Attachment id of an image.
852
     *
853
     * @return string|null
854
     */
855 1
    public function get_link_to_image( $attachment_id ) {
856 1
        return get_post_meta( $attachment_id, '_dfi_link_to_image', true );
857
    }
858
859
    /**
860
     * Get all attachment ids of the post.
861
     *
862
     * @since 2.0.0
863
     * @access public
864
     *
865
     * @see  get_post_meta()
866
     *
867
     * @param  int $post_id id of the current post.
868
     *
869
     * @return array
870
     */
871 2
    public function get_post_attachment_ids( $post_id ) {
872 2
        $dfi_images = get_post_meta( $post_id, 'dfiFeatured', true );
873 2
        $ret_val    = array();
874
875 2 View Code Duplication
        if ( ! empty( $dfi_images ) && is_array( $dfi_images ) ) {
876 2
            foreach ( $dfi_images as $dfi_image ) {
877 2
                $dfi_image_full = $this->separate( $dfi_image, 'full' );
878 2
                $ret_val[]      = (int) $this->get_image_id( $this->upload_url . $dfi_image_full );
879 2
            }
880 2
        }
881
882 2
        return $ret_val;
883
    }
884
885
    /**
886
     * Get real post id.
887
     *
888
     * @since 3.6.0
889
     * @access protected
890
     *
891
     * @param int|null $post_id Post id.
892
     *
893
     * @return int|null
894
     */
895 6
    protected function get_real_post_id( $post_id = null ) {
896 6
        if ( ! is_null( $post_id ) && is_numeric( $post_id ) ) {
897 5
            return $post_id;
898
        }
899
900 3
        global $post;
901
902 3
        return $post->ID;
903
    }
904
905
    /**
906
     * Fetches featured image data of nth position.
907
     *
908
     * @since  3.0.0
909
     * @access  public
910
     *
911
     * @see  get_featured_images()
912
     *
913
     * @param  int $position Position of the featured image.
914
     * @param  int $post_id Current post id.
915
     *
916
     * @return array if found, null otherwise.
917
     */
918 2
    public function get_nth_featured_image( $position, $post_id = null ) {
919 2
        $post_id = $this->get_real_post_id( ( $post_id ) );
920
921 2
        $featured_images = $this->get_featured_images( $post_id );
922
923 2
        return isset( $featured_images[ $position - 2 ] ) ? $featured_images[ $position - 2 ] : null;
924
    }
925
926
    /**
927
     * Check if the image is attached with the particular post.
928
     *
929
     * @since 2.0.0
930
     * @access public
931
     *
932
     * @see  get_post_attachment_ids()
933
     *
934
     * @param  int $attachment_id Attachment id of an image.
935
     * @param  int $post_id Current post id.
936
     *
937
     * @return bool
938
     */
939 1
    public function is_attached( $attachment_id, $post_id ) {
940 1
        if ( empty( $attachment_id ) ) {
941 1
            return false;
942
        }
943
944 1
        $attachment_ids = $this->get_post_attachment_ids( $post_id );
945
946 1
        return in_array( $attachment_id, $attachment_ids, true ) ? true : false;
947
    }
948
949
    /**
950
     * Retrieve featured images for specific post(s).
951
     *
952
     * @since 2.0.0
953
     * @access public
954
     *
955
     * @see get_post_meta()
956
     *
957
     * @param  int $post_id id of the current post.
958
     *
959
     * @return array
960
     */
961 7
    public function get_featured_images( $post_id = null ) {
962 7
        $post_id    = $this->get_real_post_id( $post_id );
963 7
        $dfi_images = get_post_meta( $post_id, 'dfiFeatured', true );
964 7
        $ret_images = array();
965
966 7
        if ( ! empty( $dfi_images ) && is_array( $dfi_images ) ) {
967 7
            $dfi_images = array_filter( $dfi_images );
968
969 7
            $count = 0;
970 7
            foreach ( $dfi_images as $dfi_image ) {
971 7
                $dfi_image_trimmed = $this->separate( $dfi_image );
972 7
                $dfi_image_full    = $this->separate( $dfi_image, 'full' );
973
974
                try {
975 7
                    $ret_images[ $count ]['thumb']         = $this->get_real_upload_path( $dfi_image_trimmed );
976 7
                    $ret_images[ $count ]['full']          = $this->get_real_upload_path( $dfi_image_full );
977 7
                    $ret_images[ $count ]['attachment_id'] = $this->get_image_id( $ret_images[ $count ]['full'] );
978 7
                } catch ( Exception $e ) {
979
                    /* Ignore the exception and continue with other featured images */
980
                }
981
982 7
                $count ++;
983 7
            }
984 7
        }
985
986 7
        return $ret_images;
987
    }
988
989
    /**
990
     * Check to see if the upload url is already available in path.
991
     *
992
     * @since  3.1.14
993
     * @access protected
994
     *
995
     * @param  string $img Uploaded image.
996
     *
997
     * @return string
998
     */
999 2
    protected function get_real_upload_path( $img ) {
1000
        // check if upload path is already attached.
1001 2
        if ( false !== strpos( $img, $this->upload_url ) || preg_match( '/https?:\/\//', $img ) ) {
1002 2
            return $img;
1003
        }
1004
1005 2
        return $this->upload_url . $img;
1006
    }
1007
1008
    /**
1009
     * Retrieve featured images for specific post(s) including the default Featured Image.
1010
     *
1011
     * @since 3.1.7
1012
     * @access public
1013
     *
1014
     * @see  $this->get_featured_images()
1015
     *
1016
     * @param int $post_id Current post id.
1017
     *
1018
     * @return array An array of images or an empty array on failure
1019
     */
1020 2
    public function get_all_featured_images( $post_id = null ) {
1021 2
        $post_id      = $this->get_real_post_id( $post_id );
1022 2
        $thumbnail_id = get_post_thumbnail_id( $post_id );
1023 2
        $all_images   = array();
1024
1025 2
        if ( ! empty( $thumbnail_id ) ) {
1026
            $featured_image         = array(
1027 2
                'thumb'         => wp_get_attachment_thumb_url( $thumbnail_id ),
1028 2
                'full'          => wp_get_attachment_url( $thumbnail_id ),
1029 2
                'attachment_id' => $thumbnail_id,
1030 2
            );
1031
1032 2
            $all_images[] = $featured_image;
1033 2
        }
1034
1035 2
        return array_merge( $all_images, $this->get_featured_images( $post_id ) );
1036
    }
1037
1038
    /**
1039
     * Load the plugin's textdomain hooked to 'plugins_loaded'.
1040
     *
1041
     * @since 1.0.0
1042
     * @access public
1043
     *
1044
     * @see    load_plugin_textdomain()
1045
     * @see    plugin_basename()
1046
     * @action plugins_loaded
1047
     *
1048
     * @codeCoverageIgnore
1049
     *
1050
     * @return void
1051
     */
1052
    public function load_plugin_textdomain() {
1053
        load_plugin_textdomain(
1054
            self::TEXT_DOMAIN,
1055
            false,
1056
            dirname( plugin_basename( __FILE__ ) ) . '/languages/'
1057
        );
1058
    }
1059
}
1060
1061
// Sponsors who support this plugin.
1062
include 'sponsors.php';
1063
1064
/**
1065
 * Instantiate the main class.
1066
 *
1067
 * @since 1.0.0
1068
 * @access public
1069
 *
1070
 * @var object $dynamic_featured_image holds the instantiated class {@uses Dynamic_Featured_Image}
1071
 */
1072
global $dynamic_featured_image;
1073
$dynamic_featured_image = new Dynamic_Featured_Image();
1074