* @license GPL-2.0+ * @link https://robincornett.com * @copyright 2014-2017 Robin Cornett Creative, LLC */ class Display_Featured_Image_Genesis_Settings extends Display_Featured_Image_Genesis_Helper { /** * The common plugin class. * @var $commmon Display_Featured_Image_Genesis_Common */ protected $common; /** * The plugin admin page. * @var $page string */ protected $page = 'displayfeaturedimagegenesis'; /** * The plugin setting. * @var $setting string */ protected $setting; /** * Public post types on the site. * @var $post_types array */ protected $post_types; /** * The plugin settings fields. * @var $fields array */ protected $fields; /** * The db query for old term options. * @var $term_option_query */ protected $term_option_query = array(); /** * add a submenu page under Appearance * @since 1.4.0 */ public function do_submenu_page() { $this->common = new Display_Featured_Image_Genesis_Common(); $this->setting = $this->get_display_setting(); $this->post_types = $this->get_content_types(); add_theme_page( __( 'Display Featured Image for Genesis', 'display-featured-image-genesis' ), __( 'Display Featured Image for Genesis', 'display-featured-image-genesis' ), 'manage_options', $this->page, array( $this, 'do_settings_form' ) ); add_action( 'admin_init', array( $this, 'register_settings' ) ); $sections = $this->register_sections(); $this->fields = $this->register_fields(); $this->add_sections( $sections ); $this->add_fields( $this->fields, $sections ); } /** * create settings form * * @since 1.4.0 */ public function do_settings_form() { $page_title = get_admin_page_title(); echo '
'; printf( '

%s

