Generic::get_instance()->get_options(), 'Flickr.php' => Flickr::get_instance()->get_options(), // 'Google.php' => Google::get_instance()->get_options(), 'SmugMug.php' => SmugMug::get_instance()->get_options(), 'Zenfolio.php' => Zenfolio::get_instance()->get_options(), // 'Instagram.php' => Instagram::get_instance()->get_options(), 'DeviantArt.php' => DeviantArt::get_instance()->get_options(), 'Lightbox.php' => Lightbox::get_instance()->get_options(), ]; $tab_name_array = [ 'Generic.php' => 'Generic Options', 'Flickr.php' => 'Flickr Options', // 'Google.php' => 'Google Photos Options', 'SmugMug.php' => 'SmugMug Options', 'Zenfolio.php' => 'Zenfolio Options', // 'Instagram.php' => 'Instagram Options', 'DeviantArt.php' => 'DeviantArt Options', 'Lightbox.php' => 'Lightbox Options', ]; $this->core = $core; $this->file = $file; $this->tab = 'Generic.php'; if (isset($_REQUEST['tab']) && array_key_exists($_REQUEST['tab'], $tab_name_array)) { // phpcs:ignore WordPress.Security.NonceVerification $this->tab = sanitize_text_field($_REQUEST['tab']); // phpcs:ignore WordPress.Security.NonceVerification } $this->tab_options = $options_page_array[$this->tab]; $this->tab_name = $tab_name_array[$this->tab]; $this->reverse_options = []; $this->nested_options = []; $this->displayed_sections = 0; $this->option_structure = $this->get_option_structure(); $this->option_defaults = []; $this->allowed_values = []; $all_options = get_option('photonic_options'); if (!isset($all_options)) { $this->hidden_options = []; } else { $this->hidden_options = $all_options; } foreach ($this->tab_options as $option) { if (isset($option['id'])) { if (isset($this->hidden_options[$option['id']])) { unset($this->hidden_options[$option['id']]); } } } $defaults = Defaults::get_options(); foreach ($photonic_setup_options as $option) { if (isset($option['category']) && !isset($this->nested_options[$option['category']])) { $this->nested_options[$option['category']] = []; } if (isset($option['id'])) { $this->reverse_options[$option['id']] = $option['type']; $this->option_defaults[$option['id']] = $defaults[$option['id']]; $option['std'] = $defaults[$option['id']]; if (isset($option['options'])) { if ('radio-group' !== $option['type']) { $this->allowed_values[$option['id']] = $option['options']; } else { $this->allowed_values[$option['id']] = []; foreach ($option['options'] as $radio_group) { $this->allowed_values[$option['id']] = array_merge($this->allowed_values[$option['id']], $radio_group['options']); } } } if (isset($option['grouping'])) { if (!isset($this->nested_options[$option['grouping']])) { $this->nested_options[$option['grouping']] = []; } $this->nested_options[$option['grouping']][] = $option['id']; } } } } public function render_content() { $saved_options = get_option('photonic_options'); if (!empty($saved_options) && current_user_can('edit_theme_options')) { $generated_css = $this->core->generate_css(false); update_option('photonic_css', $generated_css); if (!empty($saved_options['css_in_file'])) { $this->save_css_to_file($generated_css); } } ?>
\n"; ?> \n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; } } public function init() { foreach ($this->option_structure as $slug => $option) { if (!in_array($slug, Defaults::get_options_pages(), true)) { wp_die(esc_html("Invalid option section: $slug")); } // Since we are not including this file on all admin pages due to the size and associated load, register_setting cannot be done here. // It is instead done via Admin_Menu, which is loaded for all admin pages. // register_setting('photonic_options-'.$slug, 'photonic_options', [&$this, 'validate_options']); add_settings_section($slug, "", [&$this, "create_settings_section"], $this->file); $this->add_settings_fields($this->file); } } public function validate_options($options): array { foreach ($options as $option => $option_value) { if (isset($this->reverse_options[$option])) { // Sanitize options switch ($this->reverse_options[$option]) { // For all text type of options make sure that the eventual text is properly escaped. case "text": case "background": case "border": $options[$option] = sanitize_text_field($option_value); break; case "textarea": $options[$option] = sanitize_textarea_field($option_value); break; case "select": case "radio": case "radio-group": if (isset($this->allowed_values[$option])) { if (!array_key_exists($option_value, $this->allowed_values[$option])) { $options[$option] = $this->option_defaults[$option]; } } break; case "multi-select": $selections = explode(',', $option_value); $final_selections = []; foreach ($selections as $selection) { if (array_key_exists($selection, $this->allowed_values[$option])) { $final_selections[] = $selection; } } $options[$option] = implode(',', $final_selections); break; case "checkbox": if (!in_array($option_value, ['on', 'off', 'true', 'false'], true) && isset($this->option_defaults[$option])) { $options[$option] = $this->option_defaults[$option]; } break; } } } /* * The Settings API does an update_option($option, $value), overwriting the $photonic_options array with the values on THIS page * This is problematic because all options are stored in a single array, but are displayed on different options pages. * Hence the overwrite kills the options from the other pages. * So this is a workaround to include the options from other pages as hidden fields on this page, so that the array gets properly updated. * The alternative would be to separate options for each page, but that would cause a migration headache for current users. */ $current_options = array_keys($options); if (isset($this->hidden_options) && is_array($this->hidden_options)) { foreach ($this->hidden_options as $hidden_option => $hidden_value) { if (strlen($hidden_option) >= 7 && ('submit-' === substr($hidden_option, 0, 7) || 'reset-' === substr($hidden_option, 0, 6)) || in_array($hidden_option, $current_options, true)) { continue; } $options[$hidden_option] = esc_attr($hidden_value); } } foreach ($this->nested_options as $section => $children) { if (isset($options['submit-' . $section])) { $options['last-set-section'] = $section; if ('Save page' === substr($options['submit-' . $section], 0, 9) || 'Reset page' === substr($options['submit-' . $section], 0, 10)) { global $photonic_options; foreach ($this->nested_options as $inner_section => $inner_children) { if ($section !== $inner_section) { foreach ($inner_children as $inner_child) { if (isset($photonic_options[$inner_child]) && !in_array($inner_child, $current_options, true)) { $options[$inner_child] = $photonic_options[$inner_child]; } } } } if ('Reset page' === substr($options['submit-' . $section], 0, 10)) { unset($options['submit-' . $section]); // This is a reset for an individual section. So we will unset the child fields. foreach ($children as $child) { unset($options[$child]); } } unset($options['submit-' . $section]); } elseif ('Delete' === substr($options['submit-' . $section], 0, 6)) { return []; } break; } } return $options; } public function get_option_structure() { if (isset($this->option_structure)) { return $this->option_structure; } $options = $this->tab_options; $option_structure = []; foreach ($options as $value) { switch ($value['type']) { case "title": case "section": $option_structure[$value['category']] = []; $option_structure[$value['category']]['slug'] = $value['category']; $option_structure[$value['category']]['name'] = $value['name']; $option_structure[$value['category']]['children'] = []; if (isset($value['help'])) { $option_structure[$value['category']]['help'] = $value['help']; } if (isset($value['buttons'])) { $option_structure[$value['category']]['buttons'] = $value['buttons']; } if (isset($value['preface'])) { $option_structure[$value['category']]['preface'] = $value['preface']; } break; default: if (isset($value['id'])) { $option_structure[$value['grouping']]['children'][$value['id']] = $value['name']; } } } return $option_structure; } private function add_settings_fields($page) { $ctr = 0; foreach ($this->tab_options as $value) { $ctr++; switch ($value['type']) { case "blurb": add_settings_field($value['grouping'] . '-' . $ctr, $value['name'], [&$this, "create_section_for_blurb"], $page, $value['grouping'], $value); break; case "text": add_settings_field($value['id'], $value['name'], [&$this, "create_section_for_text"], $page, $value['grouping'], $value); break; case "textarea": add_settings_field($value['id'], $value['name'], [&$this, "create_section_for_textarea"], $page, $value['grouping'], $value); break; case "select": add_settings_field($value['id'], $value['name'], [&$this, "create_section_for_select"], $page, $value['grouping'], $value); break; case "multi-select": add_settings_field($value['id'], $value['name'], [&$this, "create_section_for_multi_select"], $page, $value['grouping'], $value); break; case "radio": add_settings_field($value['id'], $value['name'], [&$this, "create_section_for_radio"], $page, $value['grouping'], $value); break; case "radio-group": add_settings_field($value['id'], $value['name'], [&$this, "create_section_for_radio_group"], $page, $value['grouping'], $value); break; case "checkbox": add_settings_field($value['id'], $value['name'], [&$this, "create_section_for_checkbox"], $page, $value['grouping'], $value); break; case "background": add_settings_field($value['id'], $value['name'], [&$this, "create_section_for_background"], $page, $value['grouping'], $value); break; } } } public function create_section_for_radio($value) { $defaults = Defaults::get_options(); $this->create_opening_tag($value); foreach ($value['options'] as $option_value => $option_text) { $this->create_individual_radio_item($value, $option_value, $option_text, $defaults); } $this->create_closing_tag(); } public function create_section_for_radio_group($value) { $defaults = Defaults::get_options(); $this->create_opening_tag($value); foreach ($value['options'] as $radio_group) { if (!empty($radio_group['header'])) { echo "