PluginProbe
Cooked – Recipe Management / 1.16.1
Cooked – Recipe Management v1.16.1
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-allergens.php

class.cooked-allergens.php in Cooked – Recipe Management 1.16.1, at includes/class.cooked-allergens.php

372 lines 11.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Cooked Allergens
4 *
5 * @package Cooked
6 * @subpackage Allergens
7 * @since 1.15.0
8 */
9
10 // Exit if accessed directly
11 if ( ! defined( 'ABSPATH' ) ) exit;
12
13 /**
14 * Cooked_Allergens Class
15 *
16 * Handles allergen storage, admin UI, recipe card icons,
17 * and the `allergens` field for the [cooked-info] shortcode.
18 *
19 * @since 1.15.0
20 */
21 class Cooked_Allergens {
22
23 /**
24 * Initialize allergen hooks.
25 *
26 * @since 1.15.0
27 */
28 public static function init() {
29 add_action( 'add_meta_boxes', [ __CLASS__, 'register_meta_box' ] );
30
31 foreach ( self::get_recipe_card_hooks() as $hook ) {
32 add_action( $hook, [ __CLASS__, 'render_from_recipe' ], 10 );
33 }
34
35 add_filter( 'cooked_settings_tabs_fields', [ __CLASS__, 'settings_tabs_fields' ], 11 );
36
37 // [cooked-info] integration
38 add_filter( 'cooked_default_info_array', [ __CLASS__, 'register_info_field' ] );
39 add_filter( 'cooked_available_info_shortcode_methods', [ __CLASS__, 'register_info_method' ] );
40 add_filter( 'cooked_available_info_vars', [ __CLASS__, 'register_info_var' ] );
41 }
42
43 /**
44 * Recipe card hooks used by Cooked list styles.
45 *
46 * @since 1.15.0
47 * @return array
48 */
49 public static function get_recipe_card_hooks() {
50 return apply_filters( 'cooked_recipe_card_allergen_hooks', [
51 'cooked_recipe_grid_after_name',
52 'cooked_recipe_modern_after_name',
53 'cooked_recipe_full_after_name',
54 ] );
55 }
56
57 /**
58 * Add allergen display settings to the General settings tab.
59 *
60 * @since 1.15.0
61 * @param array $settings Settings tabs and fields.
62 * @return array
63 */
64 public static function settings_tabs_fields( $settings ) {
65 if ( ! isset( $settings['recipe_settings']['fields'] ) ) {
66 return $settings;
67 }
68
69 $after = isset( $settings['recipe_settings']['fields']['recipe_list_style'] )
70 ? 'recipe_list_style'
71 : 'browse_page';
72
73 Cooked_Functions::array_splice_assoc( $settings['recipe_settings']['fields'], $after, 0, [
74 'recipe_list_allergens' => [
75 'title' => __( 'Recipe List Allergens', 'cooked' ),
76 'desc' => __( 'Show allergen icons on recipe cards in browse and list views.', 'cooked' ),
77 'type' => 'checkboxes',
78 'default' => [
79 'enabled' => false,
80 ],
81 'options' => [
82 'enabled' => __( 'Show Allergens on Recipe Cards', 'cooked' ),
83 ],
84 ],
85 ] );
86
87 return $settings;
88 }
89
90 /**
91 * Whether allergen icons should display on recipe list cards.
92 *
93 * @since 1.15.0
94 * @return bool
95 */
96 public static function show_on_recipe_cards() {
97 global $_cooked_settings;
98
99 return ! empty( $_cooked_settings['recipe_list_allergens'] )
100 && in_array( 'enabled', (array) $_cooked_settings['recipe_list_allergens'], true );
101 }
102
103 /**
104 * Register the allergens meta box for the sidebar.
105 *
106 * @since 1.15.0
107 */
108 public static function register_meta_box() {
109 add_meta_box(
110 'cooked_allergens',
111 __( 'Allergens', 'cooked' ),
112 [ __CLASS__, 'render_meta_box' ],
113 'cp_recipe',
114 'side',
115 'default'
116 );
117 }
118
119 /**
120 * Render the allergens meta box content.
121 *
122 * @since 1.15.0
123 * @param WP_Post $post The post object.
124 */
125 public static function render_meta_box( $post ) {
126 $recipe_settings = get_post_meta( $post->ID, '_recipe_settings', true );
127 $selected = isset( $recipe_settings['allergens'] ) && is_array( $recipe_settings['allergens'] )
128 ? $recipe_settings['allergens']
129 : [];
130 self::render_field_checkboxes( $selected );
131 }
132
133 /**
134 * Render allergen checkbox field markup (admin metabox and front-end form).
135 *
136 * @since 1.15.0
137 * @param array $selected Selected allergen storage keys.
138 */
139 public static function render_field_checkboxes( $selected = [] ) {
140 if ( ! is_array( $selected ) ) {
141 $selected = [];
142 }
143
144 $allergens = self::get_allergens();
145 ?>
146 <div class="cooked-allergens-checkboxes">
147 <?php foreach ( $allergens as $key => $allergen ) : ?>
148 <label class="cooked-allergen-checkbox">
149 <input type="checkbox"
150 name="_recipe_settings[allergens][]"
151 value="<?php echo esc_attr( $key ); ?>"
152 <?php checked( in_array( $key, $selected, true ) ); ?>>
153 <span class="cooked-allergen cooked-allergen-<?php echo esc_attr( $key ); ?>">
154 <i class="cooked-icon <?php echo esc_attr( self::get_icon_class( $allergen ) ); ?>" aria-hidden="true"></i>
155 </span>
156 <span class="cooked-allergen-label"><?php echo esc_html( $allergen['label'] ); ?></span>
157 </label>
158 <?php endforeach; ?>
159 </div>
160 <?php
161 }
162
163 /**
164 * Whitelist selected allergen keys against known definitions.
165 *
166 * @since 1.15.0
167 * @param array $selected Submitted allergen keys.
168 * @return array
169 */
170 public static function sanitize_selected( $selected ) {
171 if ( ! is_array( $selected ) ) {
172 return [];
173 }
174
175 $valid_keys = array_keys( self::get_allergens() );
176
177 return array_values( array_intersect( $selected, $valid_keys ) );
178 }
179
180 /**
181 * Get the list of major allergens (FDA + EU).
182 *
183 * @since 1.15.0
184 * @return array
185 */
186 public static function get_allergens() {
187 return apply_filters( 'cooked_allergens', [
188 'celery' => [
189 'label' => __( 'Celery', 'cooked' ),
190 'icon' => 'allergen-celery',
191 ],
192 'shellfish' => [
193 'label' => __( 'Crustacean shellfish', 'cooked' ),
194 'icon' => 'allergen-shellfish',
195 ],
196 'eggs' => [
197 'label' => __( 'Eggs', 'cooked' ),
198 'icon' => 'allergen-egg',
199 ],
200 'fish' => [
201 'label' => __( 'Fish', 'cooked' ),
202 'icon' => 'allergen-fish',
203 ],
204 'lupin' => [
205 'label' => __( 'Lupin', 'cooked' ),
206 'icon' => 'allergen-lupin',
207 ],
208 'milk' => [
209 'label' => __( 'Milk', 'cooked' ),
210 'icon' => 'allergen-milk',
211 ],
212 'molluscs' => [
213 'label' => __( 'Molluscs', 'cooked' ),
214 'icon' => 'allergen-molluscs',
215 ],
216 'mustard' => [
217 'label' => __( 'Mustard', 'cooked' ),
218 'icon' => 'allergen-mustard',
219 ],
220 'peanuts' => [
221 'label' => __( 'Peanuts', 'cooked' ),
222 'icon' => 'allergen-peanut',
223 ],
224 'sesame' => [
225 'label' => __( 'Sesame', 'cooked' ),
226 'icon' => 'allergen-sesame',
227 ],
228 'soybeans' => [
229 'label' => __( 'Soybeans', 'cooked' ),
230 'icon' => 'allergen-soy',
231 ],
232 'sulphites' => [
233 'label' => __( 'Sulphur dioxide and sulphites', 'cooked' ),
234 'icon' => 'allergen-sulphites',
235 ],
236 'tree_nuts' => [
237 'label' => __( 'Tree nuts', 'cooked' ),
238 'icon' => 'allergen-tree-nut',
239 ],
240 'wheat' => [
241 'label' => __( 'Wheat', 'cooked' ),
242 'icon' => 'allergen-wheat',
243 ],
244 ] );
245 }
246
247 /**
248 * Get the CookedIcons class for an allergen.
249 *
250 * @since 1.15.0
251 * @param array $allergen Allergen definition.
252 * @return string
253 */
254 public static function get_icon_class( $allergen ) {
255 return 'cooked-icon-' . $allergen['icon'];
256 }
257
258 /**
259 * Render allergen badges from recipe array (used in hooks).
260 *
261 * @since 1.15.0
262 * @param array $recipe Recipe data array with 'id' key.
263 */
264 public static function render_from_recipe( $recipe ) {
265 if ( ! self::show_on_recipe_cards() ) {
266 return;
267 }
268
269 if ( empty( $recipe['id'] ) ) {
270 return;
271 }
272
273 $recipe_settings = Cooked_Recipes::get_settings( $recipe['id'] );
274 echo wp_kses_post( self::render( $recipe_settings ) );
275 }
276
277 /**
278 * Render allergen badges HTML.
279 *
280 * @since 1.15.0
281 * @param array $recipe_settings Recipe settings array.
282 * @return string HTML output.
283 */
284 public static function render( $recipe_settings ) {
285 if ( empty( $recipe_settings['allergens'] ) || ! is_array( $recipe_settings['allergens'] ) ) {
286 return '';
287 }
288
289 $allergens = self::get_allergens();
290 $selected = $recipe_settings['allergens'];
291 $output = '<span class="cooked-allergens">';
292
293 foreach ( $selected as $key ) {
294 if ( ! isset( $allergens[ $key ] ) ) {
295 continue;
296 }
297
298 $allergen = $allergens[ $key ];
299 $output .= sprintf(
300 '<span class="cooked-allergen cooked-allergen-%1$s" title="%2$s"><i class="cooked-icon %3$s" aria-hidden="true"></i></span>',
301 esc_attr( $key ),
302 /* translators: %s: allergen name */
303 esc_attr( sprintf( __( 'Contains %s', 'cooked' ), $allergen['label'] ) ),
304 esc_attr( self::get_icon_class( $allergen ) )
305 );
306 }
307
308 $output .= '</span>';
309
310 return $output;
311 }
312
313 /**
314 * Register `allergens` in the [cooked-info] default info array.
315 *
316 * @since 1.15.0
317 * @param array $info Default info array.
318 * @return array
319 */
320 public static function register_info_field( $info ) {
321 $info['allergens'] = __( 'Allergens', 'cooked' );
322 return $info;
323 }
324
325 /**
326 * Register the handler that renders the `allergens` info field.
327 *
328 * @since 1.15.0
329 * @param array $methods Method map keyed by function name.
330 * @return array
331 */
332 public static function register_info_method( $methods ) {
333 $methods['cooked_info_allergens'] = __CLASS__;
334 return $methods;
335 }
336
337 /**
338 * Add `allergens` to the documented variables in the Shortcodes tab.
339 *
340 * @since 1.15.0
341 * @param array $vars Documented variables.
342 * @return array
343 */
344 public static function register_info_var( $vars ) {
345 $vars['allergens'] = __( 'Allergens', 'cooked' );
346 return $vars;
347 }
348
349 /**
350 * [cooked-info] handler for the `allergens` field.
351 *
352 * Outputs nothing when no allergens are selected on the recipe.
353 *
354 * @since 1.15.0
355 * @param array $recipe_settings Recipe settings array.
356 */
357 public static function cooked_info_allergens( $recipe_settings ) {
358 $html = self::render( $recipe_settings );
359 if ( ! $html ) {
360 return;
361 }
362
363 echo '<span class="cooked-allergens-info">';
364 echo '<strong class="cooked-meta-title">' . esc_html__( 'Allergens', 'cooked' ) . '</strong>';
365 echo wp_kses_post( $html );
366 echo '</span>';
367 }
368
369 }
370
371 add_action( 'init', [ 'Cooked_Allergens', 'init' ] );
372