WP Recipe Maker – Video Instructions

If you have a video specified for your recipe / how-to card, and you have specified video timestamps for each step, this will include an embedded video at each step.

function be_wprm_video_instructions( $atts ) {

	$atts = shortcode_atts(
		[
			'id' => false,
			'header' => 'Instructions',
			'header_tag' => 'h2',
			'group_tag'	=> 'h4',
			'image_position'	=> 'before',
			'image_alignment'	=> 'center',
			'image_size'		=> 'medium',
		],
		$atts
	);

	$recipe = WPRM_Template_Shortcodes::get_recipe( $atts['id'] );
	if ( ! $recipe || ! $recipe->instructions() ) {
		return '';
	}

	$video = $recipe->video();

	// Output.
	$classes = array(
		'wprm-recipe-instructions-container',
	);

	$output = '<div class="' . implode( ' ', $classes ) . '">';

	if ( $atts['header'] ) {
		$classes = array(
			'wprm-recipe-header',
			'wprm-recipe-instructions-header',
		);

		$tag = trim( $atts['header_tag'] );
		$output .= '<' . $tag . ' class="' . implode( ' ', $classes ) . '">' . __( $atts['header'], 'wp-recipe-maker' ) . '</' . $tag . '>';
	}

	$instructions = $recipe->instructions();
	foreach ( $instructions as $group_index => $instruction_group ) {
		$output .= '<div class="wprm-recipe-instruction-group">';

		if ( $instruction_group['name'] ) {
			$classes = array(
				'wprm-recipe-group-name',
				'wprm-recipe-instruction-group-name',
			);

			$tag = trim( $atts['group_tag'] );
			$output .= '<' . $tag . ' class="' . implode( ' ', $classes ) . '">' . $instruction_group['name'] . '</' . $tag . '>';
		}

		$output .= '<ul class="wprm-recipe-instructions">';

		foreach ( $instruction_group['instructions'] as $index => $instruction ) {
			$output .= '<li id="wprm-recipe-' . $recipe->id() . '-step-' . $group_index . '-' . $index . '" class="wprm-recipe-instruction">';

			if( !empty( $video ) && !empty( $instruction['video'] ) ) {
				$step_video = str_replace( '" frameborder="0"', '&start=' . be_video_start( $instruction['video'] ) . '" frameborder="0"', $video );
				$output .= '<div class="wprm-recipe-instructions-video">' . $step_video . '</div>';
			}


			if ( 'before' === $atts['image_position'] && $instruction['image'] ) {
				$output .= '<div class="wprm-recipe-instruction-image" style="text-align: ' . $atts['image_alignment'] . ';">' . be_wprm_instruction_image( $recipe, $instruction, $atts['image_size'] ) . '</div> ';
			}
			if ( $instruction['text'] ) {
				$output .= '<div class="wprm-recipe-instruction-text">' . wpautop( $instruction['text'] ) . '</div> ';
			}
			if ( 'after' === $atts['image_position'] && $instruction['image'] ) {
				$output .= '<div class="wprm-recipe-instruction-image" style="text-align: ' . $atts['image_alignment'] . ';">' . be_wprm_instruction_image( $recipe, $instruction, $atts['image_size'] ) . '</div> ';
			}

			$output .= '</li>';
		}

		$output .= '</ul>';
		$output .= '</div>';
	}

	$output .= '</div>';

	return $output;
}
add_shortcode( 'be_wprm_video_instructions', 'be_wprm_video_instructions' );

/**
 * Output an instruction image.
 *
 * @since	3.3.0
 * @param	mixed $recipe			  Recipe to output the instruction for.
 * @param	mixed $instruction		  Instruction to output the image for.
 * @param	mixed $default_image_size Default image size to use.
 */
function be_wprm_instruction_image( $recipe, $instruction, $default_image_size ) {
	$settings_size = 'legacy' === WPRM_Settings::get( 'recipe_template_mode' ) ? WPRM_Settings::get( 'template_instruction_image' ) : false;
	$size = $settings_size ? $settings_size : $default_image_size;

	preg_match( '/^(\d+)x(\d+)$/i', $size, $match );
	if ( ! empty( $match ) ) {
		$size = array( intval( $match[1] ), intval( $match[2] ) );
	}

	$img = wp_get_attachment_image( $instruction['image'], $size );

	// Prevent instruction image from getting stretched in Gutenberg preview.
	if ( isset( $GLOBALS['wp']->query_vars['rest_route'] ) && '/wp/v2/block-renderer/wp-recipe-maker/recipe' === $GLOBALS['wp']->query_vars['rest_route'] ) {
		$image_data = wp_get_attachment_image_src( $instruction['image'], $size );
		if ( $image_data[1] ) {
			$style = 'max-width: ' . $image_data[1] . 'px;';

			if ( false !== stripos( $img, ' style="' ) ) {
				$img = str_ireplace( ' style="', ' style="' . $style, $img );
			} else {
				$img = str_ireplace( '<img ', '<img style="' . $style . '" ', $img );
			}
		}
	}

	// Disable instruction image pinning.
	if ( WPRM_Settings::get( 'pinterest_nopin_instruction_image' ) ) {
		$img = str_ireplace( '<img ', '<img data-pin-nopin="true" ', $img );
	}

	// Clickable images.
	if ( WPRM_Settings::get( 'instruction_image_clickable' ) ) {
		$settings_size = WPRM_Settings::get( 'clickable_image_size' );

		preg_match( '/^(\d+)x(\d+)$/i', $settings_size, $match );
		if ( ! empty( $match ) ) {
			$size = array( intval( $match[1] ), intval( $match[2] ) );
		} else {
			$size = $settings_size;
		}

		$clickable_image = wp_get_attachment_image_src( $instruction['image'], $size );
		$clickable_image_url = $clickable_image && isset( $clickable_image[0] ) ? $clickable_image[0] : '';
		if ( $clickable_image_url ) {
			$img = '<a href="' . esc_url( $clickable_image_url ) . '">' . $img . '</a>';
		}
	}

	return $img;
}

function be_video_start( $video ) {
	if( empty( $video['start'] ) )
		return 0;

	$parts = array_reverse( explode( ':', $video['start'] ) );
	$seconds = $parts[0];
	if( !empty( $parts[1] ) )
		$seconds += $parts[1] * 60;
	if( !empty( $parts[2] ) )
		$seconds += $parts[2] * HOUR_IN_SECONDS;

	return $seconds;
}
Bill Erickson

Bill Erickson is a freelance WordPress developer and a contributing developer to the Genesis framework. For the past 14 years he has worked with attorneys, publishers, corporations, and non-profits, building custom websites tailored to their needs and goals.

Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk