Completed
Pull Request — master (#51)
by
unknown
04:33
created

dynamic-featured-image.php (4 issues)

Upgrade to new PHP Analysis Engine

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

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 45 and the first side effect is on line 33.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/***
3
 * Plugin Name: Dynamic Featured Image
4
 * Plugin URI: http://wordpress.org/plugins/dynamic-featured-image/
5
 * Description: Dynamically adds multiple featured image or post thumbnail functionality to your posts, pages and custom post types.
6
 * Version: 3.5.2
7
 * Author: Ankit Pokhrel
8
 * Author URI: http://ankitpokhrel.com.np
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
 * Copyright (C) 2013 Ankit Pokhrel <[email protected], http://ankitpokhrel.com.np>,
16
 *
17
 * This program is free software; you can redistribute it and/or modify
18
 * it under the terms of the GNU General Public License as published by
19
 * the Free Software Foundation; either version 3 of the License, or
20
 * (at your option) any later version.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
 * GNU General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU General Public License
28
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
29
 */
30
31
// Avoid direct calls to this file
32
if ( ! defined( 'ABSPATH' ) ) {
33
	header( 'Status: 403 Forbidden' );
34
	header( 'HTTP/1.1 403 Forbidden' );
35
	exit();
36
}
37
38
/**
39
 * Dynamic Featured Image plugin main class
40
 *
41
 * @package dynamic-featured-image
42
 * @author Ankit Pokhrel <[email protected]>
43
 * @version 3.0.1
44
 */
45
class Dynamic_Featured_Image {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
46
	/**
47
	 * Current version of the plugin.
48
	 *
49
	 * @since 3.0.0
50
	 */
51
	const VERSION = '3.5.2';
52
53
	/* Image upload directory */
54
	private $__upload_dir;
55
56
	/* Image upload URL */
57
	private $__upload_url;
58
59
	/* Database object */
60
	private $__db;
61
62
	/* Plugin text domain */
63
	protected $_textDomain;
64
65
	/* Title for dfi metabox */
66
	protected $_metabox_title;
67
68
	/* Users post type filter for dfi metabox */
69
	protected $_userFilter;
70
71
	/**
72
	 * Constructor. Hooks all interactions to initialize the class.
73
	 *
74
	 * @since 1.0.0
75
	 * @access public
76
	 * @global object $wpdb
77
	 *
78
	 * @see     add_action()
79
	 */
80
	public function __construct() {
81
		$this->_textDomain = 'dynamic-featured-image';
82
83
		//plugin update warning
84
		add_action( 'in_plugin_update_message-' . plugin_basename( __FILE__ ), array( $this, 'update_notice' ) );
85
86
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
87
		add_action( 'add_meta_boxes', array( $this, 'initialize_featured_box' ) );
88
		add_action( 'save_post', array( $this, 'save_meta' ) );
89
		add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );
90
91
		//handle ajax request
92
		add_action( 'wp_ajax_dfiMetaBox_callback', array( $this, 'ajax_callback' ) );
93
94
		//add action links
95
		add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'dfi_action_links' ) );
96
97
		//media uploader custom fields
98
		add_filter( 'attachment_fields_to_edit', array( $this, 'media_attachment_custom_fields' ), 10, 2 );
99
		add_filter( 'attachment_fields_to_save', array( $this, 'media_attachment_custom_fields_save' ), 10, 2 );
100
101
		//get the site protocol
102
		$protocol = $this->__get_protocol();
103
104
		$this->__upload_dir = wp_upload_dir();
105
		$this->__upload_url = preg_replace( '#^https?://#', '', $this->__upload_dir['baseurl'] );
106
107
		//add protocol to the upload url
108
		$this->__upload_url = $protocol . $this->__upload_url;
109
110
		//post type filter added by user
111
		$this->_userFilter = array();
112
113
		global $wpdb;
114
		$this->__db = $wpdb;
115
116
	} // END __construct()
117
118
	/**
119
	 * Return site protocol
120
	 *
121
	 * @since 3.5.1
122
	 * @access public
123
	 *
124
	 * @return string
125
	 */
126
	private function __get_protocol() {
0 ignored issues
show
__get_protocol uses the super-global variable $_SERVER which is generally not recommended.

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

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

// Better
class Router
{
    private $host;

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

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

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

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
127
		return ( ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] != 'off' ) ||
128
		         ( ! empty( $_SERVER['SERVER_PORT'] ) && $_SERVER['SERVER_PORT'] == 443 ) ) ? "https://" : "http://";
129
	}
