'', 'prefix' => '', 'post_type' => '', 'title' => '', 'registered_settings' => array(), 'translation_strings' => array(), ); $args = wp_parse_args( $args, $defaults ); foreach ( $args as $name => $value ) { $this->$name = $value; } add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) ); add_action( "save_post_{$this->post_type}", array( $this, 'save' ) ); } /** * Function to add the metabox. */ public function add_meta_boxes() { add_meta_box( $this->prefix . '_metabox_id', $this->title, array( $this, 'html' ), $this->post_type, 'advanced', 'high' ); } /** * Enqueue scripts and styles. * * @param string $hook The current admin page. */ public function admin_enqueue_scripts( $hook ) { if ( in_array( $hook, array( 'post.php', 'post-new.php' ), true ) || get_current_screen()->post_type === $this->post_type ) { $args = array( 'strings' => array( 'no_results' => isset( $this->translation_strings['tom_select_no_results'] ) ? esc_html( $this->translation_strings['tom_select_no_results'] ) : 'No results found for "%s"', ), ); self::enqueue_scripts_styles( $this->prefix, $args ); } } /** * Enqueues all scripts, styles, settings, and templates necessary to use the Settings API. * * @param string $prefix Prefix which is used for creating the unique filters and actions. * @param array $args Array of arguments. */ public static function enqueue_scripts_styles( $prefix, $args = array() ) { Settings_API::enqueue_scripts_styles( $prefix, $args ); } /** * Function to save the metabox. * * @param int|string $post_id Post ID. */ public function save( $post_id ) { $post_meta = array(); // Bail if we're doing an auto save. if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } // If our nonce isn't there, or we can't verify it, bail. if ( ! isset( $_POST[ $this->prefix . '_meta_box_nonce' ] ) || ! wp_verify_nonce( sanitize_key( $_POST[ $this->prefix . '_meta_box_nonce' ] ), $this->prefix . '_meta_box' ) ) { return; } // If our current user can't edit this post, bail. if ( ! current_user_can( 'edit_post', $post_id ) ) { return; } if ( empty( $_POST[ $this->settings_key ] ) ) { return; } $settings_sanitize = new Settings_Sanitize( array( 'settings_key' => $this->settings_key, 'prefix' => $this->prefix, ) ); $posted = $_POST[ $this->settings_key ]; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash foreach ( $this->registered_settings as $setting ) { $id = $setting['id']; $type = $setting['type'] ?? 'text'; /** * Skip settings that are not really settings. * * @param array $non_setting_types Array of types which are not settings. */ $non_setting_types = apply_filters( $this->prefix . '_metabox_non_setting_types', array( 'header', 'descriptive_text' ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound if ( in_array( $type, $non_setting_types, true ) ) { continue; } if ( isset( $posted[ $id ] ) ) { $value = $posted[ $id ]; $sanitize_callback = is_callable( array( $settings_sanitize, "sanitize_{$type}_field" ) ) ? array( $settings_sanitize, "sanitize_{$type}_field" ) : array( $settings_sanitize, 'sanitize_missing' ); $post_meta[ $id ] = call_user_func( $sanitize_callback, $value ); } } // Run the array through a generic function that allows access to all of the settings. $post_meta = call_user_func( array( $this, 'sanitize_post_meta' ), $post_meta ); /** * Filter the post meta array which contains post-specific settings. * * @param array $post_meta Array of metabox settings. * @param int $post_id Post ID */ $post_meta = apply_filters( "{$this->prefix}_meta_key", $post_meta, $post_id ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound // Now loop through the settings array and either save or delete the meta key. foreach ( $this->registered_settings as $setting ) { if ( empty( $post_meta[ $setting['id'] ] ) ) { delete_post_meta( $post_id, "_{$this->prefix}_{$setting['id']}" ); } } foreach ( $post_meta as $setting => $value ) { if ( empty( $post_meta[ $setting ] ) ) { delete_post_meta( $post_id, "_{$this->prefix}_$setting" ); } else { update_post_meta( $post_id, "_{$this->prefix}_$setting", $value ); } } } /** * Function to display the metabox. * * @param \WP_Post $post Post object. */ public function html( $post ) { // Add an nonce field so we can check for it later. wp_nonce_field( $this->prefix . '_meta_box', $this->prefix . '_meta_box_nonce' ); $settings_form = new Settings_Form( array( 'settings_key' => $this->settings_key, 'prefix' => $this->prefix, 'translation_strings' => $this->translation_strings, ) ); echo ''; foreach ( $this->registered_settings as $setting ) { $args = Settings_API::parse_field_args( $setting ); $id = $args['id']; $value = get_post_meta( $post->ID, "_{$this->prefix}_{$id}", true ); $args['value'] = ! empty( $value ) ? $value : ( $args['default'] ?? '' ); $type = $args['type'] ?? 'text'; $callback = method_exists( $settings_form, "callback_{$type}" ) ? array( $settings_form, "callback_{$type}" ) : array( $settings_form, 'callback_missing' ); echo ''; echo ''; echo ''; echo ''; } echo '
' . wp_kses_post( $args['name'] ) . ''; call_user_func( $callback, $args ); echo '
'; /** * Action triggered when displaying the meta box. * * @param object $post Post object. */ do_action( $this->prefix . '_meta_box', $post ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound } /** * Sanitize Post Meta array. * * @param array $settings Post meta settings array. * @return array Sanitized value. */ public function sanitize_post_meta( $settings ) { // This array holds a list of keys that will be passed through our category/tags loop to determine the ids. $keys = array( 'include_on_category' => array( 'tax' => 'category', 'ids_field' => 'include_on_category_ids', ), 'include_on_post_tag' => array( 'tax' => 'post_tag', 'ids_field' => 'include_on_post_tag_ids', ), ); foreach ( $keys as $key => $fields ) { if ( isset( $settings[ $key ] ) ) { $ids = array(); $names = array(); $taxes = array_unique( str_getcsv( $settings[ $key ], ',', '"', '' ) ); foreach ( $taxes as $tax ) { $tax_name = get_term_by( 'name', $tax, $fields['tax'] ); if ( isset( $tax_name->term_taxonomy_id ) ) { $ids[] = $tax_name->term_taxonomy_id; $names[] = $tax_name->name; } } $settings[ $fields['ids_field'] ] = join( ',', $ids ); $settings[ $key ] = Settings_Sanitize::str_putcsv( $names ); } else { $settings[ $fields['ids_field'] ] = ''; } } return $settings; } }