Completed
Push — master ( 91739f...3f04be )
by Ankit
01:58
created

Dynamic_Featured_Image::nonce_field()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
/**
3
 * Plugin Name: Dynamic Featured Image
4
 * Plugin URI: http://wordpress.org/plugins/dynamic-featured-image/
5
 * Description: Dynamically adds multiple featured image or post thumbnail functionality to your posts, pages and custom post types.
6
 * Version: 3.7.0
7
 * Author: Ankit Pokhrel
8
 * Author URI: https://ankitpokhrel.com
9
 * License: GPL2 or later
10
 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 * Text Domain: dynamic-featured-image
12
 * Domain Path: /languages
13
 * GitHub Plugin URI: https://github.com/ankitpokhrel/Dynamic-Featured-Image
14
 *
15
 * @package dynamic-featured-image
16
 *
17
 * Copyright (C) 2013-2019 Ankit Pokhrel <[email protected], https://ankitpokhrel.com>
18
 *
19
 * This program is free software; you can redistribute it and/or modify
20
 * it under the terms of the GNU General Public License as published by
21
 * the Free Software Foundation; either version 3 of the License, or
22
 * (at your option) any later version.
23
 *
24
 * This program is distributed in the hope that it will be useful,
25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
 * GNU General Public License for more details.
28
 *
29
 * You should have received a copy of the GNU General Public License
30
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
31
 */
32
33
// Avoid direct calls to this file.
34
if ( ! defined( 'ABSPATH' ) ) {
35
    header( 'Status: 403 Forbidden' );
36
    header( 'HTTP/1.1 403 Forbidden' );
37
    exit();
38
}
39
40
/**
41
 * Dynamic Featured Image plugin main class.
42
 *
43
 * @author Ankit Pokhrel <[email protected]>
44
 * @version 3.7.0
45
 */
