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