Completed
Push — branch-3.8 ( 6dae2a...5ea8e7 )
by
unknown
57:29 queued 49:08
created

Jetpack_Portfolio::get_project_author()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 11
rs 9.4286
cc 1
eloc 7
nc 1
nop 0
1
<?php
2
3
class Jetpack_Portfolio {
4
	const CUSTOM_POST_TYPE       = 'jetpack-portfolio';
5
	const CUSTOM_TAXONOMY_TYPE   = 'jetpack-portfolio-type';
6
	const CUSTOM_TAXONOMY_TAG    = 'jetpack-portfolio-tag';
7
	const OPTION_NAME            = 'jetpack_portfolio';
8
	const OPTION_READING_SETTING = 'jetpack_portfolio_posts_per_page';
9
10
	public $version = '0.1';
11
12
	static function init() {
13
		static $instance = false;
14
15
		if ( ! $instance ) {
16
			$instance = new Jetpack_Portfolio;
17
		}
18
19
		return $instance;
20
	}
21
22
	/**
23
	 * Conditionally hook into WordPress.
24
	 *
25
	 * Setup user option for enabling CPT
26
	 * If user has CPT enabled, show in admin
27
	 */
28
	function __construct() {
29
		// Add an option to enable the CPT
30
		add_action( 'admin_init',                                                      array( $this, 'settings_api_init' ) );
31
32
		// Check on theme switch if theme supports CPT and setting is disabled
33
		add_action( 'after_switch_theme',                                              array( $this, 'activation_post_type_support' ) );
34
35
		// Make sure the post types are loaded for imports
36
		add_action( 'import_start',                                                    array( $this, 'register_post_types' ) );
37
38
		$setting = get_option( self::OPTION_NAME, '0' );
39
40
		// Bail early if Portfolio option is not set and the theme doesn't declare support
41
		if ( empty( $setting ) && ! $this->site_supports_custom_post_type() ) {
42
			return;
43
		}
44
45
		// Enable Omnisearch for Portfolio Items.
46
		if ( class_exists( 'Jetpack_Omnisearch_Posts' ) )
47
			new Jetpack_Omnisearch_Posts( self::CUSTOM_POST_TYPE );
48
49
		// CPT magic
50
		$this->register_post_types();
51
		add_action( sprintf( 'add_option_%s', self::OPTION_NAME ),                     array( $this, 'flush_rules_on_enable' ), 10 );
52
		add_action( sprintf( 'update_option_%s', self::OPTION_NAME ),                  array( $this, 'flush_rules_on_enable' ), 10 );
53
		add_action( sprintf( 'publish_%s', self::CUSTOM_POST_TYPE),                    array( $this, 'flush_rules_on_first_project' ) );
54
		add_action( 'after_switch_theme',                                              array( $this, 'flush_rules_on_switch' ) );
55
56
		// Admin Customization
57
		add_filter( 'post_updated_messages',                                           array( $this, 'updated_messages'   ) );
58
		add_filter( sprintf( 'manage_%s_posts_columns', self::CUSTOM_POST_TYPE),       array( $this, 'edit_admin_columns' ) );
59
		add_filter( sprintf( 'manage_%s_posts_custom_column', self::CUSTOM_POST_TYPE), array( $this, 'image_column'       ), 10, 2 );
60
61
		add_image_size( 'jetpack-portfolio-admin-thumb', 50, 50, true );
62
		add_action( 'admin_enqueue_scripts',                                           array( $this, 'enqueue_admin_styles'  ) );
63
64
		// register jetpack_portfolio shortcode and portfolio shortcode (legacy)
65
		add_shortcode( 'portfolio',                                                    array( $this, 'portfolio_shortcode' ) );
66
		add_shortcode( 'jetpack_portfolio',                                            array( $this, 'portfolio_shortcode' ) );
67
68
		// Adjust CPT archive and custom taxonomies to obey CPT reading setting
69
		add_filter( 'pre_get_posts',                                                   array( $this, 'query_reading_setting' ) );
70
71
		// If CPT was enabled programatically and no CPT items exist when user switches away, disable
72
		if ( $setting && $this->site_supports_custom_post_type() ) {
73
			add_action( 'switch_theme',                                                array( $this, 'deactivation_post_type_support' ) );
74
		}
75
	}
76
77
	/**
78
	 * Add a checkbox field in 'Settings' > 'Writing'
79
	 * for enabling CPT functionality.
80
	 *
81
	 * @return null
82
	 */
83
	function settings_api_init() {
84
		add_settings_field(
85
			self::OPTION_NAME,
86
			'<span class="cpt-options">' . __( 'Portfolio Projects', 'jetpack' ) . '</span>',
87
			array( $this, 'setting_html' ),
88
			'writing',
89
			'jetpack_cpt_section'
90
		);
91
		register_setting(
92
			'writing',
93
			self::OPTION_NAME,
94
			'intval'
95
		);
96
97
		// Check if CPT is enabled first so that intval doesn't get set to NULL on re-registering
98
		if ( get_option( self::OPTION_NAME, '0' ) || current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
99
			register_setting(
100
				'writing',
101
				self::OPTION_READING_SETTING,
102
				'intval'
103
			);
104
		}
105
	}
106
107
	/**
108
	 * HTML code to display a checkbox true/false option
109
	 * for the Portfolio CPT setting.
110
	 *
111
	 * @return html
112
	 */
113
	function setting_html() {
114 View Code Duplication
		if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) : ?>
115
			<p><?php printf( __( 'Your theme supports <strong>%s</strong>', 'jetpack' ), self::CUSTOM_POST_TYPE ); ?></p>
116
		<?php else : ?>
117
			<label for="<?php echo esc_attr( self::OPTION_NAME ); ?>">
118
				<input name="<?php echo esc_attr( self::OPTION_NAME ); ?>" id="<?php echo esc_attr( self::OPTION_NAME ); ?>" <?php echo checked( get_option( self::OPTION_NAME, '0' ), true, false ); ?> type="checkbox" value="1" />
119
				<?php esc_html_e( 'Enable Portfolio Projects for this site.', 'jetpack' ); ?>
120
				<a target="_blank" href="http://en.support.wordpress.com/portfolios/"><?php esc_html_e( 'Learn More', 'jetpack' ); ?></a>
121
			</label>
122
		<?php endif;
123
		if ( get_option( self::OPTION_NAME, '0' ) || current_theme_supports( self::CUSTOM_POST_TYPE ) ) :
124
			printf( '<p><label for="%1$s">%2$s</label></p>',
125
				esc_attr( self::OPTION_READING_SETTING ),
126
				sprintf( __( 'Portfolio pages display at most %1$s projects', 'jetpack' ),
127
					sprintf( '<input name="%1$s" id="%1$s" type="number" step="1" min="1" value="%2$s" class="small-text" />',
128
						esc_attr( self::OPTION_READING_SETTING ),
129
						esc_attr( get_option( self::OPTION_READING_SETTING, '10' ) )
130
					)
131
				)
132
			);
133
		endif;
134
	}
