PluginProbe
Cooked – Recipe Management / 1.11.4
Cooked – Recipe Management v1.11.4
1.16.1 1.16.0 1.15.0 trunk 1.10.0 1.11.0 1.11.1 1.11.2 1.11.3 1.11.4 1.12.0 1.13.0 1.14.0 1.7.10 1.7.11 1.7.12 1.7.13 1.7.15.1 1.7.15.3 1.7.15.4 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 All 37 releases
cooked / includes / class.cooked-recipes.php

class.cooked-recipes.php in Cooked – Recipe Management 1.11.4, at includes/class.cooked-recipes.php

1,344 lines 66.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Cooked Recipe-Specific Functions
4 *
5 * @package Cooked
6 * @subpackage Recipe-Specific Functions
7 * @since 1.0.0
8 */
9
10 // Exit if accessed directly
11 if ( ! defined( 'ABSPATH' ) ) exit;
12
13 /**
14 * Cooked_Recipe_Meta Class
15 *
16 * This class handles the Cooked Recipe Meta Box creation.
17 *
18 * @since 1.0.0
19 */
20 class Cooked_Recipes {
21
22 public function __construct() {
23 add_filter( 'cooked_recipe_content_filter', [&$this, 'vendor_checks'], 1, 1 );
24 add_filter( 'the_content', [&$this, 'recipe_template'], 10 );
25
26 add_filter( 'parse_query', [&$this, 'custom_taxonomy_in_query'], 10 );
27
28 add_action( 'template_redirect', [&$this, 'print_recipe_template'], 10 );
29 add_action( 'cooked_check_recipe_query', [&$this, 'check_recipe_query'], 10 );
30 add_action( 'pre_get_posts', [&$this, 'cooked_pre_get_posts'], 10, 1 );
31 add_action( 'restrict_manage_posts', [&$this, 'filter_recipes_by_taxonomy'], 10 );
32
33 add_filter('get_canonical_url', [&$this, 'modify_browse_page_canonical_url'], 20, 2);
34 }
35
36 public static function get( $args = false, $single = false, $ids_only = false, $limit = false, $ids_and_titles_only = false, $post_status = 'publish' ) {
37 $recipes = [];
38 $counter = 0;
39
40 // Get by Recipe ID
41 if ( $args && !is_array($args) ):
42
43 $recipe_id = $args;
44 $args = [
45 'post_type' => 'cp_recipe',
46 'post__in' => [$recipe_id],
47 'post_status' => $post_status
48 ];
49
50 // Default Query
51 elseif ( !$args || !is_array($args) ):
52
53 $args = [
54 'post_type' => 'cp_recipe',
55 'posts_per_page' => -1,
56 'post_status' => $post_status,
57 'orderby' => 'name',
58 'order' => 'ASC'
59 ];
60
61 if ( $ids_only || $ids_and_titles_only ):
62 $args['fields'] = 'ids';
63 endif;
64
65 if ( $limit ):
66 $args['limit'] = $limit;
67 endif;
68
69 // Search Query
70 elseif ( $args && isset($args['s']) && isset($args['meta_query']) ):
71
72 $meta_query = $args['meta_query'];
73 $recipe_ids = [];
74
75 $pre_search_args = $args;
76 $pre_search_args['posts_per_page'] = -1;
77 $pre_search_args['fields'] = 'ids';
78
79 unset($pre_search_args['meta_query']);
80
81 $recipes_pre_search = new WP_Query($pre_search_args);
82 if ( $recipes_pre_search->have_posts() ):
83 $recipe_ids = $recipes_pre_search->posts;
84 endif;
85
86 $pre_search_args['meta_query'] = $meta_query;
87 unset($pre_search_args['s']);
88
89 $recipes_pre_search = new WP_Query($pre_search_args);
90 if ( $recipes_pre_search->have_posts() ):
91 $rposts = $recipes_pre_search->posts;
92 $recipe_ids = !empty($recipe_ids) ? array_merge( $recipe_ids, $rposts ) : $rposts;
93 endif;
94
95 $recipe_ids = array_unique( $recipe_ids );
96
97 if ( !empty($recipe_ids) ):
98 unset($args['s']);
99 unset($args['meta_query']);
100 $args['post__in'] = $recipe_ids;
101 endif;
102
103 endif;
104
105 $recipes_results = new WP_Query($args);
106
107 if ( $recipes_results->have_posts() ) {
108 if ( $ids_only ) {
109 return $recipes_results->posts;
110 } elseif ( $ids_and_titles_only ) {
111 while ( $recipes_results->have_posts() ) {
112 $recipes_results->the_post();
113 $recipes[$counter]['id'] = $recipes_results->post->ID;
114 $recipes[$counter]['title'] = $recipes_results->post->post_title;
115
116 $counter++;
117 }
118 } else {
119 while ( $recipes_results->have_posts() ) {
120 $recipes_results->the_post();
121 $recipes[$counter]['id'] = $recipes_results->post->ID;
122 $recipes[$counter]['title'] = $recipes_results->post->post_title;
123 $recipe_settings = self::get_settings($recipes_results->post->ID);
124
125 foreach ($recipe_settings as $key => $setting) {
126 $recipes[$counter][$key] = $setting;
127 }
128
129 $counter++;
130 }
131 }
132 } else {
133 wp_reset_postdata();
134 return;
135 }
136
137 $recipes['raw'] = $recipes_results;
138
139 if ( $single && isset( $recipes[0] ) ):
140 $recipes = $recipes[0];
141 endif;
142
143 wp_reset_postdata();
144
145 return $recipes;
146 }
147
148 public static function get_settings( $post_id, $bc = true ) {
149 if ( !$post_id ) return;
150
151 $recipe_settings = get_post_meta( $post_id, '_recipe_settings', true );
152
153 if ( !is_array( $recipe_settings ) || empty($recipe_settings) ) {
154 $recipe_settings = [];
155 }
156
157 $recipe_settings['title'] = get_the_title( $post_id );
158
159 $recipe_post = get_post($post_id);
160 $wp_excerpt = $recipe_post->post_excerpt;
161
162 // Check for excerpt/content
163 // if ( isset($recipe_settings['excerpt']) && !$recipe_settings['excerpt'] && !$wp_excerpt || !isset($recipe_settings['excerpt']) ) {
164 // wp_update_post(['ID' => $post_id, 'post_excerpt' => $recipe_settings['title']] );
165 // }
166
167 // Check for nutrition data
168 if ( !isset($recipe_settings['nutrition']) ):
169 $recipe_settings['nutrition'] = [];
170 $recipe_settings['nutrition']['servings'] = 1;
171 endif;
172
173 // Backwards Compatibility with Cooked 2.x
174 if ( !isset($recipe_settings['cooked_version']) && $bc ):
175 $c2_recipe_settings = self::get_c2_recipe_meta( $post_id );
176 $recipe_settings = self::sync_c2_recipe_settings( $c2_recipe_settings, $post_id );
177 endif;
178
179 // Get the author information
180 $recipe_settings['author'] = Cooked_Users::get( $recipe_post->post_author, true );
181
182 // Include the Post ID
183 $recipe_settings['id'] = $post_id;
184
185 // You're welcome developers!
186 $recipe_settings = apply_filters( 'cooked_single_recipe_settings', $recipe_settings, $post_id );
187
188 return $recipe_settings;
189 }
190
191 public function check_recipe_query() {
192 global $_cooked_settings, $recipe_query;
193
194 if ( !isset($recipe_query['cp_recipe_category']) ):
195 $recipe_query['cp_recipe_category'] = ( isset($_GET['cp_recipe_category']) && $_GET['cp_recipe_category'] ? intval($_GET['cp_recipe_category']) : ( isset($_cooked_settings['browse_default_cp_recipe_category']) && $_cooked_settings['browse_default_cp_recipe_category'] ? $_cooked_settings['browse_default_cp_recipe_category'] : false ) );
196 endif;
197 }
198
199 public static function cooked_pre_get_posts( $q ) {
200 if ( $title = $q->get( '_cooked_title' ) ) {
201 add_filter( 'get_meta_sql', function( $sql ) use ( $title ) {
202 global $wpdb, $cooked_modified_where;
203
204 if ( $cooked_modified_where ) return $sql;
205 $cooked_modified_where = 1;
206
207 // Modified WHERE
208 $sql['where'] = sprintf(
209 " AND ( %s OR %s ) ",
210 apply_filters( 'cooked_query_where_filter', $wpdb->prepare( "{$wpdb->posts}.post_title like '%%%s%%'", $wpdb->esc_like( $title ) ) ),
211 mb_substr( $sql['where'], 5, mb_strlen( $sql['where'] ) )
212 );
213
214 return $sql;
215 });
216 }
217 }
218
219 public static function recipe_list( $orderby = 'date', $show = 5, $recipes = false, $width = false, $hide_image = false, $hide_author = false ) {
220 global $_cooked_settings;
221
222 $width = !$width ? '100%' : $width;
223 $pixel_width = stristr( $width, 'px', true );
224 $percent_width = stristr( $width, '%', true );
225 $width = $pixel_width ? $pixel_width . 'px' : ( $percent_width ? $percent_width . '%' : ( is_numeric( $width ) ? $width . 'px' : '100%' ) );
226
227 $args = [
228 'post_type' => 'cp_recipe',
229 'posts_per_page' => $show,
230 'post_status' => 'publish',
231 'orderby' => $orderby,
232 'order' => 'DESC'
233 ];
234
235 if ( !empty($recipes) ) {
236 $args['posts_per_page'] = -1;
237 $args['orderby'] = 'post__in';
238 $args['order'] = 'ASC';
239 $args['post__in'] = $recipes;
240 }
241
242 $recipes = Cooked_Recipes::get( $args );
243
244 if ( isset($recipes['raw']) ): unset( $recipes['raw'] ); endif;
245 $recipe_list = [];
246
247 if ( !empty($recipes) ):
248
249 echo '<div class="cooked-shortcode-recipe-list">';
250
251 foreach ( $recipes as $key => $recipe ):
252
253 $rid = $recipe['id'];
254 $has_image_class = has_post_thumbnail($rid) && !$hide_image ? ' cooked-srl-has-image' : '';
255
256 echo '<div class="cooked-srl-single' . esc_attr( $has_image_class ) . '" style="width:100%; max-width:' . esc_attr( $width ) . '">';
257
258 echo has_post_thumbnail($rid) && !$hide_image ? '<div class="cooked-srl-image"><a href="' . esc_url( get_permalink($rid) ) . '">' . get_the_post_thumbnail( $rid, 'thumbnail' ) . '</a></div>' : '';
259
260 echo '<div class="cooked-srl-content">';
261
262 echo '<div class="cooked-srl-title"><a href="' . esc_url( get_permalink($rid) ) . '">' . esc_html( $recipe['title'] ) . '</a></div>';
263
264 if ( in_array('author', $_cooked_settings['recipe_info_display_options']) && !$hide_author ):
265 echo '<div class="cooked-srl-author">';
266 $author = $recipe['author'];
267 /* translators: stating the recipe author with a "By" in front of it. (ex: "By John Smith") */
268 echo sprintf( __( 'By %s', 'cooked' ), '<strong>' . wp_kses_post( $author['name'] ) . '</strong>' );
269 echo '</div>';
270 endif;
271
272 echo '</div>';
273
274 echo '</div>';
275 endforeach;
276
277 echo '</div>';
278
279 endif;
280
281 }
282
283 public static function card( $rid, $width = false, $hide_image = false, $hide_title = false, $hide_excerpt = false, $hide_author = false, $style = false ) {
284 global $_cooked_settings;
285
286 $recipe = self::get( $rid, true );
287 $style_class = $style ? ' cooked-recipe-card-' . esc_attr($style) : '';
288
289 $width = !$width ? '100%' : $width;
290 $pixel_width = stristr( $width, 'px', true );
291 $percent_width = stristr( $width, '%', true );
292 $width = $pixel_width ? $pixel_width . 'px' : ( $percent_width ? $percent_width . '%' : ( is_numeric( $width ) ? $width . 'px' : '100%' ) );
293
294 ob_start();
295
296 echo '<a href="' . esc_url( get_permalink($rid) ) . '" class="cooked-recipe-card' . esc_attr( $style_class ) . '" style="width:100%; max-width:' . esc_attr( $width ) . '">';
297
298 do_action( 'cooked_recipe_grid_before_recipe', $recipe );
299
300 do_action( 'cooked_recipe_grid_before_image', $recipe );
301
302 echo has_post_thumbnail($rid) && !$hide_image ? '<span class="cooked-recipe-card-image" style="background-image:url(' . get_the_post_thumbnail_url( $recipe['id'], 'cooked-medium' ) . ');"></span>' : '';
303
304 //do_action( 'cooked_recipe_grid_after_image', $recipe );
305
306 echo '<span class="cooked-recipe-card-content">';
307
308 do_action( 'cooked_recipe_grid_before_name', $recipe );
309
310 echo !$hide_title ? '<span class="cooked-recipe-card-title">' . esc_html( $recipe['title'] ) . '</span>' : '';
311
312 do_action( 'cooked_recipe_grid_after_name', $recipe );
313
314 if ( $hide_excerpt && !$hide_title && !$hide_author ): echo '<span class="cooked-recipe-card-sep"></span>'; endif;
315
316 do_action( 'cooked_recipe_grid_before_author', $recipe );
317
318 if ( in_array('author',$_cooked_settings['recipe_info_display_options']) && !$hide_author ):
319 echo '<span class="cooked-recipe-card-author">';
320 $author = $recipe['author'];
321 /* translators: stating the recipe author with a "By" in front of it. (ex: "By John Smith") */
322 echo sprintf( __( 'By %s', 'cooked' ), '<strong>' . $author['name'] . '</strong>' );
323 echo '</span>';
324 endif;
325
326 do_action( 'cooked_recipe_grid_after_author', $recipe );
327
328 if ( !$hide_excerpt && !$hide_title || !$hide_excerpt && !$hide_author ): echo '<span class="cooked-recipe-card-sep"></span>'; endif;
329
330 do_action( 'cooked_recipe_grid_before_excerpt', $recipe );
331
332 echo !$hide_excerpt ? '<span class="cooked-recipe-card-excerpt">' . wp_kses_post( $recipe['excerpt'] ) . '</span>' : '';
333
334 do_action( 'cooked_recipe_grid_after_excerpt', $recipe );
335
336 echo '</span>';
337
338 do_action( 'cooked_recipe_grid_after_recipe', $recipe );
339
340 echo '</a>';
341
342 return ob_get_clean();
343 }
344
345 public function print_recipe_template() {
346 if ( is_singular('cp_recipe') && isset($_GET['print']) ):
347 load_template( COOKED_DIR . 'templates/front/recipe-print.php', false);
348 exit;
349 endif;
350 }
351
352 public static function vendor_checks( $content ) {
353 global $wp_query, $post;
354
355 // WooCommerce Memberships
356 if ( function_exists('wc_memberships_user_can') && function_exists('wc_memberships_is_post_content_restricted') && function_exists('wc_memberships_user_can') ):
357
358 if ( !is_user_logged_in() && wc_memberships_is_post_content_restricted() ):
359 return WC_Memberships_User_Messages::get_message_html( 'content_restricted', ['post' => $post] );
360 elseif ( is_user_logged_in() ):
361 $_user = wp_get_current_user();
362 if ( !wc_memberships_user_can( $_user->ID, 'view', ['cp_recipe' => $post->ID] ) ):
363 return WC_Memberships_User_Messages::get_message_html( 'content_restricted', ['post' => $post] );
364 endif;
365 endif;
366
367 endif;
368
369 return $content;
370 }
371
372 public function filter_recipes_by_taxonomy() {
373 global $typenow, $cooked_taxonomies_shown;
374 $taxonomies = apply_filters( 'cooked_active_taxonomies', ['cp_recipe_category'] );
375 if ( $typenow == 'cp_recipe' ):
376 foreach ( $taxonomies as $taxonomy ):
377 if ( is_array($cooked_taxonomies_shown) && !in_array( $taxonomy, $cooked_taxonomies_shown ) || !is_array($cooked_taxonomies_shown) ):
378 $cooked_taxonomies_shown[] = $taxonomy;
379 $selected = isset($_GET[$taxonomy]) ? sanitize_title($_GET[$taxonomy]) : '';
380 $info_taxonomy = get_taxonomy($taxonomy);
381 $taxonomy_label = $info_taxonomy->label;
382
383 /* translators: For showing "All" of a taxonomy (ex: "All Burgers") */
384 $all_string = sprintf( __( "All %s", "cooked" ), $taxonomy_label );
385
386 wp_dropdown_categories([
387 'show_option_all' => $all_string,
388 'taxonomy' => $taxonomy,
389 'name' => $taxonomy,
390 'orderby' => 'name',
391 'selected' => $selected,
392 'show_count' => true,
393 'hide_empty' => true,
394 ]);
395 endif;
396 endforeach;
397 endif;
398 }
399
400 public function custom_taxonomy_in_query($query) {
401 global $pagenow;
402 $taxonomies = apply_filters( 'cooked_active_taxonomies', ['cp_recipe_category'] );
403 $q_vars = &$query->query_vars;
404
405 foreach ( $taxonomies as $taxonomy ):
406 if ( $pagenow == 'edit.php' && isset($q_vars['post_type']) && $q_vars['post_type'] == 'cp_recipe' && isset($q_vars[$taxonomy]) && is_numeric($q_vars[$taxonomy]) && $q_vars[$taxonomy] != 0 ):
407 $term = get_term_by('id', $q_vars[$taxonomy], $taxonomy);
408 $q_vars[$taxonomy] = $term->slug;
409 endif;
410 endforeach;
411 }
412
413 public static function list_view( $list_atts = false ) {
414 global $wp_query, $recipe_query, $atts, $_cooked_settings, $recipes, $recipe_args, $current_recipe_page;
415
416 // Get the attributes for this view
417 $atts = array_change_key_case( (array) $list_atts, CASE_LOWER );;
418 $ls_method = 'list_style_grid';
419 $ls_class = 'Cooked_Recipes';
420
421 // Change the recipe layout
422 if ( $atts['layout'] ) {
423 $recipe_list_style = apply_filters( 'cooked_recipe_list_style', [ 'grid' => 'Cooked_Recipes' ], $atts['layout'] );
424 $list_style = esc_html( key( $recipe_list_style ) );
425 $ls_method = 'list_style_' . $list_style;
426 $ls_class = current( $recipe_list_style );
427
428 $_cooked_settings['recipe_list_style'] = $list_style;
429 }
430
431 $recipe_query = $wp_query->query;
432 $tax_query = [];
433
434 do_action( 'cooked_check_recipe_query' );
435
436 if ( isset($_cooked_settings['recipe_taxonomies']) && !empty($_cooked_settings['recipe_taxonomies']) ):
437 foreach ( $_cooked_settings['recipe_taxonomies'] as $taxonomy ):
438 if ( isset($recipe_query[$taxonomy]) && $recipe_query[$taxonomy] ):
439 $field_type = is_numeric($recipe_query[$taxonomy]) ? 'id' : 'slug';
440 $tax_query['relation'] = 'AND';
441 $tax_query[] = [
442 'taxonomy' => $taxonomy,
443 'field' => $field_type,
444 'terms' => array_map('trim', explode(',', esc_html($recipe_query[$taxonomy])))
445 ];
446 endif;
447 endforeach;
448
449 if ( empty($tax_query) ):
450 foreach ( $_cooked_settings['recipe_taxonomies'] as $taxonomy ):
451 if ( isset( $_cooked_settings['browse_default_' . $taxonomy] ) && $_cooked_settings['browse_default_' . $taxonomy] ):
452 $tax_query['relation'] = 'AND';
453 $tax_query[] = [
454 'taxonomy' => $taxonomy,
455 'field' => 'id',
456 'terms' => [esc_html($_cooked_settings['browse_default_' . $taxonomy])]
457 ];
458 endif;
459 endforeach;
460 endif;
461 endif;
462
463 if ( empty($tax_query) ):
464
465 if ( $atts['category'] ):
466 $tax_query['relation'] = 'AND';
467 $tax_query[] = [
468 'taxonomy' => 'cp_recipe_category',
469 'field' => (is_numeric($atts['category']) ? 'id' : 'slug'),
470 'terms' => array_map('trim', explode(',', esc_html($atts['category'])))
471 ];
472 endif;
473
474 $tax_query = apply_filters( 'cooked_tax_query_filter', $tax_query, $atts );
475
476 endif;
477
478 $sorting_type = get_query_var('cooked_browse_sort_by', isset($_cooked_settings['browse_default_sort']) && $_cooked_settings['browse_default_sort'] ? $_cooked_settings['browse_default_sort'] : 'date_desc' );
479 $sorting_type = sanitize_key($sorting_type);
480 $sorting_types = explode('_', $sorting_type);
481
482 $text_search = get_query_var('cooked_search_s', '');
483 $text_search = urldecode($text_search);
484 $text_search = esc_html($text_search);
485 $recipes_per_page = ( $atts['show'] ? $atts['show'] : ( isset($_cooked_settings['recipes_per_page']) && $_cooked_settings['recipes_per_page'] ? $_cooked_settings['recipes_per_page'] : get_option( 'posts_per_page' ) ) );
486 $current_recipe_page = Cooked_Recipes::current_page();
487
488 $orderby = $atts['orderby'] ? esc_html( $atts['orderby'] ) : $sorting_types[0];
489 $meta_sort = false;
490
491 $post_status = 'publish';
492 if ( isset($atts['public_recipes']) && $atts['public_recipes'] == false ):
493 $post_status = ['publish', 'pending', 'draft'];
494 endif;
495
496 $recipe_args = [
497 'paged' => $current_recipe_page,
498 'post_type' => 'cp_recipe',
499 'posts_per_page' => $recipes_per_page,
500 'post_status' => $post_status,
501 'orderby' => $orderby,
502 'order' => ($atts['order'] ? esc_html($atts['order']) : $sorting_types[1])
503 ];
504
505 if ( isset($atts['exclude']) && $atts['exclude'] ):
506 $exclude = explode( ',', str_replace( ' ', '', $atts['exclude'] ) );
507 $recipe_args['post__not_in'] = $exclude;
508 endif;
509
510 if ( $text_search ):
511 // Replace [+] [,] [;] with spaces
512 $prep_text = str_replace(['+', ',', ';'], ' ', $text_search);
513
514 // Replace duplicate spaces
515 $prep_text = preg_replace('/\s+/', ' ', $prep_text);
516
517 // Explode into an array of search terms
518 $words = explode( ' ', $prep_text );
519
520 if ( !empty($words) ):
521 $meta_query['relation'] = 'AND';
522 foreach ( $words as $word ):
523 $meta_query[] = [
524 'key' => '_recipe_settings',
525 'value' => $word,
526 'compare' => 'LIKE'
527 ];
528 endforeach;
529 else:
530 $meta_query[] = [
531 'key' => '_recipe_settings',
532 'value' => $text_search,
533 'compare' => 'LIKE'
534 ];
535 endif;
536 $recipe_args['_cooked_title'] = $prep_text;
537 $recipe_args['s'] = $prep_text;
538 $recipe_args['meta_query'] = $meta_query;
539
540 endif;
541
542 if ( !empty($tax_query) ):
543 $recipe_args['tax_query'] = $tax_query;
544 endif;
545
546 if ( $atts['author'] && is_numeric( $atts['author'] ) ):
547 $recipe_args['author'] = $atts['author'];
548 elseif ( $atts['author'] ):
549 $recipe_args['author_name'] = $atts['author'];
550 endif;
551
552 if ( isset( $atts['include'] ) && !empty($atts['include']) ):
553 $recipe_args['post__in'] = $atts['include'];
554 endif;
555
556 $recipe_args = apply_filters( 'cooked_recipe_query_args', $recipe_args, $atts, $sorting_types );
557 if ( !isset($atts['public_recipes']) || isset($atts['public_recipes']) && $atts['public_recipes'] ):
558 $recipe_args = apply_filters( 'cooked_recipe_public_query_filters', $recipe_args );
559 endif;
560
561 wp_suspend_cache_addition(true);
562
563 ob_start();
564 $recipes = Cooked_Recipes::get( $recipe_args );
565 ( $theme_template_override = locate_template( 'recipe-list.php')) ? load_template( $theme_template_override, false ) : load_template( COOKED_DIR . 'templates/front/recipe-list.php', false );
566 wp_reset_postdata();
567 Cooked_Settings::reset();
568
569 wp_suspend_cache_addition(false);
570
571 return ob_get_clean();
572 }
573
574 public static function list_style_grid($atts = []) {
575 load_template(COOKED_DIR . 'templates/front/recipe-single.php', false, $atts);
576 }
577
578 public static function current_page() {
579 return get_query_var( 'paged' ) ? max( 1, get_query_var('paged') ) : ( get_query_var( 'page' ) ? max( 1, get_query_var('page') ) : 1 );
580 }
581
582 public static function pagination( $recipe_query, $recipe_args ) {
583 global $_cooked_settings, $current_recipe_page, $paged, $atts;
584
585 $paged = self::current_page();
586 $total_recipe_pages = $recipe_query->max_num_pages;
587 $pagination = '';
588
589 if ( $total_recipe_pages > 1) {
590 do_action( 'cooked_init_pagination', $recipe_args, $current_recipe_page, $total_recipe_pages, $atts );
591
592 $pagination_style = apply_filters( 'cooked_pagination_style', ['numbered_pagination' => 'Cooked_Recipes'] );
593 $p_method = key( $pagination_style );
594 $p_class = current( $pagination_style );
595
596 $pagination = $p_class::$p_method( $current_recipe_page, $total_recipe_pages );
597 }
598
599 return $pagination;
600 }
601
602 public static function numbered_pagination( $current_recipe_page, $total_recipe_pages ) {
603 if ( get_option('permalink_structure') ) {
604 $format = '?paged=%#%';
605 } else {
606 $format = 'page/%#%/';
607 }
608
609 $big = 999999999;
610 $base = $format =='?paged=%#%' ? $base = str_replace( $big, '%#%', get_pagenum_link( $big ) ) : $base = @add_query_arg('paged','%#%');
611
612 $recipe_pagination = apply_filters( 'cooked_pagination_args', [
613 'base' => $base,
614 'format' => $format,
615 'mid-size' => 1,
616 'current' => $current_recipe_page,
617 'total' => $total_recipe_pages,
618 'prev_next' => true,
619 'prev_text' => '<i class="cooked-icon cooked-icon-angle-left"></i>',
620 'next_text' => '<i class="cooked-icon cooked-icon-angle-right"></i>',
621 ]);
622 return '<div class="cooked-pagination-numbered cooked-clearfix">' . paginate_links( $recipe_pagination ) . '</div>';
623 }
624
625 public static function default_content() {
626 return apply_filters( 'cooked_default_content', '<p>[cooked-info left="author,taxonomies,difficulty" right="print,fullscreen"]</p><p>[cooked-excerpt]</p><p>[cooked-image]</p><p>[cooked-info left="servings" right="prep_time,cook_time,total_time"]</p><p>[cooked-ingredients]</p><p>[cooked-directions]</p><p>[cooked-notes show_header=true]</p><p>[cooked-gallery]</p>' );
627 }
628
629 public static function print_content() {
630 return apply_filters( 'cooked_print_content', '<p>[cooked-info include="servings,prep_time,cook_time,total_time"]</p><p>[cooked-excerpt]</p><p>[cooked-image]</p><p>[cooked-ingredients]</p><p>[cooked-directions]</p><p>[cooked-notes show_header=true]</p><p>[cooked-nutrition]</p>' );
631 }
632
633 public static function fsm_content() {
634 return apply_filters( 'cooked_fsm_content', '
635 <div class="cooked-fsm-ingredients cooked-fsm-content cooked-active" data-nosnippet aria-hidden="false">
636 <div class="cooked-panel"><h2>' . __('Ingredients', 'cooked') . '</h2>[cooked-ingredients]</div>
637 </div>
638 <div class="cooked-fsm-directions-wrap cooked-fsm-content" data-nosnippet aria-hidden="true">
639 <div class="cooked-fsm-directions cooked-fsm-content">
640 <div class="cooked-panel"><h2>' . __('Directions', 'cooked') . '</h2>[cooked-directions]</div>
641 </div>
642 <div class="cooked-fsm-notes cooked-fsm-content" data-nosnippet aria-hidden="true">
643 <div class="cooked-panel"><h2>' . __('Notes', 'cooked') . '</h2>[cooked-notes]</div>
644 </div>
645 </div>
646 ' );
647 }
648
649 public static function difficulty_levels() {
650 return apply_filters( 'cooked_difficulty_levels', [
651 1 => __('Beginner', 'cooked'),
652 2 => __('Intermediate', 'cooked'),
653 3 => __('Advanced', 'cooked')
654 ]);
655 }
656
657 public static function get_by_slug($slug = false) {
658 if ($slug):
659 if (!function_exists('ctype_digit') || function_exists('ctype_digit') && !ctype_digit($slug)):
660 $recipe_query = new WP_Query(['name' => $slug, 'post_type' => 'cp_recipe'] );
661 if ($recipe_query->have_posts()):
662 $recipe_query->the_post();
663 return get_the_ID();
664 else:
665 return false;
666 endif;
667 else:
668 return $slug;
669 endif;
670 else:
671 return false;
672 endif;
673 }
674
675 public static function gallery_types() {
676
677 $gallery_types = apply_filters( 'cooked_gallery_types', [
678 'cooked' => [
679 'title' => __('Cooked Gallery', 'cooked'),
680 'required_class' => ''
681 ],
682 'envira' => [
683 'title' => __('Envira Gallery', 'cooked'),
684 'required_class' => 'Envira_Gallery'
685 ],
686 'soliloquy' => [
687 'title' => __('Soliloquy Slider', 'cooked'),
688 'required_class' => 'Soliloquy'
689 ],
690 'revslider' => [
691 'title' => __('Slider Revolution', 'cooked'),
692 'required_class' => 'RevSlider'
693 ]
694 ]);
695
696 foreach ( $gallery_types as $slug => $gtype ):
697
698 $results = [];
699
700 if ( $gtype['required_class'] && class_exists($gtype['required_class']) ):
701
702 if ( $slug == 'revslider' ):
703
704 $slider = new RevSlider();
705 $arrSliders = $slider->getArrSliders();
706 if (!empty($arrSliders)):
707 foreach($arrSliders as $slider):
708 $results[ $slider->getAlias() ] = $slider->getTitle();
709 endforeach;
710 endif;
711
712 else:
713
714 $args = apply_filters( 'cooked_gallery_type_' . $slug . '_query', [
715 'post_type' => $slug,
716 'post_status' => 'publish',
717 'posts_per_page' => -1
718 ]);
719 $gallery_query = new WP_Query( $args );
720 if ( $gallery_query->have_posts() ):
721 while( $gallery_query->have_posts() ):
722 $gallery_query->the_post();
723 $results[$gallery_query->post->ID] = get_the_title();
724 endwhile;
725 endif;
726
727 endif;
728
729 if ( !empty($results) ):
730 $gallery_types[$slug]['posts'] = $results;
731 else:
732 unset( $gallery_types[$slug] );
733 endif;
734
735 else:
736
737 if ( $slug != 'cooked' ): unset( $gallery_types[$slug] ); endif;
738
739 endif;
740
741 endforeach;
742
743 wp_reset_query();
744 wp_reset_postdata();
745
746 return $gallery_types;
747 }
748
749 public static function serving_size_switcher( $servings ) {
750 global $_cooked_settings, $post;
751 $switcher_disabled = ( isset( $_cooked_settings['advanced'] ) && in_array( 'disable_servings_switcher', $_cooked_settings['advanced'] ) ? true : false );
752 $printing = ( is_singular('cp_recipe') && isset($_GET['print']) );
753
754 if ( !$printing && !$switcher_disabled ):
755 $default = $servings;
756 $servings = (float)esc_html( get_query_var( 'servings', $servings ) );
757 $servings = ( !$servings ? $default : $servings );
758 $counter = 1;
759
760 $quarter = $default / 4;
761 $half = $default / 2;
762 $double = $default * 2;
763 $triple = $default * 3;
764
765 /* translators: singular and plural quarter "serving" size */
766 $quarter_string = sprintf( esc_html( _n('Quarter (%s Serving)','Quarter (%s Servings)',$quarter,'cooked')),$quarter );
767
768 /* translators: singular and plural quarter "serving" size */
769 $half_string = sprintf( esc_html( _n('Half (%s Serving)','Half (%s Servings)',$half,'cooked')),$half );
770
771 /* translators: singular and plural quarter "serving" size */
772 $default_string = sprintf( esc_html( _n('Default (%s Serving)','Default (%s Servings)',$default,'cooked')),$default );
773
774 /* translators: singular and plural quarter "serving" size */
775 $double_string = sprintf( __( 'Double (%s Servings)','cooked'),$double );
776
777 /* translators: singular and plural quarter "serving" size */
778 $triple_string = sprintf( __( 'Triple (%s Servings)','cooked'),$triple );
779
780 $servings_array = apply_filters( 'cooked_servings_switcher_options', [
781 'quarter' => ['name' => $quarter_string, 'value' => $quarter],
782 'half' => ['name' => $half_string, 'value' => $half],
783 'default' => ['name' => $default_string, 'value' => $default],
784 'double' => ['name' => $double_string, 'value' => $double],
785 'triple' => ['name' => $triple_string, 'value' => $triple],
786 ], $quarter, $half, $default, $double, $triple );
787 else:
788 $servings_array = [];
789 endif;
790
791 echo '<span class="cooked-servings"><span class="cooked-servings-icon"><i class="cooked-icon cooked-icon-recipe-icon"></i></span>';
792 echo '<strong class="cooked-meta-title">' . __('Yields','cooked') . '</strong>';
793 if ( !$printing && !$switcher_disabled ):
794
795 /* translators: singular and plural "serving" sizes */
796 $servings_string = sprintf( esc_html( _n( '%s Serving', '%s Servings', $servings, 'cooked' ) ), $servings );
797
798 echo '<a aria-label="' . $servings_string . '" href="#">' . $servings_string . '</a>';
799 echo '<label for="cooked-servings-changer" class="screen-reader-text">' . __('Servings', 'cooked') . '</label>';
800 echo '<select id="cooked-servings-changer" name="servings" class="cooked-servings-changer">';
801 foreach ( $servings_array as $stype ):
802 echo '<option value="' . $stype['value'] . '"' . ( $stype['value'] == $servings ? ' selected' : '' ) . '>' . esc_attr( $stype['name'] ) . '</option>';
803 endforeach;
804 echo '</select>';
805 else:
806 /* translators: singular and plural "serving" sizes */
807 echo '<span>' . sprintf( esc_html( _n( '%s Serving', '%s Servings', $servings, 'cooked' ) ), $servings ) . '</span>';
808 endif;
809 echo '</span>';
810
811 }
812
813 public static function single_ingredient( $ing, $checkboxes = true, $plain_text = false ) {
814 global $recipe_settings;
815
816 $Cooked_Measurements = new Cooked_Measurements();
817 $measurements = $Cooked_Measurements->get();
818
819 ob_start();
820
821 if ( isset($ing['section_heading_name']) && $ing['section_heading_name'] ) {
822
823 if ( $plain_text ) {
824 return $ing['section_heading_name'];
825 } else {
826 $valid_elements = ['div', 'h2', 'h3', 'h4', 'h5', 'h6'];
827 global $_cooked_settings;
828 $default_element = isset($_cooked_settings['section_heading_default_html_tag']) ? $_cooked_settings['section_heading_default_html_tag'] : 'div';
829
830 $element = (isset($ing['section_heading_element']) && in_array($ing['section_heading_element'], $valid_elements, true))
831 ? ($ing['section_heading_element'] === 'div' ? $default_element : $ing['section_heading_element'])
832 : $default_element;
833
834 echo '<' . $element . ' class="cooked-single-ingredient cooked-heading">' . esc_html($ing['section_heading_name']) . '</' . $element . '>';
835 }
836
837 } elseif ( isset($ing['name']) && $ing['name'] ) {
838
839 $default_serving_size = ( isset($recipe_settings['nutrition']['servings']) && $recipe_settings['nutrition']['servings'] ? $recipe_settings['nutrition']['servings'] : 1 );
840 $multiplier = (float)esc_html( get_query_var( 'servings', $recipe_settings['nutrition']['servings'] ) );
841 $multiplier = ( !$multiplier ? $default_serving_size : $multiplier );
842
843 if ( !$multiplier || $multiplier == $default_serving_size ) {
844 $multiplier = 1;
845 } else {
846 $multiplier = $multiplier / $default_serving_size;
847 }
848
849 if ($multiplier === 1) {
850 $amount = ( isset($ing['amount']) && $ing['amount'] ? esc_html( $ing['amount'] ) : false );
851 $amount = $Cooked_Measurements->cleanup_amount($amount);
852 $format = ( strpos($amount, '/') === false ? ( strpos($amount, '.') !== false || strpos($amount, ',') !== false ? 'decimal' : 'fraction' ) : 'fraction' );
853 $float_amount = $Cooked_Measurements->calculate( $amount, 'decimal' );
854 $amount = $Cooked_Measurements->format_amount( $float_amount, $format );
855 } else {
856 $amount = ( isset($ing['amount']) && $ing['amount'] ? esc_html( $ing['amount'] ) : false );
857 $amount = $Cooked_Measurements->cleanup_amount($amount);
858 $format = ( strpos($amount, '/') === false ? ( strpos($amount, '.') !== false || strpos($amount, ',') !== false ? 'decimal' : 'fraction' ) : 'fraction' );
859 $float_amount = $Cooked_Measurements->calculate( $amount, 'decimal' );
860
861 if ($float_amount) {
862 $float_amount = $float_amount * $multiplier;
863 $amount = $Cooked_Measurements->format_amount( $float_amount, $format );
864 }
865 }
866
867 $measurement = ( isset($ing['measurement']) && $ing['measurement'] ? esc_html( $ing['measurement'] ) : false );
868 $measurement = ( $measurement && $float_amount ? $Cooked_Measurements->singular_plural( $measurements[ $measurement ]['singular_abbr'], $measurements[ $measurement ]['plural_abbr'], $float_amount ) : false );
869
870 $name = ( isset($ing['name']) && $ing['name'] ? apply_filters( 'cooked_ingredient_name', wp_kses_post( $ing['name'] ), $ing ) : false );
871
872 if ( $plain_text ) {
873 return ( $amount ? $amount . ' ' : '' ) . ( $measurement ? $measurement . ' ' : '' ) . ( $name ? $name : '' );
874 } else {
875 echo '<div itemprop="recipeIngredient" class="cooked-single-ingredient cooked-ingredient' . ( !$checkboxes ? ' cooked-ing-no-checkbox' : '' ) . '">';
876 echo ( $checkboxes ? '<span class="cooked-ingredient-checkbox">&nbsp;</span>' : '' );
877 do_action( 'cooked_ingredient_after_checkbox', $ing );
878 echo ( $amount ? '<span class="cooked-ing-amount" data-decimal="' . esc_html($float_amount) . '">' . wp_kses_post($amount) . '</span> <span class="cooked-ing-measurement">' . wp_kses_post( $measurement ) . '</span> ' : '' );
879 do_action( 'cooked_ingredient_after_amount', $ing );
880 echo ( $name ? '<span class="cooked-ing-name">' . wp_kses_post( $name ) . '</span>' : '' );
881 do_action( 'cooked_ingredient_after_name', $ing );
882 echo '</div>';
883 }
884 }
885
886 $ing_html = ob_get_clean();
887 echo apply_filters( 'cooked_single_ingredient_html', $ing_html, $ing, $checkboxes, $plain_text );
888 }
889
890 public static function single_direction($dir, $number = false, $plain_text = false, $step = false, $atts = false) {
891 global $recipe_settings;
892
893 if (isset($dir['section_heading_name']) && $dir['section_heading_name']) {
894
895 if ($plain_text) {
896 return $dir['section_heading_name'];
897 } else {
898 $valid_elements = ['div', 'h2', 'h3', 'h4', 'h5', 'h6'];
899 global $_cooked_settings;
900 $default_element = isset($_cooked_settings['section_heading_default_html_tag']) ? $_cooked_settings['section_heading_default_html_tag'] : 'div';
901
902 $element = (isset($dir['section_heading_element']) && in_array($dir['section_heading_element'], $valid_elements, true))
903 ? ($dir['section_heading_element'] === 'div' ? $default_element : $dir['section_heading_element'])
904 : $default_element;
905
906 echo '<' . $element . ' class="cooked-single-direction cooked-heading">' . esc_html($dir['section_heading_name']) . '</' . $element . '>';
907 }
908
909 } elseif (isset($dir['content']) && $dir['content'] || isset($dir['image']) && $dir['image']) {
910
911 $dir_image_size = apply_filters( 'cooked_direction_image_size', 'large' );
912 $image = isset($dir['image']) && $dir['image'] ? wp_get_attachment_image( $dir['image'], $dir_image_size, false, ['title' => esc_attr(get_the_title($dir['image']))] ) : '';
913 $content = !empty($dir['content']) ? Cooked_Recipes::format_content($dir['content']) : '';
914
915 $image = apply_filters('cooked_direction_image_html', $image, $atts);
916
917 if ($plain_text) {
918 return $content;
919 } else {
920 /* translators: singular and plural "steps" */
921 $step_string = sprintf( __( 'Step %d', 'cooked' ), $step );
922
923 echo '<div id="cooked-single-direction-step-'. $number .'" class="cooked-single-direction cooked-direction' . ($image ? ' cooked-direction-has-image' : '') . ( $number ? ' cooked-direction-has-number' . ( $number > 9 ? '-wide' : '' ) : '' ) . '"' . ( $step ? ' data-step="' . $step_string . '"' : '' ) . '>';
924 echo $number ? '<span class="cooked-direction-number">' . esc_html($number) . '</span>' : '';
925 echo '<div class="cooked-dir-content">' . do_shortcode($content) . ($image ? wpautop($image) : '') . '</div>';
926 echo '</div>';
927 }
928 }
929 }
930
931 public static function format_content($content) {
932 return wpautop(wp_kses_post(html_entity_decode($content)));
933 }
934
935 public static function difficulty_level($level) {
936 $level_names = self::difficulty_levels();
937 $level_text = isset($level_names[$level]) ? $level_names[$level] : false;
938 return $level_text ? '<span class="cooked-difficulty-level-' . esc_attr($level) . '">' . wp_kses_post($level_text) . '</span>' : '';
939 }
940
941 public static function recipe_search_box( $options = false ) {
942 global $_cooked_settings, $recipe_args, $tax_col_count, $active_taxonomy;
943
944 $tax_col_count = 0;
945 $filters_set = [];
946 $taxonomy_search_fields = '';
947
948 if ( isset($recipe_args['tax_query']) ):
949 foreach ( $recipe_args['tax_query'] as $query ):
950 // Only process inclusion queries (default operator or explicit 'IN')
951 // Skip exclusion queries ('NOT IN') and other complex operators
952 $operator = isset($query['operator']) ? $query['operator'] : 'IN';
953 if ( $operator === 'IN' && isset($query['taxonomy']) && isset($query['terms']) ):
954 $filters_set[$query['taxonomy']] = implode( ',', $query['terms'] );
955 endif;
956 endforeach;
957
958 if ( isset($filters_set) ):
959 foreach ( $filters_set as $taxonomy => $filter ):
960 $this_tax = get_term_by( 'slug', $filter, $taxonomy );
961 $this_tax = $this_tax ? $this_tax : get_term_by( 'id', $filter, $taxonomy );
962 if ( $this_tax && !is_wp_error($this_tax) ):
963 $filters_set[$taxonomy] = $this_tax->term_id;
964 $active_taxonomy = !isset($active_taxonomy) ? $this_tax->name : $active_taxonomy;
965 endif;
966 endforeach;
967 endif;
968 endif;
969
970 $total_taxonomies = 0;
971
972 $inline_browse = isset($options['inline_browse']) && $options['inline_browse'] ? true : false;
973
974 ob_start();
975 if ( !empty($_cooked_settings['recipe_taxonomies']) ):
976
977 if ( !$inline_browse ):
978
979 echo '<div class="cooked-field-wrap cooked-field-wrap-select' . ( isset($active_taxonomy) ? ' cooked-taxonomy-selected' : '' ) . '">';
980 echo '<span class="cooked-browse-select">';
981 echo '<span class="cooked-field-title">' . ( isset($active_taxonomy) ? esc_html( $active_taxonomy ) : __('Browse','cooked') ) . '</span>';
982 echo '<span class="cooked-browse-select-block cooked-clearfix">';
983
984 endif;
985
986 ob_start();
987
988 do_action( 'cooked_before_search_filter_columns' );
989
990 if ( isset($active_taxonomy) ):
991 $recipes_page_id = ( $_cooked_settings['browse_page'] ? $_cooked_settings['browse_page'] : get_the_ID() );
992 $view_all_recipes_url = get_permalink( $recipes_page_id );
993 else:
994 $view_all_recipes_url = false;
995 endif;
996
997 if ( in_array( 'cp_recipe_category', $_cooked_settings['recipe_taxonomies']) ):
998 $terms_array = Cooked_Settings::terms_array( 'cp_recipe_category', false, __('No categories','cooked'), true, true, false );
999 if ( !empty($terms_array) ):
1000 echo '<span class="cooked-tax-column">';
1001 echo '<span class="cooked-tax-column-title">' . __('Categories','cooked') . '</span>';
1002 echo '<div class="cooked-tax-scrollable">';
1003 echo ( $view_all_recipes_url ? '<a href="' . esc_url( $view_all_recipes_url ) . '">' . __( 'All Categories','cooked' ) . '</a>' : '' );
1004 foreach ( $terms_array as $key => $val ):
1005 if ( $key ):
1006 $term = get_term( $key );
1007 $term_link = ( !empty($term) ? get_term_link( $term ) : false );
1008 $term_name = apply_filters( 'cooked_term_name', $term->name, $term->ID, $term->taxonomy );
1009 echo ( $term_link ? ( isset($active_taxonomy) && $active_taxonomy == $val ? '<strong><i class="cooked-icon cooked-icon-angle-right"></i>&nbsp;&nbsp;' : '' ) . '<a href="' . esc_url($term_link) . '">' . esc_html($term_name) . '</a>' . ( isset($active_taxonomy) && $active_taxonomy == $val ? '</strong>' : '' ) : '' );
1010 $total_taxonomies++;
1011 $sub_terms_array = Cooked_Settings::terms_array( 'cp_recipe_category', false, false, true, false, $key );
1012 if ( !empty($sub_terms_array) ):
1013 foreach ( $sub_terms_array as $sub_key => $sub_val ):
1014 if ( $sub_key ):
1015 $sub_term = get_term( $sub_key );
1016 $sub_term_link = ( !empty($sub_term) ? get_term_link( $sub_term ) : false );
1017 $sub_term_name = apply_filters( 'cooked_term_name', $sub_term->name, $sub_term->ID, $sub_term->taxonomy );
1018 echo ( $sub_term_link ? '<span class="cooked-tax-sub-item">' . ( isset($active_taxonomy) && $active_taxonomy == $sub_val ? '<strong><i class="cooked-icon cooked-icon-angle-right"></i>&nbsp;&nbsp;' : '' ) . '<a href="' . esc_url($sub_term_link) . '">' . esc_html($sub_term_name) . '</a>' . ( isset($active_taxonomy) && $active_taxonomy == $sub_val ? '</strong>' : '' ) . '</span>' : '' );
1019 $total_taxonomies++;
1020 endif;
1021 endforeach;
1022 endif;
1023 endif;
1024 endforeach;
1025 $tax_col_count++;
1026 echo '</div>';
1027 echo '</span>';
1028 endif;
1029 endif;
1030
1031 do_action( 'cooked_after_search_filter_columns' );
1032
1033 $browse_html = ob_get_clean();
1034
1035 if ( !$inline_browse ):
1036
1037 echo wp_kses_post( $browse_html );
1038 echo '</span></span></div>';
1039
1040 endif;
1041
1042 endif;
1043
1044 if ( $total_taxonomies ):
1045 $taxonomy_search_fields = ob_get_clean();
1046 else:
1047 ob_clean();
1048 $taxonomy_search_fields = false;
1049 endif;
1050
1051 $page_id = $_cooked_settings['browse_page'] ? $_cooked_settings['browse_page'] : get_the_ID();
1052 $form_redirect = get_permalink($page_id);
1053
1054 $cooked_search_s = get_query_var('cooked_search_s', '');
1055 $cooked_search_s = urldecode($cooked_search_s);
1056 $cooked_search_s = Cooked_Functions::sanitize_text_field( $cooked_search_s );
1057
1058 ob_start();
1059
1060 echo '<section class="cooked-recipe-search cooked-clearfix' . ( isset( $options['compact'] ) && $options['compact'] ? ' cooked-search-compact' : '' ) . ( isset( $options['hide_sorting'] ) && $options['hide_sorting'] ? ' cooked-search-no-sorting' : '' ) . ( isset( $options['hide_browse'] ) && $options['hide_browse'] ? ' cooked-search-no-browse' : '' ) . '">';
1061
1062 echo '<form action="' . esc_url( $form_redirect ) . '" method="get">';
1063
1064 echo '<input type="hidden" name="page_id" value="' . intval( $page_id ) . '">';
1065 if ( isset($recipe_args['tax_query'][0]['taxonomy']) ):
1066 echo '<input type="hidden" name="' . esc_attr( $recipe_args['tax_query'][0]['taxonomy'] ) . '" value="' . esc_attr( $recipe_args['tax_query'][0]['terms'][0] ) . '">';
1067 endif;
1068
1069 echo '<div class="cooked-fields-wrap cooked-' . esc_attr( $tax_col_count ) . '-search-fields">';
1070
1071 echo !$options['hide_browse'] && $taxonomy_search_fields ? $taxonomy_search_fields : '';
1072
1073 echo '<input aria-label="' . __('Find a recipe...', 'cooked') . '" class="cooked-browse-search" type="text" name="cooked_search_s" value="' . ( !empty($cooked_search_s) ? $cooked_search_s : '' ) . '" placeholder="' . __('Find a recipe...','cooked') . '" />';
1074
1075 echo '<a aria-label="' . __('Search', 'cooked') . '" href="#" class="cooked-browse-search-button"><i class="cooked-icon cooked-icon-search"></i></a>';
1076
1077 echo '</div>';
1078
1079 if ( isset( $recipe_args['orderby'] ) && is_array( $recipe_args['orderby'] ) ):
1080 $sorting_type = key($recipe_args['orderby']) . '_' . current( $recipe_args['orderby'] );
1081 else:
1082 $sorting_type = ( isset( $recipe_args['orderby'] ) && isset( $recipe_args['order'] ) ? $recipe_args['orderby'] . '_' . $recipe_args['order'] : 'date_desc' );
1083 endif;
1084
1085 $sorting_types = apply_filters( 'cooked_browse_sorting_types', [
1086 'date_desc' => [
1087 'slug' => 'date_desc',
1088 'name' => __("Newest first", "cooked")
1089 ],
1090 'date_asc' => [
1091 'slug' => 'date_asc',
1092 'name' => __("Oldest first", "cooked")
1093 ],
1094 'title_asc' => [
1095 'slug' => 'title_asc',
1096 'name' => __("Alphabetical (A-Z)", "cooked")
1097 ],
1098 'title_desc' => [
1099 'slug' => 'title_desc',
1100 'name' => __("Alphabetical (Z-A)", "cooked")
1101 ]
1102 ], $sorting_type );
1103
1104 if ( !$options['hide_sorting'] ):
1105
1106 echo '<span class="cooked-sortby-wrap"><select class="cooked-sortby-select" name="cooked_browse_sort_by">';
1107 foreach ( $sorting_types as $value => $type ):
1108 echo '<option value="' . esc_attr( $value ) . '"' . ( $sorting_type == $type['slug'] ? ' selected' : '' ) . '>' . esc_attr( $type['name'] ) . '</option>';
1109 endforeach;
1110 echo '</select></span>';
1111
1112 endif;
1113
1114 echo '</form>';
1115
1116 echo '</section>';
1117
1118 if ( $inline_browse ):
1119 echo '<div class="cooked-browse-select-inline-block cooked-clearfix">';
1120 echo wp_kses_post( $browse_html );
1121 echo '</div>';
1122 endif;
1123
1124 return ob_get_clean();
1125 }
1126
1127 public function recipe_template( $content ) {
1128 global $wp_query, $post, $_cooked_content_unfiltered;
1129
1130 if ( post_password_required() ):
1131 return $content;
1132 endif;
1133
1134 if ( is_singular('cp_recipe') && is_main_query() && $_cooked_content_unfiltered == false ):
1135 ob_start();
1136
1137 include COOKED_DIR . 'templates/front/recipe.php';
1138 // load_template( COOKED_DIR . 'templates/front/recipe.php', false );
1139
1140 $recipe_content = ob_get_clean();
1141 return shortcode_unautop( apply_filters( 'cooked_recipe_content_filter', $recipe_content, $content, $post->ID ) );
1142
1143 endif;
1144
1145 return $content;
1146 }
1147
1148 /**
1149 * Cooked Classic 2.x Backwards Compatibility
1150 *
1151 * @since 1.0.0
1152 */
1153
1154 // Get and return the Cooked 2.x Classic recipe meta information
1155 public static function get_c2_recipe_meta( $post_id ) {
1156 $recipe_meta = [];
1157 $revised_array = [];
1158 $recipe_cs2_meta = get_post_meta($post_id);
1159
1160 if ( isset($recipe_cs2_meta['_cp_recipe_ingredients']) ):
1161
1162 foreach($recipe_cs2_meta as $key => $content):
1163 $revised_array[$key] = $content[0];
1164 endforeach;
1165
1166 $recipe_cs2_meta = $revised_array;
1167
1168 $recipe_meta['_cp_recipe_title'] = get_the_title( $post_id );
1169 $recipe_meta['_cp_recipe_ingredients'] = isset($recipe_cs2_meta['_cp_recipe_ingredients']) ? $recipe_cs2_meta['_cp_recipe_ingredients'] : false;
1170 $recipe_meta['_cp_recipe_detailed_ingredients'] = isset($recipe_cs2_meta['_cp_recipe_detailed_ingredients']) ? $recipe_cs2_meta['_cp_recipe_detailed_ingredients'] : false;
1171 $recipe_meta['_cp_recipe_directions'] = isset($recipe_cs2_meta['_cp_recipe_directions']) ? $recipe_cs2_meta['_cp_recipe_directions'] : false;
1172 $recipe_meta['_cp_recipe_detailed_directions'] = isset($recipe_cs2_meta['_cp_recipe_detailed_directions']) ? $recipe_cs2_meta['_cp_recipe_detailed_directions'] : false;
1173 $recipe_meta['_cp_recipe_external_video'] = isset($recipe_cs2_meta['_cp_recipe_external_video']) ? $recipe_cs2_meta['_cp_recipe_external_video'] : false;
1174 $recipe_meta['_cp_recipe_short_description'] = isset($recipe_cs2_meta['_cp_recipe_short_description']) ? $recipe_cs2_meta['_cp_recipe_short_description'] : false;
1175 $recipe_meta['_cp_recipe_excerpt'] = isset($recipe_cs2_meta['_cp_recipe_excerpt']) ? $recipe_cs2_meta['_cp_recipe_excerpt'] : false;
1176 $recipe_meta['_cp_recipe_difficulty_level'] = isset($recipe_cs2_meta['_cp_recipe_difficulty_level']) ? $recipe_cs2_meta['_cp_recipe_difficulty_level'] : false;
1177 $recipe_meta['_cp_recipe_prep_time'] = isset($recipe_cs2_meta['_cp_recipe_prep_time']) ? $recipe_cs2_meta['_cp_recipe_prep_time'] : false;
1178 $recipe_meta['_cp_recipe_cook_time'] = isset($recipe_cs2_meta['_cp_recipe_cook_time']) ? $recipe_cs2_meta['_cp_recipe_cook_time'] : false;
1179 $recipe_meta['_cp_recipe_additional_notes'] = isset($recipe_cs2_meta['_cp_recipe_additional_notes']) ? $recipe_cs2_meta['_cp_recipe_additional_notes'] : false;
1180 $recipe_meta['_cp_recipe_admin_rating'] = isset($recipe_cs2_meta['_cp_recipe_admin_rating']) ? $recipe_cs2_meta['_cp_recipe_admin_rating'] : false;
1181 $recipe_meta['_cp_recipe_yields'] = isset($recipe_cs2_meta['_cp_recipe_yields']) ? $recipe_cs2_meta['_cp_recipe_yields'] : false;
1182 $recipe_meta['_cp_recipe_nutrition_servingsize'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_servingsize']) ? $recipe_cs2_meta['_cp_recipe_nutrition_servingsize'] : false;
1183 $recipe_meta['_cp_recipe_nutrition_calories'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_calories']) ? $recipe_cs2_meta['_cp_recipe_nutrition_calories'] : false;
1184 $recipe_meta['_cp_recipe_nutrition_fat'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_fat']) ? $recipe_cs2_meta['_cp_recipe_nutrition_fat'] : false;
1185 $recipe_meta['_cp_recipe_nutrition_satfat'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_satfat']) ? $recipe_cs2_meta['_cp_recipe_nutrition_satfat'] : false;
1186 $recipe_meta['_cp_recipe_nutrition_transfat'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_transfat']) ? $recipe_cs2_meta['_cp_recipe_nutrition_transfat'] : false;
1187 $recipe_meta['_cp_recipe_nutrition_cholesterol'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_cholesterol']) ? $recipe_cs2_meta['_cp_recipe_nutrition_cholesterol'] : false;
1188 $recipe_meta['_cp_recipe_nutrition_sodium'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_sodium']) ? $recipe_cs2_meta['_cp_recipe_nutrition_sodium'] : false;
1189 $recipe_meta['_cp_recipe_nutrition_potassium'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_potassium']) ? $recipe_cs2_meta['_cp_recipe_nutrition_potassium'] : false;
1190 $recipe_meta['_cp_recipe_nutrition_carbs'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_carbs']) ? $recipe_cs2_meta['_cp_recipe_nutrition_carbs'] : false;
1191 $recipe_meta['_cp_recipe_nutrition_fiber'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_fiber']) ? $recipe_cs2_meta['_cp_recipe_nutrition_fiber'] : false;
1192 $recipe_meta['_cp_recipe_nutrition_sugar'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_sugar']) ? $recipe_cs2_meta['_cp_recipe_nutrition_sugar'] : false;
1193 $recipe_meta['_cp_recipe_nutrition_protein'] = isset($recipe_cs2_meta['_cp_recipe_nutrition_protein']) ? $recipe_cs2_meta['_cp_recipe_nutrition_protein'] : false;
1194
1195 if ( !$recipe_meta['_cp_recipe_excerpt'] ):
1196 $recipe_meta['_cp_recipe_excerpt'] = $recipe_meta['_cp_recipe_short_description'];
1197 $recipe_meta['_cp_recipe_short_description'] = false;
1198 endif;
1199
1200 return $recipe_meta;
1201
1202 endif;
1203
1204 return [];
1205 }
1206
1207 // Sync up the Cooked 2.x Classic recipe meta fields to the new Cooked 3.x meta fields
1208 public static function sync_c2_recipe_settings( $c2_recipe_settings, $recipe_id ) {
1209 $recipe_settings = [];
1210 $ingredients = [];
1211 $directions = [];
1212
1213 $recipe_settings['title'] = isset($c2_recipe_settings['_cp_recipe_title']) ? $c2_recipe_settings['_cp_recipe_title'] : '';
1214 $recipe_settings['content'] = isset($c2_recipe_settings['_cp_recipe_short_description']) ? wpautop( $c2_recipe_settings['_cp_recipe_short_description'] . ($c2_recipe_settings['_cp_recipe_short_description'] ? '<br><br>' : '') . Cooked_Recipes::default_content() . ($c2_recipe_settings['_cp_recipe_additional_notes'] ? '<br><br>' : '') . $c2_recipe_settings['_cp_recipe_additional_notes'] ) : '';
1215 $recipe_settings['excerpt'] = isset($c2_recipe_settings['_cp_recipe_excerpt']) ? $c2_recipe_settings['_cp_recipe_excerpt'] : '';
1216 $recipe_settings['difficulty_level'] = isset($c2_recipe_settings['_cp_recipe_difficulty_level']) ? $c2_recipe_settings['_cp_recipe_difficulty_level'] : '';
1217 $recipe_settings['prep_time'] = isset($c2_recipe_settings['_cp_recipe_prep_time']) ? $c2_recipe_settings['_cp_recipe_prep_time'] : '';
1218 $recipe_settings['cook_time'] = isset($c2_recipe_settings['_cp_recipe_cook_time']) ? $c2_recipe_settings['_cp_recipe_cook_time'] : '';
1219
1220 // Ingredients
1221 if ( !empty($c2_recipe_settings['_cp_recipe_ingredients']) && empty($c2_recipe_settings['_cp_recipe_detailed_ingredients']) ):
1222 $ingredients = explode("\n", $c2_recipe_settings['_cp_recipe_ingredients']);
1223 elseif ( !empty($c2_recipe_settings['_cp_recipe_detailed_ingredients']) ):
1224 $ingredients = unserialize( $c2_recipe_settings['_cp_recipe_detailed_ingredients'] );
1225 endif;
1226
1227 if ( !empty($ingredients) ):
1228 foreach( $ingredients as $ing ):
1229 $rand_id = wp_rand( 1000000,9999999 );
1230 if ( isset($ing['type']) && $ing['type'] == 'ingredient' ):
1231 $recipe_settings['ingredients'][$rand_id]['amount'] = $ing['amount'];
1232 $recipe_settings['ingredients'][$rand_id]['measurement'] = $ing['measurement'];
1233 $recipe_settings['ingredients'][$rand_id]['name'] = $ing['name'];
1234 elseif ( isset($ing['type']) && $ing['type'] == 'section' ):
1235 $recipe_settings['ingredients'][$rand_id]['section_heading_name'] = $ing['value'];
1236 else:
1237 if ( substr($ing, 0, 2) == '--' ):
1238 $recipe_settings['ingredients'][$rand_id]['section_heading_name'] = substr($ing, 2);
1239 else:
1240 $recipe_settings['ingredients'][$rand_id]['amount'] = false;
1241 $recipe_settings['ingredients'][$rand_id]['measurement'] = false;
1242 $recipe_settings['ingredients'][$rand_id]['name'] = $ing;
1243 endif;
1244 endif;
1245 endforeach;
1246 endif;
1247
1248 // Directions
1249 if ( !empty($c2_recipe_settings['_cp_recipe_directions']) && empty($c2_recipe_settings['_cp_recipe_detailed_directions']) ):
1250 $directions = explode("\n", $c2_recipe_settings['_cp_recipe_directions']);
1251 elseif ( !empty($c2_recipe_settings['_cp_recipe_detailed_directions']) ):
1252 $directions = unserialize( $c2_recipe_settings['_cp_recipe_detailed_directions'] );
1253 endif;
1254
1255 if ( !empty($directions) ):
1256
1257 foreach( $directions as $dir ):
1258 $rand_id = wp_rand( 1000000,9999999 );
1259 if ( isset($dir['type']) && $dir['type'] == 'direction' ):
1260 $recipe_settings['directions'][$rand_id]['image'] = $dir['image_id'];
1261 $recipe_settings['directions'][$rand_id]['content'] = $dir['value'];
1262 elseif ( isset($dir['type']) && $dir['type'] == 'section' ):
1263 $recipe_settings['directions'][$rand_id]['section_heading_name'] = $dir['value'];
1264 else:
1265 if ( substr($dir, 0, 2) == '--' ):
1266 $recipe_settings['directions'][$rand_id]['section_heading_name'] = substr($dir, 2);
1267 else:
1268 $recipe_settings['directions'][$rand_id]['image'] = false;
1269 $recipe_settings['directions'][$rand_id]['content'] = $dir;
1270 endif;
1271 endif;
1272 endforeach;
1273
1274 endif;
1275
1276 if ( isset($c2_recipe_settings['_cp_recipe_external_video']) && $c2_recipe_settings['_cp_recipe_external_video'] && wp_oembed_get( $c2_recipe_settings['_cp_recipe_external_video'] ) ):
1277 $recipe_settings['gallery']['video_url'] = $c2_recipe_settings['_cp_recipe_external_video'];
1278 else:
1279 $recipe_settings['gallery']['video_url'] = false;
1280 $recipe_settings['gallery']['type'] = 'cooked';
1281 endif;
1282
1283 $recipe_settings['nutrition']['serving_size'] = ( isset($c2_recipe_settings['_cp_recipe_yields']) && $c2_recipe_settings['_cp_recipe_yields'] ? $c2_recipe_settings['_cp_recipe_yields'] : false );
1284 $recipe_settings['nutrition']['servings'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_servingsize']) && $c2_recipe_settings['_cp_recipe_nutrition_servingsize'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_servingsize']) : false );
1285 $recipe_settings['nutrition']['calories'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_calories']) && $c2_recipe_settings['_cp_recipe_nutrition_calories'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_calories']) : false );
1286 $recipe_settings['nutrition']['fat'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_fat']) && $c2_recipe_settings['_cp_recipe_nutrition_fat'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_fat']) : false );
1287 $recipe_settings['nutrition']['sat_fat'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_satfat']) && $c2_recipe_settings['_cp_recipe_nutrition_satfat'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_satfat']) : false );
1288 $recipe_settings['nutrition']['trans_fat'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_transfat']) && $c2_recipe_settings['_cp_recipe_nutrition_transfat'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_transfat']) : false );
1289 $recipe_settings['nutrition']['cholesterol'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_cholesterol']) && $c2_recipe_settings['_cp_recipe_nutrition_cholesterol'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_cholesterol']) : false );
1290 $recipe_settings['nutrition']['sodium'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_sodium']) && $c2_recipe_settings['_cp_recipe_nutrition_sodium'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_sodium']) : false );
1291 $recipe_settings['nutrition']['potassium'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_potassium']) && $c2_recipe_settings['_cp_recipe_nutrition_potassium'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_potassium']) : false );
1292 $recipe_settings['nutrition']['carbs'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_carbs']) && $c2_recipe_settings['_cp_recipe_nutrition_carbs'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_carbs']) : false );
1293 $recipe_settings['nutrition']['fiber'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_fiber']) && $c2_recipe_settings['_cp_recipe_nutrition_fiber'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_fiber']) : false );
1294 $recipe_settings['nutrition']['sugars'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_sugar']) && $c2_recipe_settings['_cp_recipe_nutrition_sugar'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_sugar']) : false );
1295 $recipe_settings['nutrition']['protein'] = ( isset($c2_recipe_settings['_cp_recipe_nutrition_protein']) && $c2_recipe_settings['_cp_recipe_nutrition_protein'] ? preg_replace("/[^0-9]/","",$c2_recipe_settings['_cp_recipe_nutrition_protein']) : false );
1296
1297 $_nutrition_facts = Cooked_Measurements::nutrition_facts();
1298 foreach( $_nutrition_facts as $nutrition_facts ):
1299 foreach( $nutrition_facts as $slug => $nf ):
1300
1301 if ( !isset($recipe_settings[$slug]) ): $recipe_settings[$slug] = false; endif;
1302 if ( isset($nf['subs']) ):
1303 foreach( $nf['subs'] as $sub_slug => $sub_nf ):
1304 if ( !isset($recipe_settings[$sub_slug]) ): $recipe_settings[$sub_slug] = false; endif;
1305 endforeach;
1306 endif;
1307 endforeach;
1308 endforeach;
1309
1310 return apply_filters( 'cooked_sync_c2_recipe_settings', $recipe_settings, $recipe_id );
1311 }
1312
1313 public function modify_browse_page_canonical_url($canonical_url, $post = null) {
1314 global $_cooked_settings, $wp_query;
1315
1316 if (!is_page()) {
1317 return $canonical_url;
1318 }
1319
1320 $browse_page_id = !empty($_cooked_settings['browse_page']) ? $_cooked_settings['browse_page'] : false;
1321
1322 // Only modify for browse page with category.
1323 if (is_page($browse_page_id) &&
1324 isset($wp_query->query['cp_recipe_category']) &&
1325 taxonomy_exists('cp_recipe_category') &&
1326 term_exists($wp_query->query['cp_recipe_category'], 'cp_recipe_category')) {
1327
1328 // Build the canonical URL based on permalink structure.
1329 if (get_option('permalink_structure')) {
1330 $new_canonical = untrailingslashit(get_permalink($browse_page_id)) . '/' . $_cooked_settings['recipe_category_permalink'] . '/' . $wp_query->query['cp_recipe_category'];
1331 } else {
1332 $new_canonical = add_query_arg('cp_recipe_category', $wp_query->query['cp_recipe_category'], get_permalink($browse_page_id));
1333 }
1334
1335 return $new_canonical;
1336 }
1337
1338 return $canonical_url;
1339 }
1340 }
1341
1342 global $Cooked_Recipes;
1343 $Cooked_Recipes = new Cooked_Recipes();
1344