', esc_attr( $page_title ) ); $this->check_and_maybe_update_terms(); $active_tab = $this->get_active_tab(); echo $this->do_tabs( $active_tab ); echo '
'; settings_fields( 'displayfeaturedimagegenesis' ); do_settings_sections( 'displayfeaturedimagegenesis_' . $active_tab ); wp_nonce_field( 'displayfeaturedimagegenesis_save-settings', 'displayfeaturedimagegenesis_nonce', false ); submit_button(); settings_errors(); echo '
'; echo '
'; } /** * Check if term images need to be updated because they were added before WP 4.4 and this plugin 2.4. * @since 2.6.1 */ protected function check_and_maybe_update_terms() { if ( ! function_exists( 'get_term_meta' ) ) { return; } if ( $this->terms_have_been_updated() ) { return; } $previous_user = get_option( 'displayfeaturedimagegenesis', false ); if ( ! $previous_user ) { update_option( 'displayfeaturedimagegenesis_updatedterms', true ); return; } $this->term_option_query = $this->check_term_images(); if ( $this->term_option_query ) { $this->update_delete_term_meta(); $this->term_meta_notice(); } else { update_option( 'displayfeaturedimagegenesis_updatedterms', true ); } } /** * Output tabs. * @return string * @since 2.5.0 */ protected function do_tabs( $active_tab ) { $tabs = $this->define_tabs(); $output = ''; return $output; } /** * Settings for options screen * @return array settings for backstretch image options * * @since 1.1.0 */ public function register_settings() { register_setting( 'displayfeaturedimagegenesis', 'displayfeaturedimagegenesis', array( $this, 'do_validation_things' ) ); } /** * Define tabs for the settings page. * @return array * @since 2.6.0 */ protected function define_tabs() { return array( 'main' => array( 'id' => 'main', 'tab' => __( 'Main', 'display-featured-image-genesis' ) ), 'style' => array( 'id' => 'style', 'tab' => __( 'Backstretch Output', 'display-featured-image-genesis' ) ), 'cpt' => array( 'id' => 'cpt', 'tab' => __( 'Content Types', 'display-featured-image-genesis' ) ), ); } /** * Register plugin settings page sections * * @since 2.3.0 */ protected function register_sections() { return array( 'main' => array( 'id' => 'main', 'title' => __( 'Optional Sitewide Settings', 'display-featured-image-genesis' ), ), 'style' => array( 'id' => 'style', 'title' => __( 'Display Settings', 'display-featured-image-genesis' ), ), 'cpt' => array( 'id' => 'cpt', 'title' => __( 'Featured Images for Custom Content Types', 'display-featured-image-genesis' ), ), ); } /** * Register plugin settings fields * @return array all settings fields * * @since 2.3.0 */ protected function register_fields() { return array_merge( $this->define_main_fields(), $this->define_style_fields(), $this->define_cpt_fields() ); } /** * Define the fields for the main/first tab. * @return array */ protected function define_main_fields() { return array( array( 'id' => 'default', 'title' => __( 'Default Featured Image', 'display-featured-image-genesis' ), 'callback' => 'set_default_image', 'section' => 'main', ), array( 'id' => 'always_default', 'title' => __( 'Always Use Default', 'display-featured-image-genesis' ), 'callback' => 'do_checkbox', 'section' => 'main', 'args' => array( 'setting' => 'always_default', 'label' => __( 'Always use the default image, even if a featured image is set.', 'display-featured-image-genesis' ) ), ), array( 'id' => 'exclude_front', 'title' => __( 'Skip Front Page', 'display-featured-image-genesis' ), 'callback' => 'do_checkbox', 'section' => 'main', 'args' => array( 'setting' => 'exclude_front', 'label' => __( 'Do not show the Featured Image on the Front Page of the site.', 'display-featured-image-genesis' ) ), ), array( 'id' => 'keep_titles', 'title' => __( 'Do Not Move Titles', 'display-featured-image-genesis' ), 'callback' => 'do_checkbox', 'section' => 'main', 'args' => array( 'setting' => 'keep_titles', 'label' => __( 'Do not move the titles to overlay the backstretch Featured Image.', 'display-featured-image-genesis' ) ), ), array( 'id' => 'move_excerpts', 'title' => __( 'Move Excerpts/Archive Descriptions', 'display-featured-image-genesis' ), 'callback' => 'do_checkbox', 'section' => 'main', 'args' => array( 'setting' => 'move_excerpts', 'label' => __( 'Move excerpts (if used) on single pages and move archive/taxonomy descriptions to overlay the Featured Image.', 'display-featured-image-genesis' ) ), ), array( 'id' => 'is_paged', 'title' => __( 'Show Featured Image on Subsequent Blog Pages', 'display-featured-image-genesis' ), 'callback' => 'do_checkbox', 'section' => 'main', 'args' => array( 'setting' => 'is_paged', 'label' => __( 'Show featured image on pages 2+ of blogs and archives.', 'display-featured-image-genesis' ) ), ), array( 'id' => 'feed_image', 'title' => __( 'Add Featured Image to Feed?', 'display-featured-image-genesis' ), 'callback' => 'do_checkbox', 'section' => 'main', 'args' => array( 'setting' => 'feed_image', 'label' => __( 'Optionally, add the featured image to your RSS feed.', 'display-featured-image-genesis' ) ), ), array( 'id' => 'thumbnails', 'title' => __( 'Archive Thumbnails', 'display-featured-image-genesis' ), 'callback' => 'do_checkbox', 'section' => 'main', 'args' => array( 'setting' => 'thumbnails', 'label' => __( 'Use term/post type fallback images for content archives?', 'display-featured-image-genesis' ) ), ), ); } /** * Define the fields for the style tab. * @return array */ protected function define_style_fields() { return array( array( 'id' => 'less_header', 'title' => __( 'Height' , 'display-featured-image-genesis' ), 'callback' => 'do_number', 'section' => 'style', 'args' => array( 'setting' => 'less_header', 'label' => __( 'pixels to remove', 'display-featured-image-genesis' ), 'min' => 0, 'max' => 400 ), ), array( 'id' => 'max_height', 'title' => __( 'Maximum Height' , 'display-featured-image-genesis' ), 'callback' => 'do_number', 'section' => 'style', 'args' => array( 'setting' => 'max_height', 'label' => __( 'pixels', 'display-featured-image-genesis' ), 'min' => 100, 'max' => 1000 ), ), array( 'id' => 'centeredX', 'title' => __( 'Center Horizontally' , 'display-featured-image-genesis' ), 'callback' => 'do_radio_buttons', 'section' => 'style', 'args' => array( 'setting' => 'centeredX', 'buttons' => $this->pick_center(), 'legend' => __( 'Center the backstretch image on the horizontal axis?', 'display-featured-image-genesis' ), ), ), array( 'id' => 'centeredY', 'title' => __( 'Center Vertically' , 'display-featured-image-genesis' ), 'callback' => 'do_radio_buttons', 'section' => 'style', 'args' => array( 'setting' => 'centeredY', 'buttons' => $this->pick_center(), 'legend' => __( 'Center the backstretch image on the vertical axis?', 'display-featured-image-genesis' ), ), ), array( 'id' => 'fade', 'title' => __( 'Fade' , 'display-featured-image-genesis' ), 'callback' => 'do_number', 'section' => 'style', 'args' => array( 'setting' => 'fade', 'label' => __( 'milliseconds', 'display-featured-image-genesis' ), 'min' => 0, 'max' => 20000 ), ), ); } /** * Define the fields for the content types tab. * @return array */ protected function define_cpt_fields() { $fields = array( array( 'id' => 'post_types][search', 'title' => __( 'Search Results', 'display-featured-image-genesis' ), 'callback' => 'set_cpt_image', 'section' => 'cpt', 'args' => array( 'post_type' => 'search' ), ), array( 'id' => 'post_types][fourohfour', 'title' => __( '404 Page', 'display-featured-image-genesis' ), 'callback' => 'set_cpt_image', 'section' => 'cpt', 'args' => array( 'post_type' => 'fourohfour' ), ), array( 'id' => 'skip', 'title' => __( 'Skip Content Types', 'display-featured-image-genesis' ), 'callback' => 'do_checkbox_array', 'section' => 'cpt', 'args' => array( 'setting' => 'skip' ), ), ); if ( $this->post_types ) { foreach ( $this->post_types as $post ) { $object = get_post_type_object( $post ); $fields[] = array( 'id' => 'post_types][' . esc_attr( $object->name ), 'title' => esc_attr( $object->label ), 'callback' => 'set_cpt_image', 'section' => 'cpt', 'args' => array( 'post_type' => $object ), ); } } return $fields; } /** * Section description * @return string description * * @since 1.1.0 */ public function main_section_description() { $description = __( 'Use these settings to modify the plugin behavior throughout your site. Check the Help tab for more information. ', 'display-featured-image-genesis' ); $this->print_section_description( $description ); } /** * Style section description */ public function style_section_description() { $description = __( 'These settings modify the output style/methods for the backstretch image.', 'display-featured-image-genesis' ); $this->print_section_description( $description ); } /** * Section description * @return string description * * @since 1.1.0 */ public function cpt_section_description() { $description = __( 'Optional: set a custom image for search results and 404 (no results found) pages.', 'display-featured-image-genesis' ); if ( $this->post_types ) { $description .= __( ' Additionally, since you have custom post types with archives, you might like to set a featured image for each of them.', 'display-featured-image-genesis' ); } $this->print_section_description( $description ); } /** * Description for less_header setting. * @return string description * * @since 2.3.0 */ protected function less_header_description() { return __( 'Changing this number will reduce the backstretch image height by this number of pixels. Default is zero.', 'display-featured-image-genesis' ); } /** * Description for the max_height setting. * @return string|void description * @since 2.6.0 */ protected function max_height_description() { return __( 'Optionally, set a max-height value for the header image; it will be added to your CSS.', 'display-featured-image-genesis' ); } /** * Default image uploader * * @since 1.2.1 */ public function set_default_image() { $id = $this->setting['default'] ? $this->setting['default'] : ''; $name = 'displayfeaturedimagegenesis[default]'; if ( ! empty( $id ) ) { echo wp_kses_post( $this->render_image_preview( $id, 'default' ) ); } $this->render_buttons( $id, $name ); $this->do_description( 'default_image' ); } /** * Description for default image setting * @return string * * @since 2.3.0 */ protected function default_image_description() { $large = $this->common->minimum_backstretch_width(); return sprintf( esc_html__( 'If you would like to use a default image for the featured image, upload it here. Must be at least %1$s pixels wide.', 'display-featured-image-genesis' ), absint( $large + 1 ) ); } /** * Custom Post Type image uploader * * @since 2.0.0 */ public function set_cpt_image( $args ) { $post_type = is_object( $args['post_type'] ) ? $args['post_type']->name : $args['post_type']; if ( empty( $this->setting['post_type'][ $post_type ] ) ) { $this->setting['post_type'][ $post_type ] = $id = ''; } if ( is_object( $args['post_type'] ) ) { $fallback_args = array( 'setting' => "fallback][{$post_type}", 'label' => sprintf( __( 'Always use a fallback image for %s.', 'display-featured-image-genesis' ), esc_attr( $args['post_type']->label ) ), 'setting_name' => 'fallback', 'name' => $post_type, ); echo '

'; $this->do_checkbox( $fallback_args ); echo '

'; } $id = $this->setting['post_type'][ $post_type ]; $name = 'displayfeaturedimagegenesis[post_type][' . esc_attr( $post_type ) . ']'; if ( $id ) { echo wp_kses_post( $this->render_image_preview( $id, $post_type ) ); } $this->render_buttons( $id, $name ); if ( empty( $id ) || ! is_object( $args['post_type'] ) ) { return; } $description = sprintf( __( 'View your %2$s archive.', 'display-featured-image-genesis' ), esc_url( get_post_type_archive_link( $post_type ) ), esc_attr( $args['post_type']->label ) ); printf( '

%s

', wp_kses_post( $description ) ); } /** * @return array */ public function pick_center() { return array( 1 => __( 'Center', 'display-featured-image-genesis' ), 0 => __( 'Do Not Center', 'display-featured-image-genesis' ), ); } /** * validate all inputs * @param string $new_value various settings * @return string number or URL * * @since 1.4.0 */ public function do_validation_things( $new_value ) { $action = 'displayfeaturedimagegenesis_save-settings'; $nonce = 'displayfeaturedimagegenesis_nonce'; // If the user doesn't have permission to save, then display an error message if ( ! $this->user_can_save( $action, $nonce ) ) { wp_die( esc_attr__( 'Something unexpected happened. Please try again.', 'display-featured-image-genesis' ) ); } check_admin_referer( $action, $nonce ); $new_value = array_merge( $this->setting, $new_value ); // validate all checkbox fields foreach ( $this->fields as $field ) { if ( 'do_checkbox' === $field['callback'] ) { $new_value[ $field['id'] ] = $this->one_zero( $new_value[ $field['id'] ] ); } elseif ( 'do_number' === $field['callback'] ) { if ( 'max_height' === $field['id'] && empty( $new_value[ $field['id'] ] ) ) { continue; } $new_value[ $field['id'] ] = $this->check_value( $new_value[ $field['id'] ], $this->setting[ $field['id'] ], $field['args']['min'], $field['args']['max'] ); } elseif ( 'do_radio_buttons' === $field['callback'] ) { $new_value[ $field['id'] ] = absint( $new_value[ $field['id'] ] ); } } // extra variables to pass through to image validation $size_to_check = $this->common->minimum_backstretch_width(); // validate default image $new_value['default'] = $this->validate_image( $new_value['default'], $this->setting['default'], __( 'Default', 'display-featured-image-genesis' ), $size_to_check ); // search/404 $size_to_check = get_option( 'medium_size_w' ); $custom_pages = array( array( 'id' => 'search', 'label' => __( 'Search Results', 'display-featured-image-genesis' ), ), array( 'id' => 'fourohfour', 'label' => __( '404 Page', 'display-featured-image-genesis' ), ), ); foreach ( $custom_pages as $page ) { $setting_to_check = isset( $this->setting['post_type'][ $page['id'] ] ) ? $this->setting['post_type'][ $page['id'] ] : ''; if ( isset( $new_value['post_type'][ $page ['id'] ] ) ) { $new_value['post_type'][ $page ['id'] ] = $this->validate_image( $new_value['post_type'][ $page['id'] ], $setting_to_check, $page['label'], $size_to_check ); } } foreach ( $this->post_types as $post_type ) { $object = get_post_type_object( $post_type ); $old_value = isset( $this->setting['post_type'][ $object->name ] ) ? $this->setting['post_type'][ $object->name ] : ''; $label = $object->label; if ( isset( $new_value['post_type'][ $post_type ] ) ) { $new_value['post_type'][ $post_type ] = $this->validate_image( $new_value['post_type'][ $post_type ], $old_value, $label, $size_to_check ); } if ( isset( $new_value['fallback'][ $post_type ] ) ) { $new_value['fallback'][ $post_type ] = $this->one_zero( $new_value['fallback'][ $post_type ] ); } } $post_types = $this->get_content_types_built_in(); foreach ( $post_types as $post_type ) { $new_value['skip'][ $post_type ] = isset( $new_value['skip'][ $post_type ] ) ? $this->one_zero( $new_value['skip'][ $post_type ] ) : 0; } return $new_value; } /** * Check the numeric value against the allowed range. If it's within the range, return it; otherwise, return the old value. * @param $new_value int new submitted value * @param $old_value int old setting value * @param $min int minimum value * @param $max int maximum value * * @return int */ protected function check_value( $new_value, $old_value, $min, $max ) { if ( $new_value >= $min && $new_value <= $max ) { return (int) $new_value; } return (int) $old_value; } /** * For 4.4, output a notice explaining that old term options can be updated to term_meta. * Options are to update all terms or to ignore, and do by hand. * @since 2.4.0 */ protected function term_meta_notice() { $screen = get_current_screen(); if ( 'appearance_page_displayfeaturedimagegenesis' !== $screen->id ) { return; } $updated_terms = get_option( 'displayfeaturedimagegenesis_updatedterms', false ); if ( $updated_terms ) { return; } $rows = $this->term_option_query; if ( ! $rows ) { update_option( 'displayfeaturedimagegenesis_updatedterms', true ); return; } $message = sprintf( '

%s

', __( 'WordPress 4.4 introduces term metadata for categories, tags, and other taxonomies. This is your opportunity to optionally update all impacted terms on your site to use the new metadata.', 'display-featured-image-genesis' ) ); $message .= sprintf( '

%s

', __( 'This will modify your database (potentially many entries at once), so if you\'d rather do it yourself, you can. Here\'s a list of the affected terms:', 'display-featured-image-genesis' ) ); $message .= ''; $message .= sprintf( '

%s

', __( 'To get rid of this notice, you can 1) update your terms by hand; 2) click the update button (please check your terms afterward); or 3) click the dismiss button.', 'display-featured-image-genesis' ) ); $faq = sprintf( __( 'For more information, please visit the plugin\'s Frequently Asked Questions on WordPress.org.', 'display-featured-image-genesis' ), esc_url( 'https://wordpress.org/plugins/display-featured-image-genesis/faq/' ) ); $message .= sprintf( '

%s

', $faq ); echo '
' . wp_kses_post( $message ); echo '
'; wp_nonce_field( 'displayfeaturedimagegenesis_metanonce', 'displayfeaturedimagegenesis_metanonce', false ); $buttons = array( array( 'value' => __( 'Update My Terms', 'display-featured-image-genesis' ), 'name' => 'displayfeaturedimagegenesis_termmeta', 'class' => 'button-primary', ), array( 'value' => __( 'Dismiss (Not Recommended)', 'display-featured-image-genesis' ), 'name' => 'displayfeaturedimagegenesis_termmetadismiss', 'class' => 'button-secondary', ), ); echo '

'; foreach ( $buttons as $button ) { printf( '', esc_attr( $button['class'] ), esc_attr( $button['name'] ), esc_attr( $button['value'] ) ); } echo '

'; echo '
'; echo '
'; } /** * Update and/or delete term_meta and wp_options * @since 2.4.0 */ protected function update_delete_term_meta() { if ( isset( $_POST['displayfeaturedimagegenesis_termmeta'] ) ) { if ( ! check_admin_referer( 'displayfeaturedimagegenesis_metanonce', 'displayfeaturedimagegenesis_metanonce' ) ) { return; } foreach ( $this->term_option_query as $option_key ) { $term_id = (int) str_replace( 'displayfeaturedimagegenesis_', '', $option_key ); $option = get_option( esc_attr( $option_key ), false ); $term = get_term( (int) $term_id ); if ( ! is_wp_error( $term ) && ! is_null( $term ) ) { $image_id = (int) displayfeaturedimagegenesis_check_image_id( $option['term_image'] ); update_term_meta( $term_id, 'displayfeaturedimagegenesis', $image_id ); } if ( false !== $option ) { delete_option( esc_attr( $option_key ) ); } } } if ( isset( $_POST['displayfeaturedimagegenesis_termmeta'] ) || isset( $_POST['displayfeaturedimagegenesis_termmetadismiss'] ) ) { if ( ! check_admin_referer( 'displayfeaturedimagegenesis_metanonce', 'displayfeaturedimagegenesis_metanonce' ) ) { return; } update_option( 'displayfeaturedimagegenesis_updatedterms', true ); } } /** * Get IDs of terms with featured images * @param array $term_ids empty array * @return array all terms with featured images * @since 2.4.0 * @deprecated 2.6.1 by check_term_images() due to heavy load on sites with many terms */ protected function get_affected_terms( $affected_terms = array() ) { _deprecated_function( __FUNCTION__, '2.6.1', array( $this, 'check_term_images' ) ); $args = apply_filters( 'displayfeaturedimagegenesis_get_taxonomies', array( 'public' => true, 'show_ui' => true, ) ); $taxonomies = get_taxonomies( $args ); foreach ( $taxonomies as $tax ) { $args = array( 'orderby' => 'name', 'order' => 'ASC', 'hide_empty' => false, ); $terms = get_terms( $tax, $args ); foreach ( $terms as $term ) { $term_id = $term->term_id; $option = get_option( "displayfeaturedimagegenesis_{$term_id}", false ); if ( false !== $option ) { $affected_terms[] = $term; } } } return $affected_terms; } /** * Check whether terms need to be updated * @return boolean true if on 4.4 and wp_options for terms exist; false otherwise * * @since 2.4.0 */ protected function terms_have_been_updated() { $updated = get_option( 'displayfeaturedimagegenesis_updatedterms', false ); return (bool) $updated; } /** * Check for term images stored as options. * @return array|bool * @since 2.6.1 */ protected function check_term_images() { $all_options = wp_load_alloptions(); $options = false; foreach ( $all_options as $name => $value ) { if ( stristr( $name, 'displayfeaturedimagegenesis_' ) && 'displayfeaturedimagegenesis_updatedterms' !== $name ) { $options[] = $name; } } return $options; } }