135
136
	/**
137
	* Should this Custom Post Type be made available?
138
	*/
139 View Code Duplication
	function site_supports_custom_post_type() {
140
		// If the current theme requests it.
141
		if ( current_theme_supports( self::CUSTOM_POST_TYPE ) || get_option( self::OPTION_NAME, '0' ) ) {
142
			return true;
143
		}
144
145
		// Otherwise, say no unless something wants to filter us to say yes.
146
		/** This action is documented in modules/custom-post-types/nova.php */
147
		return (bool) apply_filters( 'jetpack_enable_cpt', false, self::CUSTOM_POST_TYPE );
148
	}
149
150
	/*
151
	 * Flush permalinks when CPT option is turned on/off
152
	 */
153
	function flush_rules_on_enable() {
154
		flush_rewrite_rules();
155
	}
156
157
	/*
158
	 * Count published projects and flush permalinks when first projects is published
159
	 */
160 View Code Duplication
	function flush_rules_on_first_project() {
161
		$projects = get_transient( 'jetpack-portfolio-count-cache' );
162
163
		if ( false === $projects ) {
164
			flush_rewrite_rules();
165
			$projects = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
166
167
			if ( ! empty( $projects ) ) {
168
				set_transient( 'jetpack-portfolio-count-cache', $projects, HOUR_IN_SECONDS * 12 );
169
			}
170
		}
171
	}