46
class Dynamic_Featured_Image {
47
    /**
48
     * Current version of the plugin.
49
     *
50
     * @since 3.0.0
51
     */
52
    const VERSION = '3.7.0';
53
54
    /**
55
     * Text domain.
56
     *
57
     * @since 3.6.0
58
     */
59
    const TEXT_DOMAIN = 'dynamic-featured-image';
60
61
    /**
62
     * Documentation Link.
63
     *
64
     * @since 3.6.0
65
     */
66
    const WIKI_LINK = 'https://github.com/ankitpokhrel/Dynamic-Featured-Image/wiki/';
67
68
    /**
69
     * 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 1
    public function __construct() {
120
        // plugin update warning.
121 1
        add_action( 'in_plugin_update_message-' . plugin_basename( __FILE__ ), array( $this, 'update_notice' ) );
122
123 1
        add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
124 1
        add_action( 'add_meta_boxes', array( $this, 'initialize_featured_box' ) );
125 1
        add_action( 'save_post', array( $this, 'save_meta' ) );
126 1
        add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );
127
128
        // handle ajax request.
129 1
        add_action( 'wp_ajax_dfiMetaBox_callback', array( $this, 'ajax_callback' ) );
130
131
        // add action links.
132 1
        add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'dfi_action_links' ) );
133
134
        // media uploader custom fields.
135 1
        add_filter( 'attachment_fields_to_edit', array( $this, 'media_attachment_custom_fields' ), 10, 2 );
136 1
        add_filter( 'attachment_fields_to_save', array( $this, 'media_attachment_custom_fields_save' ), 10, 2 );
137
138
        // plugin sponsors.
139 1
        new PluginSponsor();
140
141
        // get the site protocol.
142 1
        $protocol = $this->get_protocol();
143
144 1
        $this->upload_dir = wp_upload_dir();
145 1
        $this->upload_url = preg_replace( '#^https?://#', '', $this->upload_dir['baseurl'] );
146
147
        // add protocol to the upload url.
148 1
        $this->upload_url = $protocol . $this->upload_url;
149
150
        // post type filter added by user.
151 1
        $this->user_filter = array();
152
153 1
        global $wpdb;
154 1
        $this->db = $wpdb;
155 1
    }
156
157
    /**
158
     * Return site protocol.
159
     *
160
     * @since 3.5.1
161
     * @access public
162
     *
163
     * @return string
164
     */
165
    private function get_protocol() {
166
        return is_ssl() ? 'https://' : 'http://';
167
    }
168
169
    /**
170
     * Add required admin scripts.
171
     *
172
     * @since 1.0.0
173
     * @access public
174
     *
175
     * @see  wp_enqueue_style()
176
     * @see  wp_register_script()
177
     * @see  wp_enqueue_script()
178
     *
179
     * @return void
180
     */
181 1
    public function enqueue_admin_scripts() {
182
        // enqueue styles.
183 1
        wp_enqueue_style( 'style-dfi', plugins_url( '/css/style-dfi.css', __FILE__ ), array(), self::VERSION );
184
185
        // register script.
186 1
        wp_register_script( 'scripts-dfi', plugins_url( '/js/script-dfi.js', __FILE__ ), array( 'jquery' ), self::VERSION );
187
188
        // localize the script with required data.
189 1
        wp_localize_script(
190 1
            'scripts-dfi',
191 1
            'DFI_SPECIFIC',
192
            array(
193 1
                'upload_url'               => $this->upload_url,
194 1
                'metabox_title'            => __( $this->metabox_title, self::TEXT_DOMAIN ),
195 1
                'mediaSelector_title'      => __( 'Dynamic Featured Image - Media Selector', self::TEXT_DOMAIN ),
196 1
                'mediaSelector_buttonText' => __( 'Set Featured Image', self::TEXT_DOMAIN ),
197 1
                'ajax_nonce'               => wp_create_nonce( plugin_basename( __FILE__ ) ),
198
            )
199
        );
200
201
        // enqueue scripts.
202 1
        wp_enqueue_script( 'scripts-dfi' );
203 1
    }
204
205
    /**
206
     * Add upgrade link.
207
     *
208
     * @access public
209
     * @since  3.5.1
210
     * @action plugin_action_links
211
     *
212
     * @codeCoverageIgnore
213
     *
214
     * @param  array $links Action links.
215
     *
216
     * @return array
217
     */
218
    public function dfi_action_links( $links ) {
219
        $upgrade_link = array(
220
            '<a href="' . self::UPGRADE_LINK . '" target="_blank">Upgrade to Premium</a>'
221
        );
222
223
        return array_merge( $links, $upgrade_link );
224
    }
225
226
    /**
227
     * Add featured meta boxes dynamically.
228
     *
229
     * @since 1.0.0
230
     * @access public
231
     * @global object $post
232
     *
233
     * @see  get_post_meta()
234
     * @see  get_post_types()
235
     * @see  add_meta_box()
236
     * @see  add_filter()
237
     *
238
     * @return void
239
     */
240
    public function initialize_featured_box() {
241
        global $post;
242
243
        // make metabox title dynamic.
244
        $this->metabox_title = apply_filters( 'dfi_set_metabox_title', __( 'Featured Image', self::TEXT_DOMAIN ) );
245
246
        $featured_data  = get_post_meta( $post->ID, 'dfiFeatured', true );
247
        $total_featured = is_array( $featured_data ) ? count( $featured_data ) : 0;
248
249
        $default_filter    = array( 'attachment', 'revision', 'nav_menu_item' );
250
        $this->user_filter = apply_filters( 'dfi_post_type_user_filter', $this->user_filter );
251
252
        $post_types = array_diff( get_post_types(), array_merge( $default_filter, $this->user_filter ) );
253
        $post_types = apply_filters( 'dfi_post_types', $post_types );
254
255
        if ( ! empty( $featured_data ) && $total_featured >= 1 ) {
256
            $i = 2;
257
            foreach ( $featured_data as $featured ) {
258
                $this->dfi_add_meta_box( $post_types, $featured, $i++ );
259
            }
260
        } else {
261
            $this->dfi_add_meta_box( $post_types );
262
        }
263
    }
264
265
    /**
266
     * Translates more than one digit number digit by digit.
267
     *
268
     * @param  int $number Integer to be translated.
269
     *
270
     * @return string Translated number
271
     */
272 3
    protected function get_number_translation( $number ) {
273 3
        if ( $number <= 9 ) {
274 2
            return __( $number, self::TEXT_DOMAIN );
275
        } else {
276 1
            $pieces = str_split( $number, 1 );
277 1
            $buffer = '';
278 1
            foreach ( $pieces as $piece ) {
279 1
                $buffer .= __( $piece, self::TEXT_DOMAIN );
280
            }
281
282 1
            return $buffer;
283
        }
284
    }
285
286
    /**
287
     * Adds meta boxes.
288
     *
289
     * @param  array  $post_types Post types to show featured image box.
290
     * @param  object $featured Callback arguments.
291
     * @param  int    $i Index of the featured image.
292
     *
293
     * @return void
294
     */
295
    private function dfi_add_meta_box( $post_types, $featured = null, $i = null ) {
296
        if ( ! is_null( $i ) ) {
297
            foreach ( $post_types as $type ) {
298
                add_meta_box(
299
                    'dfiFeaturedMetaBox-' . $i,
300
                    __( $this->metabox_title, self::TEXT_DOMAIN ) . ' ' . $this->get_number_translation( $i ),
301
                    array( $this, 'featured_meta_box' ),
302
                    $type,
303
                    apply_filters( 'dfi_metabox_context', 'side' ),
304
                    apply_filters( 'dfi_metabox_priority', 'low' ),
305
                    array( $featured, $i + 1 )
306
                );
307
308
                add_filter( "postbox_classes_{$type}_dfiFeaturedMetaBox-" . $i, array( $this, 'add_metabox_classes' ) );
309
            }
310
        } else {
311
            foreach ( $post_types as $type ) {
312
                add_meta_box(
313
                    'dfiFeaturedMetaBox',
314
                    __( $this->metabox_title, self::TEXT_DOMAIN ) . ' ' . __( 2, self::TEXT_DOMAIN ),
315
                    array( $this, 'featured_meta_box' ),
316
                    $type,
317
                    apply_filters( 'dfi_metabox_context', 'side' ),
318
                    apply_filters( 'dfi_metabox_priority', 'low' ),
319
                    array( null, null )
320
                );
321
322
                add_filter( "postbox_classes_{$type}_dfiFeaturedMetaBox", array( $this, 'add_metabox_classes' ) );
323
            }
324
        }
325
    }
326
327
    /**
328
     * Separate thumb and full image url from given URL string.
329
     *
330
     * @since  3.3.1
331
     *
332
     * @param  string $url_string Url string.
333
     * @param  string $state Thumb or full.
334
     *
335
     * @return string|null
336
     */
337 3
    private function separate( $url_string, $state = 'thumb' ) {
338 3
        $image_piece = explode( ',', $url_string );
339
340 3
        if ( 'thumb' === $state ) {
341 2
            return isset( $image_piece[0] ) ? $image_piece[0] : null;
342
        }
343
344 3
        return isset( $image_piece[1] ) ? $image_piece[1] : null;
345
    }
346
347
    /**
348
     * Create a nonce field.
349
     *
350
     * @since  3.5.0
351
     *
352
     * @see  wp_nonce_field()
353
     * @see  plugin_basename()
354
     *
355
     * @codeCoverageIgnore
356
     *
357
     * @param  string $key Nonce key.
358
     *
359
     * @return string
360
     */
361
    protected function nonce_field( $key ) {
362
        return wp_nonce_field( plugin_basename( __FILE__ ), $key, true, false );
363
    }
364
365
    /**
366
     * Featured meta box as seen in the admin.
367
     *
368
     * @since 1.0.0
369
     * @access public
370
     *
371
     * @param  object $post Global post object.
372
     * @param  array  $featured Array containing featured image count.
373
     *
374
     * @throws Exception Medium size image not found.
375
     * @return void
376
     */
377 3
    public function featured_meta_box( $post, $featured ) {
378 3
        $featured_img         = $featured['args'][0];
379 3
        $featured_id          = is_null( $featured['args'][1] ) ? 2 : --$featured['args'][1];
380 3
        $featured_img_full    = $featured_img;
381 3
        $featured_img_trimmed = $featured_img;
382
383 3
        if ( ! is_null( $featured_img ) ) {
384 3
            $featured_img_trimmed = $this->separate( $featured_img );
385 3
            $featured_img_full    = $this->separate( $featured_img, 'full' );
386
        }
387
388 3
        $thumbnail     = null;
389 3
        $attachment_id = null;
390 3 View Code Duplication
        if ( ! empty( $featured_img_full ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
391 1
            $attachment_id = $this->get_image_id( $this->upload_url . $featured_img_full );
392
393 1
            $thumbnail = $this->get_image_thumb_by_attachment_id( $attachment_id, 'medium' );
394
395 1
            if ( empty( $thumbnail ) ) {
396
                // since medium sized thumbnail image is missing,
397
                // let's set full image url as thumbnail.
398
                $thumbnail = $featured_img_full;
399
            }
400
        }
401
402
        // Add a nonce field.
403 3
        echo $this->nonce_field( 'dfi_fimageplug-' . $featured_id ); // WPCS: XSS ok.
404 3
        echo $this->get_featured_box( $featured_img_trimmed, $featured_img, $featured_id, $thumbnail, $post->ID, $attachment_id ); // WPCS: XSS ok.
405 3
    }
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          Featured id number for translation.
416
     * @param string $thumbnail            Thumb sized image.
417
     * @param int    $post_id              Post id.
418
     * @param int    $attachment_id        Attachment id.
419
     *
420
     * @return string Html content
421
     */
422 3
    private function get_featured_box( $featured_img_trimmed, $featured_img, $featured_id, $thumbnail, $post_id, $attachment_id ) {
423 3
        $has_featured_image = ! empty( $featured_img_trimmed ) ? ' hasFeaturedImage' : '';
424 3
        $thumbnail          = ! is_null( $thumbnail ) ? $thumbnail : '';
425 3
        $dfi_empty          = is_null( $featured_img_trimmed ) ? 'dfiImgEmpty' : '';
426
427 3
        return "<a href='javascript:void(0)' class='dfiFeaturedImage{$has_featured_image}' title='" . __( 'Set Featured Image', self::TEXT_DOMAIN ) . "' data-post-id='" . $post_id . "' data-attachment-id='" . $attachment_id . "'><span class='dashicons dashicons-camera'></span></a><br/>
428 3
            <img src='" . $thumbnail . "' class='dfiImg {$dfi_empty}'/>
429
            <div class='dfiLinks'>
430 3
                <a href='javascript:void(0)' data-id='{$featured_id}' data-id-local='" . $this->get_number_translation( $featured_id + 1 ) . "' class='dfiAddNew dashicons dashicons-plus' title='" . __( 'Add New', self::TEXT_DOMAIN ) . "'></a>
431 3
                <a href='javascript:void(0)' class='dfiRemove dashicons dashicons-minus' title='" . __( 'Remove', self::TEXT_DOMAIN ) . "'></a>
432
            </div>
433
            <div class='dfiClearFloat'></div>
434 3
            <input type='hidden' name='dfiFeatured[]' value='{$featured_img}'  class='dfiImageHolder' />";
435
    }
436
437
    /**
438
     * Load new featured meta box via ajax.
439
     *
440
     * @since 1.0.0
441
     * @access public
442
     *
443
     * @return void
444
     */
445 2
    public function ajax_callback() {
446 2
        check_ajax_referer( plugin_basename( __FILE__ ), 'security' );
447
448 1
        $featured_id = isset( $_POST['id'] ) ? intval( wp_unslash( $_POST['id'] ) ) : null;
449
450 1
        if ( ! is_numeric( $featured_id ) ) {
451
            return;
452
        }
453
454
        // @codingStandardsIgnoreStart
455 1
        echo $this->nonce_field( 'dfi_fimageplug-' . $featured_id );
456
        ?>
457 1
        <a href="javascript:void(0)" class="dfiFeaturedImage"
458
           title="<?php echo __( 'Set Featured Image', self::TEXT_DOMAIN ) ?>"><span
459
                    class="dashicons dashicons-camera"></span></a><br/>
460
        <img src="" class="dfiImg dfiImgEmpty"/>
461
        <div class="dfiLinks">
462
            <a href="javascript:void(0)" data-id="<?php echo $featured_id ?>"
463
               data-id-local="<?php echo $this->get_number_translation( $featured_id + 1 ) ?>"
464
               class="dfiAddNew dashicons dashicons-plus" title="<?php echo __( 'Add New', self::TEXT_DOMAIN ) ?>"></a>
465
            <a href="javascript:void(0)" class="dfiRemove dashicons dashicons-minus"
466
               title="<?php echo __( 'Remove', self::TEXT_DOMAIN ) ?>"></a>
467
        </div>
468
        <div class="dfiClearFloat"></div>
469
        <input type="hidden" name="dfiFeatured[]" value="" class="dfiImageHolder"/>
470
        <?php
471
        // @codingStandardsIgnoreEnd
472 1
        wp_die( '' );
473
    }
474
475
    /**
476
     * Add custom class 'featured-meta-box' to meta box.
477
     *
478
     * @since 1.0.0
479
     * @access public
480
     *
481
     * @see  add_metabox_classes
482
     *
483
     * @param array $classes Classes to add in the meta box.
484
     *
485
     * @return array
486
     */
487 1
    public function add_metabox_classes( $classes ) {
488 1
        array_push( $classes, 'featured-meta-box' );
489
490 1
        return $classes;
491
    }
492
493
    /**
494
     * Add custom fields in media uploader.
495
     *
496
     * @since  3.4.0
497
     *
498
     * @param array $form_fields Fields to include in media attachment form.
499
     * @param array $post Post data.
500
     *
501
     * @return array
502
     */
503 1
    public function media_attachment_custom_fields( $form_fields, $post ) {
504 1
        $form_fields['dfi-link-to-image'] = array(
505 1
            'label' => __( 'Link to Image', self::TEXT_DOMAIN ),
506 1
            'input' => 'text',
507 1
            'value' => get_post_meta( $post->ID, '_dfi_link_to_image', true ),
508
        );
509
510 1
        return $form_fields;
511
    }
512
513
    /**
514
     * Save values of media uploader custom fields.
515
     *
516
     * @since 3.4.0
517
     *
518
     * @param array $post Post data for database.
519
     * @param array $attachment Attachment fields from $_POST form.
520
     *
521
     * @return array
522
     */
523 1
    public function media_attachment_custom_fields_save( $post, $attachment ) {
524 1
        if ( isset( $attachment['dfi-link-to-image'] ) ) {
525 1
            update_post_meta( $post['ID'], '_dfi_link_to_image', $attachment['dfi-link-to-image'] );
526
        }
527
528 1
        return $post;
529
    }
530
531
    /**
532
     * Update featured images in the database.
533
     *
534
     * @since 1.0.0
535
     * @access public
536
     *
537
     * @see  plugin_basename()
538
     * @see  update_post_meta()
539
     * @see  current_user_can()
540
     *
541
     * @param  int $post_id Current post id.
542
     *
543
     * @return bool|null
544
     */
545 2
    public function save_meta( $post_id ) {
546
        // Check auto save.
547 2
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
548 1
            return false;
549
        }
550
551 2
        if ( ! $this->verify_nonces() ) {
552 2
            return false;
553
        }
554
555
        // Check permission before saving data.
556 1
        if ( current_user_can( 'edit_posts', $post_id ) && isset( $_POST['dfiFeatured'] ) ) { // WPCS: CSRF ok.
557 1
            $featured_images = is_array( $_POST['dfiFeatured'] ) ? $_POST['dfiFeatured'] : array(); // WPCS: sanitization ok, CSRF ok.
558
559 1
            update_post_meta( $post_id, 'dfiFeatured', $this->sanitize_array( $featured_images ) );
560
        }
561 1
    }
562
563
    /**
564
     * Sanitize array.
565
     *
566
     * @since 3.6.0
567
     * @access protected
568
     *
569
     * @param array $input_array Input array.
570
     *
571
     * @return array
572
     */
573 1
    protected function sanitize_array( $input_array ) {
574 1
        $sanitized = array();
575
576 1
        foreach ( $input_array as $value ) {
577 1
            $sanitized[] = sanitize_text_field( wp_unslash( $value ) );
578
        }
579
580 1
        return $sanitized;
581
    }
582
583
    /**
584
     * Verify metabox nonces.
585
     *
586
     * @access protected
587
     * @see  wp_verify_nonce()
588
     *
589
     * @return bool
590
     */
591
    protected function verify_nonces() {
592
        $keys = preg_grep( '/dfi_fimageplug-\d+$/', array_keys( $_POST ) ); // WPCS: CSRF ok.
593
594
        if ( empty( $keys ) ) {
595
            return false;
596
        }
597
598
        foreach ( $keys as $key ) {
599
            // Verify nonce.
600
            if ( ! isset( $_POST[ $key ] ) ||
601
                 ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST[ $key ] ) ), plugin_basename( __FILE__ ) )
602
            ) {
603
                return false;
604
            }
