Completed
Push — master ( daa6a5...aa42d0 )
by Ankit
01:35
created

Dynamic_Featured_Image::enqueue_admin_scripts()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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