172
173
	/*
174
	 * Flush permalinks when CPT supported theme is activated
175
	 */
176
	function flush_rules_on_switch() {
177
		if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
178
			flush_rewrite_rules();
179
		}
180
	}
181
182
	/**
183
	 * On plugin/theme activation, check if current theme supports CPT
184
	 */
185
	static function activation_post_type_support() {
186
		if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
187
			update_option( self::OPTION_NAME, '1' );
188
		}
189
	}
190
191
	/**
192
	 * On theme switch, check if CPT item exists and disable if not
193
	 */
194 View Code Duplication
	function deactivation_post_type_support() {
195
		$portfolios = get_posts( array(
196
			'fields'           => 'ids',
197
			'posts_per_page'   => 1,
198
			'post_type'        => self::CUSTOM_POST_TYPE,
199
			'suppress_filters' => false
200
		) );
201
202
		if ( empty( $portfolios ) ) {
203
			update_option( self::OPTION_NAME, '0' );
204
		}
205
	}
206
207
	/**
208
	 * Register Post Type
209
	 */
210
	function register_post_types() {
211
		if ( post_type_exists( self::CUSTOM_POST_TYPE ) ) {
212
			return;
213
		}
214
215
		register_post_type( self::CUSTOM_POST_TYPE, array(
216
			'description' => __( 'Portfolio Items', 'jetpack' ),
217
			'labels' => array(
218
				'name'                  => esc_html__( 'Projects',                   'jetpack' ),
219
				'singular_name'         => esc_html__( 'Project',                    'jetpack' ),
220
				'menu_name'             => esc_html__( 'Portfolio',                  'jetpack' ),
221
				'all_items'             => esc_html__( 'All Projects',               'jetpack' ),
222
				'add_new'               => esc_html__( 'Add New',                    'jetpack' ),
223
				'add_new_item'          => esc_html__( 'Add New Project',            'jetpack' ),
224
				'edit_item'             => esc_html__( 'Edit Project',               'jetpack' ),
225
				'new_item'              => esc_html__( 'New Project',                'jetpack' ),
226
				'view_item'             => esc_html__( 'View Project',               'jetpack' ),
227
				'search_items'          => esc_html__( 'Search Projects',            'jetpack' ),
228
				'not_found'             => esc_html__( 'No Projects found',          'jetpack' ),
229
				'not_found_in_trash'    => esc_html__( 'No Projects found in Trash', 'jetpack' ),
230
				'filter_items_list'     => esc_html__( 'Filter projects list',       'jetpack' ),
231
				'items_list_navigation' => esc_html__( 'Project list navigation',    'jetpack' ),
232
				'items_list'            => esc_html__( 'Projects list',              'jetpack' ),
233
			),
234
			'supports' => array(
235
				'title',
236
				'editor',
237
				'thumbnail',
238
				'author',
239
				'comments',
240
				'publicize',
241
				'wpcom-markdown',
242
			),
243
			'rewrite' => array(
244
				'slug'       => 'portfolio',
245
				'with_front' => false,
246
				'feeds'      => true,
247
				'pages'      => true,
248
			),
249
			'public'          => true,
250
			'show_ui'         => true,
251
			'menu_position'   => 20,                    // below Pages
252
			'menu_icon'       => 'dashicons-portfolio', // 3.8+ dashicon option
253
			'capability_type' => 'page',
254
			'map_meta_cap'    => true,
255
			'taxonomies'      => array( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_TAXONOMY_TAG ),
256
			'has_archive'     => true,
257
			'query_var'       => 'portfolio',
258
		) );
259
260
		register_taxonomy( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_POST_TYPE, array(
261
			'hierarchical'      => true,
262
			'labels'            => array(
263
				'name'                  => esc_html__( 'Project Types',                 'jetpack' ),
264
				'singular_name'         => esc_html__( 'Project Type',                  'jetpack' ),
265
				'menu_name'             => esc_html__( 'Project Types',                 'jetpack' ),
266
				'all_items'             => esc_html__( 'All Project Types',             'jetpack' ),
267
				'edit_item'             => esc_html__( 'Edit Project Type',             'jetpack' ),
268
				'view_item'             => esc_html__( 'View Project Type',             'jetpack' ),
269
				'update_item'           => esc_html__( 'Update Project Type',           'jetpack' ),
270
				'add_new_item'          => esc_html__( 'Add New Project Type',          'jetpack' ),
271
				'new_item_name'         => esc_html__( 'New Project Type Name',         'jetpack' ),
272
				'parent_item'           => esc_html__( 'Parent Project Type',           'jetpack' ),
273
				'parent_item_colon'     => esc_html__( 'Parent Project Type:',          'jetpack' ),
274
				'search_items'          => esc_html__( 'Search Project Types',          'jetpack' ),
275
				'items_list_navigation' => esc_html__( 'Project type list navigation',  'jetpack' ),
276
				'items_list'            => esc_html__( 'Project type list',             'jetpack' ),
277
			),
278
			'public'            => true,
279
			'show_ui'           => true,
280
			'show_in_nav_menus' => true,
281
			'show_admin_column' => true,
282
			'query_var'         => true,
283
			'rewrite'           => array( 'slug' => 'project-type' ),
284
		) );
285
286
		register_taxonomy( self::CUSTOM_TAXONOMY_TAG, self::CUSTOM_POST_TYPE, array(
287
			'hierarchical'      => false,
288
			'labels'            => array(
289
				'name'                       => esc_html__( 'Project Tags',                   'jetpack' ),
290
				'singular_name'              => esc_html__( 'Project Tag',                    'jetpack' ),
291
				'menu_name'                  => esc_html__( 'Project Tags',                   'jetpack' ),
292
				'all_items'                  => esc_html__( 'All Project Tags',               'jetpack' ),
293
				'edit_item'                  => esc_html__( 'Edit Project Tag',               'jetpack' ),
294
				'view_item'                  => esc_html__( 'View Project Tag',               'jetpack' ),
295
				'update_item'                => esc_html__( 'Update Project Tag',             'jetpack' ),
296
				'add_new_item'               => esc_html__( 'Add New Project Tag',            'jetpack' ),
297
				'new_item_name'              => esc_html__( 'New Project Tag Name',           'jetpack' ),
298
				'search_items'               => esc_html__( 'Search Project Tags',            'jetpack' ),
299
				'popular_items'              => esc_html__( 'Popular Project Tags',           'jetpack' ),
300
				'separate_items_with_commas' => esc_html__( 'Separate tags with commas',      'jetpack' ),
301
				'add_or_remove_items'        => esc_html__( 'Add or remove tags',             'jetpack' ),
302
				'choose_from_most_used'      => esc_html__( 'Choose from the most used tags', 'jetpack' ),
303
				'not_found'                  => esc_html__( 'No tags found.',                 'jetpack' ),
304
				'items_list_navigation'      => esc_html__( 'Project tag list navigation',    'jetpack' ),
305
				'items_list'                 => esc_html__( 'Project tag list',               'jetpack' ),
306
			),
307
			'public'            => true,
308
			'show_ui'           => true,
309
			'show_in_nav_menus' => true,
310
			'show_admin_column' => true,
311
			'query_var'         => true,
312
			'rewrite'           => array( 'slug' => 'project-tag' ),
313
		) );
314
	}
