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