La mejor colección de código para tu archivo 'functions.php'
Al igual que muchos otros que ahora están viendo esta publicación, he estado leyendo varios blogs, foros y grupos de discusión para aprender y mejorar mis habilidades en WordPress. Durante los últimos 12 meses, me he propuesto sustituir el uso de plugins añadiendo código a mi archivo functions.php
.
Si bien estoy completamente de acuerdo en que los plugins son muy útiles en muchas situaciones, mi experiencia demostró que en el 90% de los casos, aunque existe un plugin, utilizarlo podría crear complicaciones innecesarias y problemas de compatibilidad. Además, en muchos casos, estos plugins añadían menús y otros elementos administrativos que no quiero ni necesito.
En la mayoría de los casos, he descubierto que al analizar el código de los plugins, pude extraer el fragmento de código que quería e implementarlo directamente en mi functions.php
. Esto me proporcionó exactamente la funcionalidad que necesitaba sin tener que incluir elementos innecesarios.
Así que el propósito de esta publicación es mi intento de involucrarte a ti, el lector/administrador/desarrollador, a compartir conmigo y con otros aquí cualquier fragmento de código que encuentres útil y hayas añadido al archivo functions.php
de tu tema para extender o mejorar WordPress sin utilizar un plugin.
Cuando envíes una respuesta aquí, por favor, dale un título a cada fragmento de código, háznoslo saber con qué versión de WordPress sabes que es compatible, incluye cualquier descripción que consideres que mejor describe su función y (si corresponde) incluye un enlace al plugin original o la fuente donde encontraste la información.
Espero con interés todas vuestras respuestas y, por supuesto, continuaré añadiendo mis propios descubrimientos cuando los encuentre.
Por favor, vota la pregunta y cualquier respuesta que encuentres útil haciendo clic en la flecha hacia arriba en el lado izquierdo de la pregunta o respuesta.

Activar función oculta de administración para mostrar todos los ajustes del sitio
Probado en: WordPress 3.1 RC3
Este pequeño fragmento de código hace algo bastante interesante. Añadirá una opción adicional a tu menú de ajustes con un enlace a "todos los ajustes" que te mostrará una lista completa de todos los parámetros que tienes en tu base de datos relacionados con tu sitio WordPress. El código de abajo solo hará visible este enlace para usuarios administradores y lo ocultará para el resto de usuarios.
// ENLACE PERSONALIZADO EN EL MENÚ DE ADMINISTRACIÓN PARA TODOS LOS AJUSTES
function all_settings_link() {
add_options_page(__('Todos los ajustes'), __('Todos los ajustes'), 'administrator', 'options.php');
}
add_action('admin_menu', 'all_settings_link');

¡Fantástico para desarrollo! Uso frecuentemente la tabla de opciones para almacenar versiones de la base de datos en mis plugins... usar phpMyAdmin para revertir a una versión antigua de la BD y probar un script de actualización es engorroso... ¡esto lo hará mucho más fácil!!!

Modificar el Logo de Inicio de Sesión y el Enlace de la URL de la Imagen
Probado en: WordPress 3.0.1
Este código te permitirá modificar fácilmente el Logo de la página de Inicio de Sesión de WordPress, así como el enlace href y el texto del título de este logo.
add_filter( 'login_headerurl', 'namespace_login_headerurl' );
/**
* Reemplaza la URL del logo en el encabezado de inicio de sesión
*
* @param $url
*/
function namespace_login_headerurl( $url ) {
$url = home_url( '/' );
return $url;
}
add_filter( 'login_headertitle', 'namespace_login_headertitle' );
/**
* Reemplaza el título del logo en el encabezado de inicio de sesión
*
* @param $title
*/
function namespace_login_headertitle( $title ) {
$title = get_bloginfo( 'name' );
return $title;
}
add_action( 'login_head', 'namespace_login_style' );
/**
* Reemplaza el logo en el encabezado de inicio de sesión
*/
function namespace_login_style() {
echo '<style>.login h1 a { background-image: url( ' . get_template_directory_uri() . '/images/logo.png ) !important; }</style>';
}
EDITAR: Si deseas usar el logo del sitio para reemplazar el logo de inicio de sesión, puedes usar lo siguiente para obtener esa información dinámicamente (probado en WP3.5):
function namespace_login_style() {
if( function_exists('get_custom_header') ){
$width = get_custom_header()->width;
$height = get_custom_header()->height;
} else {
$width = HEADER_IMAGE_WIDTH;
$height = HEADER_IMAGE_HEIGHT;
}
echo '<style>'.PHP_EOL;
echo '.login h1 a {'.PHP_EOL;
echo ' background-image: url( '; header_image(); echo ' ) !important; '.PHP_EOL;
echo ' width: '.$width.'px !important;'.PHP_EOL;
echo ' height: '.$height.'px !important;'.PHP_EOL;
echo ' background-size: '.$width.'px '.$height.'px !important;'.PHP_EOL;
echo '}'.PHP_EOL;
echo '</style>'.PHP_EOL;
}

Incluir tipos de contenido personalizados en los resultados de búsqueda.
// HACER QUE LOS TIPOS DE CONTENIDO PERSONALIZADOS SEAN BUSCABLES
function searchAll( $query ) {
if ( $query->is_search ) { $query->set( 'post_type', array( 'site', 'plugin', 'theme', 'person' )); }
return $query;
}
add_filter( 'the_search_query', 'searchAll' );
Añadir tipos de contenido personalizados al feed RSS principal del sitio por defecto.
// AÑADIR TIPOS DE CONTENIDO PERSONALIZADOS AL FEED RSS POR DEFECTO
function custom_feed_request( $vars ) {
if (isset($vars['feed']) && !isset($vars['post_type']))
$vars['post_type'] = array( 'post', 'site', 'plugin', 'theme', 'person' );
return $vars;
}
add_filter( 'request', 'custom_feed_request' );
Incluir tipos de contenido personalizados en el widget "Ahora mismo" del panel de administración
Esto incluirá tus tipos de contenido personalizados y el recuento de publicaciones para cada tipo en el widget del panel de control "Ahora mismo".
// AÑADIR TIPOS DE CONTENIDO PERSONALIZADOS AL WIDGET 'AHORA MISMO' DEL PANEL
function wph_right_now_content_table_end() {
$args = array(
'public' => true ,
'_builtin' => false
);
$output = 'object';
$operator = 'and';
$post_types = get_post_types( $args , $output , $operator );
foreach( $post_types as $post_type ) {
$num_posts = wp_count_posts( $post_type->name );
$num = number_format_i18n( $num_posts->publish );
$text = _n( $post_type->labels->singular_name, $post_type->labels->name , intval( $num_posts->publish ) );
if ( current_user_can( 'edit_posts' ) ) {
$num = "<a href='edit.php?post_type=$post_type->name'>$num</a>";
$text = "<a href='edit.php?post_type=$post_type->name'>$text</a>";
}
echo '<tr><td class="first num b b-' . $post_type->name . '">' . $num . '</td>';
echo '<td class="text t ' . $post_type->name . '">' . $text . '</td></tr>';
}
$taxonomies = get_taxonomies( $args , $output , $operator );
foreach( $taxonomies as $taxonomy ) {
$num_terms = wp_count_terms( $taxonomy->name );
$num = number_format_i18n( $num_terms );
$text = _n( $taxonomy->labels->singular_name, $taxonomy->labels->name , intval( $num_terms ));
if ( current_user_can( 'manage_categories' ) ) {
$num = "<a href='edit-tags.php?taxonomy=$taxonomy->name'>$num</a>";
$text = "<a href='edit-tags.php?taxonomy=$taxonomy->name'>$text</a>";
}
echo '<tr><td class="first b b-' . $taxonomy->name . '">' . $num . '</td>';
echo '<td class="t ' . $taxonomy->name . '">' . $text . '</td></tr>';
}
}
add_action( 'right_now_content_table_end' , 'wph_right_now_content_table_end' );