130
131
	/**
132
	 * Add required admin scripts
133
	 *
134
	 * @since 1.0.0
135
	 * @access public
136
	 *
137
	 * @see  wp_enque_style()
138
	 * @see  wp_register_script()
139
	 * @see  wp_enqueue_script()
140
	 *
141
	 * @return Void
142
	 */
143
	public function enqueue_admin_scripts() {
144
		//enqueue styles
145
		wp_enqueue_style( 'style-dfi', plugins_url( '/css/style-dfi.css', __FILE__ ), array(), self::VERSION );
146
		wp_enqueue_style( 'dashicons', plugins_url( '/css/dashicons.css', __FILE__ ), array(), self::VERSION );
147
148
		//register script
149
		wp_register_script( 'scripts-dfi', plugins_url( '/js/script-dfi.js', __FILE__ ), array( 'jquery' ), self::VERSION );
150
151
		//localize the script with required data
152
		wp_localize_script(
153
			'scripts-dfi',
154
			'WP_SPECIFIC',
155
			array(
156
				'upload_url'               => $this->__upload_url,
157
				'metabox_title'            => __( $this->_metabox_title, $this->_textDomain ),
158
				'mediaSelector_title'      => __( 'Dynamic Featured Image - Media Selector', $this->_textDomain ),
159
				'mediaSelector_buttonText' => __( 'Set Featured Image', $this->_textDomain )
160
			)
161
		);
162
163
		//enqueue scripts
164
		wp_enqueue_script( 'scripts-dfi' );
165
166
	} // END initialize_components()
167
168
	/**
169
	 * Add upgrade link
170
	 *
171
	 * @access public
172
	 * @since  3.5.1
173
	 * @action plugin_action_links
174
	 *
175
	 * @codeCoverageIgnore
176
	 *
177
	 * @param  array $links Action links
178
	 *
179
	 * @return array
180
	 */
181
	public function dfi_action_links( $links ) {
182
		$upgrade_link = array(
183
			'<a href="http://ankitpokhrel.com.np/blog/downloads/dynamic-featured-image-pro/" target="_blank">Upgrade to Premium</a>'
184
		);
185
186
		return array_merge( $links, $upgrade_link );
187
188
	} // END dfi_action_links()
189
190
	/**
191
	 * Add featured meta boxes dynamically
192
	 *
193
	 * @since 1.0.0
194
	 * @access public
195
	 * @global object $post
196
	 *
197
	 * @see  get_post_meta()
198
	 * @see  get_post_types()
199
	 * @see  add_meta_box()
200
	 * @see  add_filter()
201
	 *
202
	 * @return Void
203
	 */
204
	public function initialize_featured_box() {
205
		global $post;
206
207
    if ( is_object( $post ) ) {
208
      //make metabox title dynamic
209
      $this->_metabox_title = apply_filters( 'dfi_set_metabox_title', __( "Featured Image" ) );
210
211
      $featuredData  = get_post_meta( $post->ID, 'dfiFeatured', true );
212
      $totalFeatured = count( $featuredData );
213
214
      $defaultFilter     = array( 'attachment', 'revision', 'nav_menu_item' );
215
      $this->_userFilter = apply_filters( 'dfi_post_type_user_filter', $this->_userFilter );
216
      $filter            = array_merge( $defaultFilter, $this->_userFilter );
217
218
      $postTypes = get_post_types();
219
      $postTypes = array_diff( $postTypes, $filter );
220
221
      $postTypes = apply_filters( 'dfi_post_types', $postTypes );
222
223
      if ( ! empty( $featuredData ) && $totalFeatured >= 1 ) {
224
        $i = 2;
225
        foreach ( $featuredData as $featured ) {
226
          self::_dfi_add_meta_box( $postTypes, $featured, $i );
227
          $i ++;
228
        }
229
      } else {
230
        self::_dfi_add_meta_box( $postTypes );
231
      }
232
    }
233
234
	} // END initialize_featured_box()
235
236
	/**
237
	 * Translates more than one digit number digit by digit.
238
	 *
239
	 * @param  Integer $number Integer to be translated
240
	 *
241
	 * @return String         Translated number
242
	 */
243
	protected function _get_number_translation( $number ) {
244
		if ( $number <= 9 ) {
245
			return __( $number, $this->_textDomain );
246
		} else {
247
			$pieces = str_split( $number, 1 );
248
			$buffer = '';
249
			foreach ( $pieces as $piece ) {
250
				$buffer .= __( $piece, $this->_textDomain );
251
			}
252
253
			return $buffer;
254
		}
255
	}
