Completed
Branch master (bc905c)
by Ankit
01:37
created

dynamic-featured-image.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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.5.2
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 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.0.1
45
 */
46
class Dynamic_Featured_Image {
47
    /**
48
     * Current version of the plugin.
49
     *
50
     * @since 3.0.0
51
     */
52
    const VERSION = '3.5.2';
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
     * Upgrade Link.
70
     *
71
     * @since 3.6.0
72
     */
73
    const UPGRADE_LINK = 'https://ankitpokhrel.com/explore/dynamic-featured-image-pro/';
74
75
    /**
76
     * Image upload directory.
77
     *
78
     * @var $upload_dir string
79
     */
80
    private $upload_dir;
81
82
    /**
83
     * Image upload URL.
84
     *
85
     * @var $upload_url string
86
     */
87
    private $upload_url;
88
89
    /**
90
     * Database object.
91
     *
92
     * @var $db wpdb
93
     */
94
    private $db;
95
96
    /**
97
     * Title for dfi metabox.
98
     *
99
     * @var $metabox_title string
100
     */
101
    protected $metabox_title;
102
103
    /**
104
     * Users post type filter for dfi metabox.
105
     *
106
     * @var $user_filter array
107
     */
108
    protected $user_filter;
109
110
    /**
111
     * Constructor. Hooks all interactions to initialize the class.
112
     *
113
     * @since 1.0.0
114
     * @access public
115
     * @global object $wpdb
116
     *
117
     * @see     add_action()
118
     */
119
    public function __construct() {
120
        // plugin update warning.
121
        add_action( 'in_plugin_update_message-' . plugin_basename( __FILE__ ), array( $this, 'update_notice' ) );
122
123
        add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
124
        add_action( 'add_meta_boxes', array( $this, 'initialize_featured_box' ) );
125
        add_action( 'save_post', array( $this, 'save_meta' ) );
126
        add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );
127
128
        // handle ajax request.
129
        add_action( 'wp_ajax_dfiMetaBox_callback', array( $this, 'ajax_callback' ) );
130
131
        // add action links.
132
        add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'dfi_action_links' ) );
133
134
        // media uploader custom fields.
135
        add_filter( 'attachment_fields_to_edit', array( $this, 'media_attachment_custom_fields' ), 10, 2 );
136
        add_filter( 'attachment_fields_to_save', array( $this, 'media_attachment_custom_fields_save' ), 10, 2 );
137
138
        // get the site protocol.
139
        $protocol = $this->get_protocol();
140
141
        $this->upload_dir = wp_upload_dir();
142
        $this->upload_url = preg_replace( '#^https?://#', '', $this->upload_dir['baseurl'] );
143
144
        // add protocol to the upload url.
145
        $this->upload_url = $protocol . $this->upload_url;
146
147
        // post type filter added by user.
148
        $this->user_filter = array();
149
150
        global $wpdb;
151
        $this->db = $wpdb;
152
    }
153
154
    /**
155
     * Return site protocol.
156
     *
157
     * @since 3.5.1
158
     * @access public
159
     *
160
     * @return string
161
     */
162
    private function get_protocol() {
0 ignored issues
show
get_protocol uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
163
        return ( ( ! empty( $_SERVER['HTTPS'] ) && 'off' !== $_SERVER['HTTPS'] ) ||
164
                 ( ! empty( $_SERVER['SERVER_PORT'] ) && 443 === $_SERVER['SERVER_PORT'] ) ) ? 'https://' : 'http://';
165
    }
166
167
    /**
168
     * Add required admin scripts.
169
     *
170
     * @since 1.0.0
171
     * @access public
172
     *
173
     * @see  wp_enque_style()
174
     * @see  wp_register_script()
175
     * @see  wp_enqueue_script()
176
     *
177
     * @return void
178
     */