En relación al último fragmento de esta respuesta. Es una gran adición ya que estaba añadiendo esto manualmente para cada tipo de publicación. El único problema que tengo con esto es que añade los datos después de las entradas predeterminadas de "categoría" y "etiqueta". ¿Podrías actualizar tu respuesta para mover las predeterminadas de "categoría" o "etiqueta" más abajo o eliminarlas para que se puedan añadir manualmente?

@NetConstructor.com No creo que entienda tu solicitud. Si es así, creo que sería algo más difícil de hacer, y realmente no tengo tiempo ahora mismo para averiguar cómo hacerlo.

Eliminar notificaciones de actualización para todos los usuarios excepto ADMINISTRADOR
Probado en: WordPress 3.0.1
Este código asegura que ningún usuario excepto "admin" reciba notificaciones de WordPress cuando hay actualizaciones disponibles.
// ELIMINAR LA NOTIFICACIÓN DE ACTUALIZACIÓN DE WORDPRESS PARA TODOS LOS USUARIOS EXCEPTO SYSADMIN
global $user_login;
get_currentuserinfo();
if ($user_login !== "admin") { // Cambiar admin por el nombre de usuario que debe recibir las actualizaciones
add_action( 'init', create_function( '$a', "remove_action( 'init', 'wp_version_check' );" ), 2 );
add_filter( 'pre_option_update_core', create_function( '$a', "return null;" ) );
}
Versión modificada para mostrar notificaciones de actualización solo a usuarios administradores (en lugar de solo al usuario 'admin'):
// ELIMINAR LA NOTIFICACIÓN DE ACTUALIZACIÓN DE WORDPRESS PARA TODOS LOS USUARIOS EXCEPTO SYSADMIN
global $user_login;
get_currentuserinfo();
if (!current_user_can('update_plugins')) { // Verifica si el usuario actual puede actualizar plugins
add_action( 'init', create_function( '$a', "remove_action( 'init', 'wp_version_check' );" ), 2 );
add_filter( 'pre_option_update_core', create_function( '$a', "return null;" ) );
}

Esto está lejos de ser ideal. Solo funcionará si el inicio de sesión del administrador sigue siendo el predeterminado 'admin', lo cual no debería ser por razones de seguridad. En su lugar, deberías verificar una capacidad específica que deseas que las personas tengan para ver los mensajes.

Es decir, if (!current_user_can('manage_options')) {...add_filter...} -- Disculpa por el comentario doble, olvidé que al presionar enter se envían los comentarios)

Por eso añadí el comentario al código donde puedes cambiar el nombre de usuario del administrador. ¿Cómo lo mejorarías/reescribirías?

La mejor manera es eliminar el global $user_login y get_currentuserinfo() y en su lugar usar current_user_can en tu cláusula if. Es solo 1 línea en lugar de 3 y es la forma estándar. Puedes verificar la capacidad específica que se necesitaría para ACTUAR sobre los mensajes, en este caso hay 'update_core' y 'update_plugins'.

entonces: if (!current_user_can('update_plugins')) {/ELIMINAR MENSAJES/}

@Jeremy Clarke entonces, ¿este código sería la forma correcta de hacerlo? Pero, si solo quisieras permitir que un nombre de usuario específico reciba los avisos, ¿el código anterior sería la mejor manera?
if (!current_user_can('update_plugins')) { add_action( 'init', create_function( '$a', "remove_action( 'init', 'wp_version_check' );" ), 2 ); add_filter( 'pre_option_update_core', create_function( '$a', "return null;" )); }

Si quisieras verificar un nombre de usuario específico, supongo que tu código en la respuesta original es aceptable, aunque podría haber una forma ligeramente más efectiva. El código completo usando mi solución se vería como lo que tienes en tu último comentario. Es lo mismo que tu respuesta pero con la verificación current_user_can() en lugar de $user_login !== 'admin'.

Edté la respuesta y añadí la versión que usa current_user_can('update_plugins')

Acabo de probar los códigos. Pero me aparece una página de error al usar los códigos. El mismo problema con ambos códigos