256
257
	/**
258
	 * adds meta boxes
259
	 *
260
	 * @param  Array $postTypes post types to show featured image box
261
	 * @param  Object $featured callback arguments
262
	 * @param  Integer $i index of the featured image
263
	 *
264
	 * @return Void
265
	 */
266
	private function _dfi_add_meta_box( $postTypes, $featured = null, $i = null ) {
267
		if ( ! is_null( $i ) ) {
268
			foreach ( $postTypes as $type ) {
269
				add_meta_box(
270
					'dfiFeaturedMetaBox-' . $i,
271
					__( $this->_metabox_title, $this->_textDomain ) . " " . self::_get_number_translation( $i ),
272
					array( $this, 'featured_meta_box' ),
273
					$type,
274
					'side',
275
					'low',
276
					array( $featured, $i + 1 )
277
				);
278
				add_filter( "postbox_classes_{$type}_dfiFeaturedMetaBox-" . $i, array( $this, 'add_metabox_classes' ) );
279
			}
280
281
		} else {
282
			foreach ( $postTypes as $type ) {
283
				add_meta_box(
284
					'dfiFeaturedMetaBox',
285
					__( $this->_metabox_title, $this->_textDomain ) . " " . __( 2, $this->_textDomain ),
286
					array( $this, 'featured_meta_box' ),
287
					$type,
288
					'side',
289
					'low',
290
					array( null, null )
291
				);
292
				add_filter( "postbox_classes_{$type}_dfiFeaturedMetaBox", array( $this, 'add_metabox_classes' ) );
293
			}
294
		}
295
296
	}
297
298
	/**
299
	 * Separate thumb and full image url from given URL string
300
	 *
301
	 * @since  3.3.1
302
	 *
303
	 * @param  string $urlString [description]
304
	 * @param  string $state Thumb or full
305
	 *
306
	 * @return string|null
307
	 */
308
	private function _separate( $urlString, $state = 'thumb' ) {
309
		$imagePiece = explode( ',', $urlString );
310
311
		if ( $state == 'thumb' ) {
312
			return isset( $imagePiece[0] ) ? $imagePiece[0] : null;
313
		}
314
315
		return isset( $imagePiece[1] ) ? $imagePiece[1] : null;
316
	}
317
318
	/**
319
	 * Create a nonce field
320
	 *
321
	 * @since  3.5.0
322
	 *
323
	 * @see  wp_nonce_field()
324
	 * @see  plugin_basename()
325
	 *
326
	 * @codeCoverageIgnore
327
	 *
328
	 * @param  string $key Nonce key
329
	 *
330
	 * @return string
331
	 */
332
	protected function _nonce_field( $key ) {
333
		return wp_nonce_field( plugin_basename( __FILE__ ), $key, true, false );
334
	}
335
336
	/**
337
	 * Featured meta box as seen in the admin
338
	 *
339
	 * @since 1.0.0
340
	 * @access public
341
	 *
342
	 * @param  Object $post global post object
343
	 * @param  Array $featured array containing featured image count
344
	 *
345
	 * @return Void
346
	 */
347
	public function featured_meta_box( $post, $featured ) {
348
		$featuredImg = $featured['args'][0];
349
		$featuredId  = is_null( $featured['args'][1] ) ? 2 : -- $featured['args'][1];
350
351
		$featuredImgTrimmed = $featuredImgFull = $featuredImg;
352
		if ( ! is_null( $featuredImg ) ) {
353
			$featuredImgTrimmed = self::_separate( $featuredImg );
354
			$featuredImgFull    = self::_separate( $featuredImg, 'full' );
355
		}
356
357
		try {
358
359
			$thumbnail = $this->get_image_thumb( $this->__upload_url . $featuredImgFull, 'medium' );
360
			if ( is_null( $thumbnail ) ) {
361
362
				//medium sized thumbnail image is missing
363
				throw new Exception( "Medium size image not found", 1 );
364
365
			}
366
367
		} catch ( Exception $e ) {
368
369
			//since medium sized thumbnail image was not found,
370
			//let's set full image url as thumbnail
371
			$thumbnail = $featuredImgFull;
372
373
		}
374
375
		//Add a nonce field
376
		echo $this->_nonce_field( 'dfi_fimageplug-' . $featuredId );
377
		echo self::_get_featured_box( $featuredImgTrimmed, $featuredImg, $featuredId, $thumbnail, $post->ID );
378
379
	} // END featured_meta_box()
