ID) ? $post->ID : false; if ($post_id && get_post_type( $post_id ) === 'cp_recipe') { $recipe_settings = Cooked_Recipes::get($post_id, true); } else { // We are in the editor but not on a recipe post type. Maybe a single recipe template? // Uses the first recipe found in the database as a sample. $recipe_settings = Cooked_Recipes::get(false, true, false, 1); } // If still empty and we have a specific recipe ID in attributes, try to get them. if (empty($recipe_settings) && isset($attr['id'])) { $recipe_settings = Cooked_Recipes::get(intval($attr['id']), true); } } return $output; } public function cooked_search_shortcode( $atts, $content = null ) { // Shortcode Attributes $options = shortcode_atts( [ 'compact' => false, 'hide_browse' => false, 'hide_sorting' => false, 'inline_browse' => false, ], $atts ); return Cooked_Recipes::recipe_search_box( $options ); } public function cooked_timer( $atts, $content = null ) { global $cooked_timer_identifier; // Shortcode Attributes $atts = shortcode_atts( [ 'seconds' => 0, 'minutes' => 0, 'length' => 0, // Deprecated, left here for backwards compatibility with 2.x 'hours' => 0, 'desc' => '' ], $atts ); $desc = esc_attr($atts['desc']); $seconds = floatval( $atts['seconds'] ); $minutes_value = floatval( $atts['minutes'] ); $minutes = $minutes_value ? $minutes_value * 60 : floatval( $atts['length'] ) * 60; $hours = floatval( $atts['hours'] ) * 60 * 60; $seconds = $seconds + $minutes + $hours; if (!$cooked_timer_identifier) { $cooked_timer_identifier = 1; } else { $cooked_timer_identifier++; } $timer_id = md5( $seconds . $desc . $content ) . '_' . $cooked_timer_identifier; $desc = $desc ? wp_strip_all_tags( $desc ) : wp_strip_all_tags( $content ); wp_enqueue_script( 'cooked-timer' ); return ' ' . wp_kses_post( $content ) . ''; } public function cooked_browse_shortcode( $sc_atts, $content = null ) { global $_cooked_settings; if ( isset($_cooked_settings['advanced']) && !empty($_cooked_settings['advanced']) && in_array( 'disable_public_recipes', $_cooked_settings['advanced'] ) ) { /* translators: referring to the bottom of the Settings page. */ return current_user_can( 'edit_cooked_settings' ) ? wpautop( sprintf( __('Public recipes are currently disabled. You can change this at the bottom of the %s page.','cooked'), '' . __( 'Settings', 'cooked' ) . '' ) ) : false; } if ( is_admin() ) return false; $author_query_var = sanitize_key( get_query_var( 'recipe_author', false ) ); // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Display-only browse author filter. if ( ! $author_query_var && isset( $_GET['recipe_author'] ) ) { $author_query_var = sanitize_key( wp_unslash( $_GET['recipe_author'] ) ); } // phpcs:enable WordPress.Security.NonceVerification.Recommended // Shortcode Attributes $atts = shortcode_atts( apply_filters( 'cooked_browse_shortcode_default_attributes', [ 'category' => false, 'order' => false, 'orderby' => false, 'show' => false, 'search' => 'true', 'pagination' => 'true', 'columns' => 3, 'layout' => false, 'author' => $author_query_var, 'compact' => false, 'hide_browse' => false, 'hide_sorting' => false, 'exclude' => false, 'inline_browse' => false, 'hide_excerpt' => false, ] ), $sc_atts); return Cooked_Recipes::list_view( $atts ); } public function cooked_recipe_card_shortcode( $atts, $content = null ) { if ( is_admin() ) return false; // Shortcode Attributes $atts = shortcode_atts([ 'id' => false, 'category' => false, 'width' => false, 'style' => false, 'hide_total' => false, 'hide_image' => false, 'hide_title' => false, 'hide_excerpt' => false, 'hide_author' => false ], $atts); $recipe_id = intval( $atts['id'] ); $category_id = intval( $atts['category'] ); $width = Cooked_Functions::sanitize_text_field( $atts['width'] ); $valid_styles = [ 'modern', 'modern-centered' ]; $style = in_array( $atts['style'], $valid_styles, true ) ? $atts['style'] : false; $hide_image = Cooked_Functions::sanitize_text_field( $atts['hide_image'] ); $hide_total = Cooked_Functions::sanitize_text_field( $atts['hide_total'] ); $hide_title = Cooked_Functions::sanitize_text_field( $atts['hide_title'] ); $hide_excerpt = Cooked_Functions::sanitize_text_field( $atts['hide_excerpt'] ); $hide_author = Cooked_Functions::sanitize_text_field( $atts['hide_author'] ); ob_start(); if ( $recipe_id ) { echo wp_kses_post( Cooked_Recipes::card( $recipe_id, $width, $hide_image, $hide_title, $hide_excerpt, $hide_author, $style ) ); } elseif ( $category_id ) { echo wp_kses_post( Cooked_Taxonomies::card( $category_id, $width, $hide_image, $hide_total, $style ) ); } return ob_get_clean(); } public function cooked_categories_shortcode( $atts, $content = null ) { if ( is_admin() ) return false; // Shortcode Attributes $atts = shortcode_atts([ 'hide_empty' => true, 'child_of' => false, 'style' => 'block' ], $atts); $hide_empty = Cooked_Functions::sanitize_text_field( $atts['hide_empty'] ); $child_of = Cooked_Functions::sanitize_text_field( $atts['child_of'] ); $valid_styles = [ 'block', 'list' ]; $style = in_array( $atts['style'], $valid_styles, true ) ? $atts['style'] : 'block'; $parents_only = $child_of ? false : true; ob_start(); $categories_array = Cooked_Settings::terms_array( 'cp_recipe_category', false, false, $hide_empty, $parents_only, $child_of ); if ( !empty($categories_array) ) { echo $style == 'list' ? '
' : '
'; foreach ( $categories_array as $key => $val ) { Cooked_Taxonomies::single_taxonomy_block( $key, $style ); } echo '
'; } return ob_get_clean(); } public function cooked_recipe_list_shortcode( $atts, $content = null ) { if ( is_admin() ) return false; // Shortcode Attributes $atts = shortcode_atts( [ 'orderby' => 'date', 'width' => '100%', 'recipes' => false, 'show' => 5, 'hide_image' => false, 'hide_author' => false ], $atts); $recipes = Cooked_Functions::sanitize_text_field( $atts['recipes'] ); $orderby = Cooked_Functions::sanitize_text_field( $atts['orderby'] ); $show = Cooked_Functions::sanitize_text_field( $atts['show'] ); $width = Cooked_Functions::sanitize_text_field( $atts['width'] ); $hide_image = Cooked_Functions::sanitize_text_field( $atts['hide_image'] ); $hide_author = Cooked_Functions::sanitize_text_field( $atts['hide_author'] ); if ( $recipes ) { $recipes = preg_replace( '/\s+/', '', $recipes ); $recipes = explode( ',', $recipes ); } ob_start(); Cooked_Recipes::recipe_list( $orderby, $show, $recipes, $width, $hide_image, $hide_author ); return ob_get_clean(); } public function cooked_recipe_shortcode( $atts, $content = null ) { if ( is_admin() ) return false; // Shortcode Attributes $atts = shortcode_atts([ 'id' => false, ], $atts); global $recipe_settings, $_cooked_content_unfiltered; $recipe_id = intval( $atts['id'] ); if ( ! $recipe_id ) { return ''; } if ( in_array( $recipe_id, self::$recipe_embed_stack, true ) ) { $output = self::recipe_embed_blocked_message( $recipe_id ); if ( $output ) { $output = '
' . $output . '
'; $output = apply_filters( 'cooked_recipe_shortcode_output', $output, $recipe_id ); } return $output; } $recipe_settings = Cooked_Recipes::get( $recipe_id, true ); if ( ! $recipe_settings || empty( $recipe_settings ) ) { $output = wpautop( '[cooked-recipe id="' . intval( $recipe_id ) . '"]
' . __( '(recipe not found or in draft status)', 'cooked' ) . '' ); if ( $output ) { $output = '
' . $output . '
'; $output = apply_filters( 'cooked_recipe_shortcode_output', $output, $recipe_id ); } return $output; } self::$recipe_embed_stack[] = $recipe_id; try { ob_start(); load_template( COOKED_DIR . 'templates/front/recipe.php', false ); $output = do_shortcode( ob_get_clean() ); if ( $output ) { $output = '
' . $output . '
'; $output = apply_filters( 'cooked_recipe_shortcode_output', $output, $recipe_id ); } return $output; } finally { array_pop( self::$recipe_embed_stack ); } } private static function recipe_embed_blocked_message( $recipe_id ) { $shortcode = '[cooked-recipe id="' . intval( $recipe_id ) . '"]'; $message = '' . sprintf( /* translators: %s: recipe embed shortcode */ __( 'This recipe could not be displayed because it is set up to include itself (containing shortcode %s). Remove the duplicate recipe embed from the Recipe Template.', 'cooked' ), $shortcode ) . ''; $message = apply_filters( 'cooked_recipe_embed_blocked_message', $message, $recipe_id, self::$recipe_embed_stack ); return wpautop( $message ); } public function cooked_gallery_shortcode($atts, $content = null) { global $recipe_settings; if ( isset($recipe_settings['gallery']) && isset($recipe_settings['gallery']['type']) && $recipe_settings['gallery']['type'] == 'cooked' ) { $gallery_options = apply_filters( 'cooked_recipe_gallery_options', [ 'data-fit' => 'cover', 'data-nav' => 'dots', 'data-width' => '100%', 'data-loop' => 'true', 'data-allowfullscreen' => 'true', 'data-ratio' => '800/600', 'data-thumbmargin' => '10', 'data-thumbborderwidth' => '5', 'data-swipe' => 'true', 'data-thumbheight' => '75', 'data-thumbwidth' => '75' ]); // Generate the Shortcode Attributes foreach ( $gallery_options as $opt_name => $opt_value ) { $name_sans_data = str_replace( 'data-', '', $opt_name ); $gallery_atts[$name_sans_data] = $opt_value; } // Set the Shortcode Attributes $atts = shortcode_atts( $gallery_atts, $atts ); // Check for Shortcode Attribute Customizations foreach ( $gallery_options as $opt_name => $opt_value ) { $name_sans_data = str_replace( 'data-', '', $opt_name ); if ( isset($atts[$name_sans_data]) && $atts[$name_sans_data] ) { $gallery_options[$opt_name] = $atts[$name_sans_data]; } } } else { $atts = []; } if ( isset($recipe_settings['gallery']) && isset($recipe_settings['gallery']['type']) ): switch( $recipe_settings['gallery']['type'] ): case 'cooked': if ( isset($recipe_settings['gallery']['items']) && !empty($recipe_settings['gallery']['items']) || isset($recipe_settings['gallery']['video_url']) && $recipe_settings['gallery']['video_url'] ): // Gallery Options // Developers: Filter these to change! // Full list here: http://fotorama.io/customize/options/ $gallery_options_array = []; foreach ( $gallery_options as $data_key => $data_val ): $gallery_options_array[] = $data_key . '="' . $data_val . '"'; endforeach; $gallery_html = ''; return wp_kses_post( $gallery_html ); endif; break; case 'envira': return ( $recipe_settings['gallery']['envira'] ? '' : '' ); break; case 'soliloquy': return ( $recipe_settings['gallery']['soliloquy'] ? '' : '' ); break; case 'revslider': return ( $recipe_settings['gallery']['revslider'] ? '' : '' ); break; endswitch; endif; return false; } public function cooked_info_shortcode($atts, $content = null) { global $recipe, $recipe_settings, $_cooked_settings; if ( !isset($recipe_settings['id']) && isset($recipe->ID) ): $recipe_settings['id'] = $recipe->ID; elseif ( !isset($recipe_settings['id']) ): global $post; $recipe_settings['id'] = $post->ID; endif; // Shortcode Attributes $atts = shortcode_atts([ 'left' => false, 'right' => false, 'include' => false, 'exclude' => false, ], $atts); $left = $atts['left'] ? array_map( 'trim', explode( ',', Cooked_Functions::sanitize_text_field($atts['left']) ) ) : false; $right = $atts['right'] ? array_map( 'trim', explode( ',', Cooked_Functions::sanitize_text_field($atts['right']) ) ) : false; $include = $atts['include'] ? array_map( 'trim', explode( ',', Cooked_Functions::sanitize_text_field($atts['include']) ) ) : false; $exclude = $atts['exclude'] ? array_map( 'trim', explode( ',', Cooked_Functions::sanitize_text_field($atts['exclude']) ) ) : false; $default_info_array = apply_filters( 'cooked_default_info_array', [ 'author' => __('Author', 'cooked'), 'difficulty_level' => __('Difficulty', 'cooked'), 'servings' => __('Yields', 'cooked'), 'prep_time' => __('Prep Time', 'cooked'), 'cook_time' => __('Cook Time', 'cooked'), 'total_time' => __('Total Time', 'cooked'), 'taxonomies' => !empty($_cooked_settings['recipe_taxonomies']) ? $_cooked_settings['recipe_taxonomies'] : [] ]); if ( $left ): // Left Content foreach( $left as $val ): $info_array['left'][$val] = isset( $default_info_array[$val] ) ? $default_info_array[$val] : ''; endforeach; if ( $right ): // Right Content foreach( $right as $val ): $info_array['right'][$val] = isset( $default_info_array[$val] ) ? $default_info_array[$val] : ''; endforeach; endif; elseif ( $right ): // Right Content foreach( $right as $val ): $info_array['right'][$val] = isset( $default_info_array[$val] ) ? $default_info_array[$val] : ''; endforeach; elseif ( $include ): // Include Content (left) foreach( $include as $val ): $info_array[$val] = isset( $default_info_array[$val] ) ? $default_info_array[$val] : ''; endforeach; elseif ( $exclude ): // Exclude Content (left) $info_array = $default_info_array; foreach( $exclude as $val ): unset($info_array[$val]); endforeach; else: $info_array = $default_info_array; endif; ob_start(); if ( !empty( $info_array ) ): $available_methods = apply_filters( 'cooked_available_info_shortcode_methods', [ 'cooked_info_author' => 'Cooked_Recipes', 'cooked_info_difficulty' => 'Cooked_Recipes', 'cooked_info_servings' => 'Cooked_Recipes', 'cooked_info_print' => 'Cooked_Recipes', 'cooked_info_fullscreen' => 'Cooked_Recipes', 'cooked_info_prep_time' => 'Cooked_Recipes', 'cooked_info_cook_time' => 'Cooked_Recipes', 'cooked_info_total_time' => 'Cooked_Recipes', 'cooked_info_taxonomies' => 'Cooked_Recipes' ]); if ( isset($info_array['left']) && !empty($info_array['left']) ): echo '
'; foreach( $info_array['left'] as $name => $val ): $function = 'cooked_info_' . $name; if ( array_key_exists( $function, $available_methods ) ): $class = ( $available_methods[$function] == 'Cooked_Recipes' ? $this : $available_methods[$function] ); if ( method_exists( $class, $function ) ): $class::$function( $recipe_settings ); endif; endif; endforeach; echo '
'; if ( isset($info_array['right']) && !empty($info_array['right']) ): echo '
'; foreach( $info_array['right'] as $name => $val ): $function = 'cooked_info_' . $name; if ( array_key_exists( $function, $available_methods ) ): $class = ( $available_methods[$function] == 'Cooked_Recipes' ? $this : $available_methods[$function] ); if ( method_exists( $class, $function ) ): $class::$function( $recipe_settings ); endif; endif; endforeach; echo '
'; endif; elseif ( isset($info_array['right']) && !empty($info_array['right']) ): echo '
'; foreach ( $info_array['right'] as $name => $val ): $function = 'cooked_info_' . $name; if ( array_key_exists( $function, $available_methods ) ): $class = ( $available_methods[$function] == 'Cooked_Recipes' ? $this : $available_methods[$function] ); if ( method_exists( $class, $function ) ): $class::$function( $recipe_settings ); endif; endif; endforeach; echo '
'; else: foreach ( $info_array as $name => $val ): $function = 'cooked_info_' . $name; if ( array_key_exists( $function, $available_methods ) ): $class = ( $available_methods[$function] == 'Cooked_Recipes' ? $this : $available_methods[$function] ); if ( method_exists( $class, $function ) ): $class::$function( $recipe_settings ); endif; endif; endforeach; endif; endif; $cooked_info_html = ob_get_clean(); if ( $cooked_info_html ): add_filter('wp_kses_allowed_html', [$this, 'cooked_kses_servings_switcher']); add_filter('wp_kses_allowed_html', [$this, 'cooked_kses_cooked_donut']); $cooked_info_html = '
' . wp_kses_post( $cooked_info_html ) . '
'; $cooked_info_html = apply_filters( 'cooked_info_shortcode_output', $cooked_info_html, $recipe_settings ); return $cooked_info_html; //return '
' . $cooked_info_html . '
'; // @TODO: Fix this endif; } function cooked_kses_servings_switcher($tags) { $tags['select'] = [ 'name' => true, 'id' => true, 'class' => true, ]; $tags['option'] = [ 'value' => true, 'selected' => true ]; return $tags; } function cooked_kses_cooked_donut($tags) { $tags['script'] = [ 'type' => true ]; return $tags; } public static function cooked_info_author() { global $recipe_settings, $_cooked_settings; if (in_array('author', $_cooked_settings['recipe_info_display_options'])) { $browse_page_id = Cooked_Multilingual::get_browse_page_id(); $front_page_id = get_option( 'page_on_front' ); $browse_page_url = $browse_page_id ? get_permalink( $browse_page_id ) : false; $author = !empty($recipe_settings['author']) ? $recipe_settings['author'] : false; if ( !empty($author['id']) && !empty($browse_page_id) ) { // Generate author slug from user_nicename, fallback to user ID if nicename is empty if ( !empty($author['user_nicename']) ) { $author_slug = urlencode(sanitize_title($author['user_nicename'])); } else { // Fallback to user ID if user_nicename is empty or missing $author_slug = $author['id']; } $permalink = $front_page_id != $browse_page_id && get_option('permalink_structure') ? esc_url( untrailingslashit( $browse_page_url ) . '/' . $_cooked_settings['recipe_author_permalink'] . '/' . trailingslashit( $author_slug ) ) : esc_url( trailingslashit( get_home_url() ) . 'index.php?page_id=' . $browse_page_id . '&recipe_author=' . $author['id'] ); $permalink = apply_filters( 'cooked_author_permalink', $permalink, $author['id'], $author_slug ); } else { $permalink = false; } $author_links = isset( $_cooked_settings['disable_author_links'][0] ) && $_cooked_settings['disable_author_links'][0] == 'disabled' ? false : true; $clickable = isset($_cooked_settings['advanced']) && !empty($_cooked_settings['advanced']) && in_array( 'disable_public_recipes', $_cooked_settings['advanced'] ) || !$author_links ? false : true; $hide_avatars = isset( $_cooked_settings['hide_author_avatars'][0] ) && $_cooked_settings['hide_author_avatars'][0] == 'hidden' ? true : false; echo ''; echo !$hide_avatars ? '' . ( !empty($author) ? wp_kses_post( $author['profile_photo'] ) : '' ) . '' : ''; echo '' . esc_html__('Author', 'cooked') . '' . ( $clickable && $permalink ? '' : '' ) . (!empty($author) ? esc_html( $author['name'] ) : '') . ( $clickable && $permalink ? '' : '' ); echo ''; wp_reset_postdata(); } } public static function cooked_info_difficulty( $recipe ) { global $_cooked_settings; if (in_array('difficulty_level', $_cooked_settings['recipe_info_display_options']) && isset($recipe['difficulty_level']) && $recipe['difficulty_level']) { $dl_html = '' . esc_html__('Difficulty','cooked') . '' . Cooked_Recipes::difficulty_level( $recipe['difficulty_level'] ) . ''; echo wp_kses_post( apply_filters( 'cooked_show_difficulty_level', $dl_html, $recipe['difficulty_level'] ) ); } } public static function cooked_info_servings( $recipe ) { global $_cooked_settings; if (in_array('servings', $_cooked_settings['recipe_info_display_options'])) { $servings = isset($recipe['nutrition']['servings']) && $recipe['nutrition']['servings'] ? $recipe['nutrition']['servings'] : 1; Cooked_Recipes::serving_size_switcher( $servings ); Cooked_Recipes::measurement_system_switcher(); } } public static function cooked_info_print() { global $recipe_settings, $_cooked_settings; $recipe_post_url = get_permalink( $recipe_settings['id'] ); $query_args['print'] = 1; $servings = (float)esc_html( get_query_var( 'servings', false ) ); $query_args['servings'] = !empty($servings) ? $servings : false; echo ''; } public static function cooked_info_fullscreen() { global $recipe_settings, $_cooked_settings; echo ''; wp_enqueue_script('cooked-nosleep'); } public static function cooked_info_prep_time( $recipe ) { global $_cooked_settings; if (!empty($_cooked_settings['recipe_info_display_options']) && in_array('timing_prep',$_cooked_settings['recipe_info_display_options'])) { $prep_time = isset($recipe['prep_time']) ? esc_html( $recipe['prep_time'] ) : 0; echo $prep_time ? '' . esc_html__('Prep Time','cooked') . '' . wp_kses_post( Cooked_Measurements::time_format( $prep_time ) ) . '' : ''; } } public static function cooked_info_cook_time( $recipe ) { global $_cooked_settings; if (!empty($_cooked_settings['recipe_info_display_options']) && in_array('timing_cook', $_cooked_settings['recipe_info_display_options'])) { $cook_time = isset($recipe['cook_time']) ? esc_html( $recipe['cook_time'] ) : 0; echo $cook_time ? '' . esc_html__('Cook Time','cooked') . '' . wp_kses_post( Cooked_Measurements::time_format( $cook_time ) ) . '' : ''; } } public static function cooked_info_total_time( $recipe ) { global $_cooked_settings; if (!empty($_cooked_settings['recipe_info_display_options']) && in_array('timing_total',$_cooked_settings['recipe_info_display_options'])) { $total_time = isset($recipe['total_time']) ? esc_html( $recipe['total_time'] ) : 0; if ( $total_time ) { echo $total_time ? '' . esc_html__('Total Time','cooked') . '' . wp_kses_post( Cooked_Measurements::time_format( $total_time ) ) . '' : ''; } else { $prep_time = isset($recipe['prep_time']) ? esc_html( $recipe['prep_time'] ) : 0; $cook_time = isset($recipe['cook_time']) ? esc_html( $recipe['cook_time'] ) : 0; if ( $prep_time && $cook_time ) { $total_time = $prep_time + $cook_time; echo $total_time ? '' . esc_html__('Total Time','cooked') . '' . wp_kses_post( Cooked_Measurements::time_format( $total_time ) ) . '' : ''; } } } } public static function cooked_info_taxonomies() { global $recipe_settings, $_cooked_settings, $clickable; $clickable = isset($_cooked_settings['advanced']) && !empty($_cooked_settings['advanced']) && in_array( 'disable_public_recipes', $_cooked_settings['advanced'] ) ? false : true; if (!empty($_cooked_settings['recipe_info_display_options']) && in_array('taxonomies', $_cooked_settings['recipe_info_display_options'])): global $recipe_terms_list; $recipe_terms_list = ''; do_action( 'cooked_info_taxonomies_shortcode_before', $recipe_settings ); if (!empty($_cooked_settings['recipe_taxonomies']) && in_array('cp_recipe_category', $_cooked_settings['recipe_taxonomies'])): if ( $clickable ): $recipe_terms_list .= get_the_term_list( $recipe_settings['id'], 'cp_recipe_category', '' . __('Category','cooked') . '', ', ', '' ); else: $_recipe_terms_array = []; $recipe_terms_list .= '' . __('Category','cooked') . ''; $recipe_terms_array = wp_get_object_terms( $recipe_settings['id'], 'cp_recipe_category' ); if ( !empty($recipe_terms_array) ): if ( ! is_wp_error( $recipe_terms_array ) ): foreach( $recipe_terms_array as $recipe_term ): $_recipe_terms_array[] = esc_html( $recipe_term->name ); endforeach; endif; endif; $recipe_terms_list .= implode( ', ', $_recipe_terms_array ); $recipe_terms_list .= ''; endif; endif; do_action( 'cooked_info_taxonomies_shortcode_after', $recipe_settings ); if ( $recipe_terms_list ): echo wp_kses_post( $recipe_terms_list ); endif; endif; } public function cooked_excerpt_shortcode($atts, $content = null) { global $_cooked_settings, $recipe_settings; if (isset($_cooked_settings['recipe_info_display_options']) && is_array($_cooked_settings['recipe_info_display_options']) && in_array('excerpt', $_cooked_settings['recipe_info_display_options'])) { ob_start(); if (isset($recipe_settings['excerpt']) && $recipe_settings['excerpt']) { $excerpt = Cooked_Recipes::format_content($recipe_settings['excerpt']); echo '
' . do_shortcode($excerpt) . '
'; } return ob_get_clean(); } } public function cooked_notes_shortcode($atts, $content = null) { global $_cooked_settings, $recipe_settings; // Shortcode Attributes $atts = shortcode_atts([ 'show_header' => false, ], $atts); $show_header = Cooked_Functions::sanitize_text_field($atts['show_header']); $show_header = !$show_header || $show_header == 'false' ? false : $show_header; if (isset($_cooked_settings['recipe_info_display_options']) && is_array($_cooked_settings['recipe_info_display_options']) && in_array('notes', $_cooked_settings['recipe_info_display_options'])) { ob_start(); if (isset($recipe_settings['notes']) && !empty($recipe_settings['notes'])) { $notes = Cooked_Recipes::format_content($recipe_settings['notes']); $show_header = $show_header ? '
' . esc_html__( 'Notes', 'cooked' ) . '
' : ''; echo '
'; echo wp_kses_post( $show_header ); echo do_shortcode($notes); echo '
'; } return ob_get_clean(); } } public function cooked_title_shortcode($atts, $content = null) { global $recipe, $recipe_settings; if (!isset($recipe_settings['id'])) { $recipe_settings['id'] = $recipe->ID; } return esc_html( get_the_title($recipe_settings['id']) ); } public function cooked_image_shortcode($atts, $content = null) { global $recipe, $recipe_settings; if ( !isset($recipe_settings['id']) ): $recipe_settings['id'] = $recipe->ID; endif; $recipe = get_post( $recipe_settings['id'] ); wp_reset_postdata(); ob_start(); if (has_post_thumbnail($recipe)) : echo '
'; echo get_the_post_thumbnail( $recipe, 'cooked-large' ); echo '
'; endif; return ob_get_clean(); } public function cooked_ingredients_shortcode($atts, $content = null) { global $recipe_settings; // Shortcode Attributes $atts = shortcode_atts([ 'checkboxes' => true, ], $atts); $checkboxes = Cooked_Functions::sanitize_text_field($atts['checkboxes']); $checkboxes = !$checkboxes || $checkboxes == 'false' ? false : $checkboxes; ob_start(); do_action( 'cooked_ingredients_shortcode_before', $recipe_settings ); if ( isset($recipe_settings['ingredients']) && !empty($recipe_settings['ingredients']) ): echo '
'; foreach ( $recipe_settings['ingredients'] as $ing ): Cooked_Recipes::single_ingredient( $ing, $checkboxes ); endforeach; echo '
'; endif; do_action( 'cooked_ingredients_shortcode_after', $recipe_settings ); return ob_get_clean(); } public function cooked_directions_shortcode($atts, $content = null) { global $recipe_settings; // Shortcode Attributes $atts = shortcode_atts(apply_filters('cooked_directions_shortcode_atts', [ 'numbers' => true, ]), $atts); $step = 0; $numbers = Cooked_Functions::sanitize_text_field( $atts['numbers'] ); $numbers = !$numbers || $numbers == 'false' ? false : $numbers; ob_start(); if (isset($recipe_settings['directions']) && !empty($recipe_settings['directions'])) { echo '
'; foreach ($recipe_settings['directions'] as $dir) { if (!isset($dir['section_heading_name'])) { $step++; $number = $numbers ? $step : false; } else { $number = 0; } Cooked_Recipes::single_direction($dir, $number, false, $step, $atts); } echo '
'; } return ob_get_clean(); } public function cooked_nutrition_shortcode($atts, $content = null) { global $_cooked_settings, $recipe_settings; // Shortcode Attributes $atts = shortcode_atts([ 'id' => false, 'float' => false, ], $atts); if ( isset( $atts['id'] ) && $atts['id'] ): $recipe_settings = Cooked_Recipes::get( intval( $atts['id'] ), true ); else: $recipe_settings = !empty($recipe_settings) ? $recipe_settings : false; endif; $float = Cooked_Functions::sanitize_text_field($atts['float']); $_nf_fields = Cooked_Measurements::nutrition_facts(); $nutrition_facts = isset($recipe_settings['nutrition']) && !empty($recipe_settings['nutrition']) ? $recipe_settings['nutrition'] : false; ob_start(); if ( $nutrition_facts ): $servings_change = (float)esc_html( get_query_var( 'servings', $recipe_settings['nutrition']['servings'] ) ); $top_facts = $_nf_fields['top']; if (!empty($top_facts)): // Start output buffer for top facts. ob_start(); echo '
'; foreach ( $top_facts as $slug => $nf ): if ( $slug === 'serving_size' ): echo '
' . esc_html($nf['name']) . ' '; echo '

' . esc_html( isset($nutrition_facts[$slug]) ? $nutrition_facts[$slug] : '' ) . '

'; echo '
'; else: echo '

' . esc_html( $servings_change ) . ' ' . esc_html(strtolower($nf['name'])) . '

'; endif; endforeach; echo '
'; // Get top facts content from buffer. $top_facts_content = ob_get_clean(); endif; $mid_facts = $_nf_fields['mid']; if (!empty($mid_facts)): // Start output buffer for mid-facts. ob_start(); foreach ( $mid_facts as $slug => $nf ): if ( isset( $nutrition_facts[$slug] ) && $nutrition_facts[$slug] || isset( $nutrition_facts[$slug] ) && $nutrition_facts[$slug] === '0' ): echo '
' . esc_html($nf['name']) . ''; echo '' . esc_html( $nutrition_facts[$slug] ) . ''; echo '
'; endif; endforeach; // Get mid facts content from buffer. $mid_facts_content = ob_get_clean(); endif; $main_facts = $_nf_fields['main']; $nut_loops = 0; if (!empty($main_facts)): // Start output buffer for main facts. ob_start(); foreach ( $main_facts as $slug => $nf ): if ( isset( $nutrition_facts[$slug] ) && $nutrition_facts[$slug] || isset( $nutrition_facts[$slug] ) && $nutrition_facts[$slug] === '0' ): echo '
'; echo '' . esc_html( $nf['name'] ) . ' ' . esc_html( $nutrition_facts[$slug] ) . '' . ( isset($nf['measurement']) ? '' . esc_html( $nf['measurement'] ) . '' : '' ); echo ( isset( $nf['pdv'] ) && $nutrition_facts[$slug] ? '' . esc_html( ceil( ( $nutrition_facts[$slug] / $nf['pdv'] ) * 100 ) ) . '%' : '' ); if ( isset($nf['subs']) ): foreach( $nf['subs'] as $sub_slug => $sub_nf ): if ( isset( $nutrition_facts[$sub_slug] ) && $nutrition_facts[$sub_slug] || isset( $nutrition_facts[$sub_slug] ) && $nutrition_facts[$sub_slug] === '0' ): echo '
'; if ($sub_slug === 'trans_fat'): echo '
'; echo wp_kses_post( $sub_nf['nutrition_info_name'] ) . ' ' . esc_html( $nutrition_facts[$sub_slug] ) . '' . ( isset($sub_nf['measurement']) ? '' . esc_html( $sub_nf['measurement'] ) . '' : '' ); echo '
'; elseif ($sub_slug === 'added_sugars'): echo '
'; echo esc_html__('Includes', 'cooked') . ' ' . esc_html( $nutrition_facts[$sub_slug] ) . '' . ( isset($sub_nf['measurement']) ? '' . esc_html( $sub_nf['measurement'] ) . '' : '' ) . ' ' . esc_html($sub_nf['name']); echo ( isset( $sub_nf['pdv'] ) ? '' . esc_html( ceil( ( $nutrition_facts[$sub_slug] / $sub_nf['pdv'] ) * 100 ) ) . '%' : '' ); echo '
'; else: echo '
'; echo esc_html( $sub_nf['name'] ) . ' ' . esc_html( $nutrition_facts[$sub_slug] ) . '' . ( isset($sub_nf['measurement']) ? '' . esc_html( $sub_nf['measurement'] ) . '' : '' ); echo ( isset( $sub_nf['pdv'] ) && $nutrition_facts[$sub_slug] ? '' . esc_html( ceil( ( $nutrition_facts[$sub_slug] / $sub_nf['pdv'] ) * 100 ) ) . '%' : '' ); echo '
'; endif; echo '
'; endif; endforeach; endif; echo '
'; endif; endforeach; // Get main facts content from buffer. $main_facts_content = ob_get_clean(); endif; $bottom_facts = $_nf_fields['bottom']; if (!empty($bottom_facts)): // Start output buffer for bottom facts. ob_start(); foreach ( $bottom_facts as $slug => $nf ): if ( isset( $nutrition_facts[$slug] ) && $nutrition_facts[$slug] || isset( $nutrition_facts[$slug] ) && $nutrition_facts[$slug] === '0' ): echo '
'; echo '' . esc_html($nf['name']) . ' ' . esc_html( $nutrition_facts[$slug] ) . '' . ( isset($nf['measurement']) ? '' . esc_html( $nf['measurement'] ) . '' : '' ); echo ( isset( $nf['pdv'] ) ? '' . esc_html( ceil( ( $nutrition_facts[$slug] / $nf['pdv'] ) * 100 ) ) . '%' : '' ); echo '
'; endif; endforeach; // Get bottom facts content from buffer. $bottom_facts_content = ob_get_clean(); endif; // Start a buffer for all nutrition facts content ob_start(); if ( isset($top_facts_content) && $top_facts_content ): echo wp_kses_post( $top_facts_content ); endif; if ( isset($mid_facts_content) && $mid_facts_content || isset($main_facts_content) && $main_facts_content ): echo '
'; echo '
'; echo '
' . esc_html__('Amount per serving','cooked') . '
'; if ( isset($mid_facts_content) && $mid_facts_content ): echo '
'; echo wp_kses_post( $mid_facts_content ); echo '
'; endif; if ( isset($main_facts_content) && $main_facts_content ): echo '
'; echo '
' . esc_html__('% Daily Value *','cooked'). '
'; echo '
'; echo wp_kses_post( $main_facts_content ); echo '
'; endif; echo '
'; echo '
'; endif; if ( isset($bottom_facts_content) && $bottom_facts_content ): echo '
'; echo wp_kses_post( $bottom_facts_content ); echo '
'; endif; $nutrition_facts_content = ob_get_clean(); if ( isset($nutrition_facts_content) && $nutrition_facts_content ): echo '
'; echo '
' . esc_html__('Nutrition Facts', 'cooked') . '
'; echo wp_kses_post( $nutrition_facts_content ); if ( isset($main_facts_content) && $main_facts_content || isset($bottom_facts_content) && $bottom_facts_content ): echo '
'; echo '

* ' . esc_html__('The % Daily Value (DV) tells you how much a nutrient in a serving of food contributes to a daily diet. 2,000 calories a day is used for general nutrition advice.','cooked') . '

'; endif; // Add the Edamam attribution "Powered by Edamam" if the Edamam API is enabled. // More Information: https://developer.edamam.com/attribution if (!empty($_cooked_settings['enable_nutrition_api'])) : echo '
'; do_action( 'cooked_nutrition_facts_powered_by_edamam' ); echo '
'; endif; echo '
'; endif; endif; return ob_get_clean(); } /** * Related Recipes Shortcode * * Displays related recipes based on shared terms in any recipe taxonomy (categories, * cuisines, cooking methods, tags, diets), random order. No scoring, ingredients, or cache. * * @param array $atts Shortcode attributes * @param string $content Shortcode content * @return string Related recipes HTML * @since 1.0.0 */ public function cooked_related_recipes_shortcode($atts, $content = null) { if ( is_admin() ) return false; global $post, $_cooked_settings; // Shortcode Attributes $atts = shortcode_atts( Cooked_Related_Recipes::get_default_atts(), $atts ); // Get recipe ID - validate if provided, otherwise try current post $recipe_id = false; if (!empty($atts['id'])) { // Validate that the ID is numeric before converting if (is_numeric($atts['id']) && $atts['id'] > 0) { $recipe_id = (int) $atts['id']; } else { // Invalid ID provided (e.g., "asdas", "", "0", "-5") return ''; } } else { // No ID provided, try to get from current post if (isset($post->ID) && get_post_type($post->ID) === 'cp_recipe') { $recipe_id = $post->ID; } } if (!$recipe_id) { return ''; } // Get the source recipe (allow any status to support drafts/pending) $source_recipe = Cooked_Recipes::get($recipe_id, true, false, false, false, 'any'); if (!$source_recipe || empty($source_recipe)) { $error_msg = __('Recipe not found.', 'cooked'); // Check if it's a different post type $post_check = get_post($recipe_id); if ($post_check && $post_check->post_type !== 'cp_recipe') { /* translators: %d: post ID */ $error_msg .= ' ' . sprintf(__('The specified ID (%d) is not a recipe.', 'cooked'), $recipe_id); } elseif (!$post_check) { /* translators: %d: post ID */ $error_msg .= ' ' . sprintf(__('No post found with ID %d.', 'cooked'), $recipe_id); } return ''; } // Find related recipes (on-demand query: taxonomies OR + orderby rand, no cache) $related_recipes = Cooked_Related_Recipes::get_related_recipes( $recipe_id, $atts ); if (empty($related_recipes)) { $empty_msg = __('No related recipes found.', 'cooked'); // Provide helpful context if (class_exists('Cooked_Multilingual') && Cooked_Multilingual::is_multilingual_active()) { $empty_msg .= ' ' . __('This may be because there are no other recipes in the current language with matching attributes.', 'cooked'); } else { $empty_msg .= ' ' . __('Try adjusting the matching criteria or ensure you have other published recipes with shared categories, tags, or ingredients.', 'cooked'); } return ''; } // Get recipe IDs for display and filter out deleted/invalid recipes // Note: Language filtering is already handled by WP_Query in find_related_recipes() $recipe_ids = array_column($related_recipes, 'id'); /** * Filter recipe IDs before display. * * @since 1.12.0 * * @param array $recipe_ids Array of recipe IDs to display. * @param array $related_recipes Full related recipes array (each item has 'id'). * @param int $recipe_id Source recipe ID. * @param array $atts Shortcode attributes. */ $recipe_ids = apply_filters( 'cooked_related_recipes_display_ids', $recipe_ids, $related_recipes, $recipe_id, $atts ); ob_start(); // Display title if ($atts['title']) { echo ''; } // Display recipes in grid $columns = intval($atts['columns']); $hide_image = $atts['hide_image'] && $atts['hide_image'] !== 'false'; $hide_excerpt = $atts['hide_excerpt'] && $atts['hide_excerpt'] !== 'false'; $hide_author = $atts['hide_author'] && $atts['hide_author'] !== 'false'; echo ''; $output = ob_get_clean(); /** * Filter the related recipes shortcode output HTML. * * @since 1.12.0 * * @param string $output The shortcode HTML output. * @param array $recipe_ids Array of recipe IDs being displayed. * @param int $recipe_id Source recipe ID. * @param array $atts Shortcode attributes. */ return apply_filters( 'cooked_related_recipes_output', $output, $recipe_ids, $recipe_id, $atts ); } }