315
316
	/**
317
	 * Update messages for the Portfolio admin.
318
	 */
319 View Code Duplication
	function updated_messages( $messages ) {
320
		global $post;
321
322
		$messages[self::CUSTOM_POST_TYPE] = array(
323
			0  => '', // Unused. Messages start at index 1.
324
			1  => sprintf( __( 'Project updated. <a href="%s">View item</a>', 'jetpack'), esc_url( get_permalink( $post->ID ) ) ),
325
			2  => esc_html__( 'Custom field updated.', 'jetpack' ),
326
			3  => esc_html__( 'Custom field deleted.', 'jetpack' ),
327
			4  => esc_html__( 'Project updated.', 'jetpack' ),
328
			/* translators: %s: date and time of the revision */
329
			5  => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Project restored to revision from %s', 'jetpack'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
330
			6  => sprintf( __( 'Project published. <a href="%s">View project</a>', 'jetpack' ), esc_url( get_permalink( $post->ID ) ) ),
331
			7  => esc_html__( 'Project saved.', 'jetpack' ),
332
			8  => sprintf( __( 'Project submitted. <a target="_blank" href="%s">Preview project</a>', 'jetpack'), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
333
			9  => sprintf( __( 'Project scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview project</a>', 'jetpack' ),
334
			// translators: Publish box date format, see http://php.net/date
335
			date_i18n( __( 'M j, Y @ G:i', 'jetpack' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post->ID ) ) ),
336
			10 => sprintf( __( 'Project item draft updated. <a target="_blank" href="%s">Preview project</a>', 'jetpack' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
337
		);
338
339
		return $messages;
340
	}
341
342
	/**
343
	 * Change ‘Title’ column label
344
	 * Add Featured Image column
345
	 */
346
	function edit_admin_columns( $columns ) {
347
		// change 'Title' to 'Project'
348
		$columns['title'] = __( 'Project', 'jetpack' );
349
		if ( current_theme_supports( 'post-thumbnails' ) ) {
350
			// add featured image before 'Project'
351
			$columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, NULL, true );
352
		}
353
354
		return $columns;
355
	}
356
357
	/**
358
	 * Add featured image to column
359
	 */
360
	function image_column( $column, $post_id ) {
361
		global $post;
362
		switch ( $column ) {
363
			case 'thumbnail':
364
				echo get_the_post_thumbnail( $post_id, 'jetpack-portfolio-admin-thumb' );
365
				break;
366
		}
367
	}
368
369
	/**
370
	 * Adjust image column width
371
	 */
372
	function enqueue_admin_styles( $hook ) {
373
		$screen = get_current_screen();
374
375
		if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
376
			wp_add_inline_style( 'wp-admin', '.manage-column.column-thumbnail { width: 50px; } @media screen and (max-width: 360px) { .column-thumbnail{ display:none; } }' );
377
		}
378
	}
379
380
	/**
381
	 * Follow CPT reading setting on CPT archive and taxonomy pages
382
	 */
383
	function query_reading_setting( $query ) {
384
		if ( ! is_admin() &&
385
			$query->is_main_query() &&
386
			( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
387
		) {
388
			$query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, '10' ) );
389
		}
390
	}