380
381
	/**
382
	 * Returns featured box html content
383
	 * @since  3.1.0
384
	 * @access private
385
	 *
386
	 * @param  String $featuredImgTrimmed Medium sized image
387
	 * @param  String $featuredImg Full sized image
388
	 * @param  String $featuredId Attachment Id
389
	 * @param  String $thumbnail Thumb sized image
390
	 *
391
	 * @return String                     Html content
392
	 */
393
	private function _get_featured_box( $featuredImgTrimmed, $featuredImg, $featuredId, $thumbnail, $postId ) {
394
		$hasFeaturedImage = ! empty( $featuredImgTrimmed ) ? 'hasFeaturedImage' : '';
395
		$thumbnail        = ! is_null( $thumbnail ) ? $thumbnail : '';
396
		$dfiEmpty         = is_null( $featuredImgTrimmed ) ? 'dfiImgEmpty' : '';
397
398
		return "<a href='javascript:void(0)' class='dfiFeaturedImage {$hasFeaturedImage}' title='" . __( 'Set Featured Image', $this->_textDomain ) . "' data-post-id='" . $postId . "'><span class='dashicons dashicons-camera'></span></a><br/>
399
			<img src='" . $thumbnail . "' class='dfiImg {$dfiEmpty}'/>
400
			<div class='dfiLinks'>
401
				<a href='javascript:void(0)' data-id='{$featuredId}' data-id-local='" . $this->_get_number_translation( ( $featuredId + 1 ) ) . "' class='dfiAddNew dashicons dashicons-plus' title='" . __( 'Add New', $this->_textDomain ) . "'></a>
402
				<a href='javascript:void(0)' class='dfiRemove dashicons dashicons-minus' title='" . __( 'Remove', $this->_textDomain ) . "'></a>
403
			</div>
404
			<div class='dfiClearFloat'></div>
405
			<input type='hidden' name='dfiFeatured[]' value='{$featuredImg}'  class='dfiImageHolder' />";
406
	}
407
408
	/**
409
	 * Load new featured meta box via ajax
410
	 *
411
	 * @since 1.0.0
412
	 * @access public
413
	 *
414
	 * @return Void
415
	 */
416
	public function ajax_callback() {
417
		$featuredId = isset( $_POST['id'] ) ? (int) strip_tags( trim( $_POST['id'] ) ) : null;
418
419
		if ( is_null( $featuredId ) ) {
420
			return;
421
		}
422
423
		echo $this->_nonce_field( 'dfi_fimageplug-' . $featuredId );
424
		?>
425
		<a href="javascript:void(0)" class="dfiFeaturedImage"
426
		   title="<?php echo __( 'Set Featured Image', $this->_textDomain ) ?>"><span
427
				class="dashicons dashicons-camera"></span></a><br/>
428
		<img src="" class="dfiImg dfiImgEmpty"/>
429
		<div class="dfiLinks">
430
			<a href="javascript:void(0)" data-id="<?php echo $featuredId ?>"
431
			   data-id-local="<?php echo self::_get_number_translation( ( $featuredId + 1 ) ) ?>"
432
			   class="dfiAddNew dashicons dashicons-plus" title="<?php echo __( 'Add New', $this->_textDomain ) ?>"></a>
433
			<a href="javascript:void(0)" class="dfiRemove dashicons dashicons-minus"
434
			   title="<?php echo __( 'Remove', $this->_textDomain ) ?>"></a>
435
		</div>
436
		<div class="dfiClearFloat"></div>
437
		<input type="hidden" name="dfiFeatured[]" value="" class="dfiImageHolder"/>
438
		<?php
439
		wp_die( '' );
440
441
	} // END ajax_callback())
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
442
443
	/**
444
	 * Add custom class 'featured-meta-box' to meta box
445
	 *
446
	 * @since 1.0.0
447
	 * @access public
448
	 *
449
	 * @see  add_metabox_classes
450
	 *
451
	 * @param  $classes classes to add in the meta box
452
	 *
453
	 * @return string
454
	 */
455
	public function add_metabox_classes( $classes ) {
456
		array_push( $classes, 'featured-meta-box' );
457
458
		return $classes;
459
460
	} // END add_metabox_classes()
461
462
	/**
463
	 * Add custom fields in media uploader
464
	 *
465
	 * @since  3.4.0
466
	 *
467
	 * @param $form_fields Array Fields to include in media attachment form
468
	 * @param $post Array Post data
469
	 *
470
	 * @return Array
471
	 */
