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

Dynamic_Featured_Image::get_protocol()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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