391
392
	/**
393
	 * Our [portfolio] shortcode.
394
	 * Prints Portfolio data styled to look good on *any* theme.
395
	 *
396
	 * @return portfolio_shortcode_html
397
	 */
398
	static function portfolio_shortcode( $atts ) {
399
		// Default attributes
400
		$atts = shortcode_atts( array(
401
			'display_types'   => true,
402
			'display_tags'    => true,
403
			'display_content' => true,
404
			'display_author'  => false,
405
			'show_filter'     => false,
406
			'include_type'    => false,
407
			'include_tag'     => false,
408
			'columns'         => 2,
409
			'showposts'       => -1,
410
			'order'           => 'asc',
411
			'orderby'         => 'date',
412
		), $atts, 'portfolio' );
413
414
		// A little sanitization
415
		if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
416
			$atts['display_types'] = false;
417
		}
418
419
		if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
420
			$atts['display_tags'] = false;
421
		}
422
423
		if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
424
			$atts['display_author'] = false;
425
		}
426
427 View Code Duplication
		if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
428
			$atts['display_content'] = false;
429
		}
430
431
		if ( $atts['include_type'] ) {
432
			$atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
433
		}
434
435
		if ( $atts['include_tag'] ) {
436
			$atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
437
		}
438
439
		$atts['columns'] = absint( $atts['columns'] );
