Completed
Push — update/recipe-fixes ( b03862...965549 )
by
unknown
06:30
created

Jetpack_Recipes::recipe_nutrition_shortcode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 27

Duplication

Lines 27
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 27
loc 27
rs 9.488
c 0
b 0
f 0
1
<?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3
use Automattic\Jetpack\Assets;
4
5
/**
6
 * Embed recipe 'cards' in post, with basic styling and print functionality
7
 *
8
 * To Do
9
 * - defaults settings
10
 * - basic styles/themecolor styles
11
 * - validation/sanitization
12
 * - print styles
13
 *
14
 * @package Jetpack
15
 */
16
17
/**
18
 * Register and display Recipes in posts.
19
 */
20
class Jetpack_Recipes {
21
22
	/**
23
	 * Have scripts and styles been enqueued already.
24
	 *
25
	 * @var bool
26
	 */
27
	private $scripts_and_style_included = false;
28
29
	/**
30
	 * Constructor
31
	 */
32
	public function __construct() {
33
		add_action( 'init', array( $this, 'action_init' ) );
34
	}
35
36
	/**
37
	 * Returns KSES tags with Schema-specific attributes.
38
	 *
39
	 * @since 8.0.0
40
	 *
41
	 * @return array Array to be used by KSES.
42
	 */
43
	private static function kses_tags() {
44
		$allowedtags = wp_kses_allowed_html( 'post' );
45
		// Create an array of all the tags we'd like to add the itemprop attribute to.
46
		$tags = array( 'li', 'ol', 'ul', 'img', 'p', 'h3', 'time', 'span' );
47
		foreach ( $tags as $tag ) {
48
			if ( ! isset( $allowedtags[ $tag ] ) ) {
49
				$allowedtags[ $tag ] = array();
50
			}
51
			$allowedtags[ $tag ]['class']    = array();
52
			$allowedtags[ $tag ]['itemprop'] = array();
53
			$allowedtags[ $tag ]['datetime'] = array();
54
		}
55
56
		// Allow itemscope and itemtype for divs.
57
		if ( ! isset( $allowedtags['div'] ) ) {
58
			$allowedtags['div'] = array();
59
		}
60
		$allowedtags['div']['class']     = array();
61
		$allowedtags['div']['itemscope'] = array();
62
		$allowedtags['div']['itemtype']  = array();
63
		return $allowedtags;
64
	}
65
66
	/**
67
	 * Register our shortcode and enqueue necessary files.
68
	 */
69
	public function action_init() {
70
		// Enqueue styles if [recipe] exists.
71
		add_action( 'wp_head', array( $this, 'add_scripts' ), 1 );
72
73
		// Render [recipe], along with other shortcodes that can be nested within.
74
		add_shortcode( 'recipe', array( $this, 'recipe_shortcode' ) );
75
		add_shortcode( 'recipe-notes', array( $this, 'recipe_notes_shortcode' ) );
76
		add_shortcode( 'recipe-ingredients', array( $this, 'recipe_ingredients_shortcode' ) );
77
		add_shortcode( 'recipe-directions', array( $this, 'recipe_directions_shortcode' ) );
78
		add_shortcode( 'recipe-nutrition', array( $this, 'recipe_nutrition_shortcode' ) );
79
		add_shortcode( 'recipe-image', array( $this, 'recipe_image_shortcode' ) );
80
	}
81
82
	/**
83
	 * Enqueue scripts and styles
84
	 */
85
	public function add_scripts() {
86
		if ( empty( $GLOBALS['posts'] ) || ! is_array( $GLOBALS['posts'] ) ) {
87
			return;
88
		}
89
90 View Code Duplication
		foreach ( $GLOBALS['posts'] as $p ) {
91
			if ( has_shortcode( $p->post_content, 'recipe' ) ) {
92
				$this->scripts_and_style_included = true;
93
				break;
94
			}
95
		}
96
97
		if ( ! $this->scripts_and_style_included ) {
98
			return;
99
		}
100
101
		wp_enqueue_style( 'jetpack-recipes-style', plugins_url( '/css/recipes.css', __FILE__ ), array(), '20130919' );
102
		wp_style_add_data( 'jetpack-recipes-style', 'rtl', 'replace' );
103
104
		// add $themecolors-defined styles.
105
		wp_add_inline_style( 'jetpack-recipes-style', self::themecolor_styles() );
106
		wp_enqueue_script(
107
			'jetpack-recipes-printthis',
108
			Assets::get_file_url_for_environment( '_inc/build/shortcodes/js/recipes-printthis.min.js', 'modules/shortcodes/js/recipes-printthis.js' ),
109
			array( 'jquery' ),
110
			'20170202',
111
			false
112
		);
113
114
		wp_enqueue_script(
115
			'jetpack-recipes-js',
116
			Assets::get_file_url_for_environment( '_inc/build/shortcodes/js/recipes.min.js', 'modules/shortcodes/js/recipes.js' ),
117
			array( 'jquery', 'jetpack-recipes-printthis' ),
118
			'20131230',
119
			false
120
		);
121
122
		$title_var     = wp_title( '|', false, 'right' );
123
		$rtl           = is_rtl() ? '-rtl' : '';
124
		$print_css_var = plugins_url( "/css/recipes-print{$rtl}.css", __FILE__ );
125
126
		wp_localize_script(
127
			'jetpack-recipes-js',
128
			'jetpack_recipes_vars',
129
			array(
130
				'pageTitle' => $title_var,
131
				'loadCSS'   => $print_css_var,
132
			)
133
		);
134
	}
135
136
	/**
137
	 * Our [recipe] shortcode.
138
	 * Prints recipe data styled to look good on *any* theme.
139
	 *
140
	 * @param array  $atts    Array of shortcode attributes.
141
	 * @param string $content Post content.
142
	 *
143
	 * @return string HTML for recipe shortcode.
144
	 */
145
	public static function recipe_shortcode( $atts, $content = '' ) {
146
		$atts = shortcode_atts(
147
			array(
148
				'title'       => '', // string.
149
				'servings'    => '', // intval.
150
				'time'        => '', // string.
151
				'difficulty'  => '', // string.
152
				'print'       => '', // string.
153
				'source'      => '', // string.
154
				'sourceurl'   => '', // string.
155
				'image'       => '', // string.
156
				'description' => '', // string.
157
				'cooktime'    => '', // string.
158
				'preptime'    => '', // string.
159
				'rating'      => '', // string.
160
			),
161
			$atts,
162
			'recipe'
163
		);
164
165
		return self::recipe_shortcode_html( $atts, $content );
166
	}
167
168
	/**
169
	 * The recipe output
170
	 *
171
	 * @param array  $atts    Array of shortcode attributes.
172
	 * @param string $content Post content.
173
	 *
174
	 * @return string HTML output
175
	 */
176
	private static function recipe_shortcode_html( $atts, $content = '' ) {
177
178
		$html = '<div class="hrecipe h-recipe jetpack-recipe" itemscope itemtype="https://schema.org/Recipe">';
179
180
		// Print the recipe title if exists.
181
		if ( '' !== $atts['title'] ) {
182
			$html .= '<h3 class="p-name jetpack-recipe-title" itemprop="name">' . esc_html( $atts['title'] ) . '</h3>';
183
		}
184
185
		// Print the recipe meta if exists.
186
		if (
187
			'' !== $atts['servings']
188
			|| '' !== $atts['time']
189
			|| '' !== $atts['difficulty']
190
			|| '' !== $atts['print']
191
			|| '' !== $atts['preptime']
192
			|| '' !== $atts['cooktime']
193
			|| '' !== $atts['rating']
194
		) {
195
			$html .= '<ul class="jetpack-recipe-meta">';
196
197 View Code Duplication
			if ( '' !== $atts['servings'] ) {
198
				$html .= sprintf(
199
					'<li class="jetpack-recipe-servings p-yield yield" itemprop="recipeYield"><strong>%1$s: </strong>%2$s</li>',
200
					esc_html_x( 'Servings', 'recipe', 'jetpack' ),
201
					esc_html( $atts['servings'] )
202
				);
203
			}
204
205
			$time_types = array( 'cooktime', 'preptime', 'time' );
206
			foreach ( $time_types as $time_type ) {
207
				if ( '' === $atts[ $time_type ] ) {
208
					continue;
209
				}
210
				$html .= self::output_time( $atts[ $time_type ], $time_type );
211
			}
212
213 View Code Duplication
			if ( '' !== $atts['difficulty'] ) {
214
				$html .= sprintf(
215
					'<li class="jetpack-recipe-difficulty"><strong>%1$s: </strong>%2$s</li>',
216
					esc_html_x( 'Difficulty', 'recipe', 'jetpack' ),
217
					esc_html( $atts['difficulty'] )
218
				);
219
			}
220
221 View Code Duplication
			if ( '' !== $atts['rating'] ) {
222
				$html .= sprintf(
223
					'<li class="jetpack-recipe-rating">
224
						<strong>%1$s: </strong>
225
						<span itemprop="contentRating">%2$s</span>
226
					</li>',
227
					esc_html_x( 'Rating', 'recipe', 'jetpack' ),
228
					esc_html( $atts['rating'] )
229
				);
230
			}
231
232 View Code Duplication
			if ( '' !== $atts['rating'] ) {
233
				$html .= sprintf(
234
					'<li class="jetpack-recipe-rating">
235
						<strong>%1$s: </strong>
236
						<span itemprop="contentRating">%2$s</span>
237
					</li>',
238
					esc_html_x( 'Rating', 'recipe', 'jetpack' ),
239
					esc_html( $atts['rating'] )
240
				);
241
			}
242
243
			if ( '' !== $atts['source'] ) {
244
				$html .= sprintf(
245
					'<li class="jetpack-recipe-source"><strong>%1$s: </strong>',
246
					esc_html_x( 'Source', 'recipe', 'jetpack' )
247
				);
248
249
				if ( '' !== $atts['sourceurl'] ) :
250
					// Show the link if we have one.
251
					$html .= sprintf(
252
						'<a href="%2$s">%1$s</a>',
253
						esc_html( $atts['source'] ),
254
						esc_url( $atts['sourceurl'] )
255
					);
256
				else :
257
					// Skip the link.
258
					$html .= sprintf(
259
						'%1$s',
260
						esc_html( $atts['source'] )
261
					);
262
				endif;
263
264
				$html .= '</li>';
265
			}
266
267
			if ( 'false' !== $atts['print'] ) {
268
				$html .= sprintf(
269
					'<li class="jetpack-recipe-print"><a href="#">%1$s</a></li>',
270
					esc_html_x( 'Print', 'recipe', 'jetpack' )
271
				);
272
			}
273
274
			$html .= '</ul>';
275
		}
276
277
		// Output the image if we have one and it's not shown elsewhere.
278
		if ( '' !== $atts['image'] ) {
279
			if ( ! has_shortcode( $content, 'recipe-image' ) ) {
280
				$html .= self::output_image_html( $atts['image'] );
281
			}
282
		}
283
284
		// Output the description, if we have one.
285
		if ( '' !== $atts['description'] ) {
286
			$html .= sprintf(
287
				'<p class="jetpack-recipe-description" itemprop="description">%1$s</p>',
288
				esc_html( $atts['description'] )
289
			);
290
		}
291
292
		// Print content between codes.
293
		$html .= '<div class="jetpack-recipe-content">' . do_shortcode( $content ) . '</div>';
294
295
		// Close it up.
296
		$html .= '</div>';
297
298
		// If there is a recipe within a recipe, remove the shortcode.
299
		if ( has_shortcode( $html, 'recipe' ) ) {
300
			remove_shortcode( 'recipe' );
301
		}
302
303
		// Sanitize html.
304
		$html = wp_kses( $html, self::kses_tags() );
305
306
		// Return the HTML block.
307
		return $html;
308
	}
309
310
	/**
311
	 * Our [recipe-image] shortcode.
312
	 * Controls placement of image in recipe.
313
	 *
314
	 * @param array $atts Array of shortcode attributes.
315
	 *
316
	 * @return string HTML for recipe notes shortcode.
317
	 */
318
	public static function recipe_image_shortcode( $atts ) {
319
		$atts = shortcode_atts(
320
			array(
321
				'image' => '', // string.
322
				0       => '', // string.
323
			),
324
			$atts,
325
			'recipe-image'
326
		);
327
		$src  = $atts['image'];
328
		if ( ! empty( $atts[0] ) ) {
329
			$src = $atts[0];
330
		}
331
		return self::output_image_html( $src );
332
	}
333
334
	/**
335
	 * Our [recipe-notes] shortcode.
336
	 * Outputs ingredients, styled in a div.
337
	 *
338
	 * @param array  $atts    Array of shortcode attributes.
339
	 * @param string $content Post content.
340
	 *
341
	 * @return string HTML for recipe notes shortcode.
342
	 */
343 View Code Duplication
	public static function recipe_notes_shortcode( $atts, $content = '' ) {
344
		$atts = shortcode_atts(
345
			array(
346
				'title' => '', // string.
347
			),
348
			$atts,
349
			'recipe-notes'
350
		);
351
352
		$html = '';
353
354
		// Print a title if one exists.
355
		if ( '' !== $atts['title'] ) {
356
			$html .= '<h4 class="jetpack-recipe-notes-title">' . esc_html( $atts['title'] ) . '</h4>';
357
		}
358
359
		$html .= '<div class="jetpack-recipe-notes">';
360
361
		// Format content using list functionality, if desired.
362
		$html .= self::output_list_content( $content, 'notes' );
363
364
		$html .= '</div>';
365
366
		// Sanitize html.
367
		$html = wp_kses( $html, self::kses_tags() );
368
369
		// Return the HTML block.
370
		return $html;
371
	}
372
373
	/**
374
	 * Our [recipe-ingredients] shortcode.
375
	 * Outputs notes, styled in a div.
376
	 *
377
	 * @param array  $atts    Array of shortcode attributes.
378
	 * @param string $content Post content.
379
	 *
380
	 * @return string HTML for recipe ingredients shortcode.
381
	 */
382 View Code Duplication
	public static function recipe_ingredients_shortcode( $atts, $content = '' ) {
383
		$atts = shortcode_atts(
384
			array(
385
				'title' => esc_html_x( 'Ingredients', 'recipe', 'jetpack' ), // string.
386
			),
387
			$atts,
388
			'recipe-ingredients'
389
		);
390
391
		$html = '<div class="jetpack-recipe-ingredients">';
392
393
		// Print a title unless the user has opted to exclude it.
394
		if ( 'false' !== $atts['title'] ) {
395
			$html .= '<h4 class="jetpack-recipe-ingredients-title">' . esc_html( $atts['title'] ) . '</h4>';
396
		}
397
398
		// Format content using list functionality.
399
		$html .= self::output_list_content( $content, 'ingredients' );
400
401
		$html .= '</div>';
402
403
		// Sanitize html.
404
		$html = wp_kses( $html, self::kses_tags() );
405
406
		// Return the HTML block.
407
		return $html;
408
	}
409
410
	/**
411
	 * Our [recipe-nutrition] shortcode.
412
	 * Outputs notes, styled in a div.
413
	 *
414
	 * @param array  $atts    Array of shortcode attributes.
415
	 * @param string $content Post content.
416
	 *
417
	 * @return string HTML for recipe nutrition shortcode.
418
	 */
419 View Code Duplication
	public static function recipe_nutrition_shortcode( $atts, $content = '' ) {
420
		$atts = shortcode_atts(
421
			array(
422
				'title' => esc_html_x( 'Nutrition', 'recipe', 'jetpack' ), // string.
423
			),
424
			$atts,
425
			'recipe-nutrition'
426
		);
427
428
		$html = '<div class="jetpack-recipe-nutrition p-nutrition nutrition">';
429
430
		// Print a title unless the user has opted to exclude it.
431
		if ( 'false' !== $atts['title'] ) {
432
			$html .= '<h4 class="jetpack-recipe-nutrition-title">' . esc_html( $atts['title'] ) . '</h4>';
433
		}
434
435
		// Format content using list functionality.
436
		$html .= self::output_list_content( $content, 'nutrition' );
437
438
		$html .= '</div>';
439
440
		// Sanitize html.
441
		$html = wp_kses( $html, self::kses_tags() );
442
443
		// Return the HTML block.
444
		return $html;
445
	}
446
447
	/**
448
	 * Reusable function to check for shortened formatting.
449
	 * Basically, users can create lists with the following shorthand:
450
	 * - item one
451
	 * - item two
452
	 * - item three
453
	 * And we'll magically convert it to a list. This has the added benefit
454
	 * of including itemprops for the recipe schema.
455
	 *
456
	 * @param string $content HTML content.
457
	 * @param string $type    Type of list.
458
	 *
459
	 * @return string content formatted as a list item
460
	 */
461
	private static function output_list_content( $content, $type ) {
462
		$html = '';
463
464
		switch ( $type ) {
465
			case 'directions':
466
				$list_item_replacement = '<li class="jetpack-recipe-directions">${1}</li>';
467
				$itemprop              = ' itemprop="recipeInstructions"';
468
				$listtype              = 'ol';
0 ignored issues
show
Unused Code introduced by
$listtype is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
469
				break;
470
			case 'ingredients':
471
				$list_item_replacement = '<li class="jetpack-recipe-ingredient" itemprop="recipeIngredient">${1}</li>';
472
				$itemprop              = ' itemprop="recipeIngredient" class="p-ingredient ingredient"';
473
				$listtype              = 'ul';
0 ignored issues
show
Unused Code introduced by
$listtype is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
474
				break;
475
			case 'nutrition':
476
				$list_item_replacement = '<li class="jetpack-recipe-nutrition">${1}</li>';
477
				$itemprop              = ' itemprop="nutrition"';
478
				$listtype              = 'ul';
0 ignored issues
show
Unused Code introduced by
$listtype is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
479
				break;
480
			case 'nutrition':
481
				$list_item_replacement = '<li class="jetpack-recipe-nutrition">${1}</li>';
482
				$itemprop              = ' itemprop="nutrition"';
483
				$listtype              = 'ul';
0 ignored issues
show
Unused Code introduced by
$listtype is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
484
				break;
485
			default:
486
				$list_item_replacement = '<li class="jetpack-recipe-notes">${1}</li>';
487
				$itemprop              = '';
488
				$listtype              = 'ul';
0 ignored issues
show
Unused Code introduced by
$listtype is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
489
		}
490
491
		// Check to see if the user is trying to use shortened formatting.
492
		if (
493
			strpos( $content, '&#8211;' ) !== false ||
494
			strpos( $content, '&#8212;' ) !== false ||
495
			strpos( $content, '-' ) !== false ||
496
			strpos( $content, '*' ) !== false ||
497
			strpos( $content, '#' ) !== false ||
498
			strpos( $content, '–' ) !== false || // ndash.
499
			strpos( $content, '—' ) !== false || // mdash.
500
			preg_match( '/\d+\.\s/', $content )
501
		) {
502
			// Remove breaks and extra whitespace.
503
			$content = str_replace( "<br />\n", "\n", $content );
504
			$content = trim( $content );
505
506
			$ul_pattern = '/(?:^|\n|\<p\>)+(?:[\-–—]+|\&#8211;|\&#8212;|\*)+\h+(.*)/mi';
507
			$ol_pattern = '/(?:^|\n|\<p\>)+(?:\d+\.|#+)+\h+(.*)/mi';
508
509
			preg_match_all( $ul_pattern, $content, $ul_matches );
510
			preg_match_all( $ol_pattern, $content, $ol_matches );
511
512
			if ( 0 !== count( $ul_matches[0] ) || 0 !== count( $ol_matches[0] ) ) {
513
514
				if ( 0 !== count( $ol_matches[0] ) ) {
515
					$listtype          = 'ol';
516
					$list_item_pattern = $ol_pattern;
517
				} else {
518
					$listtype          = 'ul';
519
					$list_item_pattern = $ul_pattern;
520
				}
521
				$html .= '<' . $listtype . $itemprop . '>';
522
				$html .= preg_replace( $list_item_pattern, $list_item_replacement, $content );
523
				$html .= '</' . $listtype . '>';
524
525
				// Strip out any empty <p> tags and stray </p> tags, because those are just silly.
526
				$empty_p_pattern = '/(<p>)*\s*<\/p>/mi';
527
				$html            = preg_replace( $empty_p_pattern, '', $html );
528
			} else {
529
				$html .= do_shortcode( $content );
530
			}
531
		} else {
532
			$html .= do_shortcode( $content );
533
		}
534
535
		// Return our formatted content.
536
		return $html;
537
	}
538
539
	/**
540
	 * Our [recipe-directions] shortcode.
541
	 * Outputs directions, styled in a div.
542
	 *
543
	 * @param array  $atts    Array of shortcode attributes.
544
	 * @param string $content Post content.
545
	 *
546
	 * @return string HTML for recipe directions shortcode.
547
	 */
548 View Code Duplication
	public static function recipe_directions_shortcode( $atts, $content = '' ) {
549
		$atts = shortcode_atts(
550
			array(
551
				'title' => esc_html_x( 'Directions', 'recipe', 'jetpack' ), // string.
552
			),
553
			$atts,
554
			'recipe-directions'
555
		);
556
557
		$html = '<div class="jetpack-recipe-directions e-instructions">';
558
559
		// Print a title unless the user has specified to exclude it.
560
		if ( 'false' !== $atts['title'] ) {
561
			$html .= '<h4 class="jetpack-recipe-directions-title">' . esc_html( $atts['title'] ) . '</h4>';
562
		}
563
564
		// Format content using list functionality.
565
		$html .= self::output_list_content( $content, 'directions' );
566
567
		$html .= '</div>';
568
569
		// Sanitize html.
570
		$html = wp_kses( $html, self::kses_tags() );
571
572
		// Return the HTML block.
573
		return $html;
574
	}
575
576
	/**
577
	 * Outputs time meta tag.
578
	 *
579
	 * @param string $time_str  Raw time to output.
580
	 * @param string $time_type Type of time to show.
581
	 *
582
	 * @return string HTML for recipe time meta.
583
	 */
584
	private static function output_time( $time_str, $time_type ) {
585
		// Get a time that's supported by Schema.org.
586
		$duration = WPCOM_JSON_API_Date::format_duration( $time_str );
587
		// If no duration can be calculated, let's output what the user provided.
588
		if ( ! $duration ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $duration of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
589
			$duration = $time_str;
590
		}
591
592
		switch ( $time_type ) {
593
			case 'cooktime':
594
				$title    = _x( 'Cook Time', 'recipe', 'jetpack' );
595
				$itemprop = 'cookTime';
596
				break;
597
			case 'preptime':
598
				$title    = _x( 'Prep Time', 'recipe', 'jetpack' );
599
				$itemprop = 'prepTime';
600
				break;
601
			default:
602
				$title    = _x( 'Time', 'recipe', 'jetpack' );
603
				$itemprop = 'totalTime';
604
				break;
605
		}
606
607
		return sprintf(
608
			'<li class="jetpack-recipe-%3$s">
609
				<time itemprop="%4$s" datetime="%5$s"><strong>%1$s: </strong>%2$s</time>
610
			</li>',
611
			esc_html( $title ),
612
			esc_html( $time_str ),
613
			esc_attr( $time_type ),
614
			esc_attr( $itemprop ),
615
			esc_attr( $duration )
616
		);
617
	}
618
619
	/**
620
	 * Outputs image tag for recipe.
621
	 *
622
	 * @param string $src The image source.
623
	 *
624
	 * @return string
625
	 */
626
	private static function output_image_html( $src ) {
627
		// Exit if there is no provided source.
628
		if ( ! $src ) {
629
			return '';
630
		}
631
632
		// If it's numeric, this may be an attachment.
633
		if ( is_numeric( $src ) ) {
634
			return wp_get_attachment_image(
635
				$src,
636
				'full',
637
				false,
638
				array(
639
					'class'    => 'jetpack-recipe-image u-photo',
640
					'itemprop' => 'image',
641
				)
642
			);
643
		}
644
		return sprintf(
645
			'<img class="jetpack-recipe-image u-photo" itemprop="image" src="%1$s" />',
646
			esc_url( $src )
647
		);
648
	}
649
650
	/**
651
	 * Use $themecolors array to style the Recipes shortcode
652
	 *
653
	 * @print style block
654
	 * @return string $style
655
	 */
656
	public function themecolor_styles() {
657
		global $themecolors;
658
		$style = '';
659
660
		if ( isset( $themecolors ) ) {
661
			$style .= '.jetpack-recipe { border-color: #' . esc_attr( $themecolors['border'] ) . '; }';
662
			$style .= '.jetpack-recipe-title { border-bottom-color: #' . esc_attr( $themecolors['link'] ) . '; }';
663
		}
664
665
		return $style;
666
	}
667
668
}
669
670
new Jetpack_Recipes();
671