472
	public function media_attachment_custom_fields( $form_fields, $post ) {
473
		$form_fields['dfi-link-to-image'] = array(
474
			'label' => _( 'Link to Image' ),
475
			'input' => 'text',
476
			'value' => get_post_meta( $post->ID, '_dfi_link_to_image', true )
477
		);
478
479
		return $form_fields;
480
481
	} // END media_attachment_custom_fields()
482
483
	/**
484
	 * Save values of media uploader custom fields
485
	 *
486
	 * @since 3.4.0
487
	 *
488
	 * @param $post Array The post data for database
489
	 * @param $attachment Array Attachment fields from $_POST form
490
	 *
491
	 * @return Array
492
	 */
493
	public function media_attachment_custom_fields_save( $post, $attachment ) {
494
		if ( isset( $attachment['dfi-link-to-image'] ) ) {
495
			update_post_meta( $post['ID'], '_dfi_link_to_image', $attachment['dfi-link-to-image'] );
496
		}
497
498
		return $post;
499
500
	} // END media_attachment_custom_fields_save()
501
502
	/**
503
	 * Update featured images in the database
504
	 *
505
	 * @since 1.0.0
506
	 * @access public
507
	 *
508
	 * @see  plugin_basename()
509
	 * @see  update_post_meta()
510
	 * @see  current_user_can()
511
	 *
512
	 * @param  Integer $post_id current post id
513
	 *
514
	 * @return Void
515
	 */
516
	public function save_meta( $post_id ) {
517
		//Check autosave
518
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
519
			return false;
520
		}
521
522
		if ( $this->_verify_nonces() ) {
523
			//Check permission before saving data
524
			if ( current_user_can( 'edit_posts', $post_id ) && isset( $_POST['dfiFeatured'] ) ) {
525
				update_post_meta( $post_id, 'dfiFeatured', $_POST['dfiFeatured'] );
526
			}
527
		}
528
529
		return false;
530
531
	} // END save_meta()
532
533
	/**
534
	 * Verify metabox nonces
535
	 *
536
	 * @access protected
537
	 * @see  wp_verify_nonce()
538
	 *
539
	 * @return boolean
540
	 */
541
	protected function _verify_nonces() {
542
		$keys = array_keys( $_POST );
543
		foreach ( $keys as $key ) {
544
			if ( preg_match( '/dfi_fimageplug-\d+$/', $key ) ) {
545
				//Verify nonce
546
				if ( ! wp_verify_nonce( $_POST[ $key ], plugin_basename( __FILE__ ) ) ) {
547
					return false;
548
				}
549
			}
550
		}
551
552
		return true;
553
554
	} // END _verify_nonces()
555
556
	/**
557
	 * Add update notice. Displayed in plugin update page.
558
	 *
559
	 * @since 2.0.0
560
	 * @access public
561
	 *
562
	 * @return Void
563
	 */
564
	public function update_notice() {
565
		$info = __( 'ATTENTION! Please read the <a href="https://github.com/ankitpokhrel/Dynamic-Featured-Image/wiki" target="_blank">DOCUMENTATION</a> properly before update.', $this->_textDomain );
566
		echo '<div style="color:red; padding:7px 0;">' . strip_tags( $info, '<a><b><i><span>' ) . '</div>';
567
568
	} // END update_notice()
569
570
	/** Helper functions */
571
572
	private function execute_query( $query ) {
573
		return $this->__db->get_var( $query );
574
	}
575
576
	/**
577
	 * Get attachment id of the image by image url
578
	 *
579
	 * @since 3.1.7
580
	 * @access protected
581
	 * @global object $wpdb
582
	 *
583
	 * @param  String $image_url url of the image
584
	 *
585
	 * @return string
586
	 */
587
	protected function _get_attachment_id( $image_url ) {
588
		return self::execute_query( $this->__db->prepare( "SELECT ID FROM " . $this->__db->posts . " WHERE guid = %s", $image_url ) );
589
590
	} // END _get_attachment_id()
591
592
	/**
593
	 * Get image url of the image by attachment id
594
	 *
595
	 * @since 2.0.0
596
	 * @access public
597
	 *
598
	 * @see  wp_get_attachment_image_src()
599
	 *
600
	 * @param  Integer $attachment_id attachment id of an image
601
	 * @param  String $size size of the image to fetch (thumbnail, medium, full)
602
	 *
603
	 * @return String
604
	 */
605
	public function get_image_url( $attachment_id, $size = 'full' ) {
606
		$image_thumb = wp_get_attachment_image_src( $attachment_id, $size );
607
608
		return empty( $image_thumb ) ? null : $image_thumb[0];
609
610
	} // END get_image_url()