179
    public function enqueue_admin_scripts() {
180
        // enqueue styles.
181
        wp_enqueue_style( 'style-dfi', plugins_url( '/css/style-dfi.css', __FILE__ ), array(), self::VERSION );
182
183
        // register script.
184
        wp_register_script( 'scripts-dfi', plugins_url( '/js/script-dfi.js', __FILE__ ), array( 'jquery' ), self::VERSION );
185
186
        // localize the script with required data.
187
        wp_localize_script(
188
            'scripts-dfi',
189
            'DFI_SPECIFIC',
190
            array(
191
                'upload_url'               => $this->upload_url,
192
                'metabox_title'            => __( $this->metabox_title, self::TEXT_DOMAIN ),
193
                'mediaSelector_title'      => __( 'Dynamic Featured Image - Media Selector', self::TEXT_DOMAIN ),
194
                'mediaSelector_buttonText' => __( 'Set Featured Image', self::TEXT_DOMAIN ),
195
                'ajax_nonce'               => wp_create_nonce( plugin_basename( __FILE__ ) ),
196
            )
197
        );
198
199
        // enqueue scripts.
200
        wp_enqueue_script( 'scripts-dfi' );
201
    }
202
203
    /**
204
     * Add upgrade link.
205
     *
206
     * @access public
207
     * @since  3.5.1
208
     * @action plugin_action_links
209
     *
210
     * @codeCoverageIgnore
211
     *
212
     * @param  array $links Action links.
213
     *
214
     * @return array
215
     */
216
    public function dfi_action_links( $links ) {
217
        $upgrade_link = array(
218
            '<a href="' . self::UPGRADE_LINK . '" target="_blank">Upgrade to Premium</a>'
219
        );
220
221
        return array_merge( $links, $upgrade_link );
222
    }
223
224
    /**
225
     * Add featured meta boxes dynamically.
226
     *
227
     * @since 1.0.0
228
     * @access public
229
     * @global object $post
230
     *
231
     * @see  get_post_meta()
232
     * @see  get_post_types()
233
     * @see  add_meta_box()
234
     * @see  add_filter()
235
     *
236
     * @return void
237
     */
238
    public function initialize_featured_box() {
239
        global $post;
240
241
        // make metabox title dynamic.
242
        $this->metabox_title = apply_filters( 'dfi_set_metabox_title', __( 'Featured Image', self::TEXT_DOMAIN ) );
243
244
        $featured_data  = get_post_meta( $post->ID, 'dfiFeatured', true );
245
        $total_featured = count( $featured_data );
246
247
        $default_filter    = array( 'attachment', 'revision', 'nav_menu_item' );
248
        $this->user_filter = apply_filters( 'dfi_post_type_user_filter', $this->user_filter );
249
        $filter            = array_merge( $default_filter, $this->user_filter );
250
251
        $post_types = get_post_types();
252
        $post_types = array_diff( $post_types, $filter );
253
254
        $post_types = apply_filters( 'dfi_post_types', $post_types );
255
256
        if ( ! empty( $featured_data ) && $total_featured >= 1 ) {
257
            $i = 2;
258
            foreach ( $featured_data as $featured ) {
259
                $this->dfi_add_meta_box( $post_types, $featured, $i );
260
                $i ++;
261
            }
262
        } else {
263
            $this->dfi_add_meta_box( $post_types );
264
        }
265
    }
266
267
    /**
268
     * Translates more than one digit number digit by digit.
269
     *
270
     * @param  int $number Integer to be translated.
271
     *
272
     * @return string Translated number
273
     */
274
    protected function get_number_translation( $number ) {
275
        if ( $number <= 9 ) {
276
            return __( $number, self::TEXT_DOMAIN );
277
        } else {
278
            $pieces = str_split( $number, 1 );
279
            $buffer = '';
280
            foreach ( $pieces as $piece ) {
281
                $buffer .= __( $piece, self::TEXT_DOMAIN );
282
            }
283
284
            return $buffer;
285
        }
286
    }
287
288
    /**
289
     * Adds meta boxes.
290
     *
291
     * @param  array  $post_types Post types to show featured image box.
292
     * @param  object $featured Callback arguments.
293
     * @param  int    $i Index of the featured image.
294
     *
295
     * @return void
296
     */