440
441
		$atts['showposts'] = intval( $atts['showposts'] );
442
443
444 View Code Duplication
		if ( $atts['order'] ) {
445
			$atts['order'] = urldecode( $atts['order'] );
446
			$atts['order'] = strtoupper( $atts['order'] );
447
			if ( 'DESC' != $atts['order'] ) {
448
				$atts['order'] = 'ASC';
449
			}
450
		}
451
452 View Code Duplication
		if ( $atts['orderby'] ) {
453
			$atts['orderby'] = urldecode( $atts['orderby'] );
454
			$atts['orderby'] = strtolower( $atts['orderby'] );
455
			$allowed_keys = array( 'author', 'date', 'title', 'rand' );
456
457
			$parsed = array();
458
			foreach ( explode( ',', $atts['orderby'] ) as $portfolio_index_number => $orderby ) {
459
				if ( ! in_array( $orderby, $allowed_keys ) ) {
460
					continue;
461
				}
462
				$parsed[] = $orderby;
463
			}
464
465
			if ( empty( $parsed ) ) {
466
				unset( $atts['orderby'] );
467
			} else {
468
				$atts['orderby'] = implode( ' ', $parsed );
469
			}
470
		}
471
472
		// enqueue shortcode styles when shortcode is used
473
		wp_enqueue_style( 'jetpack-portfolio-style', plugins_url( 'css/portfolio-shortcode.css', __FILE__ ), array(), '20140326' );
474
475
		return self::portfolio_shortcode_html( $atts );
476
	}
477
478
	/**
479
	 * Query to retrieve entries from the Portfolio post_type.
480
	 *
481
	 * @return object
482
	 */
483
	static function portfolio_query( $atts ) {
484
		// Default query arguments
485
		$default = array(
486
			'order'          => $atts['order'],
487
			'orderby'        => $atts['orderby'],
488
			'posts_per_page' => $atts['showposts'],
489
		);
490
491
		$args = wp_parse_args( $atts, $default );
492
		$args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
493
494 View Code Duplication
		if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
495
			$args['tax_query'] = array();
496
		}
497
498
		// If 'include_type' has been set use it on the main query
499 View Code Duplication
		if ( false != $atts['include_type'] ) {
500
			array_push( $args['tax_query'], array(
501
				'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
502
				'field'    => 'slug',
503
				'terms'    => $atts['include_type'],
504
			) );
505
		}
506
507
		// If 'include_tag' has been set use it on the main query
508 View Code Duplication
		if ( false != $atts['include_tag'] ) {
509
			array_push( $args['tax_query'], array(
510
				'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
511
				'field'    => 'slug',
512
				'terms'    => $atts['include_tag'],
513
			) );
514
		}
515
516 View Code Duplication
		if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
517
			$args['tax_query']['relation'] = 'AND';
518
		}
519
520
		// Run the query and return
521
		$query = new WP_Query( $args );
522
		return $query;
523
	}
524
525
	/**
526
	 * The Portfolio shortcode loop.
527
	 *
528
	 * @todo add theme color styles
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
529
	 * @return html
530
	 */
