3.- desarrollo de plugins - dario bf€¦ · dariobf.com ¿qué es un plugin? un plugin es un...
TRANSCRIPT
dariobf.com
3.- Desarrollo de PluginsArchivos del plugin, Hooks, Shortcodes, Página de opciones del plugin, objeto
$wpdb, Actualización del plugin.
#1
¿Qué es un plugin?¿Y cómo crearlo?
dariobf.com
¿Qué es un plugin?Un plugin es un conjunto de ficheros cuyo fin es añadir funciones extra a WordPress.
Un plugin: • Requiere una cabecera específica, única con información del plugin. • Se guarda en wp-content/plugins (Normalmente en subdirectorio. • Se ejecuta sólo cuando está activado, a través del panel de plugins • Aplica sus funciones a todos los temas. • Debe tener un propósito; por ejemplo: convertir artículos en páginas,
ofrecer mejoras de posicionamiento o ayudar con los backups.
dariobf.com
Cabecera del plugin• Plugin name. • Plugin URI. • Description. • Author. • Author URI. • Version. • Domain Path. • Network. • Text domain.
dariobf.com
<?php/** * Plugin Name: Name of the plugin, must be unique. * Plugin URI: http://URI_Of_Page_Describing_Plugin_and_Updates * Description: A brief description of the plugin. * Version: The plugin's version number. Example: 1.0.0 * Author: Name of the plugin author * Author URI: http://URI_Of_The_Plugin_Author * Text Domain: Optional. Plugin's text domain for localization. Example: mytextdomain * Domain Path: Optional. Plugin's relative directory path to .mo files. Example: /locale/ * Network: Optional. Whether the plugin can only be activated network wide. Example: true * License: A short license name. Example: GPL2 */
Cabecera del plugin
#2
Los HooksGanchos
dariobf.com
¿Qué son los ganchos?
Técnicamente son eventos.
Por ejemplo, invocado por la llamada de do_action() o apply_filters() que desencadena después todas las funciones de filtro de acción previamente enganchados a ese evento.
dariobf.com
¿Qué son los ganchos?
En esencia, el gancho o evento invoca un Observer, que recoge una serie de funciones "enganchadas" y los llama usando la función call_user_func() de PHP; permitiendo que el código y operaciones sean implementadas en el proceso del core sin modificar el código de este.
dariobf.com
¿Qué son los ganchos?
Como los “Actions” y “Filters” requieren del uso de Hooks, es posible que escuches hablar con frecuencia de “Action hooks” y “filter hooks”.
dariobf.com
El Hook se ejecuta
¿Cómo funcionan?La llamada al servidor inicia el index.php, que ejecuta código del core. El código del core invoca al método do_action().
» » Vuelve a ejecutar el código del core.
dariobf.com
Ejemplo de Hook<?phpadd_filter(‘the_content’, ‘my_function’);
function my_function($content) {return $content . ‘<p>¡Compártelo con un amigo!</p>’;
}?>
Este código es un “Filter hook” sencillo que añade el texto “¡Comparte con un amigo!” después del contenido de cada entrada o página.
dariobf.com
CuidadínTu función se integrará con el core de WordPress. Hay que tener cuidado con los nombres que utilizamos. Aquí te dejo algunos nombres reservados.
• start_process() • output() • modify_content() • pluginname_process() • pluginname_output() • pluginname_modify_content()
dariobf.com
Naming de funciones<?phpadd_filter(‘the_content’, ‘_trackableshare_process’);
function _trackableshare_process($content) {/* whatever */
}?>
En el ejemplo, nuestro plugin llamado Trackable Social Share Icons. Recomendado empezar sus funciones con el prefijo “_trackableshare_”
Evitar confusiones con otros plugins.
dariobf.com
Naming de funciones
Si estás utilizando Programación Orientada a Objetos, o construyendo tu plugin como una clase puedes evitar los consejos anteriores, ya que tus métodos estarán separados de la función del plugin (o en otra dimensión).
Sin embargo, todavía tienes que asegurarte de que el nombre de tu clase (o de su área de trabajo) es único
dariobf.com
Ejemplo de plugin OOP<?php
class trackable_social_share{public function __construct() {// Add Hooksadd_filter('the_content', array($this, 'process'));
}public function process($content) {/* ... */
}
}
$trackable_social_share = new trackable_social_share();
?>
Esto es más complicado, es sólo un ejemplo de cómo sería.
dariobf.com
Resumen
• Un Hook es un evento que llama a una función o método en una acción.
• Tu código es integrado en el core de WordPress dinámicamente, pasando a ser parte de él.
• Nos referimos con frecuencia a los hooks como “Action hooks” y “Filter hooks”
• Puedes utilizar tanto código tradicional como Orientado a Objetos con hooks.
• Recuerda que el naming de las funciones es clave.
#3
Los Filter Hooks
dariobf.com
Filter HooksEl Filter Hook está diseñado para modificar contenido.
En lugar de ser invocado en una acción específica, el Filter Hook es invocado cuando se procesa el contenido; ya sea cuando se guarda o cuando se representa.
En los ejemplos anteriores se utilizó el Filter Hook para añadir contenido al contenido de nuestra entrada o página. Este es un perfecto ejemplo de cómo funciona este gancho.
También podemos manipular el contenido mediante otras funciones PHP.
dariobf.com
Ejemplo de manipulación de contenido
<?php
add_filter('the_content', ‘guorpres_vs_wordpress’); function guorpres_vs_wordpress($content) { return str_replace('wordpress', 'WordPress', $content);
} ?>
Reemplazamos los wordpress mal escritos por WordPress.
dariobf.com
Consejo: Filter Hooks
<?php
add_shortcode('pirate', 'ninja_function');function ninja_function() {
return ‘ninja’;}
?>
No utilices Filter Hooks para el uso de shortcodes.
Puedes utilizar str_replace, pero WordPress tiene su propia función sólo para shortcodes: add_shortcode()
dariobf.com
Filter Hooks
Los filtros pueden ser utilizados múltiples veces y en múltiples tipos de contenido.
Pueden modificar el contenido antes de guardarlo en la base de datos, o más adelante; durante la fase de renderizado.
También puedes modificar el autor, comentarios, widgets, enlaces, blogroll, fechas y horas, elementos del escritorio, etc, todo de forma dinámica sin tener que modificar el código del núcleo de WordPress.
https://codex.wordpress.org/Plugin_API/Filter_Reference
dariobf.com
Filtro pre-guardado comentarios
<?php
add_filter('comment_status_pre ', 'pluginname_malwordpress'); function pluginname_malwordpress($content) { $badwords = array('wordpress', 'Wordpress', 'güorpress', 'wordPress', 'hook'); return str_replace($badwords, 'WordPress', $content);
}
Reemplazamos los wordpress mal escritos por WordPress.
dariobf.com
Añadiendo Filter Hooks
<?php
add_filter($tag, $function, [$priority],[$accepted_args]); ?>
Todos se añaden utilizando la función add_filter()
Tag: (string) A qué tipo de proceso de contenido debe ser aplicado el filtro
Function: (callback) La función a ejecutar
Priority: (int) – opcional Orden en el que debe ser ejecutado. A número más bajo antes se ejecutará. Por defecto 10.
Accepted Args: (int) – opcional Número de argumentos aceptados cuando utilizamos apply_filters() (WP >= 1.5.1). Por defecto 1.
dariobf.com
Pregunta 1<?php
add_filter('the_content', ‘regla_poni');add_filter('the_content', ‘regla_caballo', 9);add_filter('the_content', ‘regla_batman', 8);function regla_poni($content) {return str_replace(‘mi animalito', ‘Ponis!’, $content);
}function regla_caballo($content) {return str_replace(‘mi animalito', ‘Caballitos!', $content);
}
function regla_batman($content) {return str_replace(‘mi animalito', ‘NANANA BATMAN!!’, $content);
}
?>
Si nuestro contenido es sólo “mi animalito”, ¿qué imprimirá?
dariobf.com
Resultado
La respuesta es “NANANA BATMAN!!”, porque tiene la prioridad más alta (número más bajo).
Estamos utilizando un str_replace(), reemplazará el texto “mi animalito” por “NANANA BATMAN!!” ignorando las funciones anteriores.
dariobf.com
Pregunta 2<?php
add_filter('the_content', ‘regla_poni');add_filter('the_content', ‘regla_caballo', 9);add_filter('the_content', ‘regla_batman', 8);function regla_poni($content) {return ‘Ponis!’;
}function regla_caballo($content) {return ‘Caballitos!’;
}
function regla_batman($content) {return ‘NANANA BATMAN!!’;
}
?>
Si nuestro contenido es sólo “mi animalito”, ¿qué imprimirá?
dariobf.com
Resultado
La respuesta es “Ponis!”. Tiene la prioridad más baja.
Ahora, no estamos reemplazando un trozo del texto, estamos reemplazando TODO el contenido.
Primero lo reemplazamos por “NANANA BATMAN!!”, después lo reemplazamos por “Caballitos!” y, por último, por “Ponis!”.
#4
Los Action Hooks
dariobf.com
Action Hooks
El Action Hook se invoca en WordPress cuando una acción tiene lugar, como cargar una página (front-end o wp-admin), se inserta un comentario, se guarda un artículo o incluso cuando cambiamos el tema.
dariobf.com
Action Hooks
Por ejemplo, un Action Hook puede ser invocado cuando cargamos el header, footer o el escritorio de administración.
Así mismo, cuando creamos un artículo, el Action Hook admin_init es invocado, y cuando lo guardamos es invocado el save_post.
dariobf.com
Action Hooks
El Action Hook está diseñado para proporcionar una mayor flexibilidad en cómo se procesan los elementos, así como la posibilidad de añadir funciones adicionales al sistema WordPress (tales como campos de texto adicionales al crear o editar una entrada), la adición de JavaScript / hojas de estilo, y otros artículos.
dariobf.com
Ejemplo de Action Hook
<?phpadd_action(‘admin_menu', ‘mi_plugin_extraordinario’);function mi_plugin_extraordinario() {
if(function_exists('add_submenu_page')) {add_submenu_page(‘plugins.php','Extraordinario', ‘Extraordinario’, 10, ‘my_new_plugin', 'my_new_plugin_admin_page_function');
}}
?>
¿Qué hace mi plugin?
dariobf.com
Resultado
El Action: Obtiene el menú de administración.
La petición: Cuando estés generando el Menú de administración, ejecuta esta función que añade un elemento bajo la sección de plugins.
El Resultado: El menú es generado con nuestro enlace, justo debajo de la sección de plugins.
dariobf.com
Añadiendo Action Hooks
<?php
add_action($tag, $function, [$priority],[$accepted_args]); ?>
Todos se añaden utilizando la función add_action()
Tag: (string) A qué tipo de proceso de contenido debe ser aplicado el filtro
Function: (callback) La función a ejecutar
Priority: (int) – opcional Orden en el que debe ser ejecutado. A número más bajo antes se ejecutará. Por defecto 10.
Accepted Args: (int) – opcional Número de argumentos aceptados cuando utilizamos apply_filters() (WP >= 1.5.1). Por defecto 1.
dariobf.com
Resumen
Filter Hooks
Modifican contenido.
Se crean con add_filter().
Es importante la prioridad. Recuerda que un número más bajo significa más prioridad.
Action Hooks
Añaden o eliminan código en una acción concreta.
Se crean con add_action().
#5
Advanced Hooking
dariobf.com
Advanced Hooking
WordPress integra algunas funciones para determinar las funciones que han sido enganchadas a un filtro, si el hook ya ha sido invocado, eliminando funciones de hooks e incluso eliminando todas las llamadas a funciones de un hook.
dariobf.com
Funciones basadas en un Action
has_action(‘hook’, ‘function’);
did_action(‘hook’);
remove_action(‘hook’, ’function’);
remove_all_actions(‘hook’);
dariobf.com
Funciones basadas en un Filter
has_filter(‘hook’, ‘function’);
did_filter(‘hook’);
current_filter();
remove_filter(‘hook’, ’function’);
remove_all_filters(‘hook’);
dariobf.com
has_*
Las funciones has_action() y has_filter() detectan cuando (o cuando no) se ha añadido una función al array de hooks para un evento determinado.
Esto retornará verdadero o falso.
dariobf.com
did_*
Las funciones did_action() y did_filter() detectan cuando (o cuando no) se ha invocado un evento. Si tu evento no ha sido enganchado al hook, pero el evento se ha invocado retornará true.
Esto retornará verdadero o falso.
dariobf.com
current_filter
La función current_filter() retorna si el evento actual ha sido procesado. Por ejemplo, si el hook invocado es “the_content”, esta función retornará “the_content”.
Es muy útil cuando utilizamos una función o método para manejar varios tipos de filtros.
dariobf.com
remove_*
Las funciones remove_action() y remove_filter() eliminará una función específica de un hook determinado.
Es útil si quieres evitar que una función sea llamada cuando suceda el evento.
dariobf.com
remove_all_*
Las funciones remove_all_actions() y remove_all_filters() eliminará todas las funciones específica de un hook.
Esta función recibe el nombre del hook como primer parámetro y acepta un segundo (opcional) que es la prioridad.
Por ejemplo, si quieres eliminar todas las funciones de “the_content” con prioridad 4: remove_all_filters(‘the_content”, 4);
dariobf.com
Creando Hooks personalizados
Podemos definir Hooks personalizados en nuestro plugin o tema que pueden ser enganchados dentro de otros plugins utilizando la función do_action() y apply_filters().
do_action(‘hook_name’);apply_filters(‘hook_name’, $content);
‘hook_name’ es el nombre que le damos a nuestro nuevo Hook y como nos referiremos a él.
dariobf.com
Ejemplo de Hook personalizado
<?php
function my_plugin_function() {// Allow hooks into this functiondo_action('my_plugin_init');// Create Content$content = 'Hello world';// Allow Content to have filters ran against it// Be sure to store the returned result of the FILTER!!!$content = apply_filters('my_plugin_content', $content);
}
?>
dariobf.com
Resumen
WordPress nos facilita varias funciones que pueden ser utilizadas para modificar Hooks incluso después de haber utilizado las funciones add_filter() o add_action().
También nos facilita crear nuestros propios Hooks en nuestro tema o plugin.
dariobf.com
Utiliza el Codex
Hemos visto mucha información sobre los Hooks de WordPress, pero hay mucha más disponible en el Codex, incluyendo los tipos de parámetros que algunos Hooks enviarán a tus funciones cuando el evento es invocado.
Todo sobre Filter Hooks: http://codex.wordpress.org/Plugin_API/Filter_Reference
Todo sobre Action Hooks: http://codex.wordpress.org/Plugin_API/Action_Reference
#6
Shortcodes
dariobf.com
Shortcodes
• El uso es muy simple: [recent-posts]
• Y pueden recibir parámetros: [recent-posts posts=“5”]
• Y, además, pueden recibir más contenido:
[recent-posts posts=“5”]Cabecera de los últimos posts[/shortcode]
Shortcode simple<?php
function recent_posts_function() {
query_posts(array('orderby' => 'date', 'order' => 'DESC' , 'showposts' => 1));
if (have_posts()) :
while (have_posts()) : the_post();
$return_string = '<a href="'.get_permalink().'">'.get_the_title().'</a>';
endwhile;
endif;
wp_reset_query();
return $return_string;
}
function register_shortcodes(){
add_shortcode('recent-posts', 'recent_posts_function');
}
add_action( 'init', 'register_shortcodes');
?>
[recent-posts]
Shortcode avanzadofunction recent_posts_function($atts){
extract(shortcode_atts(array(
'posts' => 1,
), $atts));
$return_string = '<ul>';
query_posts(array('orderby' => 'date', 'order' => 'DESC' , 'showposts' => $posts));
if (have_posts()) :
while (have_posts()) : the_post();
$return_string .= '<li><a href="'.get_permalink().'">'.get_the_title().'</a></li>';
endwhile;
endif;
$return_string .= '</ul>';
wp_reset_query();
return $return_string;
}
[recent-posts posts=“5”]
Shortcode avanzado 2function recent_posts_function($atts, $content = null) {
extract(shortcode_atts(array(
'posts' => 1,
), $atts));
$return_string = '<h3>'.$content.'</h3>';
$return_string .= '<ul>';
query_posts(array('orderby' => 'date', 'order' => 'DESC' , 'showposts' => $posts));
if (have_posts()) :
while (have_posts()) : the_post();
$return_string .= '<li><a href="'.get_permalink().'">'.get_the_title().'</a></li>';
endwhile;
endif;
$return_string .= '</ul>';
wp_reset_query();
return $return_string;
}
[recent-posts posts=“5”]Cabecera de los últimos posts[/shortcode]
dariobf.com
Habilitar shortcodes
<?phpadd_filter('widget_text', ‘do_shortcode');add_filter( 'comment_text', 'do_shortcode' );add_filter( 'the_excerpt', 'do_shortcode');
?>
dariobf.com
Shortcodes útiles
<?phpfunction linkbutton_function( $atts, $content = null ) {
return '<button type="button">'.do_shortcode($content).'</button>';
}
add_shortcode('linkbutton', 'linkbutton_function');
?>
[linkbutton]¡Soy un botón![/linkbutton]
function menu_function($atts, $content = null) {
extract(
shortcode_atts(
array( 'name' => null, ),
$atts
)
);
return wp_nav_menu(
array(
'menu' => $name,
'echo' => false
)
);
}
add_shortcode('menu', 'menu_function');?>
[menu name=“main-menu”]
function googlemap_function($atts, $content = null) {
extract(shortcode_atts(array(
"width" => '640',
"height" => '480',
"src" => ''
), $atts));
return '<iframe width="'.$width.'" height="'.$height.'" src="'.$src.'&output=embed" ></iframe>';
}
add_shortcode("googlemap", “googlemap_function");
[googlemap width="600" height="300" src="http://maps.google.com/maps?q=Heraklion,+Greece&hl=en&ll=35.327451,25.140495&spn=0.233326,0.445976& sll=37.0625,-95.677068&sspn=57.161276,114.169922& oq=Heraklion&hnear=Heraklion,+Greece&t=h&z=12"]
function pdf_function($attr, $url) {
extract(shortcode_atts(array(
'width' => '640',
'height' => '480'
), $attr));
return '<iframe src="http://docs.google.com/viewer?url=' . $url . '&embedded=true" style="width:' .$width. '; height:' .$height. ';">Your browser does not support iframes</iframe>';
}
add_shortcode('pdf', ‘pdf_function');
[pdf width="520px" height=“700px”]AQUI LA URL DEL PDF[/pdf]
#7
Pantalla de configuración
dariobf.com
Pantalla de configuración
<?phpadd_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position);
?>
$page_title - (string) (required) El texto que se mostrará en la etiqueta <title> cuando el menú está seleccionado.
$menu_title - (string) (required) El nombre del menú (Label).
$capability - (string) (required) El nivel de permisos necesarios para mostrar el menú a un usuario.
$menu_slug - (string) (required) El slug con el que nos referiremos a este menú (debe ser único).
dariobf.com
Pantalla de configuración
<?php
add_action('admin_menu', 'test_plugin_setup_menu');
function test_plugin_setup_menu(){
add_menu_page( 'Test Plugin Page', 'Test Plugin', 'manage_options', 'test-plugin', 'test_init' );
}
function test_init(){
echo "<h1>Hello World!</h1>";
}
?>
http://www.1stwebdesigner.com/wordpress-plugin-development-settings-page/
#8
Interactuando con la base de datos
dariobf.com
$wpdb
WordPress define una clase llamada wpdb, que contiene una serie de funciones utilizadas para interactuar con la base de datos. El objetivo principal es proporcionar una interfaz con la base de datos, pero se puede utilizar para comunicarse con otra base de datos cualquiera.
dariobf.com
<?php
// set the meta_key to the appropriate custom field meta key
$meta_key = 'miles';
$allmiles = $wpdb->get_var( $wpdb->prepare(
"
SELECT sum(meta_value)
FROM $wpdb->postmeta
WHERE meta_key = %s
",
$meta_key
) );
echo "<p>Total miles is {$allmiles}</p>";
?>
https://codex.wordpress.org/Class_Reference/wpdb
#9
WP_Cron
dariobf.com
WP_CronCuando vemos la palabra cron, nos imaginamos tareas programadas a una hora concreta para ejecutarse durante intervalos específicos.
Al contrario, WP-Cron no es lo mismo que el cron de Unix.
La gran diferencia está en su ejecución: WP_Cron se ejecuta cuando un visitante abre tu sitio WordPress. Es decir, su ejecución es imprecisa.
Como ejemplo, haremos un cron que cuente los suscriptores de nuestro canal RSS mediante feedburner.
dariobf.com
WP_CronPara entender bien WP_Cron es importante tener localizado el catálogo de sus funciones: http://codex.wordpress.org/Category:WP-Cron_Functions
Para nuestro propósito (contar los seguidores de feedburner) no tiene sentido hacerlo en cada carga de página en WordPress.
Para ello utilizaremos la función wp_schedule_event(), que recibe estos parámetros:
• Hora: Hora en formato Unix especificando cuándo se invoca.
• Recurrencia: Con qué frecuencia debe ser re-invocado después del tiempo programado.
• Hook: El Hook que utilizaremos para añadir la funcionalidad cuando sea invocado.
• Args: (opcional) Los argumentos a pasar (en array) para pasarle a las funciones enganchadas al hook.
dariobf.com
WP_Cron
Nuestro evento se invocará cuando la hora actual coincida o sobrepase la que le pasamos a esta función, marcada por un futuro visitante de nuestro sitio.
Será re-invocada basándonos en el parámetro de recurrencia, que puede ser definido como “hourly”, “twicedaily”, “daily” o “none”. También podemos definir nuestros propios parámetros de recurrencia.
Para ejecutar algo en nuestro evento, utilizamos un hook.
dariobf.com
WP_CronComo feedburner se actualiza diariamente, nuestra programación será diaria (daily).
<?phpwp_schedule_event( time(), 'daily', 'feedburner_refresh' );
?>
Si te das cuenta, la hora de ejecución es time(); esto significa que en cuanto el plugin esté activo se ejecutará y lo hará cada día a la misma hora.
Además, si colocamos esto en nuestro functions.php ejecutará esta acción en cada carga de página del sitio; no es lo que queremos.
Programado
dariobf.com
WP_CronLa forma sencilla de evitar esto, es hacer la comprobación siguiente:
<?phpif( !wp_next_scheduled( 'feedburner_refresh' ) ) { wp_schedule_event( time(), 'daily', 'feedburner_refresh' );}
?>
Esta función wp_next_scheduled() retornará falso si el evento no está programado para invocarse en el futuro o la hora no cumple.
Programado
dariobf.com
WP_CronSi necesitamos desprogramar un evento, es tan sencillo como utilizar la función wp_unschedule_event(), que requiere los mismos parámetros que wp_schedule_event().
Hay que tener en cuenta que el parámetro “time” será el del próximo evento a invocar (de nuestro programado); esto lo obtendremos con wp_next_scheduled().
<?phpif( false !== ($time = wp_next_scheduled('feedburner_refresh'))) { wp_unschedule_event( $time, 'feedburner_refresh' );}
?>
Desprogramado
dariobf.com
WP_Cron
También podemos desprogramarlo limpiando el hook al que hacemos referencia en nuestro programado:
<?phpwp_clear_scheduled_hook( 'feedburner_refresh' );
?>
Desprogramado
dariobf.com
WP_Cron
Ahora que ya tenemos programado nuestro evento, sólo falta definir qué queremos hacer con él.
<?phpadd_action( 'feedburner_refresh', 'update_rss_subscriber_count' );
?>
Ejecutando
En la función update_rss_subscriber_count() definiremos qué hace nuestro plugin; en este caso conectarse al API de Feedburner y obtener los seguidores. Sólo nos quedará guardarlo con update_option(‘subscriber_count’) y donde queramos ver ese dato utilizar get_option( 'subscriber_count' );
#10
Widgets
dariobf.com
Definir barra lateralEn el functions.php:
register_sidebars( $count, $args );
Con $args controlamos lo siguiente:
'before_widget' => '<li id="%1$s" class="widget %2$s">','after_widget' => "</li>n",'before_title' => '<h2 class="widgettitle">','after_title' => "</h2>"
dariobf.com
Mostrar barra lateralEn nuestra plantilla:
dynamic_sidebar($sidebar);
Forma más correcta:
<ul id="sidebar"><?php if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar() ) : ?>
<li>{static sidebar item 1}</li><li>{static sidebar item 2}</li>
<?php endif; ?></ul>
dariobf.com
Ideas para Widgets• Crear un widget que diferencie tu tema de alguna manera.
• Registrar un widget para reemplazar a uno original y modificarlo de alguna manera.
• Recuerde que un "widget" realmente no es más que un nombre para un código configurable. Puede ser invisible o posicionarse de forma absoluta; horizontalmente o verticalmente.
• Utilice los atributos de clase y el id de uno o todos los widgets en los scripts para animar su barra lateral.
• Puedes utilizar jQuery (incluido con WordPress) para hacer sus widgets arrastrables o replegables...