611
612
	/**
613
	 * Get image thumbnail url of specific size by image url
614
	 *
615
	 * @since 2.0.0
616
	 * @access public
617
	 *
618
	 * @see  get_image_id()
619
	 * @see  wp_get_attachment_image_src()
620
	 *
621
	 * @param  String $image_url url of an image
622
	 * @param  String $size size of the image to fetch (thumbnail, medium, full)
623
	 *
624
	 * @return String
625
	 */
626
	public function get_image_thumb( $image_url, $size = 'thumbnail' ) {
627
		$attachment_id = $this->get_image_id( $image_url );
628
		$image_thumb   = wp_get_attachment_image_src( $attachment_id, $size );
629
630
		return empty( $image_thumb ) ? null : $image_thumb[0];
631
632
	} // END get_image_thumb()
633
634
	/**
635
	 * Gets attachment id from given image url
636
	 *
637
	 * @param  String $image_url url of an image
638
	 *
639
	 * @return Integer|Null            attachment id of an image
640
	 *
641
	 * @since  2.0.0
642
	 * @access public
643
	 */
644
	public function get_image_id( $image_url ) {
645
		$attachment_id = $this->_get_attachment_id( $image_url );
646
		if ( is_null( $attachment_id ) ) {
647
			//check if the image is edited image
648
			//and try to get the attachment id
649
			$image_url = str_replace( $this->__upload_url . "/", '', $image_url );
650
			$row       = self::execute_query( $this->__db->prepare( "SELECT post_id FROM " . $this->__db->postmeta . " WHERE meta_value = %s", $image_url ) );
651
			if ( ! is_null( $row ) ) {
652
				$attachment_id = $row;
653
			}
654
		}
655
656
		return $attachment_id;
657
	}
658
659
	/**
660
	 * Get image title
661
	 *
662
	 * @since 2.0.0
663
	 * @access public
664
	 *
665
	 * @param  String $image_url url of an image
666
	 *
667
	 * @return String
668
	 */
669
	public function get_image_title( $image_url ) {
670
		return self::execute_query( $this->__db->prepare( "SELECT post_title FROM " . $this->__db->posts . " WHERE guid = %s", $image_url ) );
671
672
	} // END get_image_title()
673
674
	/**
675
	 * Get image title by id
676
	 *
677
	 * @since 2.0.0
678
	 * @access public
679
	 *
680
	 * @param  Integer $attachment_id attachment id of an image
681
	 *
682
	 * @return String
683
	 */
684
	public function get_image_title_by_id( $attachment_id ) {
685
		return self::execute_query( $this->__db->prepare( "SELECT post_title FROM " . $this->__db->posts . " WHERE ID = %d", $attachment_id ) );
686
687
	} // END get_image_title_by_id()
688
689
	/**
690
	 * Get image caption
691
	 *
692
	 * @since 2.0.0
693
	 * @access public
694
	 *
695
	 * @param  String $image_url url of an image
696
	 *
697
	 * @return String
698
	 */
699
	public function get_image_caption( $image_url ) {
700
		return self::execute_query( $this->__db->prepare( "SELECT post_excerpt FROM " . $this->__db->posts . " WHERE guid = %s", $image_url ) );
701
702
	} // END get_image_caption()
703
704
	/**
705
	 * Get image caption by id
706
	 *
707
	 * @since 2.0.0
708
	 * @access public
709
	 *
710
	 * @param  Integer $attachment_id attachment id of an image
711
	 *
712
	 * @return String
713
	 */
714
	public function get_image_caption_by_id( $attachment_id ) {
715
		return self::execute_query( $this->__db->prepare( "SELECT post_excerpt FROM " . $this->__db->posts . " WHERE ID = %d", $attachment_id ) );
716
717
	} // END get_image_caption_by_id()
718
719
	/**
720
	 * Get image alternate text
721
	 *
722
	 * @since 2.0.0
723
	 * @access public
724
	 *
725
	 * @see  get_post_meta()
726
	 *
727
	 * @param  String $image_url url of an image
728
	 *
729
	 * @return String
730
	 */
731
	public function get_image_alt( $image_url ) {
732
		$attachment = $this->__db->get_col( $this->__db->prepare( "SELECT ID FROM " . $this->__db->posts . " WHERE guid = %s", $image_url ) );
733
734
		$alt = null;
735
		if ( ! empty( $attachment ) ) {
736
			$alt = get_post_meta( $attachment[0], '_wp_attachment_image_alt' );
737
		}
738
739
		return ( is_null( $alt ) || empty( $alt ) ) ? null : $alt[0];
740
741
	} // END get_image_alt()
742
743
	/**
744
	 * Get image alternate text by attachment id
745
	 *
746
	 * @since 2.0.0
747
	 * @access public
748
	 *
749
	 * @see  get_post_meta()
750
	 *
751
	 * @param  Integer $attachment_id attachment id of an image
752
	 *
753
	 * @return String
754
	 */
755
	public function get_image_alt_by_id( $attachment_id ) {
756
		$alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt' );
757
758
		return empty( $alt ) ? null : $alt[0];
759
760
	} // END get_image_alt_by_id()
761
762
	/**
763
	 * Get image description
764
	 *
765
	 * @since 3.0.0
766
	 * @access public
767
	 *
768
	 * @param  String $image_url url of an image
769
	 *
770
	 * @return String
771
	 */
772
	public function get_image_description( $image_url ) {
773
		return self::execute_query( $this->__db->prepare( "SELECT post_content FROM " . $this->__db->posts . " WHERE guid = %s", $image_url ) );
774
775
	} // END get_image_description()
776
777
	/**
778
	 * Get image description by id
779
	 *
780
	 * @since 3.0.0
781
	 * @access public
782
	 *
783
	 * @param  Integer $attachment_id attachment id of an image
784
	 *
785
	 * @return String
786
	 */
787
	public function get_image_description_by_id( $attachment_id ) {
788
		return self::execute_query( $this->__db->prepare( "SELECT post_content FROM " . $this->__db->posts . " WHERE ID = %d", $attachment_id ) );
789
790
	} // END get_image_description_by_id()
791
792
	/**
793
	 * Get link to image
794
	 *
795
	 * @since 3.4.0
796
	 * @access public
797
	 *
798
	 * @param  Integer $attachment_id attachment id of an image
799
	 *
800
	 * @return string|null
801
	 */
802
	public function get_link_to_image( $attachment_id ) {
803
		return get_post_meta( $attachment_id, '_dfi_link_to_image', true );
804
805
	} // END get_link_to_image()
806
807
	/**
808
	 * Get all attachment ids of the post
809
	 *
810
	 * @since 2.0.0
811
	 * @access public
812
	 *
813
	 * @see  get_post_meta()
814
	 *
815
	 * @param  Integer $post_id id of the current post
816
	 *
817
	 * @return Array
818
	 */
819
	public function get_post_attachment_ids( $post_id ) {
820
		$dfiImages = get_post_meta( $post_id, 'dfiFeatured', true );
821
822
		$retVal = array();
823
		if ( ! empty( $dfiImages ) && is_array( $dfiImages ) ) {
824
			foreach ( $dfiImages as $dfiImage ) {
825
				$dfiImageFull = self::_separate( $dfiImage, 'full' );
826
				$retVal[]     = $this->get_image_id( $this->__upload_url . $dfiImageFull );
827
			}
828
		}
829
830
		return $retVal;
831
832
	} // END get_post_attachment_ids()
833
834
	/**
835
	 * Fetches featured image data of nth position
836
	 *
837
	 * @since  3.0.0
838
	 * @access  public
839
	 *
840
	 * @see  get_featured_images()
841
	 *
842
	 * @param  Integer $position position of the featured image
843
	 * @param  Integer $post_id id of the current post
844
	 *
845
	 * @return Array if found, null otherwise
846
	 */
847
	public function get_nth_featured_image( $position, $post_id = null ) {
848
		if ( is_null( $post_id ) ) {
849
			global $post;
850
			$post_id = $post->ID;
851
		}
852
853
		$featured_images = $this->get_featured_images( $post_id );
854
855
		return isset( $featured_images[ $position - 2 ] ) ? $featured_images[ $position - 2 ] : null;
856
857
	} // END get_nth_featured_image()
858
859
	/**
860
	 * Check if the image is attached with the particular post
861
	 *
862
	 * @since 2.0.0
863
	 * @access public
864
	 *
865
	 * @see  get_post_attachment_ids()
866
	 *
867
	 * @param  $attachment_id attachment id of an image
868
	 * @param  $post_id id of the current post
869
	 *
870
	 * @return boolean
871
	 */
872
	public function is_attached( $attachment_id, $post_id ) {
873
		if ( empty( $attachment_id ) ) {
874
			return false;
875
		}
876
877
		$attachment_ids = $this->get_post_attachment_ids( $post_id );
878
879
		return in_array( $attachment_id, $attachment_ids ) ? true : false;
880
881
	} // END is_attached()