531
	static function portfolio_shortcode_html( $atts ) {
532
533
		$query = self::portfolio_query( $atts );
534
		$portfolio_index_number = 0;
535
536
		ob_start();
537
538
		// If we have posts, create the html
539
		// with hportfolio markup
540
		if ( $query->have_posts() ) {
541
542
			// Render styles
543
			//self::themecolor_styles();
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% 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...
544
545
		?>
546
			<div class="jetpack-portfolio-shortcode column-<?php echo esc_attr( $atts['columns'] ); ?>">
547
			<?php  // open .jetpack-portfolio
548
549
			// Construct the loop...
550
			while ( $query->have_posts() ) {
551
				$query->the_post();
552
				$post_id = get_the_ID();
553
				?>
554
				<div class="portfolio-entry <?php echo esc_attr( self::get_project_class( $portfolio_index_number, $atts['columns'] ) ); ?>">
555
					<header class="portfolio-entry-header">
556
					<?php
557
					// Featured image
558
					echo self::get_portfolio_thumbnail_link( $post_id );
559
					?>
560
561
					<h2 class="portfolio-entry-title"><a href="<?php echo esc_url( get_permalink() ); ?>" title="<?php echo esc_attr( the_title_attribute( ) ); ?>"><?php the_title(); ?></a></h2>
562
563
						<div class="portfolio-entry-meta">
564
						<?php
565
						if ( false != $atts['display_types'] ) {
566
							echo self::get_project_type( $post_id );
567
						}
568
569
						if ( false != $atts['display_tags'] ) {
570
							echo self::get_project_tags( $post_id );
571
						}
572
573
						if ( false != $atts['display_author'] ) {
574
							echo self::get_project_author( $post_id );
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Portfolio::get_project_author() has too many arguments starting with $post_id.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
575
						}
576
						?>
577
						</div>
578
579
					</header>
580
581
				<?php
582
				// The content
583 View Code Duplication
				if ( false !== $atts['display_content'] ) {
584
					if ( 'full' === $atts['display_content'] ) {
585
					?>
586
						<div class="portfolio-entry-content"><?php the_content(); ?></div>
587
					<?php
588
					} else {
589
					?>
590
						<div class="portfolio-entry-content"><?php the_excerpt(); ?></div>
591
					<?php
592
					}
593
				}
594
				?>
595
				</div><!-- close .portfolio-entry -->
596
				<?php $portfolio_index_number++;
597
			} // end of while loop
598
599
			wp_reset_postdata();
600
			?>
601
			</div><!-- close .jetpack-portfolio -->
602
		<?php
603
		} else { ?>
604
			<p><em><?php _e( 'Your Portfolio Archive currently has no entries. You can start creating them on your dashboard.', 'jetpack' ); ?></p></em>
605
		<?php
606
		}
607
		$html = ob_get_clean();
608
609
		// If there is a [portfolio] within a [portfolio], remove the shortcode
610
		if ( has_shortcode( $html, 'portfolio' ) ){
611
			remove_shortcode( 'portfolio' );
612
		}
613
614
		// Return the HTML block
615
		return $html;
616
	}
617
618
	/**
619
	 * Individual project class
620
	 *
621
	 * @return string
622
	 */
623
	static function get_project_class( $portfolio_index_number, $columns ) {
624
		$project_types = wp_get_object_terms( get_the_ID(), self::CUSTOM_TAXONOMY_TYPE, array( 'fields' => 'slugs' ) );
625
		$class = array();
626
627
		$class[] = 'portfolio-entry-column-'.$columns;
628
		// add a type- class for each project type
629
		foreach ( $project_types as $project_type ) {
630
			$class[] = 'type-' . esc_html( $project_type );
631
		}
632
		if( $columns > 1) {
633
			if ( ( $portfolio_index_number % 2 ) == 0 ) {
634
				$class[] = 'portfolio-entry-mobile-first-item-row';
635
			} else {
636
				$class[] = 'portfolio-entry-mobile-last-item-row';
637
			}
638
		}
639
640
		// add first and last classes to first and last items in a row
641
		if ( ( $portfolio_index_number % $columns ) == 0 ) {
642
			$class[] = 'portfolio-entry-first-item-row';
643
		} elseif ( ( $portfolio_index_number % $columns ) == ( $columns - 1 ) ) {
644
			$class[] = 'portfolio-entry-last-item-row';
645
		}
646
647
648
		/**
649
		 * Filter the class applied to project div in the portfolio
650
		 *
651
		 * @module custom-content-types
652
		 *
653
		 * @since 3.1.0
654
		 *
655
		 * @param string $class class name of the div.
656
		 * @param int $portfolio_index_number iterator count the number of columns up starting from 0.
657
		 * @param int $columns number of columns to display the content in.
658
		 *
659
		 */
660
		return apply_filters( 'portfolio-project-post-class', implode( " ", $class ) , $portfolio_index_number, $columns );
661
	}
