Añadir configuración a un tipo de publicación personalizado
Tengo un tipo de publicación personalizado llamado Portfolio. Está asociado con tres taxonomías personalizadas. Todo esto funciona correctamente.
Sin embargo, para la página de archivo, necesito añadir algunas configuraciones personalizadas. Debido a una limitación en el proyecto, no puedo escribir un plugin; todos los cambios deben hacerse en el tema.
He conseguido que aparezca la subpágina de configuración en el menú (fue fácil) siguiendo esta guía, y las configuraciones aparecen en la página sin problemas. El problema ahora es que no se guardan.
Solo he añadido una configuración (header_text
) hasta que pueda resolver el problema de guardado.
Supongo que $option_group
probablemente sea el problema.
Si hago var_dump($_POST)
obtengo:
array (size=6)
'option_page' => string 'edit.php?post_type=rushhour_projects&page=projects_archive' (length=58)
'action' => string 'update' (length=6)
'_wpnonce' => string '23c70a3029' (length=10)
'_wp_http_referer' => string '/wp-admin/edit.php?post_type=rushhour_projects&page=projects_archive' (length=68)
'rushhour_projects_archive' =>
array (size=1)
'header_text' => string 'asdf' (length=4)
'submit' => string 'Save Changes' (length=12)
Aquí está el registro del tipo de publicación personalizado:
if ( ! function_exists('rushhour_post_type_projects') ) :
// Añadir Portfolio Projects a WordPress
add_action( 'init', 'rushhour_post_type_projects', 0 );
// Registrar Custom Post Type para Portfolio Projects
function rushhour_post_type_projects()
{
$labels = array(
'name' => _x( 'Portfolio', 'Post Type General Name', 'rushhour' ),
'singular_name' => _x( 'Project', 'Post Type Singular Name', 'rushhour' ),
'menu_name' => __( 'Portfolio Projects', 'rushhour' ),
'name_admin_bar' => __( 'Portfolio Project', 'rushhour' ),
'archives' => __( 'Portfolio Archives', 'rushhour' ),
'parent_item_colon' => __( 'Parent Project:', 'rushhour' ),
'all_items' => __( 'All Projects', 'rushhour' ),
'add_new_item' => __( 'Add New Project', 'rushhour' ),
'add_new' => __( 'Add New', 'rushhour' ),
'new_item' => __( 'New Project', 'rushhour' ),
'edit_item' => __( 'Edit Project', 'rushhour' ),
'update_item' => __( 'Update Project', 'rushhour' ),
'view_item' => __( 'View Project', 'rushhour' ),
'search_items' => __( 'Search Projects', 'rushhour' ),
'not_found' => __( 'Not found', 'rushhour' ),
'not_found_in_trash' => __( 'Not found in Trash', 'rushhour' ),
'featured_image' => __( 'Featured Image', 'rushhour' ),
'set_featured_image' => __( 'Set featured image', 'rushhour' ),
'remove_featured_image' => __( 'Remove featured image', 'rushhour' ),
'use_featured_image' => __( 'Use as featured image', 'rushhour' ),
'insert_into_item' => __( 'Insert into project', 'rushhour' ),
'uploaded_to_this_item' => __( 'Uploaded to this project', 'rushhour' ),
'items_list' => __( 'Projects list', 'rushhour' ),
'items_list_navigation' => __( 'Projects list navigation', 'rushhour' ),
'filter_items_list' => __( 'Filter projects list', 'rushhour' ),
);
$rewrite = array(
'slug' => 'portfolio',
'with_front' => true,
'pages' => true,
'feeds' => true,
);
$args = array(
'label' => __( 'Project', 'rushhour' ),
'description' => __( 'Portfolio projects for Global VDC.', 'rushhour' ),
'labels' => $labels,
'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'revisions', ),
'taxonomies' => array( 'rushhour_clients', 'rushhour_locations', 'rushhour_project_type' ),
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 5,
'menu_icon' => 'dashicons-portfolio',
'show_in_admin_bar' => true,
'show_in_nav_menus' => true,
'can_export' => true,
'has_archive' => 'portfolio',
'exclude_from_search' => false,
'publicly_queryable' => true,
'rewrite' => $rewrite,
'capability_type' => 'page',
);
register_post_type( 'rushhour_projects', $args );
}
endif;
Luego tengo una función para configurar la subpágina de administración:
if ( ! function_exists('rushhour_projects_admin_page') ) :
add_action( 'admin_menu' , 'rushhour_projects_admin_page' );
/**
* Generar subpágina de menú para configuraciones
*
* @uses rushhour_projects_options_display()
*/
function rushhour_projects_admin_page()
{
add_submenu_page(
'edit.php?post_type=rushhour_projects',
__('Portfolio Projects Options', 'rushhour'),
__('Portfolio Options', 'rushhour'),
'manage_options',
'projects_archive',
'rushhour_projects_options_display');
}
endif;
Los dos elementos anteriores funcionan sin problemas.
El problema, creo, está en alguna parte de las siguientes funciones para registrar y guardar las configuraciones:
if ( ! function_exists('rushhour_projects_options_display') ) :
/**
* Mostrar el formulario en la subpágina de configuración de Rush Hour Projects.
*
* Usado por 'rushhour_projects_admin_page'.
*/
function rushhour_projects_options_display()
{
// Crear un encabezado en el contenedor 'wrap' predeterminado de WordPress
echo '<div class="wrap">';
settings_errors();
echo '<form method="post" action="">';
var_dump( get_option('rushhour_projects_archive') );
settings_fields( 'edit.php?post_type=rushhour_projects&page=projects_archive' );
do_settings_sections( 'edit.php?post_type=rushhour_projects&page=projects_archive' );
submit_button();
echo '</form></div><!-- .wrap -->';
}
endif;
add_action( 'admin_init', 'rushhour_projects_settings' );
/**
* Registrar configuraciones y añadir secciones y campos a la página de administración.
*/
function rushhour_projects_settings()
{
if ( false == get_option( 'rushhour_projects_archive' ) )
add_option( 'rushhour_projects_archive' );
add_settings_section(
'projects_archive_header', // $id de la sección
__('Portfolio Project Archive Page Settings', 'rushhour'),
'rushhour_project_settings_section_title', // Callback
'edit.php?post_type=rushhour_projects&page=projects_archive' // Slug de la página de configuración
);
add_settings_field(
'header_text', // $id del campo
__('Header Text', 'rushhour'), // $title de la configuración
'projects_archive_header_text_callback',
'edit.php?post_type=rushhour_projects&page=projects_archive', // Slug de la página de configuración
'projects_archive_header', // $id de la sección
array('Text to display in the archive header.')
);
register_setting(
'edit.php?post_type=rushhour_projects&page=projects_archive', // $option_group
'rushhour_projects_archive', // $option_name
'rushhour_projects_archive_save_options'
);
}
/**
* Callback para la sección de configuraciones.
*
* Comentado hasta que las configuraciones funcionen.
*
* @param array $args Obtiene el $id, $title y $callback.
*/
function rushhour_project_settings_section_title( $args ) {
// printf( '<h2>%s</h2>', apply_filters( 'the_title', $args['title'] ) );
}
/**
* Callbacks para los campos de configuración.
*/
function projects_archive_header_text_callback($args)
{
$options = get_option('rushhour_projects_archive');
printf( '<input class="widefat" id="header_text" name="rushhour_projects_archive[header_text]" type="textarea" value="%1$s" />',
$options );
}
/**
* Guardar opciones.
*/
function rushhour_projects_archive_save_options()
{
if ( isset( $_POST['rushhour_projects_archive[header_text]'] ) )
{
update_option( 'rushhour_projects_archive', $_POST['rushhour_projects_archive[header_text]'] );
}
}
Bien, me molestó que no funcionara y decidí reescribirlo. No estoy seguro de cuál era la solución, pero sospecho dos cosas: el endpoint incorrecto para el formulario (debería ser options.php) y el $option_group
y $option_name
incorrectos (probablemente no coincidían correctamente).
Para la posteridad, dejaré mi reescritura aquí y espero que ayude a otros. Algunas diferencias entre esta y la versión anterior.
- Ahora está en su propio archivo, así que no verás el tipo de entrada personalizado registrado.
- Usé un objeto para la página según el ejemplo 2 del codex de WordPress.
- Agregué una segunda opción para un cargador de medios usando este tutorial, que actualicé para usar
wp_localize_script()
para inyectar un objeto JSON y obtener algunos datos de PHP.
<?php
class RushHourProjectArchivesAdminPage
{
/**
* Contiene los valores a usar en las devoluciones de llamada de los campos
*/
private $options;
public function __construct()
{
add_action( 'admin_menu', array( $this, 'add_submenu_page_to_post_type' ) );
add_action( 'admin_init', array( $this, 'sub_menu_page_init' ) );
add_action( 'admin_init', array( $this, 'media_selector_scripts' ) );
}
/**
* Agrega una página de submenú al tipo de entrada personalizado
*/
public function add_submenu_page_to_post_type()
{
add_submenu_page(
'edit.php?post_type=rushhour_projects',
__('Opciones de Proyectos de Portafolio', 'rushhour'),
__('Opciones de Portafolio', 'rushhour'),
'manage_options',
'projects_archive',
array($this, 'rushhour_projects_options_display'));
}
/**
* Devuelve la página de opciones
*/
public function rushhour_projects_options_display()
{
$this->options = get_option( 'rushhour_projects_archive' );
wp_enqueue_media();
echo '<div class="wrap">';
printf( '<h1>%s</h1>', __('Opciones de Portafolio', 'rushhour' ) );
echo '<form method="post" action="options.php">';
settings_fields( 'projects_archive' );
do_settings_sections( 'projects-archive-page' );
submit_button();
echo '</form></div>';
}
/**
* Registra y agrega configuraciones
*/
public function sub_menu_page_init()
{
register_setting(
'projects_archive', // Grupo de opciones
'rushhour_projects_archive', // Nombre de la opción
array( $this, 'sanitize' ) // Sanitización
);
add_settings_section(
'header_settings_section', // ID
__('Configuraciones de Encabezado', 'rushhour'), // Título
array( $this, 'print_section_info' ), // Callback
'projects-archive-page' // Página
);
add_settings_field(
'archive_description', // ID
__('Descripción del Archivo', 'rushhour'), // Título
array( $this, 'archive_description_callback' ), // Callback
'projects-archive-page', // Página
'header_settings_section' // Sección
);
add_settings_field(
'image_attachment_id',
__('Imagen de Fondo del Encabezado', 'rushhour'),
array( $this, 'header_bg_image_callback' ),
'projects-archive-page',
'header_settings_section'
);
}
/**
* Sanitiza cada campo de configuración según sea necesario
*
* @param array $input Contiene todos los campos de configuración como claves de array
*/
public function sanitize( $input )
{
$new_input = array();
if( isset( $input['archive_description'] ) )
$new_input['archive_description'] = sanitize_text_field( $input['archive_description'] );
if( isset( $input['image_attachment_id'] ) )
$new_input['image_attachment_id'] = absint( $input['image_attachment_id'] );
return $new_input;
}
/**
* Imprime el texto de la sección
*/
public function print_section_info()
{
print 'Selecciona opciones para el encabezado de la página de archivo.';
}
/**
* Obtiene el array de opciones de configuración e imprime uno de sus valores
*/
public function archive_description_callback()
{
printf(
'<input type="text" id="archive_description" name="rushhour_projects_archive[archive_description]" value="%s" />',
isset( $this->options['archive_description'] ) ? esc_attr( $this->options['archive_description']) : ''
);
}
/**
* Obtiene el array de opciones de configuración e imprime uno de sus valores
*/
public function header_bg_image_callback()
{
$attachment_id = $this->options['image_attachment_id'];
// Vista previa de la imagen
printf('<div class="image-preview-wrapper"><img id="image-preview" src="%s" ></div>', wp_get_attachment_url( $attachment_id ) );
// Botón de carga de imagen
printf( '<input id="upload_image_button" type="button" class="button" value="%s" />',
__( 'Subir imagen', 'rushhour' ) );
// Campo oculto que contiene el valor del ID de adjunto de la imagen
printf( '<input type="hidden" name="rushhour_projects_archive[image_attachment_id]" id="image_attachment_id" value="%s">',
$attachment_id );
}
public function media_selector_scripts()
{
$my_saved_attachment_post_id = get_option( 'media_selector_attachment_id', 0 );
wp_register_script( 'sub_menu_media_selector_scripts', get_template_directory_uri() . '/admin/js/media-selector.js', array('jquery'), false, true );
$selector_data = array(
'attachment_id' => get_option( 'media_selector_attachment_id', 0 )
);
wp_localize_script( 'sub_menu_media_selector_scripts', 'selector_data', $selector_data );
wp_enqueue_script( 'sub_menu_media_selector_scripts' );
}
}
Luego simplemente llama al objeto cuando is_admin()
sea verdadero:
if ( is_admin() )
$my_settings_page = new RushHourProjectArchivesAdminPage();

Esto debería funcionar. Cambia
function rushhour_projects_archive_save_options()
{
if ( isset( $_POST['rushhour_projects_archive[header_text]'] ) )
{
update_option( 'rushhour_projects_archive', $_POST['rushhour_projects_archive[header_text]'] );
}
}
por
function rushhour_projects_archive_save_options()
{
if ( isset( $_POST['rushhour_projects_archive']['header_text'] ) )
{
update_option( 'rushhour_projects_archive', $_POST['rushhour_projects_archive']['header_text'] );
}
}