297
    private function dfi_add_meta_box( $post_types, $featured = null, $i = null ) {
298
        if ( ! is_null( $i ) ) {
299
            foreach ( $post_types as $type ) {
300
                add_meta_box(
301
                    'dfiFeaturedMetaBox-' . $i,
302
                    __( $this->metabox_title, self::TEXT_DOMAIN ) . ' ' . $this->get_number_translation( $i ),
303
                    array( $this, 'featured_meta_box' ),
304
                    $type,
305
                    'side',
306
                    'low',
307
                    array( $featured, $i + 1 )
308
                );
309
310
                add_filter( "postbox_classes_{$type}_dfiFeaturedMetaBox-" . $i, array( $this, 'add_metabox_classes' ) );
311
            }
312
        } else {
313
            foreach ( $post_types as $type ) {
314
                add_meta_box(
315
                    'dfiFeaturedMetaBox',
316
                    __( $this->metabox_title, self::TEXT_DOMAIN ) . ' ' . __( 2, self::TEXT_DOMAIN ),
317
                    array( $this, 'featured_meta_box' ),
318
                    $type,
319
                    'side',
320
                    'low',
321
                    array( null, null )
322
                );
323
324
                add_filter( "postbox_classes_{$type}_dfiFeaturedMetaBox", array( $this, 'add_metabox_classes' ) );
325
            }
326
        }
327
    }
328
329
    /**
330
     * Separate thumb and full image url from given URL string.
331
     *
332
     * @since  3.3.1
333
     *
334
     * @param  string $url_string Url string.
335
     * @param  string $state Thumb or full.
336
     *
337
     * @return string|null
338
     */
339
    private function separate( $url_string, $state = 'thumb' ) {
340
        $image_piece = explode( ',', $url_string );
341
342
        if ( 'thumb' === $state ) {
343
            return isset( $image_piece[0] ) ? $image_piece[0] : null;
344
        }
345
346
        return isset( $image_piece[1] ) ? $image_piece[1] : null;
347
    }
348
349
    /**
350
     * Create a nonce field.
351
     *
352
     * @since  3.5.0
353
     *
354
     * @see  wp_nonce_field()
355
     * @see  plugin_basename()
356
     *
357
     * @codeCoverageIgnore
358
     *
359
     * @param  string $key Nonce key.
360
     *
361
     * @return string
362
     */
363
    protected function nonce_field( $key ) {
364
        return wp_nonce_field( plugin_basename( __FILE__ ), $key, true, false );
365
    }
366
367
    /**
368
     * Featured meta box as seen in the admin.
369
     *
370
     * @since 1.0.0
371
     * @access public
372
     *
373
     * @param  object $post Global post object.
374
     * @param  array  $featured Array containing featured image count.
375
     *
376
     * @throws Exception Medium size image not found.
377
     * @return void
378
     */
379
    public function featured_meta_box( $post, $featured ) {
380
        $featured_img         = $featured['args'][0];
381
        $featured_id          = is_null( $featured['args'][1] ) ? 2 : --$featured['args'][1];
382
        $featured_img_full    = $featured_img;
383
        $featured_img_trimmed = $featured_img;
384
385
        if ( ! is_null( $featured_img ) ) {
386
            $featured_img_trimmed = $this->separate( $featured_img );
387
            $featured_img_full    = $this->separate( $featured_img, 'full' );
388
        }
389
390
        try {
391
            $thumbnail = $this->get_image_thumb( $this->upload_url . $featured_img_full, 'medium' );
392
            if ( is_null( $thumbnail ) ) {
393
                // medium sized thumbnail image is missing.
394
                throw new Exception( 'Medium size image not found', 1 );
395
            }
396
        } catch ( Exception $e ) {
397
            // since medium sized thumbnail image was not found,
398
            // let's set full image url as thumbnail.
399
            $thumbnail = $featured_img_full;
400
        }
401
402
        // Add a nonce field.
403
        echo $this->nonce_field( 'dfi_fimageplug-' . $featured_id ); // WPCS: XSS ok.
404
        echo $this->get_featured_box( $featured_img_trimmed, $featured_img, $featured_id, $thumbnail, $post->ID ); // WPCS: XSS ok.
405
    }
406
407
    /**
408
     * Returns featured box html content.
409
     *
410
     * @since  3.1.0
411
     * @access private
412
     *
413
     * @param string $featured_img_trimmed Medium sized image.
414
     * @param string $featured_img Full sized image.
415
     * @param string $featured_id Attachment Id.
416
     * @param string $thumbnail Thumb sized image.
417
     * @param int    $post_id Post id.
418
     *
419
     * @return string Html content
420
     */
