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.

Pre-llenado de tipos de publicación
Aquí hay uno para esta colección.
////////////////////////////////////////////////////////////////////////////////////
// Esto auto completa tipos de publicación y publicaciones.
///////////////////////////////////////////////////////////////////////////////////
add_filter( 'default_content', 'my_editor_content' );
function my_editor_content( $content ) {
global $post_type;
switch( $post_type ) {
case 'your_post_type_here': //auto completar
$content = 'El contenido con el que deseas pre-llenar el tipo de publicación.';
break;
}
return $content;
}
Esto puede ser útil cuando necesitas publicar la misma información una y otra vez con ligeras diferencias.

¡Buena idea! Me gusta esta opción simple. ¿Podrías ampliarla mostrando formas de rellenar automáticamente campos personalizados u otros criterios/opciones o incluso medios para insertar automáticamente contenido multimedia?

Definitivamente puedo ver cómo ampliarlo. Aún no he intentado llevarlo más allá.

Incluir Automáticamente el Código de Google Analytics
Probado en: WordPress 3.1 RC3
He estado usando este script en todos mis sitios desde WordPress 2.3.0... simplemente agrega los scripts de seguimiento estándar de Google al pie de página.
// Agregar el Código de Seguimiento de Google Analytics
function add_google_analytics() {
?>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-XXXXXXX-X");
pageTracker._trackPageview();
} catch(err) {}</script>
<?php
}
add_action('wp_footer', 'add_google_analytics');
Asegúrate de reemplazar UA-XXXXXXX-X
con tu propio código de seguimiento de Google...

gracias por compartir. También he estado usando este, pero me gustaría saber si sabes cómo se puede modificar para que etiquetas específicas, páginas de tipos de publicación o incluso las publicaciones en sí puedan pasar valores adicionales automáticamente haciendo uso de las capacidades de variables de seguimiento de campaña que proporciona Google. Además, ¿qué habría que añadir si quisiéramos agregar esto al pie de página de todas las páginas de administración para rastrear la actividad del administrador?

No estoy seguro sobre agregar variables de seguimiento de campaña simplemente porque no he tenido la necesidad de eso todavía. Pero para agregar los mismos scripts a las páginas de administración, solo necesitarías usar add_action('admin_footer', 'add_google_analytics');
para engancharlo al pie de página de las páginas de administración.

Listar todas las constantes para información y depuración
Probado en: WordPress 3.0.1
Solo mostrará la información si eres un usuario registrado
if ( is_user_logged_in() ) {
print('<pre>');
print_r( @get_defined_constants() );
print('</pre>');
}
Aquí está la versión con un filtro opcional que coincidirá parcialmente con los nombres y valores de las constantes:
function constants($filter = false) {
$constants = get_defined_constants();
if( $filter ) {
$temp = array();
foreach ( $constants as $key => $constant )
if( false !== stripos( $key, $filter ) || false !== stripos( $constant, $filter ) )
$temp[$key] = $constant;
$constants = $temp;
}
ksort( $constants );
var_dump( $constants );
}

Cambiar el Slug Predeterminado del Autor
Coloca esto en tus funciones para cambiar el Slug predeterminado del Autor por el que desees,
solo cambia "sellers" por el slug que prefieras.
// Cambiar el Slug de la URL de Autor a Vendedores
function new_author_base() {
global $wp_rewrite;
$author_slug = 'sellers';
$wp_rewrite->author_base = $author_slug;
}
add_action('init', 'new_author_base');

Sí, vaciar los roles en cada carga te ahorra muchos vendedores. :) Mejor usa el plugin Edit Author Slug.

Añadir botón "Página siguiente" en el editor WYSIWYG
add_filter('mce_buttons','wysiwyg_editor');
function wysiwyg_editor($mce_buttons) {
// Buscar la posición del botón 'wp_more' en el array de botones
$pos = array_search('wp_more',$mce_buttons,true);
if ($pos !== false) {
// Dividir el array de botones en la posición encontrada
$tmp_buttons = array_slice($mce_buttons, 0, $pos+1);
// Añadir el botón de página
$tmp_buttons[] = 'wp_page';
// Combinar los arrays para incluir el nuevo botón
$mce_buttons = array_merge($tmp_buttons, array_slice($mce_buttons, $pos+1));
}
return $mce_buttons;
}

Añadir estilos personalizados al editor TinyMCE
A menudo los usuarios y clientes se confunden con la diferencia entre cómo se muestra su contenido en el editor y cómo aparece en el front-end. Copiar algunas líneas relevantes de tu hoja de estilos principal a tu nuevo archivo tinymce.css puede ayudar mucho:
function custom_mce_css($wp) {
return $wp .= ',' . get_bloginfo('stylesheet_directory') . '/css/tinymce.css';
}
add_filter( 'mce_css', 'custom_mce_css' );

Genial. Acabo de descubrir que hay una solución de Seamus Leahy que lleva todo esto un paso más allá al añadir una clase body a tinymce. http://www.digwp.com/2010/11/actual-wysiwyg

Prefiero crear una hoja de estilos tanto para el front-end como para TinyMCE de una vez. Luego uso la funcionalidad básica de la función add_editor_style() para incluir la hoja de estilos y asegurarme de que se cargue cuando lo haga TinyMCE. Artículo en el Codex en http://codex.wordpress.org/Function_Reference/add_editor_style