Cargar jQuery desde el CDN de Google
Probado en: WordPress 3.0.1
// Una inclusión de jQuery aún más inteligente :)
add_action( 'init', 'jquery_register' );
// Registrar desde Google y para el footer
function jquery_register() {
if ( !is_admin() ) {
wp_deregister_script( 'jquery' );
wp_register_script( 'jquery', ( 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js' ), false, null, true );
wp_enqueue_script( 'jquery' );
}
}
Eliminar la información de versión de WordPress por seguridad
Probado en: WordPress 3.0.1
// Eliminar información de versión del head y feeds
function complete_version_removal() {
return '';
}
add_filter('the_generator', 'complete_version_removal');
Añadir enlaces de Spam y Eliminar a los comentarios en el Front End
Probado en: WordPress 3.0.1
Esto facilita mucho la gestión de comentarios desde el front end al añadir enlaces de spam y eliminar.**
// Enlaces de spam y eliminar para todas las versiones de WordPress
function delete_comment_link($id) {
if (current_user_can('edit_post')) {
echo '| <a href="'.get_bloginfo('wpurl').'/wp-admin/comment.php?action=cdc&c='.$id.'">eliminar</a> ';
echo '| <a href="'.get_bloginfo('wpurl').'/wp-admin/comment.php?action=cdc&dt=spam&c='.$id.'">spam</a>';
}
}
Retrasar la publicación pública en el Feed RSS
Probado en: WordPress 3.0.1
Finalmente, me gusta retrasar la publicación en mis feeds RSS durante 10-15 minutos porque siempre encuentro al menos un par de errores en mi texto. Otros usos son en caso de que quieras que el contenido sea exclusivo de tu sitio durante un día o una semana antes de enviarlo a tus lectores de RSS.
// Retrasar la actualización del feed
function publish_later_on_feed($where) {
global $wpdb;
if (is_feed()) {
// Marca de tiempo en formato WordPress
$now = gmdate('Y-m-d H:i:s');
// Valor de espera; + dispositivo
$wait = '10'; // entero
// http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_timestampdiff
$device = 'MINUTE'; // MINUTE, HOUR, DAY, WEEK, MONTH, YEAR
// Añadir sintaxis SQL al $where predeterminado
$where .= " AND TIMESTAMPDIFF($device, $wpdb->posts.post_date_gmt, '$now') > $wait ";
}
return $where;
}
add_filter('posts_where', 'publish_later_on_feed');

fuente en mi publicación: http://wpengineer.com/320/publish-the-feed-later/ con más información

También puedes simplemente eliminar el filtro del generador: remove_action('wp_head', 'wp_generator');

¿Por qué no usamos CDN de Google para el admin también? No lo entiendo

@Derek Perkins - ¿Puedes hacer que cada uno de estos fragmentos de código sea una respuesta diferente para que se pueda votar por separado?

http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js caduca después de solo una hora. Siempre usa la información completa de versión como http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js - que caduca después de un año.

¿Puedes dividir cada una de estas entradas wiki en entradas separadas en las próximas semanas? Quería hacerlo por ti pero no quería que pareciera que estoy tratando de obtener puntos por información que compartiste.

El código "Eliminar la información de versión de WordPress por seguridad" en realidad no hace nada para aumentar la seguridad de tu sitio. Ni siquiera evita que se exponga la versión de WP que estás utilizando.

No es cierto Joseph, si la versión de WordPress está expuesta, las personas pueden ver si estás ejecutando una versión antigua, exponiendo así tus vulnerabilidades. Siempre es una buena decisión eliminar esto de todas las instalaciones de WordPress. Personalmente, ni siquiera sé por qué lo incluyeron en primer lugar, ya que ES un problema de seguridad.

Establece un número máximo de revisiones de entradas para evitar la saturación de la base de datos.
Probado en: WordPress 3.0.1
Por defecto es infinito, y esto lo configurará para que solo recuerde las últimas cinco ediciones:
/**
* Establece las revisiones de entradas a menos que la constante ya esté definida en wp-config.php
*/
if (!defined('WP_POST_REVISIONS')) define('WP_POST_REVISIONS', 5);
Por si sirve de algo, hay muchas ideas geniales para CONSTANTES que se pueden configurar en la página del Codex Editando wp-config.php.

Al analizar su uso en wp_save_post_revision() no parece haber una forma de distinguir según los tipos de publicación. No hay ningún filtro ni nada en el valor, aunque probablemente debería haberlo.

gracias Jeremy - Para cualquier otra persona, si sabes cómo hacer esto por favor publícalo aquí.

Herramientas de perfilado para WordPress
Me gusta añadir herramientas de perfilado en un archivo separado, que luego incluyo desde functions.php cuando es necesario:
<?php
if ( !defined('SAVEQUERIES') && isset($_GET['debug']) && $_GET['debug'] == 'sql' )
define('SAVEQUERIES', true);
if ( !function_exists('dump') ) :
/**
* dump()
*
* @param mixed $in
* @return mixed $in
**/
function dump($in = null) {
echo '<pre style="margin-left: 0px; margin-right: 0px; padding: 10px; border: solid 1px black; background-color: ghostwhite; color: black; text-align: left;">';
foreach ( func_get_args() as $var ) {
echo "\n";
if ( is_string($var) ) {
echo "$var\n";
} else {
var_dump($var);
}
}
echo '</pre>' . "\n";
return $in;
} # dump()
endif;
/**
* add_stop()
*
* @param mixed $in
* @param string $where
* @return mixed $in
**/
function add_stop($in = null, $where = null) {
global $sem_stops;
global $wp_object_cache;
$queries = get_num_queries();
$milliseconds = timer_stop() * 1000;
$out = "$queries consultas - {$milliseconds}ms";
if ( function_exists('memory_get_usage') ) {
$memory = number_format(memory_get_usage() / ( 1024 * 1024 ), 1);
$out .= " - {$memory}MB";
}
$out .= " - $wp_object_cache->cache_hits aciertos de caché / " . ( $wp_object_cache->cache_hits + $wp_object_cache->cache_misses );
if ( $where ) {
$sem_stops[$where] = $out;
} else {
dump($out);
}
return $in;
} # add_stop()
/**
* dump_stops()
*
* @param mixed $in
* @return mixed $in
**/
function dump_stops($in = null) {
if ( $_POST )
return $in;
global $sem_stops;
global $wp_object_cache;
$stops = '';
foreach ( $sem_stops as $where => $stop )
$stops .= "$where: $stop\n";
dump("\n" . trim($stops) . "\n");
if ( defined('SAVEQUERIES') && $_GET['debug'] == 'sql' ) {
global $wpdb;
foreach ( $wpdb->queries as $key => $data ) {
$query = rtrim($data[0]);
$duration = number_format($data[1] * 1000, 1) . 'ms';
$loc = trim($data[2]);
$loc = preg_replace("/(require|include)(_once)?,\s*/ix", '', $loc);
$loc = "\n" . preg_replace("/,\s*/", ",\n", $loc) . "\n";
dump($query, $duration, $loc);
}
}
if ( $_GET['debug'] == 'cache' )
dump($wp_object_cache->cache);
if ( $_GET['debug'] == 'cron' ) {
$crons = get_option('cron');
foreach ( $crons as $time => $_crons ) {
if ( !is_array($_crons) )
continue;
foreach ( $_crons as $event => $_cron ) {
foreach ( $_cron as $details ) {
$date = date('Y-m-d H:m:i', $time);
$schedule = isset($details['schedule']) ? "({$details['schedule']})" : '';
if ( $details['args'] )
dump("$date: $event $schedule", $details['args']);
else
dump("$date: $event $schedule");
}
}
}
}
return $in;
} # dump_stops()
add_action('init', create_function('$in', '
return add_stop($in, "Carga");
'), 10000000);
add_action('template_redirect', create_function('$in', '
return add_stop($in, "Consulta");
'), -10000000);
add_action('wp_footer', create_function('$in', '
return add_stop($in, "Visualización");
'), 10000000);
add_action('admin_footer', create_function('$in', '
return add_stop($in, "Visualización");
'), 10000000);
/**
* init_dump()
*
* @return void
**/
function init_dump() {
global $hook_suffix;
if ( !is_admin() || empty($hook_suffix) ) {
add_action('wp_footer', 'dump_stops', 10000000);
add_action('admin_footer', 'dump_stops', 10000000);
} else {
add_action('wp_footer', 'dump_stops', 10000000);
add_action("admin_footer-$hook_suffix", 'dump_stops', 10000000);
}
} # init_dump()
add_action('wp_print_scripts', 'init_dump');
/**
* dump_phpinfo()
*
* @return void
**/
function dump_phpinfo() {
if ( isset($_GET['debug']) && $_GET['debug'] == 'phpinfo' ) {
phpinfo();
die;
}
} # dump_phpinfo()
add_action('init', 'dump_phpinfo');
/**
* dump_http()
*
* @param array $args
* @param string $url
* @return array $args
**/
function dump_http($args, $url) {
dump(preg_replace("|/[0-9a-f]{32}/?$|", '', $url));
return $args;
} # dump_http()
/**
* dump_trace()
*
* @return void
**/
function dump_trace() {
$backtrace = debug_backtrace();
foreach ( $backtrace as $trace )
dump(
'Archivo/Línea: ' . $trace['file'] . ', ' . $trace['line'],
'Función / Clase: ' . $trace['function'] . ', ' . $trace['class']
);
} # dump_trace()
if ( $_GET['debug'] == 'http' )
add_filter('http_request_args', 'dump_http', 0, 2);
?>

¿hay alguna forma rápida de modificar esto para que el script solo se llame cuando eres administrador Y añadir algo a la URL para mostrar la información de depuración?

Así es como se hace en mi tema: http://www.semiologic.com/software/sem-reloaded/ -- el /inc/debug.php es incluido por /functions.php o /inc/init.php (no recuerdo exactamente ahora mismo).

Enfocar imágenes redimensionadas (solo JPEG)
Esta función enfoca las imágenes JPEG redimensionadas. Un ejemplo de la diferencia:
function ajx_sharpen_resized_files( $resized_file ) {
$image = wp_load_image( $resized_file );
if ( !is_resource( $image ) )
return new WP_Error( 'error_loading_image', $image, $file );
$size = @getimagesize( $resized_file );
if ( !$size )
return new WP_Error('invalid_image', __('No se pudo leer el tamaño de la imagen'), $file);
list($orig_w, $orig_h, $orig_type) = $size;
switch ( $orig_type ) {
case IMAGETYPE_JPEG:
$matrix = array(
array(-1, -1, -1),
array(-1, 16, -1),
array(-1, -1, -1),
);
$divisor = array_sum(array_map('array_sum', $matrix));
$offset = 0;
imageconvolution($image, $matrix, $divisor, $offset);
imagejpeg($image, $resized_file,apply_filters( 'jpeg_quality', 90, 'edit_image' ));
break;
case IMAGETYPE_PNG:
return $resized_file;
case IMAGETYPE_GIF:
return $resized_file;
}
return $resized_file;
}
add_filter('image_make_intermediate_size', 'ajx_sharpen_resized_files', 900);

si quieren esto como plugin: http://wordpress.org/extend/plugins/sharpen-resized-images/

Eliminar las Meta Boxes predeterminadas de WordPress
Probado en: WordPress 3.0.1
Este código te permitirá eliminar Meta Boxes específicas que WordPress añade por defecto en las pantallas de Añadir/Editar Entrada y Añadir/Editar Página.
// ELIMINAR META BOXES DE LA PANTALLA DE ENTRADAS PREDETERMINADA
function remove_default_post_screen_metaboxes() {
remove_meta_box( 'postcustom','post','normal' ); // Meta Box de Campos Personalizados
remove_meta_box( 'postexcerpt','post','normal' ); // Meta Box de Extracto
remove_meta_box( 'commentstatusdiv','post','normal' ); // Meta Box de Comentarios
remove_meta_box( 'trackbacksdiv','post','normal' ); // Meta Box de Retroenlaces
remove_meta_box( 'slugdiv','post','normal' ); // Meta Box de Slug
remove_meta_box( 'authordiv','post','normal' ); // Meta Box de Autor
}
add_action('admin_menu', 'remove_default_post_screen_metaboxes');
// ELIMINAR META BOXES DE LA PANTALLA DE PÁGINAS PREDETERMINADA
function remove_default_page_screen_metaboxes() {
remove_meta_box( 'postcustom','page','normal' ); // Meta Box de Campos Personalizados
remove_meta_box( 'postexcerpt','page','normal' ); // Meta Box de Extracto
remove_meta_box( 'commentstatusdiv','page','normal' ); // Meta Box de Comentarios
remove_meta_box( 'trackbacksdiv','page','normal' ); // Meta Box de Retroenlaces
remove_meta_box( 'slugdiv','page','normal' ); // Meta Box de Slug
remove_meta_box( 'authordiv','page','normal' ); // Meta Box de Autor
}
add_action('admin_menu', 'remove_default_page_screen_metaboxes');

Según este http://wordpress.stackexchange.com/questions/34030/cant-change-permalink-url-after-hitting-ok-and-update/37779#37779 no ocultaría el slugdiv de esta manera, sino que usaría este https://gist.github.com/1863830 en su lugar

Filtro para eliminar la corrección de "Wordpress" a "WordPress"
Probado en: WordPress 3.0.1
Se agregó un filtro en la versión 3.0 de WordPress que convierte automáticamente todas las instancias de "Wordpress" (sin la P mayúscula) a "WordPress" (con la P mayúscula) en el contenido de las publicaciones, títulos de entradas y texto de comentarios. Algunas personas lo ven como intrusivo, pero a veces necesito escribir mal intencionalmente WordPress y encontré este filtro algo molesto.
// Eliminar el molesto filtro de la P mayúscula
if(function_exists('capital_P_dangit')) {
foreach ( array( 'the_content', 'the_title' ) as $filter )
remove_filter( $filter, 'capital_P_dangit', 11 );
remove_filter('comment_text', 'capital_P_dangit', 31 );
}

gran pequeño descubrimiento. Una de esas cosas que simplemente elimina otro trozo de código que no es necesario

En WordPress 3.0.1, este filtro se añade con prioridad 11, así que necesitas añadir 11
como tercer parámetro para eliminarlo.

Personalizar el Escritorio
add_action('wp_dashboard_setup', 'my_custom_dashboard_widgets');
function my_custom_dashboard_widgets() {
global $wp_meta_boxes;
Eliminar estos widgets del escritorio...
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_plugins']);
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_primary']);
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_secondary']);
Añadir un widget personalizado llamado 'Ayuda y Soporte'
wp_add_dashboard_widget('custom_help_widget', 'Ayuda y Soporte', 'custom_dashboard_help');
}
Este es el contenido para tu widget personalizado
function custom_dashboard_help() {
echo '<p>Lorum ipsum delor sit amet et nunc</p>';
}

Añadir campos personalizados al perfil de usuario
Coloca el siguiente código en tu archivo functions.php para añadir campos personalizados al perfil de usuario. Edita o añade líneas según necesites.
Recuerda no eliminar la línea: return $contactmethods; de lo contrario no funcionará.
// CAMPOS PERSONALIZADOS DE PERFIL DE USUARIO
function my_custom_userfields( $contactmethods ) {
// AÑADIR CAMPOS PERSONALIZADOS DE CONTACTO
$contactmethods['contact_phone_office'] = 'Teléfono de oficina';
$contactmethods['contact_phone_mobile'] = 'Teléfono móvil';
$contactmethods['contact_office_fax'] = 'Fax de oficina';
// AÑADIR CAMPOS PERSONALIZADOS DE DIRECCIÓN
$contactmethods['address_line_1'] = 'Línea de dirección 1';
$contactmethods['address_line_2'] = 'Línea de dirección 2 (opcional)';
$contactmethods['address_city'] = 'Ciudad';
$contactmethods['address_state'] = 'Estado/Provincia';
$contactmethods['address_zipcode'] = 'Código postal';
return $contactmethods;
}
add_filter('user_contactmethods','my_custom_userfields',10,1);
Para mostrar los campos personalizados puedes usar uno de los dos métodos que se indican a continuación.
Opción 1:
the_author_meta('facebook', $current_author->ID)
Opción 2:
<?php $current_author = get_userdata(get_query_var('author')); ?>
<p><a href="<?php echo esc_url($current_author->contact_phone_office);?>" title="telefono_oficina"> Teléfono de oficina</a></p>

Personalizar el orden del menú de administración
Probado en: WordPress 3.0.1
Este código te permitirá reorganizar el orden de los elementos en el menú de administración. Todo lo que necesitas hacer es hacer clic en un enlace existente en el menú de administración y copiar todo lo que aparece antes de la URL /wp-admin/. El orden que se muestra a continuación representa el orden que tendrá el nuevo menú de administración.
// PERSONALIZAR EL ORDEN DEL MENÚ DE ADMINISTRACIÓN
function custom_menu_order($menu_ord) {
if (!$menu_ord)
return true;
return array(
'index.php', // Esto representa el enlace del escritorio
'edit.php?post_type=events', // Este es un menú de tipo de entrada personalizado
'edit.php?post_type=news',
'edit.php?post_type=articles',
'edit.php?post_type=faqs',
'edit.php?post_type=mentors',
'edit.php?post_type=testimonials',
'edit.php?post_type=services',
'edit.php?post_type=page', // Este es el menú predeterminado de páginas
'edit.php', // Este es el menú de administración de ENTRADAS predeterminado
);
}
add_filter('custom_menu_order', 'custom_menu_order');
add_filter('menu_order', 'custom_menu_order');

¿Existe realmente un filtro core llamado custom_menu_order
? No pude encontrarlo...

@kaiser documentado aquí http://codex.wordpress.org/Plugin_API/Filter_Reference/custom_menu_order

Función para cambiar la longitud del Extracto
Probado en: WordPress 3.0.1
Por defecto, todos los extractos están limitados a 55 palabras. Utilizando el código siguiente puedes sobrescribir esta configuración predeterminada:
function new_excerpt_length($length) {
return 100;
}
add_filter('excerpt_length', 'new_excerpt_length');
Este ejemplo cambia la longitud del extracto a 100 palabras, pero puedes usar el mismo método para cambiarlo a cualquier valor.

@user402... ¿esto limita por palabras o caracteres? ¿Podrías publicar cómo hacer ambos?

@NetConstructor.com Esta función (y el hook excerpt_length
) limita por palabras.

Añadir Miniaturas en la Lista de Entradas/Páginas
Puedes añadir esto a tus funciones para mostrar en la lista de gestión/edición de entradas y páginas una nueva columna con la vista previa de la miniatura.
/****** Añadir Miniaturas en la Lista de Entradas/Páginas ******/
if ( !function_exists('AddThumbColumn') && function_exists('add_theme_support') ) {
// para entradas y páginas
add_theme_support('post-thumbnails', array( 'post', 'page' ) );
function AddThumbColumn($cols) {
$cols['thumbnail'] = __('Miniatura');
return $cols;
}
function AddThumbValue($column_name, $post_id) {
$width = (int) 35;
$height = (int) 35;
if ( 'thumbnail' == $column_name ) {
// miniatura de WP 2.9
$thumbnail_id = get_post_meta( $post_id, '_thumbnail_id', true );
// imagen de la galería
$attachments = get_children( array('post_parent' => $post_id, 'post_type' => 'attachment', 'post_mime_type' => 'image') );
if ($thumbnail_id)
$thumb = wp_get_attachment_image( $thumbnail_id, array($width, $height), true );
elseif ($attachments) {
foreach ( $attachments as $attachment_id => $attachment ) {
$thumb = wp_get_attachment_image( $attachment_id, array($width, $height), true );
}
}
if ( isset($thumb) && $thumb ) {
echo $thumb;
} else {
echo __('Ninguna');
}
}
}
// para entradas
add_filter( 'manage_posts_columns', 'AddThumbColumn' );
add_action( 'manage_posts_custom_column', 'AddThumbValue', 10, 2 );
// para páginas
add_filter( 'manage_pages_columns', 'AddThumbColumn' );
add_action( 'manage_pages_custom_column', 'AddThumbValue', 10, 2 );
}

Eliminar pings a tu propio blog
Probado en: WordPress 3.0.1
// Eliminar pings a uno mismo
function no_self_ping( &$links ) {
$home = get_option( 'home' );
foreach ( $links as $l => $link )
if ( 0 === strpos( $link, $home ) )
unset($links[$l]);
}
add_action( 'pre_ping', 'no_self_ping' );

¿Con qué frecuencia y cuándo WordPress se hace ping a sí mismo?

Realmente tengo ese problema con bastante frecuencia. Si hago referencia a un enlace interno hacia otra publicación en mi blog de WP, recibo un trackback o pingback (no recuerdo cuál) de mí mismo. Es molesto.

Habilitar compresión GZIP de salida
Normalmente el servidor debería estar configurado para hacer esto automáticamente, pero muchos hosts compartidos no lo hacen (probablemente para incrementar el uso de ancho de banda de los clientes).
if(extension_loaded("zlib") && (ini_get("output_handler") != "ob_gzhandler"))
add_action('wp', create_function('', '@ob_end_clean();@ini_set("zlib.output_compression", 1);'));

Mostrar Consultas de la Base de Datos, Tiempo de Ejecución y Consumo de Memoria
Probado en: WordPress 3.0.1
function performance( $visible = false ) {
$stat = sprintf( '%d consultas en %.3f segundos, usando %.2fMB de memoria',
get_num_queries(),
timer_stop( 0, 3 ),
memory_get_peak_usage() / 1024 / 1024
);
echo $visible ? $stat : "<!-- {$stat} -->" ;
}
Luego este código debajo del código anterior que insertará automáticamente el código de arriba en el pie de página de tu sitio web público (asegúrate de que tu tema esté llamando a wp_footer
):
add_action( 'wp_footer', 'performance', 20 );
Puede ser llamado múltiples veces.

Extraer Automáticamente la Primera Imagen del Contenido del Post
Probado en: WordPress 3.0.1
Este código extraerá automáticamente la primera imagen asociada a un post y te permitirá mostrarla/usarla llamando a la función getImage.
// EXTRAER AUTOMÁTICAMENTE LA PRIMERA IMAGEN DEL POST
function getImage($num) {
global $more;
$more = 1;
$link = get_permalink();
$content = get_the_content();
$count = substr_count($content, '<img');
$start = 0;
for($i=1;$i<=$count;$i++) {
$imgBeg = strpos($content, '<img', $start);
$post = substr($content, $imgBeg);
$imgEnd = strpos($post, '>');
$postOutput = substr($post, 0, $imgEnd+1);
$postOutput = preg_replace('/width="([0-9]*)" height="([0-9]*)"/', '',$postOutput);;
$image[$i] = $postOutput;
$start=$imgEnd+1;
}
if(stristr($image[$num],'<img')) {
echo '<a href="'.$link.'">'.$image[$num]."</a>";
}
$more = 0;
}

Bien, pero get_the_image también hace un muy buen trabajo con esto. http://wordpress.org/extend/plugins/get-the-image/

correcto, pero este funciona de forma diferente y soluciona varios problemas que get_the_image no tiene en cuenta

@matt -- En WordPress hay diferentes formas de agregar imágenes a las publicaciones y creo que el script get_the_image solo verifica una de ellas. Esto verifica si hay una imagen destacada y la usa primero si está disponible, luego creo que verifica la primera imagen agregada al contenido de la publicación y si no se encuentra, revisa la galería multimedia en busca de la imagen con el orden de clasificación más alto (al menos así recuerdo que funciona el orden).

Sugiero http://wordpress.org/extend/plugins/auto-post-thumbnail/ Genera automáticamente la imagen destacada (Post Thumbnail) a partir de la primera imagen en la publicación o cualquier tipo de publicación personalizada, solo si no se ha establecido una imagen destacada.

Desregistrar los Widgets Predeterminados de WordPress
Probado en: WordPress 3.0.1
// Desregistrar todos los Widgets predeterminados de WordPress
function unregister_default_wp_widgets() {
unregister_widget('WP_Widget_Pages');
unregister_widget('WP_Widget_Calendar');
unregister_widget('WP_Widget_Archives');
unregister_widget('WP_Widget_Links');
unregister_widget('WP_Widget_Meta');
unregister_widget('WP_Widget_Search');
unregister_widget('WP_Widget_Text');
unregister_widget('WP_Widget_Categories');
unregister_widget('WP_Widget_Recent_Posts');
unregister_widget('WP_Widget_Recent_Comments');
unregister_widget('WP_Widget_RSS');
unregister_widget('WP_Widget_Tag_Cloud');
}
add_action('widgets_init', 'unregister_default_wp_widgets', 1);

Mostrar qué archivo de plantilla de tema está usando una entrada/página en el encabezado
add_action('wp_head', 'show_template');
function show_template() {
global $template;
print_r($template);
}
Acortar la salida DIV predeterminada si tu tema usa post_class.
Si tu tema está usando algo como:
<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
Puedes tener divs extremadamente largos en tu código fuente que podrían verse así o incluso más largos:
<div id="post-4" class="post-4 post type-post hentry category-uncategorized category-test category-test-1-billion category-test2 category-test3 category-testing">
Esto realmente puede empezar a saturar tu código fuente y parece bastante innecesario en la mayoría de los casos, con 3-4 niveles es suficiente.
Para el primer ejemplo podemos cortar la salida así:
// Cortar salidas DIV extremadamente largas
function category_id_class($classes) {
global $post;
foreach((get_the_category($post->ID)) as $category)
$classes[] = $category->category_nicename;
return array_slice($classes, 0,5);
}
add_filter('post_class', 'category_id_class');
Esto corta la salida para incluir solo los primeros 5 valores, por lo que el ejemplo anterior se convierte en:
<div id="post-4" class="post-4 post type-post hentry category-uncategorized">
Hacer que los archivos de categoría muestren todas las entradas, independientemente del tipo de entrada: útil para tipos de entrada personalizados
function any_ptype_on_cat($request) {
if ( isset($request['category_name']) )
$request['post_type'] = 'any';
return $request;
}
add_filter('request', 'any_ptype_on_cat');
Eliminar elementos no deseados del panel de control
Esto ya se había publicado pero no incluía la lista completa de elementos. Especialmente esos molestos "enlaces entrantes!"
add_action('wp_dashboard_setup', 'my_custom_dashboard_widgets');
function my_custom_dashboard_widgets() {
global $wp_meta_boxes;
// Right Now - Comentarios, Entradas, Páginas de un vistazo
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_right_now']);
// Comentarios recientes
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_recent_comments']);
// Enlaces entrantes
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_incoming_links']);
// Plugins - Populares, nuevos y recientemente actualizados
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_plugins']);
// Blog de desarrollo de WordPress
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_primary']);
// Otras noticias de WordPress
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_secondary']);
// Formulario de publicación rápida
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_quick_press']);
// Lista de borradores recientes
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_recent_drafts']);
}
Eliminar saltos de página "Leer más"
En su lugar, volver a la parte superior de la página. Ya sabes, cuando haces clic en "leer más" salta al lugar en la página, lo cual puede ser molesto, esto hace que cargue la página normalmente, ¡sin saltos!
function remove_more_jump_link($link) {
$offset = strpos($link, '#more-');
if ($offset) {
$end = strpos($link, '"', $offset);
}
if ($end) {
$link = substr_replace($link, '', $offset, $end-$offset);
}
return $link;
}
add_filter('the_content_more_link', 'remove_more_jump_link');
Restringir elementos del menú de ADMINISTRACIÓN basado en nombre de usuario, reemplaza username con el nombre de un usuario real.
function remove_menus()
{
global $menu;
global $current_user;
get_currentuserinfo();
if($current_user->user_login == 'username')
{
$restricted = array(__('Entradas'),
__('Medios'),
__('Enlaces'),
__('Páginas'),
__('Comentarios'),
__('Apariencia'),
__('Plugins'),
__('Usuarios'),
__('Herramientas'),
__('Ajustes')
);
end ($menu);
while (prev($menu)) {
$value = explode(' ',$menu[key($menu)][0]);
if(in_array($value[0] != NULL ? $value[0] : "" , $restricted)) {
unset($menu[key($menu)]);
}
} // end while
} // end if
}
add_action('admin_menu', 'remove_menus');
//alternativamente puedes usar if($current_user->user_login != 'admin') en su lugar, probablemente más útil
Estilizar la nube de etiquetas
// Personalización de nube de etiquetas
add_filter('widget_tag_cloud_args', 'style_tags');
function style_tags($args) {
$args = array(
'largest' => '10',
'smallest' => '10',
'format' => 'list',
);
return $args;
}
Una referencia completa de opciones está aquí (¡hay muchas!) http://codex.wordpress.org/Function_Reference/wp_tag_cloud
Cambiar el intervalo de actualización predeterminado del Widget RSS
(El predeterminado es 6 o 12 horas - no recuerdo (1800 = 30 minutos).
add_filter( 'wp_feed_cache_transient_lifetime', create_function('$fixrss', 'return 1800;') );

¿Podrías dividir cada uno de estos en respuestas separadas en las próximas semanas? Iba a hacerlo por ti pero no quería que pareciera que me estoy atribuyendo el crédito de tus respuestas. En cualquier caso, estoy intentando mantener esto organizado para que los usuarios puedan encontrar fácilmente la información que buscan. Gracias de antemano

Estaba usando el código "Restringir elementos del menú de ADMIN basado en nombre de usuario, reemplaza nombre de usuario con el nombre de un usuario real" que es genial, pero ¿podrías actualizar el código para que también muestre cómo se puede hacer esto para un "rol de usuario" específico? ¡Creo que sería muy útil!

Lo siento NetConstructor, acabo de ver tu comentario ahora. Para el rol de usuario usaría "current_user_can". No tengo tiempo para probarlo ahora, pero cuando lo haga, lo agregaré.

Eliminar el aviso de actualización de plugins SOLO para plugins INACTIVOS
function update_active_plugins($value = '') {
/*
El array $value pasado contiene la lista de plugins con marcas de tiempo
de la última vez que se verificó la coincidencia de versiones del grupo.
El nodo $value->response contiene un array de los elementos que están
desactualizados. Este nodo response es usado por el menú 'Plugins'
por ejemplo para indicar que hay actualizaciones. También en el listado
real de plugins para mostrar el cuadro amarillo debajo de un plugin
que indica que se requiere una acción por parte del usuario.
*/
if ((isset($value->response)) && (count($value->response))) {
// Obtener la lista de plugins activos actuales
$active_plugins = get_option('active_plugins');
if ($active_plugins) {
// Aquí comenzamos a comparar los elementos $value->response
// verificando cada uno contra la lista de plugins activos.
foreach($value->response as $plugin_idx => $plugin_item) {
// Si el elemento de respuesta no es un plugin activo, lo eliminamos.
// Esto evitará que WordPress indique que el plugin necesita acciones de actualización.
if (!in_array($plugin_idx, $active_plugins))
unset($value->response[$plugin_idx]);
}
}
else {
// Si no hay plugins activos, ignoramos los inactivos desactualizados.
foreach($value->response as $plugin_idx => $plugin_item) {
unset($value->response);
}
}
}
return $value;
}
add_filter('transient_update_plugins', 'update_active_plugins'); // Hook para 2.8.+
//add_filter( 'option_update_plugins', 'update_active_plugins'); // Hook para 2.7.x

Eliminar información y HTML superfluo dentro de la etiqueta <head>
// eliminar información innecesaria del encabezado
add_action( 'init', 'remove_header_info' );
function remove_header_info() {
remove_action( 'wp_head', 'rsd_link' );
remove_action( 'wp_head', 'wlwmanifest_link' );
remove_action( 'wp_head', 'wp_generator' );
remove_action( 'wp_head', 'start_post_rel_link' );
remove_action( 'wp_head', 'index_rel_link' );
remove_action( 'wp_head', 'adjacent_posts_rel_link' ); // para WordPress < 3.0
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head' ); // para WordPress >= 3.0
}
// eliminar CSS extra que inyecta el widget 'Comentarios recientes'
add_action( 'widgets_init', 'remove_recent_comments_style' );
function remove_recent_comments_style() {
global $wp_widget_factory;
remove_action( 'wp_head', array(
$wp_widget_factory->widgets['WP_Widget_Recent_Comments'],
'recent_comments_style'
) );
}

Activar Depuración de Errores y Registro para Uso en Sitios en Producción
Este es un fragmento de código que escribí para hacer uso de las constantes WP_DEBUG que normalmente están desactivadas por defecto. Bueno, creé una forma no solo de activar WP_DEBUG para que puedas usarlo en un sitio en producción sin efectos secundarios negativos, sino que también hice uso de otras constantes de depuración para forzar que se muestren los errores y para crear un archivo de registro de los errores y Notices en el directorio /wp-content.
Coloca este código en tu archivo wp-config.php (DESPUÉS DE HACER UNA COPIA DE SEGURIDAD POR SI ACASO) y luego puedes pasar los parámetros ?debug=1, 2 o 3 al final de cualquier URL en tu sitio.
?debug=1 = muestra todos los errores/notices ?debug=2 = fuerza que se muestren ?debug=3 = crea un archivo debug.log con todos los errores en el directorio /wp-content.
/**
* Escrito por Jared Williams - http://new2wp.com
* @wp-config.php reemplaza la constante WP_DEBUG con este código
* Activa la depuración de WP para uso en un sitio en producción
* http://core.trac.wordpress.org/browser/trunk/wp-includes/load.php#L230
* Pasa el parámetro '?debug=#' al final de cualquier URL del sitio
*
* http://ejemplo.com/?debug=1, /?debug=2, /?debug=3
*/
if ( isset($_GET['debug']) && $_GET['debug'] == '1' ) {
// Habilita el reporte de notices durante el desarrollo - E_ALL
define('WP_DEBUG', true);
} elseif ( isset($_GET['debug']) && $_GET['debug'] == '2' ) {
// Debe ser true para que WP_DEBUG_DISPLAY funcione
define('WP_DEBUG', true);
// Fuerza la visualización de errores
define('WP_DEBUG_DISPLAY', true);
} elseif ( isset($_GET['debug']) && $_GET['debug'] == '3' ) {
// Debe ser true para que WP_DEBUG_LOG funcione
define('WP_DEBUG', true);
// Registra errores en debug.log en el directorio wp-content
define('WP_DEBUG_LOG', true);
}
Entro en más detalles en la publicación que escribí como invitado para Comluv si estás interesado, aquí: http://comluv.com/dev/enable-debugging-and-logging-for-live-site-usage/
Todavía estoy trabajando en una forma de hacer esto protegido por contraseña, o preferiblemente hacer que funcione con if (current_user_can('manage_themes') and is_logged_in().
Pero ahí es donde se vuelve mucho más complicado.

Agregar Títulos Dinámicos Automáticamente a Páginas Públicas
Probado en: WordPress 3.0.1
Utilizando el código siguiente se crearán automáticamente títulos dinámicos basados en las páginas/entradas que se estén visualizando públicamente.
/* Títulos Dinámicos **/
// Esto configura tu <title> dependiendo de la página en la que estés, para mejor formato y SEO
// Necesitas establecer la variable $longd con algún texto personalizado al inicio de la función
function dynamictitles() {
$longd = __('Ingresa tu descripción larga aquí.', 'texdomainstring');
if ( is_single() ) {
wp_title('');
echo ' | '.get_bloginfo('name');
} else if ( is_page() || is_paged() ) {
bloginfo('name');
wp_title('|');
} else if ( is_author() ) {
bloginfo('name');
wp_title(' | '.__('Autor', 'texdomainstring'));
} else if ( is_category() ) {
bloginfo('name');
wp_title(' | '.__('Archivo para', 'texdomainstring'));
} else if ( is_tag() ) {
echo get_bloginfo('name').' | '.__('Archivo de etiqueta para', 'texdomainstring');
wp_title('');
} else if ( is_archive() ) {
echo get_bloginfo('name').' | '.__('Archivo para', 'texdomainstring');
wp_title('');
} else if ( is_search() ) {
echo get_bloginfo('name').' | '.__('Resultados de Búsqueda', 'texdomainstring');
} else if ( is_404() ) {
echo get_bloginfo('name').' | '.__('Error 404 (Página No Encontrada)', 'texdomainstring');
} else if ( is_home() ) {
echo get_bloginfo('name').' | '.get_bloginfo('description');
} else {
echo get_bloginfo('name').' | '.($blog_longd);
}
}

Nuevos Roles y Capacidades - ¡Ejecutar solo una vez!
Mantengo estos códigos a mano, esta es la forma correcta de hacerlo sin un plugin. Establecen un solo campo (prefix_user_roles) en la base de datos de opciones, y no necesitas un plugin para configurarlos. Consulta la página del Codex para obtener una lista de capacidades disponibles y descripciones de lo que hacen. ¡Solo necesitas descomentar uno de estos bloques, cargar cualquier página y luego volver a comentarlos! Aquí estoy creando un rol que tiene las capacidades que necesito:
/* Capacidades */
// Para agregar el nuevo rol, usando 'international' como nombre corto y
// 'International Blogger' como nombre mostrado en la lista de Usuarios y página de edición:
/*
add_role('international', 'International Blogger', array(
'read' => true, // True permite esa capacidad, False específicamente la elimina.
'edit_posts' => true,
'delete_posts' => true,
'edit_published_posts' => true,
'publish_posts' => true,
'edit_files' => true,
'import' => true,
'upload_files' => true //¡El último en el array no necesita coma!
));
*/
// Para eliminar un rol completamente o eliminar uno de los predeterminados:
/*
remove_role('international');
*/
A veces es útil agregar/eliminar de un rol existente en lugar de eliminar y volver a agregar uno. Nuevamente, solo necesitas descomentarlo, recargar una página y luego volver a comentarlo. Esto almacenará el rol/capacidad correctamente en la tabla de opciones. (Esto te permite a ti, el desarrollador, controlarlos y elimina la sobrecarga de los plugins voluminosos que hacen lo mismo.) Aquí estoy modificando el rol de autor para eliminar sus publicaciones (el predeterminado), pero permitiéndoles la capacidad de editar sus publicaciones (que no es posible para este rol por defecto) - usando *add_cap* o *remove_cap*.
/*
$edit_role = get_role('author');
$edit_role->add_cap('edit_published_posts');
$edit_role->remove_cap('delete_published_posts');
*/
Mantengo una hoja de cálculo con la cuadrícula de la página del Codex para sitios que modifican de esta manera, para recordar cómo están configuradas las cosas, aunque dejar el código comentado en tu archivo functions.php también funcionará. ¡No dejes estos ejemplos sin comentar, o escribirá en la base de datos con cada carga de página!

Las funciones que menciono anteriormente escriben en un campo de la base de datos de opciones. Comentarlas y descomentarlas es el camino a seguir. Existen plugins para roles de usuario, pero si usas las funciones mencionadas anteriormente, no puedes dejar estas funciones ejecutándose, y NO NECESITAS configurarlas más de una vez, ni configurarlas basándote en si un usuario específico está accediendo a algo. Si deseas eso, configura ese usuario con un rol específico y único. Y consulta el codex, todo lo que escribo arriba es 100% correcto si lo haces sin un plugin.
Para casi todos los casos, solo necesitas configurar los roles de usuario una vez.

@tomcat23: Para ilustrar, lo envolví en una función para agregar el rol solo cuando no existe previamente. Otra nota: Supongo que sería más fácil colocar el rol en algún lugar de la jerarquía de roles, obteniendo las capacidades de algún rol incorporado y luego agregar/eliminar las capacidades del rol incorporado. Haría que sea más claro y fácil de recordar si sus capacidades se colocan entre, por ejemplo, admin y editor. - Espero que no te moleste que haya editado tu respuesta. Si es así, por favor reviértelo. :)

Mantengo mi respuesta como la dejé. Tu función no capta el punto y no proporciona la misma respuesta que mi texto. Además, me parece bastante grosero de tu parte cambiar mi código y respuesta.

No solo eso, sino que tu función no hace lo mismo que mi código. ¡Tu función deja solo una verificación más en su lugar, get_role('international', que no es necesaria! Usé este código para migrar un cliente que tenía un servidor que usaba php4 y por lo tanto no podía usar el plugin role scoper que habían estado usando, el cual era solo para php5. (Y era el único plugin que necesitaba php5 en su instalación). Como desarrollador, vi que la única razón por la que lo necesitaban era para configurar un par de roles y cambiar algunas capacidades. ¡Y este código, mi respuesta original aquí, es cómo se hace!

No necesitas, ni deberías, envolver esto en una función. Solo necesitas configurar correctamente los roles y capacidades. Si quieres experimentar con ellos, hay algunos plugins geniales (aunque inflados) para eso.
Si entiendes los roles y capacidades en WordPress y no solo estás probando cosas, y no estás escribiendo tu propio plugin, entonces esta es la forma correcta de hacerlo. Por favor no edites mi código. Lo he revertido. Tu envoltura de función está en el historial para que cualquiera la vea, aunque no estoy de acuerdo con lo que has hecho.

Para aclarar más, no necesitas envolver esto en una función ni hacer verificaciones de administrador. add_role(), remove_role(), add_cap() y remove_cap(), como muestro en mi respuesta original, no necesitan ejecutarse una y otra vez -- solo establecen un campo en la tabla de opciones que no necesita escribirse repetidamente -- por eso tu envoltura de función es incorrecta. Lo sé, estás agregando una acción a after_setup_theme, pero configurar un rol con ese hook no es de lo que trataba mi respuesta. (Y generalmente los roles no necesitan venir empaquetados con temas).

Uf... Como escribí: "Espero que no te importe que haya editado tu respuesta. Si es así, por favor reviértelo. :)". Lo revertiste, explicaste tu razón y adivina qué: Está bien. Así que tranquilo. Pero para ofrecerte la misma cantidad de explicación: Siempre envuelvo las cosas en funciones y las agrego a mi carpeta de archivos de prueba de mi tema. De esta manera puedo probar cosas fácilmente, por ej. respuestas de WA y agregarlas rápidamente si necesito algo, así que envolverlo en una función está bien. Además es más fácil desactivar (solo la llamada add_action) y permitir comentarios de documentación con /**/ en lugar de comentarios multilínea //. Eso es todo sobre mi "por qué".

@tomcat23 - Ten en cuenta que somos una comunidad que se apoya mutuamente, no una que se desafía excepto de manera académica. Como ves en la respuesta de @kaiser, él solo estaba intentando ayudar.

@MikeSchinkel Recuerdo que hubo dos comentarios de @kaiser el 1 de Feb, por eso respondí como lo hice en ese momento. (Eres moderador, ¿puedes ver si él lo hizo? Porque no creo que me equivoque al pensar que él hizo 2 comentarios sobre que mi uso simplemente no le parecía bien). No sentí que mi código o explicación necesitaran ayuda y se lo dije el 1 de Feb. Vuelvo algún tiempo después y encuentro que él ha cambiado mi código -- mi primera exposición al aspecto "wiki" de este sitio -- y estaba, en mi opinión, justificadamente molesto de que mientras mi texto y comentarios discutían una cosa, el código en sí era diferente.

Mi respuesta está en el espíritu de la pregunta original. Este es mi código útil, esto es lo que funciona bien para mí y no lo uso envuelto en una función. Si @kaiser hubiera querido responder esta pregunta con el código envuelto en una función y adjunto a un hook, todavía es libre de hacerlo.
De nuevo, @kaiser lo que hiciste al cambiar mi código pero no mi texto fue perjudicial para otras personas que vendrían aquí, lo verían y encontrarían que mi discusión sobre el código no tenía sentido. Por eso siento que fue grosero de tu parte hacer lo que hiciste y por qué respondí ayer de manera tan dura.

@tomcat23 - Agua pasada en este punto. Todo lo que digo es que no estoy interesado en echar culpas, solo en tener paz para todos de ahora en adelante. :)

@MikeSchinkel Sí, tienes razón.
@kaiser Mis disculpas si te he causado algún insulto.

Pie de página personalizado en el administrador de WordPress
// personalizar el texto del pie de página del administrador
function custom_admin_footer() {
echo 'agrega aquí tu texto y html personalizado para el pie de página';
}
add_filter('admin_footer_text', 'custom_admin_footer');
Utilizo esto en los sitios de clientes como una simple referencia para contactarme como desarrollador.

Función para Desactivar los Feeds RSS
Probado en: Wordpress 3.0.1
Puedes desactivar los feeds RSS si deseas mantener tu sitio web basado en Wordpress como estático.
Puedes usar esta función:
function fb_disable_feed() {
wp_die( __('No hay feed disponible, por favor visita nuestra <a href="'. get_bloginfo('url') .'">página de inicio</a>!') );
}
add_action('do_feed', 'fb_disable_feed', 1);
add_action('do_feed_rdf', 'fb_disable_feed', 1);
add_action('do_feed_rss', 'fb_disable_feed', 1);
add_action('do_feed_rss2', 'fb_disable_feed', 1);
add_action('do_feed_atom', 'fb_disable_feed', 1);

Fuente: http://bueltge.de/wordpress-feeds-deaktivieren/794/ (Frank Bueltge)

¡Gracias Toscho! la fuente también está disponible en inglés http://wpengineer.com/287/disable-wordpress-feed/

Cambiar el mensaje "Howdy" por "Bienvenido"
Con esta función puedes personalizar el mensaje "Howdy" en la parte superior derecha de tu área de administración.
Esta función utiliza jQuery para cambiar el mensaje "Howdy" por "Bienvenido".
/****** Personalizar el mensaje de administración "Howdy" a "Bienvenido" ******/
$nohowdy = "Bienvenido";
if (is_admin()) {
add_action('init', 'artdev_nohowdy_h');
add_action('admin_footer', 'artdev_nohowdy_f');
}
// Cargar jQuery
function artdev_nohowdy_h() {
wp_enqueue_script('jquery');
}
// Modificar
function artdev_nohowdy_f() {
global $nohowdy;
echo <<<JS
<script type="text/javascript">
//<![CDATA[
var nohowdy = "$nohowdy";
jQuery('#user_info p')
.html(
jQuery('#user_info p')
.html()
.replace(/Howdy/,nohowdy)
);
//]]>
JS;
}
Versión PHP, usando el filtro gettext
:
add_filter('gettext', 'change_howdy', 10, 3);
function change_howdy($translated, $text, $domain) {
if (!is_admin() || 'default' != $domain)
return $translated;
if (false !== strpos($translated, 'Howdy'))
return str_replace('Howdy', 'Bienvenido', $translated);
return $translated;
}

¿No se puede editar esto ya en el lado de PHP para que no se muestre en absoluto?