421
    private function get_featured_box( $featured_img_trimmed, $featured_img, $featured_id, $thumbnail, $post_id ) {
422
        $has_featured_image = ! empty( $featured_img_trimmed ) ? 'hasFeaturedImage' : '';
423
        $thumbnail          = ! is_null( $thumbnail ) ? $thumbnail : '';
424
        $dfi_empty          = is_null( $featured_img_trimmed ) ? 'dfiImgEmpty' : '';
425
426
        return "<a href='javascript:void(0)' class='dfiFeaturedImage {$has_featured_image}' title='" . __( 'Set Featured Image', self::TEXT_DOMAIN ) . "' data-post-id='" . $post_id . "'><span class='dashicons dashicons-camera'></span></a><br/>
427
            <img src='" . $thumbnail . "' class='dfiImg {$dfi_empty}'/>
428
            <div class='dfiLinks'>
429
                <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>
430
                <a href='javascript:void(0)' class='dfiRemove dashicons dashicons-minus' title='" . __( 'Remove', self::TEXT_DOMAIN ) . "'></a>
431
            </div>
432
            <div class='dfiClearFloat'></div>
433
            <input type='hidden' name='dfiFeatured[]' value='{$featured_img}'  class='dfiImageHolder' />";
434
    }
435
436
    /**
437
     * Load new featured meta box via ajax.
438
     *
439
     * @since 1.0.0
440
     * @access public
441
     *
442
     * @return void
443
     */
444
    public function ajax_callback() {
445
        check_ajax_referer( plugin_basename( __FILE__ ), 'security' );
446
447
        $featured_id = isset( $_POST['id'] ) ? intval( wp_unslash( $_POST['id'] ) ) : null;
448
449
        if ( ! is_numeric( $featured_id ) ) {
450
            return;
451
        }
452
453
        // @codingStandardsIgnoreStart
454
        echo $this->nonce_field( 'dfi_fimageplug-' . $featured_id );
455
        ?>
456
        <a href="javascript:void(0)" class="dfiFeaturedImage"
457
           title="<?php echo __( 'Set Featured Image', self::TEXT_DOMAIN ) ?>"><span
458
                    class="dashicons dashicons-camera"></span></a><br/>
459
        <img src="" class="dfiImg dfiImgEmpty"/>
460
        <div class="dfiLinks">
461
            <a href="javascript:void(0)" data-id="<?php echo $featured_id ?>"
462
               data-id-local="<?php echo $this->get_number_translation( $featured_id + 1 ) ?>"
463
               class="dfiAddNew dashicons dashicons-plus" title="<?php echo __( 'Add New', self::TEXT_DOMAIN ) ?>"></a>
464
            <a href="javascript:void(0)" class="dfiRemove dashicons dashicons-minus"
465
               title="<?php echo __( 'Remove', self::TEXT_DOMAIN ) ?>"></a>
466
        </div>
467
        <div class="dfiClearFloat"></div>
468
        <input type="hidden" name="dfiFeatured[]" value="" class="dfiImageHolder"/>
469
        <?php
470
        // @codingStandardsIgnoreEnd
471
        wp_die( '' );
472
    }
473
474
    /**
475
     * Add custom class 'featured-meta-box' to meta box.
476
     *
477
     * @since 1.0.0
478
     * @access public
479
     *
480
     * @see  add_metabox_classes
481
     *
482
     * @param array $classes Classes to add in the meta box.
483
     *
484
     * @return array
485
     */
486
    public function add_metabox_classes( $classes ) {
487
        array_push( $classes, 'featured-meta-box' );
488
489
        return $classes;
490
    }
491
492
    /**
493
     * Add custom fields in media uploader.
494
     *
495
     * @since  3.4.0
496
     *
497
     * @param array $form_fields Fields to include in media attachment form.
498
     * @param array $post Post data.
499
     *
500
     * @return array
501
     */
502
    public function media_attachment_custom_fields( $form_fields, $post ) {
503
        $form_fields['dfi-link-to-image'] = array(
504
            'label' => __( 'Link to Image', self::TEXT_DOMAIN ),
505
            'input' => 'text',
506
            'value' => get_post_meta( $post->ID, '_dfi_link_to_image', true ),
507
        );
508
509
        return $form_fields;
510
    }