Redimensionar imagen grande al subir
La imagen se redimensionará de acuerdo al tamaño grande en tus ajustes de medios.
/**redimensionar al subir al tamaño más grande en los ajustes de medios */
function replace_uploaded_image($image_data) {
// si no hay imagen grande: retornar
if (!isset($image_data['sizes']['large'])) return $image_data;
// ruta a la imagen subida y la imagen grande
$upload_dir = wp_upload_dir();
$uploaded_image_location = $upload_dir['basedir'] . '/' .$image_data['file'];
$large_image_location = $upload_dir['path'] . '/'.$image_data['sizes']['large']['file'];
// eliminar la imagen subida
unlink($uploaded_image_location);
// renombrar la imagen grande
rename($large_image_location,$uploaded_image_location);
// actualizar los metadatos de la imagen y retornarlos
$image_data['width'] = $image_data['sizes']['large']['width'];
$image_data['height'] = $image_data['sizes']['large']['height'];
unset($image_data['sizes']['large']);
return $image_data;
}
add_filter('wp_generate_attachment_metadata','replace_uploaded_image');

¿Esto significa que el archivo grande original subido es realmente reemplazado? Mi PHP no es excelente, pero la respuesta parece ser sí?

@davemac Me doy cuenta de que esto es muy antiguo ahora, pero por lo que entiendo del código, el archivo de imagen original se redimensiona a las mismas dimensiones que el tamaño de imagen 'grande' establecido en la pantalla de configuración de WordPress. Lo cual es genial, pero luego terminas con 2 imágenes del mismo tamaño. Sugeriría establecer manualmente los valores para que la imagen original solo sea tan grande como el archivo más grande que realmente usarás en tu sitio. Así tendrás una imagen casi original con la que trabajar en el futuro.