605
        }
606
607
        return true;
608
    }
609
610
    /**
611
     * Add update notice. Displayed in plugin update page.
612
     *
613
     * @since 2.0.0
614
     * @access public
615
     *
616
     * @return void
617
     */
618 1
    public function update_notice() {
619 1
        $info = __( 'ATTENTION! Please read the <a href="' . self::WIKI_LINK . '" target="_blank">DOCUMENTATION</a> properly before update.',
620 1
        self::TEXT_DOMAIN );
621
622 1
        echo '<span style="color: red; padding: 7px 0; display: block">' . strip_tags( $info, '<a><b><i><span>' ) . '</span>'; // WPCS: XSS ok.
623 1
    }
624
625
    /**
626
     * Execute query.
627
     *
628
     * @param string $query Query to execute.
629
     *
630
     * @return null|string
631
     */
632 6
    private function execute_query( $query ) {
633 6
        return $this->db->get_var( $query );
634
    }
635
636
    /**
637
     * Get attachment id of the image by image url.
638
     *
639
     * @since 3.1.7
640
     * @access protected
641
     * @global object $wpdb
642
     *
643
     * @param  string $image_url URL of an image.
644
     *
645
     * @return string
646
     */
647 1
    protected function get_attachment_id( $image_url ) {
648 1
        return $this->execute_query( $this->db->prepare( 'SELECT ID FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
649
    }
650
651
    /**
652
     * Get image url of the image by attachment id.
653
     *
654
     * @since 2.0.0
655
     * @access public
656
     *
657
     * @see  wp_get_attachment_image_src()
658
     *
659
     * @param  int    $attachment_id attachment id of an image.
660
     * @param  string $size size of the image to fetch (thumbnail, medium, full).
661
     *
662
     * @return string
663
     */
664 1
    public function get_image_url( $attachment_id, $size = 'full' ) {
665 1
        $image_thumb = wp_get_attachment_image_src( $attachment_id, $size );
666
667 1
        return empty( $image_thumb ) ? null : $image_thumb[0];
668
    }
669
670
    /**
671
     * Get image thumbnail url of specific size by attachment id.
672
     *
673
     * @since 3.7.0
674
     * @access public
675
     *
676
     * @see wp_get_attachment_image_src()
677
     *
678
     * @param int $attachment_id attachment id of an image.
679
     * @param string $size size of the image to fetch (thumbnail, medium, full).
680
     *
681
     * @return string|null
682
     */
683 1
    public function get_image_thumb_by_attachment_id( $attachment_id, $size = 'thumbnail' ) {
684 1
        if ( empty( $attachment_id ) ) {
685
            return null;
686
        }
687
688 1
        $image_thumb = wp_get_attachment_image_src( $attachment_id, $size );
689
690 1
        return empty( $image_thumb ) ? null : $image_thumb[0];
691
    }
692
693
    /**
694
     * Get image thumbnail url of specific size by image url.
695
     *
696
     * @since 2.0.0
697
     * @access public
698
     *
699
     * @see  get_image_id()
700
     * @see  wp_get_attachment_image_src()
701
     *
702
     * @param  string $image_url url of an image.
703
     * @param  string $size size of the image to fetch (thumbnail, medium, full).
704
     *
705
     * @return string
706
     */
707 1
    public function get_image_thumb( $image_url, $size = 'thumbnail' ) {
708 1
        $attachment_id = $this->get_image_id( $image_url );
709 1
        $image_thumb   = wp_get_attachment_image_src( $attachment_id, $size );
710
711 1
        return empty( $image_thumb ) ? null : $image_thumb[0];
712
    }
713
714
    /**
715
     * Gets attachment id from given image url.
716
     *
717
     * @param  string $image_url url of an image.
718
     *
719
     * @since  2.0.0
720
     * @access public
721
     *
722
     * @return int|null attachment id of an image
723
     */
724 5
    public function get_image_id( $image_url ) {
725 5
        $attachment_id = $this->get_attachment_id( $image_url );
726
727 5
        if ( is_null( $attachment_id ) ) {
728
            /*
729
             * Check if the image is an edited image.
730
             * and try to get the attachment id.
731
             */
732
733 4
            global $wp_version;
734
735 4
            if ( intval( $wp_version ) >= 4 ) {
736 4
                return attachment_url_to_postid( $image_url );
737
            }
738
739
            // Fallback.
740
            $image_url = str_replace( $this->upload_url . '/', '', $image_url );
741
742
            $row = $this->execute_query( $this->db->prepare( 'SELECT post_id FROM ' . $this->db->postmeta . ' WHERE meta_key = %s AND meta_value = %s', '_wp_attached_file', $image_url ) );
743
            if ( ! is_null( $row ) ) {
744
                $attachment_id = $row;
745
            }
746
        }
747
748 4
        return $attachment_id;
749
    }
750
751
    /**
752
     * Get image title.
753
     *
754
     * @since 2.0.0
755
     * @access public
756
     *
757
     * @param string $image_url URL of an image.
758
     *
759
     * @return string
760
     */
761 1
    public function get_image_title( $image_url ) {
762 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_title FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
763
    }
764
765
    /**
766
     * Get image title by id.
767
     *
768
     * @since 2.0.0
769
     * @access public
770
     *
771
     * @param  int $attachment_id Attachment id of an image.
772
     *
773
     * @return string
774
     */
775 1
    public function get_image_title_by_id( $attachment_id ) {
776 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_title FROM ' . $this->db->posts . ' WHERE ID = %d', $attachment_id ) );
777
    }
778
779
    /**
780
     * Get image caption.
781
     *
782
     * @since 2.0.0
783
     * @access public
784
     *
785
     * @param  string $image_url URL of an image.
786
     *
787
     * @return string
788
     */
789 1
    public function get_image_caption( $image_url ) {
790 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_excerpt FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
791
    }
792
793
    /**
794
     * Get image caption by id.
795
     *
796
     * @since 2.0.0
797
     * @access public
798
     *
799
     * @param  int $attachment_id Attachment id of an image.
800
     *
801
     * @return string
802
     */
803 1
    public function get_image_caption_by_id( $attachment_id ) {
804 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_excerpt FROM ' . $this->db->posts . ' WHERE ID = %d', $attachment_id ) );
805
    }
806
807
    /**
808
     * Get image alternate text.
809
     *
810
     * @since 2.0.0
811
     * @access public
812
     *
813
     * @see  get_post_meta()
814
     *
815
     * @param  string $image_url URL of an image.
816
     *
817
     * @return string
818
     */
819 1
    public function get_image_alt( $image_url ) {
820 1
        $attachment = $this->db->get_col( $this->db->prepare( 'SELECT ID FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
821
822 1
        $alt = null;
823 1
        if ( ! empty( $attachment ) ) {
824 1
            $alt = get_post_meta( $attachment[0], '_wp_attachment_image_alt' );
825
        }
826
827 1
        return ( is_null( $alt ) || empty( $alt ) ) ? null : $alt[0];
828
    }
829
830
    /**
831
     * Get image alternate text by attachment id.
832
     *
833
     * @since 2.0.0
834
     * @access public
835
     *
836
     * @see  get_post_meta()
837
     *
838
     * @param  int $attachment_id Attachment id of an image.
839
     *
840
     * @return string
841
     */
842 1
    public function get_image_alt_by_id( $attachment_id ) {
843 1
        $alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt' );
844
845 1
        return empty( $alt ) ? null : $alt[0];
846
    }
847
848
    /**
849
     * Get image description.
850
     *
851
     * @since 3.0.0
852
     * @access public
853
     *
854
     * @param  string $image_url URL of an image.
855
     *
856
     * @return string
857
     */
858 1
    public function get_image_description( $image_url ) {
859 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_content FROM ' . $this->db->posts . ' WHERE guid = %s', $image_url ) );
860
    }
861
862
    /**
863
     * Get image description by id.
864
     *
865
     * @since 3.0.0
866
     * @access public
867
     *
868
     * @param  int $attachment_id attachment id of an image.
869
     *
870
     * @return string
871
     */
872 1
    public function get_image_description_by_id( $attachment_id ) {
873 1
        return $this->execute_query( $this->db->prepare( 'SELECT post_content FROM ' . $this->db->posts . ' WHERE ID = %d', $attachment_id ) );
874
    }
875
876
    /**
877
     * Get link to image.
878
     *
879
     * @since 3.4.0
880
     * @access public
881
     *
882
     * @param  int $attachment_id Attachment id of an image.
883
     *
884
     * @return string|null
885
     */
886 1
    public function get_link_to_image( $attachment_id ) {
887 1
        return get_post_meta( $attachment_id, '_dfi_link_to_image', true );
888
    }
889
890
    /**
891
     * Get all attachment ids of the post.
892
     *
893
     * @since 2.0.0
894
     * @access public
895
     *
896
     * @see  get_post_meta()
897
     *
898
     * @param  int $post_id id of the current post.
899
     *
900
     * @return array
901
     */
902 2
    public function get_post_attachment_ids( $post_id ) {
903 2
        $dfi_images = get_post_meta( $post_id, 'dfiFeatured', true );
904 2
        $ret_val    = array();
905
906 2 View Code Duplication
        if ( ! empty( $dfi_images ) && is_array( $dfi_images ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
907 2
            foreach ( $dfi_images as $dfi_image ) {
908 2
                $dfi_image_full = $this->separate( $dfi_image, 'full' );
909 2
                $ret_val[]      = (int) $this->get_image_id( $this->upload_url . $dfi_image_full );
910
            }
911
        }
912
913 2
        return $ret_val;
914
    }
915
916
    /**
917
     * Get real post id.
918
     *
919
     * @since 3.6.0
920
     * @access protected
921
     *
922
     * @param int|null $post_id Post id.
923
     *
924
     * @return int|null
925
     */
926 6
    protected function get_real_post_id( $post_id = null ) {
927 6
        if ( ! is_null( $post_id ) && is_numeric( $post_id ) ) {
928 5
            return $post_id;
929
        }
930
931 3
        global $post;
932
933 3
        return $post->ID;
934
    }
935
936
    /**
937
     * Fetches featured image data of nth position.
938
     *
939
     * @since  3.0.0
940
     * @access  public
941
     *
942
     * @see  get_featured_images()
943
     *
944
     * @param  int $position Position of the featured image.
945
     * @param  int $post_id Current post id.
946
     *
947
     * @return array if found, null otherwise.
948
     */
949 2
    public function get_nth_featured_image( $position, $post_id = null ) {
950 2
        $post_id = $this->get_real_post_id( ( $post_id ) );
951
952 2
        $featured_images = $this->get_featured_images( $post_id );
953
954 2
        return isset( $featured_images[ $position - 2 ] ) ? $featured_images[ $position - 2 ] : null;
955
    }
956
957
    /**
958
     * Check if the image is attached with the particular post.
959
     *
960
     * @since 2.0.0
961
     * @access public
962
     *
963
     * @see  get_post_attachment_ids()
964
     *
965
     * @param  int $attachment_id Attachment id of an image.
966
     * @param  int $post_id Current post id.
967
     *
968
     * @return bool
969
     */
970 1
    public function is_attached( $attachment_id, $post_id ) {
971 1
        if ( empty( $attachment_id ) ) {
972 1
            return false;
973
        }
974
975 1
        $attachment_ids = $this->get_post_attachment_ids( $post_id );
976
977 1
        return in_array( $attachment_id, $attachment_ids, true ) ? true : false;
978
    }
979
980
    /**
981
     * Retrieve featured images for specific post(s).
982
     *
983
     * @since 2.0.0
984
     * @access public
985
     *
986
     * @see get_post_meta()
987
     *
988
     * @param  int $post_id id of the current post.
989
     *
990
     * @return array
991
     */
992 7
    public function get_featured_images( $post_id = null ) {
993 7
        $post_id    = $this->get_real_post_id( $post_id );
994 7
        $dfi_images = get_post_meta( $post_id, 'dfiFeatured', true );
995 7
        $ret_images = array();
996
997 7
        if ( ! empty( $dfi_images ) && is_array( $dfi_images ) ) {
998 7
            $dfi_images = array_filter( $dfi_images );
999
1000 7
            $count = 0;
1001 7
            foreach ( $dfi_images as $dfi_image ) {
1002 7
                $dfi_image_trimmed = $this->separate( $dfi_image );
1003 7
                $dfi_image_full    = $this->separate( $dfi_image, 'full' );
1004
1005
                try {
1006 7
                    $ret_images[ $count ]['thumb']         = $this->get_real_upload_path( $dfi_image_trimmed );
1007 7
                    $ret_images[ $count ]['full']          = $this->get_real_upload_path( $dfi_image_full );
1008 7
                    $ret_images[ $count ]['attachment_id'] = $this->get_image_id( $ret_images[ $count ]['full'] );
1009
                } catch ( Exception $e ) {
1010
                    /* Ignore the exception and continue with other featured images */
1011
                }
1012
1013 7
                $count ++;
1014
            }
1015
        }
1016
1017 7
        return $ret_images;
1018
    }
1019
1020
    /**
1021
     * Check to see if the upload url is already available in path.
1022
     *
1023
     * @since  3.1.14
1024
     * @access protected
1025
     *
1026
     * @param  string $img Uploaded image.
1027
     *
1028
     * @return string
1029
     */
1030 2
    protected function get_real_upload_path( $img ) {
1031
        // check if upload path is already attached.
1032 2
        if ( false !== strpos( $img, $this->upload_url ) || preg_match( '/https?:\/\//', $img ) ) {
1033 2
            return $img;
1034
        }
1035
1036 2
        return $this->upload_url . $img;
1037
    }
1038
1039
    /**
1040
     * Retrieve featured images for specific post(s) including the default Featured Image.
1041
     *
1042
     * @since 3.1.7
1043
     * @access public
1044
     *
1045
     * @see  $this->get_featured_images()
1046
     *
1047
     * @param int $post_id Current post id.
1048
     *
1049
     * @return array An array of images or an empty array on failure
1050
     */
1051 2
    public function get_all_featured_images( $post_id = null ) {
1052 2
        $post_id      = $this->get_real_post_id( $post_id );
1053 2
        $thumbnail_id = get_post_thumbnail_id( $post_id );
1054 2
        $all_images   = array();
1055
1056 2
        if ( ! empty( $thumbnail_id ) ) {
1057
            $featured_image         = array(
1058 2
                'thumb'         => wp_get_attachment_thumb_url( $thumbnail_id ),
1059 2
                'full'          => wp_get_attachment_url( $thumbnail_id ),
1060 2
                'attachment_id' => $thumbnail_id,
1061
            );
1062
1063 2
            $all_images[] = $featured_image;
1064
        }
1065
1066 2
        return array_merge( $all_images, $this->get_featured_images( $post_id ) );
1067
    }
1068
1069
    /**
1070
     * Load the plugin's textdomain hooked to 'plugins_loaded'.
1071
     *
1072
     * @since 1.0.0
1073
     * @access public
1074
     *
1075
     * @see    load_plugin_textdomain()
1076
     * @see    plugin_basename()
1077
     * @action plugins_loaded
1078
     *
1079
     * @codeCoverageIgnore
1080
     *
1081
     * @return void
1082
     */
1083
    public function load_plugin_textdomain() {
1084
        load_plugin_textdomain(
1085
            self::TEXT_DOMAIN,
1086
            false,
1087
            dirname( plugin_basename( __FILE__ ) ) . '/languages/'
1088
        );
1089
    }
1090
}
1091
1092
// Sponsors who support this plugin.
1093
include 'sponsors.php';
1094
1095
/**
1096
 * Instantiate the main class.
1097
 *
1098
 * @since 1.0.0
1099
 * @access public
1100
 *
1101
 * @var object $dynamic_featured_image holds the instantiated class {@uses Dynamic_Featured_Image}
1102
 */
1103
global $dynamic_featured_image;
1104
$dynamic_featured_image = new Dynamic_Featured_Image();
1105