511
512
    /**
513
     * Save values of media uploader custom fields.
514
     *
515
     * @since 3.4.0
516
     *
517
     * @param array $post Post data for database.
518
     * @param array $attachment Attachment fields from $_POST form.
519
     *
520
     * @return array
521
     */
522
    public function media_attachment_custom_fields_save( $post, $attachment ) {
523
        if ( isset( $attachment['dfi-link-to-image'] ) ) {
524
            update_post_meta( $post['ID'], '_dfi_link_to_image', $attachment['dfi-link-to-image'] );
525
        }
526
527
        return $post;
528
    }
529
530
    /**
531
     * Update featured images in the database.
532
     *
533
     * @since 1.0.0
534
     * @access public
535
     *
536
     * @see  plugin_basename()
537
     * @see  update_post_meta()
538
     * @see  current_user_can()
539
     *
540
     * @param  int $post_id Current post id.
541
     *
542
     * @return bool|null
543
     */
544
    public function save_meta( $post_id ) {
545
        // Check auto save.
546
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
547
            return false;
548
        }
549
550
        if ( ! $this->verify_nonces() ) {
551
            return false;
552
        }
553
554
        // Check permission before saving data.
555
        if ( current_user_can( 'edit_posts', $post_id ) && isset( $_POST['dfiFeatured'] ) ) { // WPCS: CSRF ok.
556
            $featured_images = is_array( $_POST['dfiFeatured'] ) ? $_POST['dfiFeatured'] : []; // WPCS: sanitization ok, CSRF ok.
557
558
            $sanitized = [];
559
            foreach ( $featured_images as $image ) {
560
                $sanitized[] = sanitize_text_field( wp_unslash( $image ) );
561
            }
562
563
            update_post_meta( $post_id, 'dfiFeatured', $sanitized );
564
        }
565
    }
566
567
    /**
568
     * Verify metabox nonces.
569
     *
570
     * @access protected
571
     * @see  wp_verify_nonce()
572
     *
573
     * @return bool
574
     */
575
    protected function verify_nonces() {
576
        $keys = preg_grep( '/dfi_fimageplug-\d+$/', array_keys( $_POST ) ); // WPCS: CSRF ok.
577
578
        if ( empty( $keys ) ) {
579
            return false;
580
        }
581
582
        foreach ( $keys as $key ) {
583
            // Verify nonce.
584
            if ( ! isset( $_POST[ $key ] ) ||
585
                 ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST[ $key ] ) ), plugin_basename( __FILE__ ) )
586
            ) {
587
                return false;
588
            }
589
        }
590
591
        return true;
592
    }
593
594
    /**
595
     * Add update notice. Displayed in plugin update page.
596
     *
597
     * @since 2.0.0
598
     * @access public
599
     *
600
     * @return void
601
     */
602
    public function update_notice() {
603
        $info = __( 'ATTENTION! Please read the <a href="' . self::WIKI_LINK . '" target="_blank">DOCUMENTATION</a> properly before update.',
604
        self::TEXT_DOMAIN );
605
606
        echo '<span style="color: red; padding: 7px 0; display: block">' . strip_tags( $info, '<a><b><i><span>' ) . '</span>'; // WPCS: XSS ok.
607
    }
608
609
    /**
610
     * Execute query.
611
     *
612
     * @param string $query Query to execute.
613
     *
614
     * @return null|string
615
     */
616
    private function execute_query( $query ) {
617
        return $this->db->get_var( $query );
618
    }
619
620
    /**
621
     * Get attachment id of the image by image url.
622
     *
623
     * @since 3.1.7
624
     * @access protected
625
     * @global object $wpdb
626
     *
627
     * @param  string $image_url URL of an image.
628
     *
629
     * @return string
630
     */
