Cómo aplicar consistentemente reglas de reescritura en el desarrollo de plugins

26 mar 2012, 19:50:44
Vistas: 447
Votos: 1

Digamos que creo un plugin de soporte al cliente que intercepta la parte /support de la URL y la redirige a un framework MVC en la carpeta app de mi directorio de plugin, así:

RewriteRule ^support(.*)$ wp-content/plugins/csupport/app/$1 [L]

Sé que puedo hacer esto en el .htaccess del blog justo antes de la línea RewriteBase, pero no todos tienen .htaccess activado a menos que agreguen un permalink personalizado. Encontré una técnica para forzar permalinks personalizados, pero es algo forzado y no recomendado.

¿Cuál es la forma recomendada para que los desarrolladores de plugins agreguen una regla de reescritura que pueda capturar una llamada a subdirectorio como /support y redirigirla a otro lugar?

0
Todas las respuestas a la pregunta 1
6

Aquí hay una solución. Ver comentarios al final...

// Soy un archivo functions.php de un plugin llamado "sample" -- impleméntame ligeramente diferente para un tema.
// Nota: este código requiere WP 3.0 o superior.
class SAMPLE {

public static function activatePlugin() {
  self::rewriteURL();
  flush_rewrite_rules();
  if (get_option('permalink_structure') == '') {
    self::updatePermalinks();
  }
  // añade aquí tu otro código de activación del plugin
}

public static function deactivatePlugin(){
  flush_rewrite_rules();
  // añade aquí tu otro código de desactivación del plugin
}

public static function drawAdminMenu(){
$s = <<<EOD
<div class="wrap">
  <div id="icon-options-general" class="icon32"><br></div>
  <h2>Panel de Muestra</h2>
  <!-- solución temporal para el problema de permalinks -- esto se vincula con el código de activación del plugin -->
  <iframe style="position:absolute;top:-5000px" src="<?= admin_url() ?>options-permalink.php"></iframe>
  <p>Tus opciones van aquí.</p>
</div><!-- .wrap -->
EOD;
  echo $s;
}

public static function rewriteURL(){
  add_rewrite_rule('support(.*)$','wp-content/plugins/sample/app/$1','top');
  // esto edita tu archivo .htaccess y añade: 
  // RewriteRule ^support(.*)$ /wp-content/plugins/sample/app/$1 [QSA,L]
}

public static function updatePermalinks(){
global $wp_rewrite;
  $wp_rewrite->set_permalink_structure('/%postname%/');
  $wp_rewrite->flush_rules();
  // Nota que el resto de esto se ejecuta mediante el formulario de registro vía IFRAME oculto
  // para crear el archivo .htaccess. Es una solución temporal -- ¡pero funciona bien!
}

} // fin de la clase SAMPLE

register_activation_hook(__FILE__,'SAMPLE::activatePlugin');
register_deactivation_hook(__FILE__,'SAMPLE::deactivatePlugin');
add_action('admin_menu', 'SAMPLE::drawAdminMenu');
add_action('init','SAMPLE::rewriteURL');
  1. Nunca deberías ejecutar flush_rewrite_rules() continuamente. Andrew Nacin, uno de los desarrolladores principales de WordPress, aconseja en más de una ocasión que esto debe hacerse desde los callbacks de activación y desactivación de un plugin o tema. (Los temas no tienen estos callbacks, pero hay ejemplos en la web que implementan soluciones temporales para callbacks de activación/desactivación en temas.) Andrew dice que degrada el rendimiento si se hace de otra manera. Esto es obvio porque potencialmente podría reescribir el archivo .htaccess cada vez que se carga una página.

  2. Utilizo métodos estáticos de clase en lugar de funciones globales en el espacio de nombres. Es menos peligroso y más ordenado.

  3. Nota la secuencia en activatePlugin() -- eso es importante. Deberías reescribir la URL, limpiar las reglas y, si los permalinks personalizados no están activados, activarlos.

  4. Los permalinks personalizados son cruciales. Sin ellos no obtienes el archivo .htaccess y por lo tanto no hay reglas de reescritura.

  5. Nota que no activamos los permalinks personalizados a la fuerza. Verificamos si están habilitados. Si no lo están, los activamos y usamos un tipo común de permalink frecuentemente utilizado con SEO.

  6. Nota que mi función updatePermalinks() tiene un problema. Es algo que detecté en todas las versiones de WordPress. Descubrí que el archivo .htaccess no se creaba a menos que uno hiciera clic para ver el panel de opciones de Permalinks. No tengo idea de por qué WordPress tiene este error, pero lo tiene. Así que, como puedes ver con el IFRAME abajo, ideé una solución temporal decente. Ese IFRAME asegurará que el archivo .htaccess se cree si no lo estaba -- siempre y cuando esa llamada a updatePermalinks() se haya hecho previamente.

  7. El Codex de WordPress parecía indicar que tendría muchos problemas con los parámetros de consulta en mi URL reescrita si no implementaba add_query_vars(). Sin embargo, descubrí que ese no era el caso en absoluto. Pude redirigir /support a un framework MVC dentro de mi plugin, y luego cargar ese framework con URLs elegantes como /support/tickets/1, así como usar parámetros de consulta al final como /support/tickets/1?q=open&s=palabras+clave.

  8. Nota que:

add_rewrite_rule('support(.*)$','wp-content/plugins/sample/app/$1','top');

...equivale a:

RewriteRule ^support(.*)$ /wp-content/plugins/sample/app/$1 [QSA,L]

...en el archivo .htaccess, que es exactamente lo que necesitaba.

En cuanto a por qué la documentación es tan confusa y engañosa sobre el tema de RewriteRules, no tengo idea.

EDIT1: Cambiado site_url() por admin_url() en la llamada del IFRAME.

27 mar 2012 01:16:48
Comentarios

esto funciona en ciertos casos, pero no es muy portable ya que dependes de que mod_rewrite esté disponible y que .htaccess sea escribible. además tu regla de reescritura asume que la url del home y la url del sitio son las mismas. quizás considera un respaldo creando una página a través de la cual se puedan enrutar las peticiones y dar a los usuarios la opción de seleccionar qué método usar.

Milo Milo
27 mar 2012 03:00:49

Tienes razón. No está destinado a ser portable y debe requerir .htaccess y mod_rewrite. Es decir, a menos que puedas proponer una solución que funcione sin eso.

Volomike Volomike
27 mar 2012 03:09:53

@Milo ¿puedes explicar por qué la url del home y la url del sitio podrían no ser las mismas?

Volomike Volomike
27 mar 2012 03:10:29

WordPress puede instalarse en un directorio diferente desde donde se sirve públicamente, por lo que es posible que wp-content esté un directorio debajo de ese archivo htaccess. Como solución alternativa: no uses reescrituras en absoluto, crea una página a través de la cual se enruten las solicitudes, engancha temprano en la solicitud y verifica si esa página es la página solicitada, y luego carga el código de tu plugin. Para ver un ejemplo, mira cómo la mayoría de los plugins de carritos de compras crean sus páginas de carrito y pago.

Milo Milo
27 mar 2012 04:04:41

@Milo ¡Qué bien que interactué contigo! Acabo de aprender la diferencia entre site_url() y home_url(). Tenía varias otras partes de mi código haciendo referencia a site_url() en lugar de home_url(). En el código anterior, también cambié y usé admin_url().

Volomike Volomike
27 mar 2012 07:59:41

También estoy investigando cómo obtener "wp-content/plugins/" -- puedo usar plugins_url(), pero necesitaré eliminar home_url() de ello.

Volomike Volomike
27 mar 2012 08:11:04
Mostrar los 1 comentarios restantes