Usar figure y figcaption para pies de foto
Probado en: WordPress 3.1.3
(Créditos a WP Engineer: http://wpengineer.com/917/filter-caption-shortcode-in-wordpress/)
function mytheme_caption( $attr, $content = null ) {
$output = apply_filters( 'img_caption_shortcode', '', $attr, $content );
if ( $output != '' )
return $output;
extract( shortcode_atts ( array(
'id' => '',
'align' => 'alignnone',
'width'=> '',
'caption' => ''
), $attr ) );
if ( 1 > (int) $width || empty( $caption ) )
return $content;
if ( $id ) $id = 'id="' . $id . '" ';
return '<figure ' . $id . 'class="wp-caption ' . $align . '" style="width: ' . $width . 'px">'
. do_shortcode( $content ) . '<figcaption class="wp-caption-text">' . $caption . '</figcaption></figure>';
}
add_shortcode( 'wp_caption', 'mytheme_caption' );
add_shortcode( 'caption', 'mytheme_caption' );

Aquí tienes algunos shortcodes útiles para que uses:
1. Shortcode fácil para añadir botones de compartir en Twitter y Facebook
function shreplz() {
return '
<div class="sharebox">
<div class="twittme"><a href="https://twitter.com/share" class="twitter-share-button" data-count="horizontal">Tweet</a><script type="text/javascript" src="//platform.twitter.com/widgets.js"></script></div>
<div class="shareface"><a name="fb_share"></a> <script src="http://static.ak.fbcdn.net/connect.php/js/FB.Share" type="text/javascript"></script></div>
<br style="clear: left;" />
</div>
';
}
add_shortcode('sharethis', 'shreplz');
// Cómo usar: [sharethis]
2. Shortcode fácil para captura remota de sitio usando la API de WordPress
function wpr_snap($atts, $content = null) {
extract(shortcode_atts(array(
"snap" => 'http://s.wordpress.com/mshots/v1/',
"url" => 'http://www.sagive.co.il',
"alt" => 'Mi imagen',
"w" => '400', // ancho
"h" => '300' // alto
), $atts));
$img = '<img src="' . $snap . '' . urlencode($url) . '?w=' . $w . '&h=' . $h . '" alt="' . $alt . '"/>';
return $img;
}
add_shortcode("snap", "wpr_snap");
// Cómo usar: [snap url="http://www.ejemplo.com" alt="¡Sitio Genial!" w="300px" h="200px"]
3. Shortcode fácil para usar e incrustar iFrame
function GenerateIframe( $atts ) {
extract( shortcode_atts( array(
'href' => 'http://la-url',
'height' => '550px',
'width' => '600px',
), $atts ) );
return '<iframe src="'.$href.'" width="'.$width.'" height="'.$height.'"> <p>Tu navegador no soporta Iframes.</p></iframe>';
}
add_shortcode('iframe', 'GenerateIframe');
// Cómo usar: [iframe href="http://www.ejemplo.com" height="480" width="640"]
4. Shortcode fácil para incluir archivo o documento remoto
function getfile_content( $atts ) {
extract( shortcode_atts( array(
'fileurl' => ''
), $atts ) );
if ($fileurl!='')
return @file_get_contents($fileurl);
}
add_shortcode( 'getfile', 'getfile_content' );
// Cómo usar: [getfile fileurl="http://www.ejemplo.com/alguna-pagina.html"]
. Aquí tienes algunos fragmentos relacionados con comentarios:
1. Desactivar la capacidad de comentar globalmente
function closeCommentsGlobaly($data) { return false; }
add_filter('comments_number', 'closeCommentsGlobaly');
add_filter('comments_open', 'closeCommentsGlobaly');
2. Dar al administrador una clase CSS diferente para sus comentarios
if (1 == $comment->user_id)
echo 'siteadmin'; // Elige tu clase aquí
3. Una lista de comentarios enriquecida con datos - ideal para páginas personalizadas bloqueadas
$comments = get_comments( array(
'number' => 10, // Cuántos comentarios
'status' => 'approve' // Tipo de comentarios
) );
foreach($comments as $eachComment){
// Recopilar los datos y asignarlos
$commentID = comment_ID;
$commentAuthorEmail = $eachComment->comment_author_email;
$commentPostId = $eachComment->comment_post_ID;
$commentPostTitle = get_the_title( $commentPostId );
$commentPostUrl = get_permalink( $commentPostId );
$comment_sidebarnumber = get_comments_number( $commentPostId );
global $wpdb;
$userCommentCount = $wpdb->get_var('SELECT COUNT('.$commentID.') FROM ' . $wpdb->comments. ' WHERE comment_author_email = "' . $commentAuthorEmail . '"');
echo '<div style="border: 1px solid #ccc; padding: 10px;">';
echo '<ul style="margin: 0px;">';
echo '<li>Nombre: '. $eachComment->comment_author .'</li>';
echo '<li>Comentó sobre: <a href="'.$commentPostUrl.'">'. $commentPostTitle .'</a></li>';
echo '<li>Comentado el: '. $eachComment->comment_date .'</li>';
echo '<li>Sitio del comentarista: '. $eachComment->comment_author_email .'</</li>';
echo '<li>Email del comentarista: '. $eachComment->comment_author_email .'</</li>';
echo '<li>Este comentarista '. $eachComment->comment_author .' ha comentado '. $userCommentCount .' veces en tu sitio</</li>';
echo '</ul>';
echo '<p style="padding: 10px;"><strong>'. $eachComment->comment_author .' escribió</strong>: '. $eachComment->comment_content .'</p>';
echo '</div>';
}

Condicional para verificar descendientes en la jerarquía
Una función condicional para verificar si la página actual es descendiente del ID proporcionado. Útil para determinar si una página es nieta, bisnieta o hija en el árbol jerárquico.
function is_tree($pid) { // $pid = El ID de la página que buscamos como ancestro
global $post; // cargar detalles sobre esta página
$anc = get_post_ancestors( $post->ID );
foreach($anc as $ancestor) {
if(is_page() && $ancestor == $pid) {
return true;
}
}
if(is_page()&&(is_page($pid)))
return true; // estamos en la página o en una subpágina
else
return false; // estamos en otra parte
};

He estado buscando esto por un tiempo. ¡Gracias por compartirlo! ¿Podría pedirte un poco de aclaración sobre el caso de uso? Idealmente, me gustaría usarlo en mis listados de menú para que si tengo un menú principal de nivel superior en la parte superior del sitio que solo muestre elementos de Gen 1. Cuando estoy en un elemento de Gen 2-3, el elemento Gen1 pueda resaltarse mediante un atributo CSS "current-parent". ¿Es esto posible?

Crear una etiqueta condicional para taxonomías personalizadas
En este ejemplo, 'student' era un tipo de contenido personalizado y 'stud_cat' era la taxonomía personalizada. Usa has_student(null)
para la condición
function has_student( $student, $_post = null ) {
if ( !empty( $student ) )
return false;
if ( $_post )
$_post = get_post( $_post );
else
$_post =& $GLOBALS['post'];
if ( !$_post )
return false;
$r = is_object_in_term( $_post->ID, 'studcat', $student );
if ( is_wp_error( $r ) )
return false;
return $r;
}

¿Creo que esto se reemplaza con has_term()
ahora que la versión 3.1 está lanzada?

Soluciones fáciles de seguridad para WordPress
La seguridad por oscurecimiento es la clave aquí. Estas funciones realizan tres acciones diferentes.
- Elimina la cadena de versión del código. No hay necesidad de decirle a la gente qué versión estamos ejecutando.
- Elimina cualquier mensaje de error (Contraseña incorrecta, Usuario no existe, etc.) de las pantallas de inicio de sesión de administrador
Cuando el administrador publica un comentario, se agrega una clase CSS. Esto elimina el nombre del administrador en los comentarios.
// ELIMINAR LA CADENA DE VERSIÓN DEL ENCABEZADO remove_action('wp_head', 'wp_generator'); // OCULTAR MENSAJES DE ERROR EN EL INICIO DE SESIÓN (Contraseña incorrecta, Usuario no existe, etc.) add_filter('login_errors',create_function('$a', "return null;")); // Eliminar el nombre del administrador en la clase de comentarios // Fuente: http://www.wprecipes.com/wordpress-hack-remove-admin-name-in-comments-class function remove_comment_author_class( $classes ) { foreach( $classes as $key => $class ) { if(strstr($class, "comment-author-")) { unset( $classes[$key] ); } } return $classes; } add_filter( 'comment_class' , 'remove_comment_author_class' );

Eliminar el número de versión de WordPress es una mala práctica. Es mucho más seguro mantener tu WordPress actualizado con los últimos parches de seguridad EN TODO MOMENTO. Beneficio adicional: los aspirantes a script kiddies pasarán a versiones más antiguas.

Reemplazar el Gravatar predeterminado con una imagen personalizada
Todo lo que necesitarás personalizar es la ruta a tu imagen predeterminada.
function custom_gravatar($avatar_defaults) {
$logo = get_bloginfo('template_directory') . '/images/icons/gravatar_logo.jpg'; //Cambia a la ruta que prefieras.
$avatar_defaults[$logo] = get_bloginfo('name');
return $avatar_defaults;
}//FIN DE LA FUNCIÓN
add_filter( 'avatar_defaults', 'custom_gravatar' );

Crear automáticamente una nueva página al activar un tema
if (isset($_GET['activated']) && is_admin()){
$new_page_title = 'Este es el título de la página';
$new_page_content = 'Este es el contenido de la página';
$new_page_template = ''; //ej. plantilla-personalizada.php. Déjalo en blanco si no quieres una plantilla de página personalizada.
//no edites debajo de esta línea
$page_check = get_page_by_title($new_page_title);
$new_page = array(
'post_type' => 'page',
'post_title' => $new_page_title,
'post_content' => $new_page_content,
'post_status' => 'publish',
'post_author' => 1,
);
if(!isset($page_check->ID)){
$new_page_id = wp_insert_post($new_page);
if(!empty($new_page_template)){
update_post_meta($new_page_id,'_wp_page_template', $new_page_template);
}
}

Listar todas las SubCategorías
Probado en: WordPress 3.0.1
$echo = '<ul>' . "\n";
$childcats = get_categories('child_of=' . $cat . '&hide_empty=1');
foreach ($childcats as $childcat) {
if (1 == $childcat->category_parent) {
$echo .= "\t" . '<li><a href="' . get_category_link($childcat->cat_ID).'" title="' . $childcat->category_description . '">';
$echo .= $childcat->cat_name . '</a>';
$echo .= '</li>' . "\n";
}
}
$echo .= '</ul>' . "\n";
echo $echo;
También puedes encontrar más información y funciones en el post http://wpengineer.com/2025/list-all-subcategories/

¿Por qué harías esto cuando hay una función disponible específicamente para mostrar una lista de categorías? Consulta: http://codex.wordpress.org/Template_Tags/wp_list_categories#Only_Show_Children_of_a_Category

Limpieza automática de slugs SEO sin eliminar funcionalidad
Probado en: WordPress 3.0.1
Al agregar este código a tu archivo functions.php, WordPress limpiará automáticamente el título del slug URL eliminando todas las palabras innecesarias. También he ampliado las capacidades con personalizaciones adicionales que ocultan la opción de pantalla para el slug así como el metabox. Al incluir el código siguiente, cualquier nueva entrada que crees se acortará automáticamente y aún tendrás la capacidad de editar manualmente el slug haciendo clic en la URL bajo el título de la entrada y guardando la publicación.
// SANITIZAR AUTOMÁTICAMENTE EL SLUG SEO DE PÁGINAS/ENTRADAS ELIMINANDO PALABRAS CORTAS
add_filter('name_save_pre', 'seo_slugs', 0);
function seo_slugs($slug) {
// No queremos cambiar un slug existente
if ($slug) return $slug;
global $wpdb;
$seo_slug = strtolower(stripslashes($_POST['post_title']));
$seo_slug = preg_replace('/&.+?;/', '', $seo_slug); // eliminar entidades HTML
// eliminar todo lo que no sea letra, dígito, espacio o apóstrofe
$seo_slug = preg_replace ("/[^a-zA-Z0-9 \']/", "", $seo_slug);
// Convertir en array y eliminar palabras comunes comparando con array c.w.
$seo_slug_array = array_diff (split(" ", $seo_slug), seo_slugs_stop_words());
// Convertir el array sanitizado en una cadena
$seo_slug = join("-", $seo_slug_array);
return $seo_slug;
}
function seo_slugs_stop_words () {
return array ("a", "able", "about", "above", "abroad", "according", "accordingly", "across", "actually", "adj", "after", "afterwards", "again", "against", "ago", "ahead", "ain't", "all", "allow", "allows", "almost", "alone", "along", "alongside", "already", "also", "although", "always", "am", "amid", "amidst", "among", "amongst", "an", "and", "another", "any", "anybody", "anyhow", "anyone", "anything", "anyway", "anyways", "anywhere", "apart", "appear", "appreciate", "appropriate", "are", "aren't", "around", "as", "a's", "aside", "ask", "asking", "associated", "at", "available", "away", "awfully", "b", "back", "backward", "backwards", "be", "became", "because", "become", "becomes", "becoming", "been", "before", "beforehand", "begin", "behind", "being", "believe", "below", "beside", "besides", "best", "better", "between", "beyond", "both", "brief", "but", "by", "c", "came", "can", "cannot", "cant", "can't", "caption", "cause", "causes", "certain", "certainly", "changes", "clearly", "c'mon", "co", "co.", "com", "come", "comes", "concerning", "consequently", "consider", "considering", "contain", "containing", "contains", "corresponding", "could", "couldn't", "course", "c's", "currently", "d", "dare", "daren't", "definitely", "described", "despite", "did", "didn't", "different", "directly", "do", "does", "doesn't", "doing", "done", "don't", "down", "downwards", "during", "e", "each", "edu", "eg", "eight", "eighty", "either", "else", "elsewhere", "end", "ending", "enough", "entirely", "especially", "et", "etc", "even", "ever", "evermore", "every", "everybody", "everyone", "everything", "everywhere", "ex", "exactly", "example", "except", "f", "fairly", "far", "farther", "few", "fewer", "fifth", "first", "five", "followed", "following", "follows", "for", "forever", "former", "formerly", "forth", "forward", "found", "four", "from", "further", "furthermore", "g", "get", "gets", "getting", "given", "gives", "go", "goes", "going", "gone", "got", "gotten", "greetings", "h", "had", "hadn't", "half", "happens", "hardly", "has", "hasn't", "have", "haven't", "having", "he", "he'd", "he'll", "hello", "help", "hence", "her", "here", "hereafter", "hereby", "herein", "here's", "hereupon", "hers", "herself", "he's", "hi", "him", "himself", "his", "hither", "hopefully", "how", "howbeit", "however", "hundred", "i", "i'd", "ie", "if", "ignored", "i'll", "i'm", "immediate", "in", "inasmuch", "inc", "inc.", "indeed", "indicate", "indicated", "indicates", "inner", "inside", "insofar", "instead", "into", "inward", "is", "isn't", "it", "it'd", "it'll", "its", "it's", "itself", "i've", "j", "just", "k", "keep", "keeps", "kept", "know", "known", "knows", "l", "last", "lately", "later", "latter", "latterly", "least", "less", "lest", "let", "let's", "like", "liked", "likely", "likewise", "little", "look", "looking", "looks", "low", "lower", "ltd", "m", "made", "mainly", "make", "makes", "many", "may", "maybe", "mayn't", "me", "mean", "meantime", "meanwhile", "merely", "might", "mightn't", "mine", "minus", "miss", "more", "moreover", "most", "mostly", "mr", "mrs", "much", "must", "mustn't", "my", "myself", "n", "name", "namely", "nd", "near", "nearly", "necessary", "need", "needn't", "needs", "neither", "never", "neverf", "neverless", "nevertheless", "new", "next", "nine", "ninety", "no", "nobody", "non", "none", "nonetheless", "noone", "no-one", "nor", "normally", "not", "nothing", "notwithstanding", "novel", "now", "nowhere", "o", "obviously", "of", "off", "often", "oh", "ok", "okay", "old", "on", "once", "one", "ones", "one's", "only", "onto", "opposite", "or", "other", "others", "otherwise", "ought", "oughtn't", "our", "ours", "ourselves", "out", "outside", "over", "overall", "own", "p", "particular", "particularly", "past", "per", "perhaps", "placed", "please", "plus", "possible", "presumably", "probably", "provided", "provides", "q", "que", "quite", "qv", "r", "rather", "rd", "re", "really", "reasonably", "recent", "recently", "regarding", "regardless", "regards", "relatively", "respectively", "right", "round", "s", "said", "same", "saw", "say", "saying", "says", "second", "secondly", "see", "seeing", "seem", "seemed", "seeming", "seems", "seen", "self", "selves", "sensible", "sent", "serious", "seriously", "seven", "several", "shall", "shan't", "she", "she'd", "she'll", "she's", "should", "shouldn't", "since", "six", "so", "some", "somebody", "someday", "somehow", "someone", "something", "sometime", "sometimes", "somewhat", "somewhere", "soon", "sorry", "specified", "specify", "specifying", "still", "sub", "such", "sup", "sure", "t", "take", "taken", "taking", "tell", "tends", "th", "than", "thank", "thanks", "thanx", "that", "that'll", "thats", "that's", "that've", "the", "their", "theirs", "them", "themselves", "then", "thence", "there", "thereafter", "thereby", "there'd", "therefore", "therein", "there'll", "there're", "theres", "there's", "thereupon", "there've", "these", "they", "they'd", "they'll", "they're", "they've", "thing", "things", "think", "third", "thirty", "this", "thorough", "thoroughly", "those", "though", "three", "through", "throughout", "thru", "thus", "till", "to", "together", "too", "took", "toward", "towards", "tried", "tries", "truly", "try", "trying", "t's", "twice", "two", "u", "un", "under", "underneath", "undoing", "unfortunately", "unless", "unlike", "unlikely", "until", "unto", "up", "upon", "upwards", "us", "use", "used", "useful", "uses", "using", "usually", "v", "value", "various", "versus", "very", "via", "viz", "vs", "w", "want", "wants", "was", "wasn't", "way", "we", "we'd", "welcome", "well", "we'll", "went", "were", "we're", "weren't", "we've", "what", "whatever", "what'll", "what's", "what've", "when", "whence", "whenever", "where", "whereafter", "whereas", "whereby", "wherein", "where's", "whereupon", "wherever", "whether", "which", "whichever", "while", "whilst", "whither", "who", "who'd", "whoever", "whole", "who'll", "whom", "whomever", "who's", "whose", "why", "will", "willing", "wish", "with", "within", "without", "wonder", "won't", "would", "wouldn't", "x", "y", "yes", "yet", "you", "you'd", "you'll", "your", "you're", "yours", "yourself", "yourselves", "you've", "z", "zero");
}
Al agregar el código adicional siguiente a tu archivo functions.php, se eliminará/ocultará la opción de slug del menú desplegable de opciones de pantalla así como el metabox.
// OCULTAR EL METABOX DE SLUG Y LAS OPCIONES DE PANTALLA DE SLUG
function hide_slug_options() {
global $post;
global $pagenow;
$hide_slugs = "<style type=\"text/css\">#slugdiv, #edit-slug-box, [for=\"slugdiv-hide\"] { display: none; }</style>\n";
if (is_admin() && $pagenow=='post-new.php' OR $pagenow=='post.php') print($hide_slugs);
}
add_action( 'admin_head', 'hide_slug_options' );

Excluir categorías hijas de una categoría específica
Bastante directo, pero no encontré a nadie haciendo exactamente lo que necesitaba. Además, mostrará la publicación si la categoría padre está seleccionada, excepto si esa publicación tiene una categoría hija de ese padre seleccionada.
/* Este código excluye todas las publicaciones de las categorías hijas de (ID de categoría = 20)
en la página de INICIO, pero permite mostrar la categoría padre (ID de categoría = 20). */
function excluir_categorias_hijas($query) {
$categorias_hijas = (array) get_term_children('20', 'category');
if ( $query->is_home ) {
$query->set('category__not_in', $categorias_hijas);
return $query;
}
}
add_filter('pre_get_posts', 'excluir_categorias_hijas');

Permitir iFrames en el Editor de WordPress
// hacer que TinyMCE permita iframes
add_filter('tiny_mce_before_init', create_function( '$a',
'$a["extended_valid_elements"] = "iframe[id|class|title|style|align|frameborder|height|longdesc|marginheight|marginwidth|name|scrolling|src|width]"; return $a;') );

Eliminar menús del panel de administración para todos los usuarios, excepto el Usuario #1 (normalmente el primer Administrador)
/*-----------------------------------------------------------------------------------*/
/* Restringir acceso
/*-----------------------------------------------------------------------------------*/
function remove_menus () {
global $menu;
$user = wp_get_current_user();
if ($user->ID!=1) { // No es administrador,
$restricted = array(__('Escritorio'), __('Entradas'), __('Medios'), __('Enlaces'), __('Páginas'), __('Apariencia'), __('Herramientas'), __('Usuarios'), __('Ajustes'), __('Comentarios'), __('Plugins'));
end ($menu);
while (prev($menu)){
$value = explode(' ',$menu[key($menu)][0]);
if(in_array($value[0] != NULL?$value[0]:"" , $restricted)){unset($menu[key($menu)]);}
}
}
}
add_action('admin_menu', 'remove_menus');

El Usuario 1 puede ser el primer administrador. Pero después de agregar nuevos administradores, el primero puede convertirse en un usuario regular. Solicita capacidades, no números. Además, este código pertenece a un plugin, no al functions.php. No tiene ninguna relación con el tema.

De esta manera puedes permitir que todos los administradores actúen normalmente, pero al mismo tiempo ocultar al primer administrador y reservarlo para el administrador del sistema / equipo de soporte. No estoy de acuerdo en que este código pertenezca a un plugin. Functions.php es un plugin. Este archivo básicamente actúa como un plugin
Theme_Development#Functions_File

Pero el functions.php contiene lógica que está vinculada al tema, porque si cambias de tema todo el código desaparece. Por lo tanto, a menos que el código dependa del tema y viceversa, no uses el functions.php como un mu-plugin.

Sí. Pero consideremos esto: Estás desarrollando un sitio web para un cliente. Este sitio web siempre usará solo un tema, el diseñado por el diseñador. El tema es el sitio web. Añades tipos de entradas personalizados, metaboxes, cargas funciones adicionales, etc. Ahora sí quieres dar a algunos usuarios las capacidades de administrador, pero deseas ocultar algunas secciones del sitio que tu cliente nunca usará o que lo confundirán (Enlaces, Herramientas, Comentarios, son los mejores ejemplos) y dar al equipo de soporte una especie de "SuperAdmin" para que puedan ver toda el área de administración.

Veo que no estás de acuerdo con el uso, pero la función funciona y es útil, así que no entiendo por qué votar -1.

No pertenece a un functions.php – como muchas respuestas aquí, desafortunadamente – y se romperá tarde o temprano. Además de eso, viola los estándares de codificación de WordPress. Por favor, no lo tomes como algo personal. Mi voto es una recomendación para el lector.

Por supuesto, nada personal, tosco. Todos intentamos ayudar y aprender. No estamos de acuerdo, sucede :)

@Daniel Sachs Echa un vistazo a este gist y reemplaza user_login
con role
(?).

@kaiser Esto es genial, si quisiera usarlo como plugin o desactivar menús para todos los administradores. Como dije, esto permite desactivarlo solo para un usuario específico con ID1

Desactivar la advertencia de actualización del navegador en WordPress 3.2
//Desactivar la advertencia de actualización del navegador en WordPress 3.2
function disable_browser_upgrade_warning() {
remove_meta_box( 'dashboard_browser_nag', 'dashboard', 'normal' );
}
add_action( 'wp_dashboard_setup', 'disable_browser_upgrade_warning' );

Mostrar archivos de plantilla incluidos
Muestra comentarios en línea con el Archivo de Plantilla y los archivos get_template_part que se están incluyendo al renderizar páginas. Útil para solucionar problemas con plantillas multiparte.
add_action('all','template_snoop');
function template_snoop(){
$args = func_get_args();
if( !is_admin() and $args[0] ){
if( $args[0] == 'template_include' ) {
echo "<!-- Plantilla Base: {$args[1]} -->\n";
} elseif( strpos($args[0],'get_template_part_') === 0 ) {
global $last_template_snoop;
if( $last_template_snoop )
echo "\n\n<!-- Fin Parte de Plantilla: {$last_template_snoop} -->";
$tpl = rtrim(join('-', array_slice($args,1)),'-').'.php';
echo "\n<!-- Parte de Plantilla: {$tpl} -->\n\n";
$last_template_snoop = $tpl;
}
}
}

Función condicional is_tree()
/* Adaptado de csstricks con adición de
ancestros ... uso = if(is_tree($id)) { // hacer algo } ... Devuelve verdadero si la
página es = $id O cualquiera de sus hijos O descendientes */
function is_tree($pid) { // $pid = El ID de la página que buscamos bajo sus páginas
global $post; // cargar detalles sobre esta página
$ancestores = get_post_ancestors($post);
if(is_page()&&($post->post_parent==$pid||is_page($pid)||(in_array($pid,$ancestores))))
return true; // estamos en la página o en una subpágina
else
return false; // estamos en otro lugar
};

Mostrar los usuarios que han enviado más comentarios sin necesidad de un plugin
function top_comment_authors($amount = 5) {
global $wpdb;
$results = $wpdb->get_results('
SELECT
COUNT(comment_author_email) AS comments_count, comment_author_email, comment_author, comment_author_url
FROM '.$wpdb->comments.'
WHERE comment_author_email != "" AND comment_type = "" AND comment_approved = 1
GROUP BY comment_author_email
ORDER BY comments_count DESC, comment_author ASC
LIMIT '.$amount
);
$output = "<ul>";
foreach($results as $result) {
$output .= "<li>".$result->comment_author."</li>";
}
$output .= "</ul>";
echo $output;
}
Otras opciones que puedes utilizar: $result->comment_author_email $result->comments_count $result->comment_author_url

Obtener la dirección IP real del usuario cuando sea posible
Probado en: WordPress 3.0.1
Si estás usando un proxy o balanceador de carga, añade esto a tu archivo wp-config.php o functions.php
// Obtiene la dirección IP real del usuario
$_SERVER['REMOTE_ADDR'] = getRealIpAddress();
function getRealIpAddress( $validate = true ) {
if ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = trim($ips[count($ips) - 1]);
} elseif ( isset($_SERVER['HTTP_X_REAL_IP']) && !empty($_SERVER['HTTP_X_REAL_IP']) ) {
$ip = $_SERVER['HTTP_X_REAL_IP'];
} elseif ( isset($_SERVER['HTTP_CLIENT_IP']) && !empty($_SERVER['HTTP_CLIENT_IP']) ) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
if ( $validate && function_exists('filter_var') && filter_var($ip, FILTER_VALIDATE_IP, array('flags' => FILTER_FLAG_IPV4, FILTER_FLAG_NO_PRIV_RANGE, FILTER_FLAG_NO_RES_RANGE)) )
return $ip;
elseif ( $validate )
return long2ip(ip2long($ip));
return $ip;
}