662
663
	/**
664
	 * Displays the project type that a project belongs to.
665
	 *
666
	 * @return html
667
	 */
668 View Code Duplication
	static function get_project_type( $post_id ) {
669
		$project_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
670
671
		// If no types, return empty string
672
		if ( empty( $project_types ) || is_wp_error( $project_types ) ) {
673
			return;
674
		}
675
676
		$html = '<div class="project-types"><span>' . __( 'Types', 'jetpack' ) . ':</span>';
677
		$types = array();
678
		// Loop thorugh all the types
679
		foreach ( $project_types as $project_type ) {
680
			$project_type_link = get_term_link( $project_type, self::CUSTOM_TAXONOMY_TYPE );
681
682
			if ( is_wp_error( $project_type_link ) ) {
683
				return $project_type_link;
684
			}
685
686
			$types[] = '<a href="' . esc_url( $project_type_link ) . '" rel="tag">' . esc_html( $project_type->name ) . '</a>';
687
		}
688
		$html .= ' '.implode( ', ', $types );
689
		$html .= '</div>';
690
691
		return $html;
692
	}
693
694
	/**
695
	 * Displays the project tags that a project belongs to.
696
	 *
697
	 * @return html
698
	 */
699 View Code Duplication
	static function get_project_tags( $post_id ) {
700
		$project_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
701
702
		// If no tags, return empty string
703
		if ( empty( $project_tags ) || is_wp_error( $project_tags ) ) {
704
			return false;
705
		}
706
707
		$html = '<div class="project-tags"><span>' . __( 'Tags', 'jetpack' ) . ':</span>';
708
		$tags = array();
709
		// Loop thorugh all the tags
710
		foreach ( $project_tags as $project_tag ) {
711
			$project_tag_link = get_term_link( $project_tag, self::CUSTOM_TAXONOMY_TYPE );
712
713
			if ( is_wp_error( $project_tag_link ) ) {
714
				return $project_tag_link;
715
			}
716
717
			$tags[] = '<a href="' . esc_url( $project_tag_link ) . '" rel="tag">' . esc_html( $project_tag->name ) . '</a>';
718
		}
719
		$html .= ' '. implode( ', ', $tags );
720
		$html .= '</div>';
721
722
		return $html;
723
	}
724
725
	/**
726
	 * Displays the author of the current portfolio project.
727
	 *
728
	 * @return html
729
	 */
730
	static function get_project_author() {
731
		$html = '<div class="project-author">';
732
		/* translators: %1$s is link to author posts, %2$s is author display name */
733
		$html .= sprintf( __( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'jetpack' ),
734
			esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
735
			esc_html( get_the_author() )
736
		);
737
		$html .= '</div>';
738
739
		return $html;
740
	}
741
742
	/**
743
	 * Display the featured image if it's available
744
	 *
745
	 * @return html
746
	 */
747 View Code Duplication
	static function get_portfolio_thumbnail_link( $post_id ) {
748
		if ( has_post_thumbnail( $post_id ) ) {
749
			/**
750
			 * Change the Portfolio thumbnail size.
751
			 *
752
			 * @module custom-content-types
753
			 *
754
			 * @since 3.4.0
755
			 *
756
			 * @param string|array $var Either a registered size keyword or size array.
757
			 */
758
			return '<a class="portfolio-featured-image" href="' . esc_url( get_permalink( $post_id ) ) . '">' . get_the_post_thumbnail( $post_id, apply_filters( 'jetpack_portfolio_thumbnail_size', 'large' ) ) . '</a>';
759
		}
760
	}
761
}
762
763
add_action( 'init', array( 'Jetpack_Portfolio', 'init' ) );
764
765
// Check on plugin activation if theme supports CPT
766
register_activation_hook( __FILE__,                         array( 'Jetpack_Portfolio', 'activation_post_type_support' ) );
767
add_action( 'jetpack_activate_module_custom-content-types', array( 'Jetpack_Portfolio', 'activation_post_type_support' ) );
768