631
    protected function get_attachment_id( $image_url ) {
632
        return $this->execute_query( $this->db->prepare( 'SELECT ID FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
633
    }
634
635
    /**
636
     * Get image url of the image by attachment id.
637
     *
638
     * @since 2.0.0
639
     * @access public
640
     *
641
     * @see  wp_get_attachment_image_src()
642
     *
643
     * @param  int    $attachment_id attachment id of an image.
644
     * @param  string $size size of the image to fetch (thumbnail, medium, full).
645
     *
646
     * @return string
647
     */
648
    public function get_image_url( $attachment_id, $size = 'full' ) {
649
        $image_thumb = wp_get_attachment_image_src( $attachment_id, $size );
650
651
        return empty( $image_thumb ) ? null : $image_thumb[0];
652
    }
653
654
    /**
655
     * Get image thumbnail url of specific size by image url.
656
     *
657
     * @since 2.0.0
658
     * @access public
659
     *
660
     * @see  get_image_id()
661
     * @see  wp_get_attachment_image_src()
662
     *
663
     * @param  string $image_url url of an image.
664
     * @param  string $size size of the image to fetch (thumbnail, medium, full).
665
     *
666
     * @return string
667
     */
668
    public function get_image_thumb( $image_url, $size = 'thumbnail' ) {
669
        $attachment_id = $this->get_image_id( $image_url );
670
        $image_thumb   = wp_get_attachment_image_src( $attachment_id, $size );
671
672
        return empty( $image_thumb ) ? null : $image_thumb[0];
673
    }
674
675
    /**
676
     * Gets attachment id from given image url.
677
     *
678
     * @param  string $image_url url of an image.
679
     *
680
     * @since  2.0.0
681
     * @access public
682
     *
683
     * @return int|null attachment id of an image
684
     */
685
    public function get_image_id( $image_url ) {
686
        $attachment_id = $this->get_attachment_id( $image_url );
687
688
        if ( is_null( $attachment_id ) ) {
689
            // check if the image is edited image.
690
            // and try to get the attachment id.
691
            $image_url = str_replace( $this->upload_url . '/', '', $image_url );
692
            $row       = $this->execute_query( $this->db->prepare( 'SELECT post_id FROM ' . $this->db->postmeta . ' WHERE meta_value = %s', $image_url ) );
693
            if ( ! is_null( $row ) ) {
694
                $attachment_id = $row;
695
            }
696
        }
697
698
        return $attachment_id;
699
    }
700
701
    /**
702
     * Get image title.
703
     *
704
     * @since 2.0.0
705
     * @access public
706
     *
707
     * @param string $image_url URL of an image.
708
     *
709
     * @return string
710
     */
711
    public function get_image_title( $image_url ) {
712
        return $this->execute_query( $this->db->prepare( 'SELECT post_title FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
713
    }
714
715
    /**
716
     * Get image title by id.
717
     *
718
     * @since 2.0.0
719
     * @access public
720
     *
721
     * @param  int $attachment_id Attachment id of an image.
722
     *
723
     * @return string
724
     */
725
    public function get_image_title_by_id( $attachment_id ) {
726
        return $this->execute_query( $this->db->prepare( 'SELECT post_title FROM ' . $this->db->posts . ' WHERE ID = %d', $attachment_id ) );
727
    }
728
729
    /**
730
     * Get image caption.
731
     *
732
     * @since 2.0.0
733
     * @access public
734
     *
735
     * @param  string $image_url URL of an image.
736
     *
737
     * @return string
738
     */
739
    public function get_image_caption( $image_url ) {
740
        return $this->execute_query( $this->db->prepare( 'SELECT post_excerpt FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
741
    }
742
743
    /**
744
     * Get image caption by id.
745
     *
746
     * @since 2.0.0
747
     * @access public
748
     *
749
     * @param  int $attachment_id Attachment id of an image.
750
     *
751
     * @return string
752
     */
753
    public function get_image_caption_by_id( $attachment_id ) {
754
        return $this->execute_query( $this->db->prepare( 'SELECT post_excerpt FROM ' . $this->db->posts . ' WHERE ID = %d', $attachment_id ) );
755
    }
756
757
    /**
758
     * Get image alternate text.
759
     *
760
     * @since 2.0.0
761
     * @access public
762
     *
763
     * @see  get_post_meta()
764
     *
765
     * @param  string $image_url URL of an image.
766
     *
767
     * @return string
768
     */
769
    public function get_image_alt( $image_url ) {
770
        $attachment = $this->db->get_col( $this->db->prepare( 'SELECT ID FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
771
772
        $alt = null;
773
        if ( ! empty( $attachment ) ) {
774
            $alt = get_post_meta( $attachment[0], '_wp_attachment_image_alt' );
775
        }
776
777
        return ( is_null( $alt ) || empty( $alt ) ) ? null : $alt[0];
778
    }
779
780
    /**
781
     * Get image alternate text by attachment id.
782
     *
783
     * @since 2.0.0
784
     * @access public
785
     *
786
     * @see  get_post_meta()
787
     *
788
     * @param  int $attachment_id Attachment id of an image.
789
     *
790
     * @return string
791
     */
792
    public function get_image_alt_by_id( $attachment_id ) {
793
        $alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt' );
794
795
        return empty( $alt ) ? null : $alt[0];
796
    }
797
798
    /**
799
     * Get image description.
800
     *
801
     * @since 3.0.0
802
     * @access public
803
     *
804
     * @param  string $image_url URL of an image.
805
     *
806
     * @return string
807
     */
808
    public function get_image_description( $image_url ) {
809
        return $this->execute_query( $this->db->prepare( 'SELECT post_content FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
810
    }
811
812
    /**
813
     * Get image description by id.
814
     *
815
     * @since 3.0.0
816
     * @access public
817
     *
818
     * @param  int $attachment_id attachment id of an image.
819
     *
820
     * @return string
821
     */
822
    public function get_image_description_by_id( $attachment_id ) {
823
        return $this->execute_query( $this->db->prepare( 'SELECT post_content FROM ' . $this->db->posts . ' WHERE ID = %d', $attachment_id ) );
824
    }
825
826
    /**
827
     * Get link to image.
828
     *
829
     * @since 3.4.0
830
     * @access public
831
     *
832
     * @param  int $attachment_id Attachment id of an image.
833
     *
834
     * @return string|null
835
     */
836
    public function get_link_to_image( $attachment_id ) {
837
        return get_post_meta( $attachment_id, '_dfi_link_to_image', true );
838
    }
839
840
    /**
841
     * Get all attachment ids of the post.
842
     *
843
     * @since 2.0.0
844
     * @access public
845
     *
846
     * @see  get_post_meta()
847
     *
848
     * @param  int $post_id id of the current post.
849
     *
850
     * @return array
851
     */
852
    public function get_post_attachment_ids( $post_id ) {
853
        $dfi_images = get_post_meta( $post_id, 'dfiFeatured', true );
854
        $ret_val    = array();
855
856
        if ( ! empty( $dfi_images ) && is_array( $dfi_images ) ) {
857
            foreach ( $dfi_images as $dfi_image ) {
858
                $dfi_image_full = $this->separate( $dfi_image, 'full' );
859
                $ret_val[]     = (int) $this->get_image_id( $this->upload_url . $dfi_image_full );
860
            }
861
        }
862
863
        return $ret_val;
864
    }
865
866
    /**
867
     * Fetches featured image data of nth position.
868
     *
869
     * @since  3.0.0
870
     * @access  public
871
     *
872
     * @see  get_featured_images()
873
     *
874
     * @param  int $position Position of the featured image.
875
     * @param  int $post_id Current post id.
876
     *
877
     * @return array if found, null otherwise.
878
     */
879
    public function get_nth_featured_image( $position, $post_id = null ) {
880
        if ( is_null( $post_id ) ) {
881
            global $post;
882
            $post_id = $post->ID;
883
        }
884
885
        $featured_images = $this->get_featured_images( $post_id );
886
887
        return isset( $featured_images[ $position - 2 ] ) ? $featured_images[ $position - 2 ] : null;
888
    }
889
890
    /**
891
     * Check if the image is attached with the particular post.
892
     *
893
     * @since 2.0.0
894
     * @access public
895
     *
896
     * @see  get_post_attachment_ids()
897
     *
898
     * @param  int $attachment_id Attachment id of an image.
899
     * @param  int $post_id Current post id.
900
     *
901
     * @return bool
902
     */
903
    public function is_attached( $attachment_id, $post_id ) {
904
        if ( empty( $attachment_id ) ) {
905
            return false;
906
        }
907
908
        $attachment_ids = $this->get_post_attachment_ids( $post_id );
909
910
        return in_array( $attachment_id, $attachment_ids, true ) ? true : false;
911
    }
912
913
    /**
914
     * Retrieve featured images for specific post(s).
915
     *
916
     * @since 2.0.0
917
     * @access public
918
     *
919
     * @see get_post_meta()
920
     *
921
     * @param  integer $post_id id of the current post.
922
     *
923
     * @return array
924
     */
925
    public function get_featured_images( $post_id = null ) {
926
        if ( is_null( $post_id ) ) {
927
            global $post;
928
929
            $post_id = $post->ID;
930
        }
931
932
        $dfi_images = get_post_meta( $post_id, 'dfiFeatured', true );
933
        $ret_images = array();
934
935
        if ( ! empty( $dfi_images ) && is_array( $dfi_images ) ) {
936
            $dfi_images = array_filter( $dfi_images );
937
938
            $count = 0;
939
            foreach ( $dfi_images as $dfi_image ) {
940
                $dfi_image_trimmed = $this->separate( $dfi_image );
941
                $dfi_image_full    = $this->separate( $dfi_image, 'full' );
942
943
                try {
944
                    $ret_images[ $count ]['thumb']         = $this->get_real_upload_path( $dfi_image_trimmed );
945
                    $ret_images[ $count ]['full']          = $this->get_real_upload_path( $dfi_image_full );
946
                    $ret_images[ $count ]['attachment_id'] = $this->get_image_id( $ret_images[ $count ]['full'] );
947
948
                } catch ( Exception $e ) {
949
                    /* Ignore the exception and continue with other featured images */
950
                }
951
952
                $count ++;
953
            }
954
        }
955
956
        return $ret_images;
957
    }
958
959
    /**
960
     * Check to see if the upload url is already available in path.
961
     *
962
     * @since  3.1.14
963
     * @access protected
964
     *
965
     * @param  string $img Uploaded image.
966
     *
967
     * @return string
968
     */
969
    protected function get_real_upload_path( $img ) {
970
        // check if upload path is already attached.
971
        if ( false !== strpos( $img, $this->upload_url ) || preg_match( '/https?:\/\//', $img ) ) {
972
            return $img;
973
        }
974
975
        return $this->upload_url . $img;
976
    }
977
978
    /**
979
     * Retrieve featured images for specific post(s) including the default Featured Image.
980
     *
981
     * @since 3.1.7
982
     * @access public
983
     *
984
     * @see  $this->get_featured_images()
985
     *
986
     * @param int $post_id Current post id.
987
     *
988
     * @return array An array of images or an empty array on failure
989
     */
990
    public function get_all_featured_images( $post_id = null ) {
991
        if ( is_null( $post_id ) ) {
992
            global $post;
993
994
            $post_id = $post->ID;
995
        }
996
997
        $thumbnail_id         = get_post_thumbnail_id( $post_id );
998
        $featured_image_array = array();
999
1000
        if ( ! empty( $thumbnail_id ) ) {
1001
            $featured_image         = array(
1002
                'thumb'         => wp_get_attachment_thumb_url( $thumbnail_id ),
1003
                'full'          => wp_get_attachment_url( $thumbnail_id ),
1004
                'attachment_id' => $thumbnail_id,
1005
            );
1006
1007
            $featured_image_array[] = $featured_image;
1008
        }
1009
1010
        return array_merge( $featured_image_array, $this->get_featured_images( $post_id ) );
1011
    }
1012
1013
    /**
1014
     * Load the plugin's textdomain hooked to 'plugins_loaded'.
1015
     *
1016
     * @since 1.0.0
1017
     * @access public
1018
     *
1019
     * @see    load_plugin_textdomain()
1020
     * @see    plugin_basename()
1021
     * @action plugins_loaded
1022
     *
1023
     * @codeCoverageIgnore
1024
     *
1025
     * @return void
1026
     */
1027
    public function load_plugin_textdomain() {
1028
        load_plugin_textdomain(
1029
            self::TEXT_DOMAIN,
1030
            false,
1031
            dirname( plugin_basename( __FILE__ ) ) . '/languages/'
1032
        );
1033
    }
1034
}
1035
1036
/**
1037
 * Instantiate the main class.
1038
 *
1039
 * @since 1.0.0
1040
 * @access public
1041
 *
1042
 * @var object $dynamic_featured_image holds the instantiated class {@uses Dynamic_Featured_Image}
1043
 */
1044
global $dynamic_featured_image;
1045
$dynamic_featured_image = new Dynamic_Featured_Image();
1046