Cuando un usuario está detrás de un proxy o balanceador de carga, cualquier cosa que obtenga la dirección IP del usuario usando el superglobal $_SERVER['REMOTE_ADDR'] verá la dirección IP del proxy o balanceador de carga. A su vez, el proxy/balanceador coloca la dirección IP original del usuario en los encabezados X-Forwarded-For, X-Real-Ip o Client-Ip (dependiendo de la configuración del proxy/balanceador). Por lo tanto, al comentar (o publicar, aunque eso es menos relevante), WordPress verá muchos usuarios provenientes de la misma dirección IP. Esto soluciona ese problema reemplazando $_SERVER['REMOTE_ADDR'] con la IP original.

Excluir la categoría por defecto de las páginas públicas
Excluye la categoría por defecto del lado público del sitio web.
El código excluye el área de administración, de lo contrario no tendrás forma de gestionar las publicaciones asignadas a la categoría por defecto.
add_filter( 'list_terms_exclusions', 'exclude_default_cat' );
function exclude_default_cat( $exclusions ) {
if( !is_admin() )
$exclusions .= "AND t.term_id != " . get_option( 'default_category' ) . " ";
return $exclusions;
}

Eliminar el enlace "Comentarios" de la barra de administración si el estado de comentarios está cerrado
Puedes configurar el estado predeterminado de los comentarios como 'cerrado', pero el enlace de comentarios permanecerá. Simplemente agrega lo siguiente en tu archivo functions.php
para eliminarlo basado en la condición. Ofrece 2 enfoques diferentes.
/**
* Deshabilitar el enlace 'Comentarios' si el estado predeterminado es _cerrado_
*/
function remover_comentarios()
{
$estado_comentarios_predeterminado = get_option( 'default_comment_status' );
if ( $estado_comentarios_predeterminado == 'closed' )
{
remove_action( 'admin_bar_menu', 'wp_admin_bar_comments_menu', 50 );
// solución opcional usando la clase WP_Admin_Bar de /wp-includes/class-wp-admin-bar.php
# global $wp_admin_bar;
# $wp_admin_bar->remove_menu( 'comments' );
}
else
{
return;
}
}

