$page_data ) { if ( $page_data['id'] == $post_id ) { flush_rewrite_rules(false); return; } } } public static function init() { global $_cooked_settings, $list_id_counter; $list_id_counter = 0; $_cooked_settings = Cooked_Settings::get(); register_setting( 'cooked_settings_group', 'cooked_settings', ['sanitize_callback' => [__CLASS__, 'sanitize_settings']] ); register_setting( 'cooked_settings_group', 'cooked_settings_saved', ['sanitize_callback' => [__CLASS__, 'sanitize_saved_flag']] ); } public static function sanitize_saved_flag( $value ) { return rest_sanitize_boolean( $value ); } // Add this new method to handle settings sanitization. public static function sanitize_settings($settings) { $cooked_tabs_fields = self::tabs_fields(); // Process each field foreach ($cooked_tabs_fields as $tab) { if (isset($tab['fields']) && !empty($tab['fields'])) { foreach ($tab['fields'] as $field_name => $field) { // Handle checkbox fields specifically if ($field['type'] === 'checkboxes') { // If the field is missing from submission, set it as an empty array if (!isset($settings[$field_name])) { $settings[$field_name] = []; } else { // Remove any empty string values from checkbox arrays if (!isset($settings[$field_name]) || !is_array($settings[$field_name])) { $settings[$field_name] = []; } else { $settings[$field_name] = array_filter($settings[$field_name], function($value) { return $value !== ''; }); } } } elseif ( $field['type'] === 'image_field' ) { $image_id = isset( $settings[ $field_name ] ) ? absint( $settings[ $field_name ] ) : 0; if ( $image_id && ! wp_attachment_is_image( $image_id ) ) { $image_id = 0; } $settings[ $field_name ] = $image_id; } } } } if ( isset( $settings['dark_mode'] ) ) { $settings['dark_mode'] = self::normalize_dark_mode( $settings['dark_mode'] ); } return $settings; } function cooked_settings_saved_admin_notice() { // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Display-only Settings API query vars. $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; $settings_updated = isset( $_GET['settings-updated'] ) ? rest_sanitize_boolean( wp_unslash( $_GET['settings-updated'] ) ) : false; // phpcs:enable WordPress.Security.NonceVerification.Recommended if ( $settings_updated && $page === 'cooked_settings' ) { add_settings_error( 'cooked_settings_group', 'cooked_settings_updated', __( 'Cooked settings has been updated!', 'cooked' ), 'updated' ); } } function browse_page_missing_notice() { // Only show on admin pages, not on the Cooked settings page itself // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Display-only admin page query var. $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; if ( $page === 'cooked_settings' ) { return; } // Get Cooked settings $_cooked_settings = self::get(); // Check if browse page is set if ( empty($_cooked_settings['browse_page']) || !$_cooked_settings['browse_page'] ) { $class = 'notice notice-warning is-dismissible'; $message = sprintf( '' . __( 'Cooked Plugin Setup', 'cooked' ) . ' ' . /* translators: %s: Browse/Search Recipes Page link */ __( 'To display your recipes properly, please set up your %s.', 'cooked' ), '' . __( 'Browse/Search Recipes Page', 'cooked' ) . '' ); printf( '
%2$s
[cooked-browse]') . '[cooked-browse]'),
'type' => 'select',
'default' => 0,
'options' => $categories_array
],
'browse_default_sort' => [
'title' => __('Default Sort Order', 'cooked'),
/* translators: a description on how to set the default sort order for the [cooked-browse] shortcode. */
'desc' => sprintf(__('Set the default sort order for your %s shortcode display.', 'cooked'), '[cooked-browse]'),
'type' => 'select',
'default' => 'date_desc',
'options' => apply_filters(
'cooked_settings_sort_options',
[
'date_desc' => __('Newest First', 'cooked'),
'date_asc' => __('Oldest First', 'cooked'),
'title_asc' => __('Alphabetical', 'cooked'),
'title_desc' => __('Alphabetical (reversed)', 'cooked'),
]
)
],
'section_heading_default_html_tag' => [
'title' => __('Section Heading Default HTML Tag', 'cooked'),
/* translators: a description on how to set the default sort order for the [cooked-browse] shortcode. */
'desc' => __('Set the default HTML tag for your section headings.', 'cooked'),
'type' => 'select',
'default' => 'div',
'options' => apply_filters(
'cooked_settings_section_heading_default_html_tag_options',
[
'div' => __('div', 'cooked'),
'h2' => __('h2', 'cooked'),
'h3' => __('h3', 'cooked'),
'h4' => __('h4', 'cooked'),
'h5' => __('h5', 'cooked'),
'h6' => __('h6', 'cooked'),
]
)
],
'recipe_wp_editor_roles' => [
'title' => __('WP Editor Roles', 'cooked'),
'desc' => __('Choose which user roles can use the WP Editor for the Excerpt, Directions & Notes fields.', 'cooked'),
'type' => 'checkboxes',
'default' => apply_filters('cooked_recipe_wp_editor_roles_defaults', ['administrator', 'editor', 'cooked_recipe_editor']),
'options' => $role_options
],
'advanced' => [
'title' => __('Advanced Settings', 'cooked'),
'desc' => '',
'type' => 'checkboxes',
'color' => 'red',
'class' => 'cooked-danger',
'default' => [],
'options' => apply_filters(
'cooked_advanced_options',
[
/* translators: an option to only show recipes with the [cooked-recipe] shortcode. */
'disable_public_recipes' => '' . __('Disable Public Recipes', 'cooked') . ' — ' . sprintf(__('Only show recipes using the %s shortcode.', 'cooked'), '[cooked-recipe]'),
/* translators: an option to disable "meta" tags. */
'disable_meta_tags' => '' . sprintf(__('Disable %s Tags', 'cooked'), 'Cooked <meta>') . ' — ' . __('Prevents duplicates when tags already exist.', 'cooked'),
'disable_servings_switcher' => '' . __('Disable "Servings Switcher"', 'cooked') . ' — ' . __('Removes the servings dropdown on recipes.', 'cooked'),
'enable_measurement_switcher' => '' . __('Enable "Measurement System Switcher"', 'cooked') . ' — ' . __('Shows the Metric/Imperial toggle on recipes.', 'cooked'),
'disable_schema_output' => '' . __('Disable Recipe Schema Output', 'cooked') . ' — ' . __('You should only do this if you\'re using something else to output schema information.', 'cooked'),
'disable_cp_recipe_archive' => '' . __( 'Disable Recipe Archive Page', 'cooked' ) . ' — ' . sprintf(
/* translators: %s: recipe archive URL, e.g. https://example.com/recipe-archive/ */
__( 'Prevents the recipe archive from being displayed at %s.', 'cooked' ),
'' . esc_html( untrailingslashit( $recipe_archive_url ) ) . '/'
)
]
)
],
]
],
'design' => [
'name' => __('Design', 'cooked'),
'icon' => 'pencil',
'fields' => [
'dark_mode' => [
'title' => __('Dark Mode', 'cooked'),
'desc' => apply_filters(
'cooked_dark_mode_field_desc',
__( 'Use Auto if your theme has a visitor dark mode toggle. Cooked will then match that choice. Otherwise leave this Off.', 'cooked' )
),
'type' => 'select',
'default' => 'off',
'options' => apply_filters(
'cooked_dark_mode_options',
[
'off' => __('Off', 'cooked'),
'enabled' => __('On', 'cooked'),
'auto' => __('Auto (match theme dark mode)', 'cooked'),
]
)
],
'hide_author_avatars' => [
'title' => __('Author Images', 'cooked'),
'desc' => __('If you do not want to display the author images (avatars), you can disable them here.', 'cooked'),
'type' => 'checkboxes',
'color' => 'red',
'default' => [],
'options' => apply_filters(
'cooked_author_image_options',
[
'hidden' => __('Hide Author Images', 'cooked'),
]
)
],
'default_recipe_image' => [
'title' => __( 'Default Recipe Image', 'cooked' ),
'desc' => __( 'Used as the featured image for recipes that do not have one set.', 'cooked' ),
'type' => 'image_field',
'default' => 0,
],
'main_color' => [
'title' => __('Main Color', 'cooked'),
'desc' => __('Used on buttons, cooking timer, etc.', 'cooked'),
'type' => 'color_field',
'default' => '#16a780',
'options' => '#16a780'
],
'main_color_hover' => [
'title' => __('Main Color (on hover)', 'cooked'),
'desc' => __('Used when hovering over buttons.', 'cooked'),
'type' => 'color_field',
'default' => '#1b9371',
'options' => '#1b9371'
],
'responsive_breakpoint_1' => [
'title' => __('First Responsive Breakpoint', 'cooked'),
'desc' => __('Set the first responsive breakpoint. Best for large tablets.', 'cooked'),
'type' => 'number_field',
'default' => '1000',
'options' => ''
],
'responsive_breakpoint_2' => [
'title' => __('Second Responsive Breakpoint', 'cooked'),
'desc' => __('Set the second responsive breakpoint. Best for small tablets.', 'cooked'),
'type' => 'number_field',
'default' => '750',
'options' => ''
],
'responsive_breakpoint_3' => [
'title' => __('Third Responsive Breakpoint', 'cooked'),
'desc' => __('Set the third responsive breakpoint. Best for phones and other small devices.', 'cooked'),
'type' => 'number_field',
'default' => '520',
'options' => ''
]
]
],
'permalinks' => [
'name' => __('Permalinks', 'cooked'),
'icon' => 'link-lt',
'fields' => [
'recipe_permalink' => [
'title' => __('Recipe Permalink', 'cooked'),
'desc' => '',
'type' => 'permalink_field',
'options' => __('recipe-name', 'cooked'),
'default' => 'recipes'
],
'recipe_author_permalink' => [
'title' => __('Recipe Author Permalink', 'cooked'),
'desc' => '',
'type' => 'permalink_field',
'options' => __('author-name', 'cooked'),
'default' => 'recipe-author'
],
'recipe_category_permalink' => [
'title' => __('Recipe Category Permalink', 'cooked'),
'desc' => '',
'type' => 'permalink_field',
'options' => __('recipe-category-name', 'cooked'),
'default' => 'recipe-category'
]
]
]
], $pages_array, $categories_array);
}
public static function per_page_array() {
$counter = 0;
/* translators: posts_per_page default */
$per_page_array[] = sprintf( __('WordPress Default %s','cooked'), '(' . get_option( 'posts_per_page' ) . ')' );
do {
$counter++;
$per_page_array[$counter] = $counter;
} while ( $counter < 50 );
$per_page_array['-1'] = __('Show All (no pagination)','cooked');
return apply_filters( 'cooked_per_page_options', $per_page_array );
}
public static function pages_array( $choose_text, $none_text = false ) {
$page_array = [];
$pages = get_posts([
'post_type' => 'page',
'posts_per_page' => -1
]);
if( !empty($pages) ) {
$page_array[0] = $choose_text;
foreach ($pages as $_page) {
$page_array[$_page->ID] = $_page->post_title . ' (ID:' . $_page->ID . ')';
}
} elseif ( $none_text ) {
$page_array[0] = $none_text;
}
return apply_filters( 'cooked_settings_pages_array', $page_array );
}
public static function terms_array( $term, $choose_text, $none_text = false, $hide_empty = false, $parents_only = false, $child_of = false ) {
$terms_array = [];
$args = [
'taxonomy' => $term,
'hide_empty' => $hide_empty
];
if ( $parents_only ) {
$args['parent'] = '0';
} elseif ( $child_of ) {
$_term = is_numeric($child_of) ? $child_of : get_term_by( 'slug', $child_of, $term );
$term_id = is_object( $_term ) ? $_term->term_id : $_term;
$args['parent'] = $term_id;
}
$terms = get_terms( $args );
if ( !empty($terms) ) {
if ($choose_text) {
$terms_array[0] = $choose_text;
}
foreach ($terms as $_term) {
if ( !is_array($_term) ) {
$terms_array[$_term->term_id] = $_term->name;
}
}
} elseif ( $none_text ) {
$terms_array[0] = $none_text;
}
return apply_filters( 'cooked_settings_' . $term . '_array', $terms_array );
}
public static function field_radio( $field_name, $options ) {
global $_cooked_settings, $conditions;
$counter = 1;
echo '';
foreach ( $options as $value => $name) {
$is_disabled = '';
$conditional_value = '';
$conditional_requirement = '';
if ( is_array($name) ):
if ( isset($name['read_only']) && $name['read_only'] ):
$is_disabled = ' disabled';
endif;
if ( isset($name['conditional_value']) && $name['conditional_value'] ):
$conditional_value = ' v-model="' . esc_attr($name['conditional_value']) . '"';
if ( !in_array( $name['conditional_value'], $conditions ) ):
$conditions[$value] = esc_attr($name['conditional_requirement']);
endif;
endif;
if ( isset($name['conditional_requirement']) && $name['conditional_requirement'] ):
if ( is_array($name['conditional_requirement']) ):
$conditional_requirement = ' v-show="' . implode( ' && ', $name['conditional_requirement'] ) . '"';
else:
$conditional_requirement = ' v-show="' . esc_attr($name['conditional_requirement']) . '"';
endif;
endif;
$name = $name['label'];
endif;
$combined_extras = $is_disabled . $conditional_value;
if ( $conditional_requirement ): echo '
';
if ( $conditional_requirement ): echo '
'; echo ''; echo '
'; } public static function field_nonce( $field_name, $options ) { wp_nonce_field( $field_name, $field_name ); } // Kept here for backwards compatibility only. Removed used in Cooked Pro 1.0.1 public static function field_misc_button( $field_name, $title ) { echo ''; echo ''; echo '
'; } // END public static function field_migrate_button( $field_name, $title ) { $old_recipes = get_transient('cooked_classic_recipes'); if ($old_recipes != 'complete') { $total = count($old_recipes); if ($total > 0) { echo ''; echo ''; echo '
'; echo ''; echo '0 / ' . esc_html( $total ) . ''; echo '
'; echo 'Migration Complete! You can now ' . esc_html__( 'reload', 'cooked' ) . ' the settings screen.
'; } } } public static function field_text($field_name, $placeholder) { global $_cooked_settings; echo ''; echo ''; echo '
'; } public static function field_password($field_name, $placeholder) { global $_cooked_settings; echo ''; echo ''; echo '
'; } public static function field_html($field_name, $html) { echo wp_kses_post($html); } public static function field_permalink_field($field_name, $end_of_url) { global $_cooked_settings; $browse_page_id = $_cooked_settings['browse_page']; $browse_page_url = ''; if (!empty($browse_page_id) && $field_name !== 'recipe_permalink') { $browse_page_url = get_permalink( $browse_page_id ); } if (empty($browse_page_url)) { $browse_page_url = get_home_url(); } if (substr($browse_page_url, -1) !== '/') { $browse_page_url .= '/'; } echo ''; echo '' . esc_url( $browse_page_url ) . '/' . esc_html( $end_of_url ) . '/'; echo '
'; } public static function field_number_field( $field_name, $options ) { global $_cooked_settings; echo ''; echo ''; echo '
'; } public static function field_color_field( $field_name, $default ) { global $_cooked_settings; echo ''; echo ''; echo '
'; } public static function field_image_field( $field_name, $default ) { global $_cooked_settings; $attachment_id = isset( $_cooked_settings[ $field_name ] ) ? absint( $_cooked_settings[ $field_name ] ) : 0; $has_image = $attachment_id && wp_attachment_is_image( $attachment_id ); $preview_id = 'cooked-settings-image-' . esc_attr( $field_name ) . '-src'; echo '';
foreach ($options as $value => $name) {
$is_disabled = '';
$conditional_value = '';
$conditional_requirement = '';
if (is_array($name)) {
if (isset($name['read_only']) && $name['read_only']):
$is_disabled = ' disabled';
endif;
if (isset($name['conditional_value']) && $name['conditional_value']):
$conditional_value = ' v-model="' . esc_attr($name['conditional_value']) . '"';
if ( !in_array( $name['conditional_value'], $conditions ) ):
$conditions[$field_name][$name['conditional_value']] = $value;
endif;
endif;
if (isset($name['conditional_requirement']) && $name['conditional_requirement']):
if (is_array($name['conditional_requirement'])):
$conditional_requirement = ' v-show="' . implode( ' && ', $name['conditional_requirement'] ) . '"';
else:
$conditional_requirement = ' v-show="' . esc_attr($name['conditional_requirement']) . '"';
endif;
endif;
$name = $name['label'];
}
$combined_extras = $is_disabled . $conditional_value;
if ($conditional_requirement) {
echo '
';
if ($conditional_requirement) {
echo '