Completed
Pull Request — master (#86)
by
unknown
02:49
created

Dynamic_Featured_Image::initialize_featured_box()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

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