Añade una opción personalizada de menú desplegable a WP_NAV_MENUS donde el usuario puede seleccionar una clase CSS predefinida para cada elemento del menú
<?php function menu_item_class_select(){
global $pagenow;
if ($pagenow == "nav-menus.php"){
?>
<script>
jQuery(document).ready(function(){
function create_dd(v){
//crear menú desplegable
var dd = jQuery('<select class="my_class"></select>');
//crear opciones del menú
//array con las opciones que deseas
var classes = ["","class1","class2","class3"];
jQuery.each(classes, function(i,val) {
if (v == val){
dd.append('<option value="'+val+'" selected="selected">'+val+'</option>');
}else{
dd.append('<option value="'+val+'">'+val+'</option>');
}
});
return dd;
}
jQuery(".edit-menu-item-classes").each(function() {
//añadir menú desplegable
var t = create_dd(jQuery(this).val());
jQuery(this).before(t);
//ocultar todos los inputs
jQuery(this).css("display","none");
});
//actualizar input al seleccionar
jQuery(".my_class").bind("change", function() {
var v = jQuery(this).val();
var inp = jQuery(this).next();
inp.attr("value",v);
});
});
</script>
<?php } }
add_action('admin_footer','menu_item_class_select');
?>

Eliminar elementos del menú de la barra de administración de WordPress 3.3
function dashboard_tweaks() {
global $wp_admin_bar;
$wp_admin_bar->remove_menu('wp-logo');
$wp_admin_bar->remove_menu('about');
$wp_admin_bar->remove_menu('wporg');
$wp_admin_bar->remove_menu('documentation');
$wp_admin_bar->remove_menu('support-forums');
$wp_admin_bar->remove_menu('feedback');
$wp_admin_bar->remove_menu('view-site');
}
add_action( 'wp_before_admin_bar_render', 'dashboard_tweaks' );
Referencia: http://pastebin.com/Wrk0JPxw