882
883
	/**
884
	 * Retrieve featured images for specific post(s)
885
	 *
886
	 * @since 2.0.0
887
	 * @access public
888
	 *
889
	 * @see  get_post_meta()
890
	 *
891
	 * @param  Integer $post_id id of the current post
892
	 *
893
	 * @return Array
894
	 */
895
	public function get_featured_images( $post_id = null ) {
896
		if ( is_null( $post_id ) ) {
897
			global $post;
898
			$post_id = $post->ID;
899
		}
900
901
		$dfiImages = get_post_meta( $post_id, 'dfiFeatured', true );
902
903
		$retImages = array();
904
		if ( ! empty( $dfiImages ) && is_array( $dfiImages ) ) {
905
			$dfiImages = array_filter( $dfiImages );
906
907
			$count = 0;
908
			foreach ( $dfiImages as $dfiImage ) {
909
				$dfiImageTrimmed = self::_separate( $dfiImage );
910
				$dfiImageFull    = self::_separate( $dfiImage, 'full' );
911
912
				try {
913
914
					$retImages[ $count ]['thumb']         = $this->_get_real_upload_path( $dfiImageTrimmed );
915
					$retImages[ $count ]['full']          = $this->_get_real_upload_path( $dfiImageFull );
916
					$retImages[ $count ]['attachment_id'] = $this->get_image_id( $retImages[ $count ]['full'] );
917
918
				} catch ( Exception $e ) { /* Ignore the exception and continue with other featured images */
919
				}
920
921
				$count ++;
922
			}
923
		}
924
925
		return $retImages;
926
927
	} // END get_featured_images()
928
929
	/**
930
	 * Check to see if the upload url is already available in path.
931
	 *
932
	 * @since  3.1.14
933
	 * @access protected
934
	 *
935
	 * @param  string $img
936
	 *
937
	 * @return string
938
	 */
939
	protected function _get_real_upload_path( $img ) {
940
		//check if upload path is already attached
941
		if ( strpos( $img, $this->__upload_url ) !== false || preg_match('/https?:\/\//', $img) ) {
942
			return $img;
943
		}
944
945
		return $this->__upload_url . $img;
946
	} // END _get_real_upload_path()
947
948
	/**
949
	 * Retrieve featured images for specific post(s) including the default Featured Image
950
	 *
951
	 * @since 3.1.7
952
	 * @access public
953
	 *
954
	 * @see  $this->get_featured_images()
955
	 *
956
	 * @param Integer $post_id id of the current post
957
	 *
958
	 * @return Array An array of images or an empty array on failure
959
	 */
960
	public function get_all_featured_images( $post_id = null ) {
961
		if ( is_null( $post_id ) ) {
962
			global $post;
963
			$post_id = $post->ID;
964
		}
965
966
		$thumbnail_id = get_post_thumbnail_id( $post_id );
967
968
		$featured_image_array = array();
969
		if ( ! empty( $thumbnail_id ) ) {
970
			$featured_image         = array(
971
				'thumb'         => wp_get_attachment_thumb_url( $thumbnail_id ),
972
				'full'          => wp_get_attachment_url( $thumbnail_id ),
973
				'attachment_id' => $thumbnail_id
974
			);
975
			$featured_image_array[] = $featured_image;
976
		}
977
978
		$dfiImages = $this->get_featured_images( $post_id );
979
980
		$all_featured_images = array_merge( $featured_image_array, $dfiImages );
981
982
		return $all_featured_images;
983
984
	}
985
986
	/**
987
	 * Load the plugin's textdomain hooked to 'plugins_loaded'.
988
	 *
989
	 * @since 1.0.0
990
	 * @access public
991
	 *
992
	 * @see    load_plugin_textdomain()
993
	 * @see    plugin_basename()
994
	 * @action    plugins_loaded
995
	 *
996
	 * @codeCoverageIgnore
997
	 *
998
	 * @return    void
999
	 */
1000
	public function load_plugin_textdomain() {
1001
		load_plugin_textdomain(
1002
			$this->_textDomain,
1003
			false,
1004
			dirname( plugin_basename( __FILE__ ) ) . '/languages/'
1005
		);
1006
1007
	} // END load_plugin_textdomain()
1008
1009
} // END class Dynamic_Featured_Image
1010
1011
1012
/**
1013
 * Instantiate the main class
1014
 *
1015
 * @since 1.0.0
1016
 * @access public
1017
 *
1018
 * @var    object $dynamic_featured_image holds the instantiated class {@uses Dynamic_Featured_Image}
1019
 */
1020
global $dynamic_featured_image;
1021
$dynamic_featured_image = new Dynamic_Featured_Image();
1022