Consulta de Etiquetas Cruzadas entre Taxonomías
Una consulta en caché que devuelve una cadena HTML similar a get_tags()
con todas las etiquetas para un parámetro de Taxonomía dado, por defecto Categoría. Puedes usar $where_slug
y $where_tax
para obtener etiquetas de posts filtradas por cualquier otra taxonomía. SQL probado desde WP 3.1 hasta WP 3.3.1.
function tags_by_other_taxonomy($where_slug,$where_tax = 'category',$bust_cache = false) {
$cache_key = "{$where_slug}:{$where_tax}";
$cache = get_transient('tags_by_other_taxonomy');
$html = '';
if( true !== $bust_cache and false !== $cache and isset($cache[$cache_key]) and !empty($cache[$cache_key]) ) {
$html = $cache[$cache_key];
} else {
global $wpdb;
$cat_id = $wpdb->get_var("SELECT tt.term_taxonomy_id FROM $wpdb->terms t INNER JOIN $wpdb->term_taxonomy tt ON t.term_id = tt.term_id WHERE t.slug = '{$where_slug}' AND tt.taxonomy = '{$where_tax}' LIMIT 1");
if( !empty($cat_id) ) {
$cat_posts = $wpdb->get_col("SELECT tr.object_id FROM $wpdb->term_relationships tr inner join $wpdb->posts p ON p.ID = tr.object_id WHERE term_taxonomy_id = {$cat_id} AND p.post_status = 'publish' AND p.post_type = 'post'");
if( count($cat_posts) ) {
$tags = $wpdb->get_results("SELECT DISTINCT t.name,t.slug FROM $wpdb->term_taxonomy tt
INNER JOIN $wpdb->term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
INNER JOIN $wpdb->terms t ON t.term_id = tt.term_id
WHERE tt.taxonomy = 'post_tag' and tr.object_id IN (".implode(',',$cat_posts) .')');
$html = '<ul class="post-tags-'.$where_slug.'">';
if( count($tags) ) {
foreach($tags as $tag)
$html .= '<li><a href="/tag/'.$tag->slug.'/" title="Posts etiquetados con '.$tag->name.'">'.$tag->name.'</a></li>';
}
$html .= '</ul>';
if( !is_array($cache) )
$cache = array();
$cache[$cache_key] = $html;
set_transient('sc_cross_tax', $cache, 86400);
}
}
}
echo $html;
}
Por ejemplo, para obtener todas las etiquetas de Posts Publicados en la categoría con slug news:
<?php echo tags_by_other_taxonomy('news'); ?>
