¿Por qué la API de WP Filesystem no puede leer googlefonts.json?

22 oct 2014, 18:49:25
Vistas: 1.76K
Votos: 2

Heredé un sitio construido con un tema de Highgrade (southcentral) que utiliza el framework Redux.

Estoy viendo el siguiente error tanto en el frontend como en el panel de administración:

Warning: Invalid argument supplied for foreach() in /Volumes/Data/Users/me/Sites/reference360.eu/wordpress/wp-content/themes/southcentral/highgrade/framework/inc/fields/typography/field_typography.php on line 772

Intenté cambiar los permisos y la propiedad de googlefonts.json pero sin éxito.

El problema parece estar dentro del framework Redux - ver este hilo en github

Estoy depurando en la clase typography.php:

if (!isset($this->parent->fonts['google']) || empty($this->parent->fonts['google'])) {
    $this->parent->fonts['google'] = json_decode($wp_filesystem->get_contents(ReduxFramework::$_dir . 'inc/fields/typography/googlefonts.json'), true);
    var_dump(ReduxFramework::$_dir . 'inc/fields/typography/googlefonts.json');
    var_dump($wp_filesystem->get_contents(ReduxFramework::$_dir . 'inc/fields/typography/googlefonts.json')); exit;
    $this->parent->font_groups['google'] = array(
        'id'        => 'google',
        'text'      => __('Google Webfonts', 'redux-framework'),
        'children'  => array(),
    );
    foreach ($this->parent->fonts['google'] as $font => $extra) {
        $this->parent->font_groups['google']['children'][] = array(
            'id'    => $font,
            'text'  => $font
        );
    }
}

¿Alguien tiene idea de qué podría estar causando esto? El archivo existe y está en la ruta especificada. El entorno de desarrollo es OSX Mavericks.

ACTUALIZACIÓN:

Cambiar la propiedad de todo el directorio de WordPress a _www:_www resuelve el problema pero obviamente no es una gran solución.

4
Comentarios

¿Por qué estás intentando usar $wp_filesystem->get_contents aquí? Simplemente usa el método normal de PHP file_get_contents en su lugar.

Otto Otto
22 oct 2014 20:34:32

No lo estoy haciendo yo. Es el autor del tema. Quiero entender el problema, no buscar soluciones alternativas.

codecowboy codecowboy
22 oct 2014 20:35:01

Bueno, dile al autor que lo está haciendo mal y que cambie esos por file_get_contents. Escribiré una respuesta más detallada aquí.

Otto Otto
22 oct 2014 20:35:41

La respuesta de Otto debería ser seleccionada como la respuesta a esta pregunta. Aunque probablemente haya más contexto que podría agregarse sobre qué hacer cuando no puedes usar file_get_contents() debido a las reglas de WP.

Tim Malone Tim Malone
8 mar 2018 00:14:55
Todas las respuestas a la pregunta 4
8

No es necesario usar WP_Filesystem para cada pequeña cosa, y en este caso, la solución correcta es usar la función normal file_get_contents.

WP_Filesystem es un envoltorio alrededor de varias formas de interactuar con el sistema de archivos de manera segura... pero no está destinado para todo.

Fundamentalmente, el código WP_Filesystem fue creado para permitir que WordPress se actualice a sí mismo.

Al hacer algo así, la propiedad de los archivos es un asunto bastante importante. Muchos servidores se ejecutan como "www" (por ejemplo) en lugar de como el propietario real de los archivos PHP. Si WordPress escribiera un archivo directamente en tal caso, el archivo resultante sería propiedad de "www" también, no del verdadero y correcto propietario. Esto puede llevar a problemas de seguridad, especialmente en alojamientos compartidos.

Por lo tanto, WP_Filesystem abstrae las operaciones de archivos. Puede leer y escribir archivos de maneras que preservarán la propiedad de los archivos. Si puede escribir directamente y la propiedad se mantiene, lo hará, pero si no puede, entonces necesitará credenciales para algún método como FTP. Al usar credenciales, puede iniciar sesión a través de esa ruta y escribir archivos utilizando el propietario adecuado.

Lo que esto significa es que antes de usar WP_Filesystem, debe configurarse. Se debe realizar una prueba, y si la prueba falla, se deben obtener credenciales del usuario. Sin esas credenciales, no puede funcionar.

En tu caso, dado que "cambiar la propiedad de todo el directorio de WordPress a _www:_www" resolvió el problema, esto es lo que te está sucediendo. La prueba de intentar escribir un archivo y obtener la propiedad correcta falla. Al cambiar el propietario de los archivos existentes, estás cambiando las condiciones para esa prueba.

Ahora, la verdad es que, en este caso, no hay razón para usar WP_Filesystem en absoluto. Está leyendo un archivo. Puede leer ese archivo directamente. La propiedad no importa aquí. Entonces, realmente, solo usa file_get_contents. Usar WP_Filesystem para esto no tiene sentido.

Más sobre WP_Filesystem, desde una perspectiva de cómo usarlo: http://ottopress.com/2011/tutorial-using-the-wp_filesystem/

22 oct 2014 20:43:23
Comentarios

Me parece un poco contradictorio argumentar a favor de file_get_contents(), mientras que al mismo tiempo está prohibido por las reglas del repositorio. ¿Qué pasaría si este fuera un tema público en el repositorio? Entiendo que los temas fuera del repositorio pueden simplemente (y lo hacen, yo incluido) "ignorar" esta regla, pero creo que es un contexto importante para la respuesta y un caso dentro del repositorio no está cubierto al recomendarlo.

Rarst Rarst
22 oct 2014 21:58:02

@Otto entonces, ¿WP Filesystem realiza una prueba para escribir un archivo antes de hacer $wp_filesystem->get_contents(ReduxFramework::$_dir . 'inc/fields/typography/googlefonts.json') en mi caso? Si supiera dónde intenta escribir un archivo, podría simplemente cambiar los permisos en ese directorio, lo que sería información útil.

codecowboy codecowboy
22 oct 2014 22:05:21

Además, todo lo que parece hacer WP_Filesystem_Direct::file_get_contents es encapsular y suprimir errores del file_get_contents() de PHP.

codecowboy codecowboy
22 oct 2014 22:23:00

@codecowboy La variable global $wp_filesystem no se establece hasta que llamas a la función WP_Filesystem(), que realmente hace esa prueba para cada uno de los diversos métodos. Si el método directo funciona, entonces se asigna a esa variable. Por lo tanto, no puedes llamar a $wp_filesystem->get_contents() hasta que hayas llamado a WP_Filesystem() una vez.

Otto Otto
22 oct 2014 23:30:53

@Rarst Si esto fuera para un tema en el repositorio, recomendaría reescribir esto por completo para no tener que leer y analizar ese archivo .json cada vez. En lugar de dejarlo como un archivo json, lo lees una vez, lo pasas por json_decode, imprimes el resultado con print_r y lo pones en un archivo PHP, que luego puedes simplemente incluir para configurar cualquier variable que contenga. ¿Por qué pasar por la molestia de leer y analizar un archivo cada vez cuando puedes hacerlo solo una vez?

Otto Otto
22 oct 2014 23:32:45

@Rarst Para el caso más general de "leer un archivo en un tema", no se me ocurre ninguna razón realmente buena para que un tema haga eso. Permitimos file() específicamente para esos casos, pero en realidad, solo ha surgido un puñado de veces y en esos casos fue relativamente simple usar un enfoque alternativo que eliminó la necesidad de leer el archivo por completo.

Otto Otto
22 oct 2014 23:34:34

@Otto mi punto era principalmente que en la forma de "usar el file_get_contents() normal" la respuesta carece de contexto, como las reglas del repositorio. Si alguien simplemente lo usa y luego recibe un rechazo al intentar enviar al repositorio — considerarían ese consejo como malo.

Rarst Rarst
22 oct 2014 23:36:28

@Rarst Entiendo tu punto, pero no estoy de acuerdo. Él hizo una pregunta sobre un fragmento de código específico. Mi respuesta solo refleja eso. No hizo una pregunta que requiriera una respuesta mucho más compleja involucrando la revisión de temas, el plugin theme check y el repositorio oficial gratuito. Él quiere solucionar su problema y aprender un poco sobre WP_Filesystem, no aprender cómo funciona toda la estructura.

Otto Otto
22 oct 2014 23:42:44
Mostrar los 3 comentarios restantes
3

@codecowboy, ¿qué versión de Redux estás usando? En las versiones más recientes ni siquiera usamos el googlefonts.json de esta manera.

Te sugiero que simplemente instales Redux Framework desde el repositorio de plugins de WordPress (http://wordpress.org/plugins/redux-framework/), y este problema se resolverá para ti ya que el plugin anulará la versión de Redux integrada en tu tema.

22 oct 2014 21:20:42
Comentarios

Gracias por esto. Probaré eso como una solución rápida que no romperá ninguna posible actualización futura del tema.

codecowboy codecowboy
22 oct 2014 21:59:59

la versión de redux parece ser 3.2.8.1

codecowboy codecowboy
22 oct 2014 22:00:36

Trabajamos muy duro para asegurarnos de que las actualizaciones no destruyan los temas y si lo hacen, implementamos un parche. Creemos que instalar el plugin es tu mejor opción.

Dovy Dovy
2 nov 2014 17:39:07
0

Después de depurar un poco, parece que lo que realmente está sucediendo aquí es que WP_Filesystem intenta abrir una conexión FTP al archivo temporal mientras realiza sus verificaciones:

public function get_contents( $file ) {
        $tempfile = wp_tempnam($file);
        $temp = fopen($tempfile, 'w+');

        if ( ! $temp )
            return false;

        if ( ! @ftp_fget($this->link, $temp, $file, FTP_BINARY ) )
            return false; // Se devuelve false y termino con un array vacío de fuentes de Google

        fseek( $temp, 0 ); // Retrocede al inicio del archivo que se está escribiendo
        $contents = '';

        while ( ! feof($temp) )
            $contents .= fread($temp, 8192);

        fclose($temp);
        unlink($tempfile);
        return $contents;
    }

En mi máquina local con OSX esto falla, mientras que en el servidor destino funciona. No estoy seguro de por qué cambiar la propiedad de todo el directorio de WordPress a _www:_www permite que este ftp_fget funcione, dado que está intentando leer un archivo temporal en /var/tmp.

23 oct 2014 09:15:46
8
-2

Para que conste, la versión más reciente de Redux ya no utiliza este método en particular para cargar fuentes de Google. Y en segundo lugar, Otto tiene cierta aversión por la gente de Redux, así que toma lo que dice aquí con pinzas. Constantemente vemos errores en las revisiones de temas que dicen:

ADVERTENCIA: se encontró file_put_contents en el archivo class.redux_filesystem.php. Las operaciones con archivos deberían usar los métodos WP_Filesystem en lugar de llamadas directas al sistema de archivos de PHP.

¿En serio? Entonces, ¿Otto? ¿Estás inventando estándares y pautas sobre la marcha? Tiene sentido, realmente, ya que toda la base de $wp_filesystem parece haber sido ensamblada a trozos por niños que no tenían idea de lo que estaban haciendo. ¡Estándares, por supuesto!

22 oct 2014 21:13:38
Comentarios

No estaba abordando directamente tu tema, solo el código proporcionado. No sé nada sobre tu framework, en sí. Nunca lo he examinado en profundidad.

Otto Otto
22 oct 2014 21:17:40

Además, el uso de file_get_contents no está permitido para temas en el directorio de WordPress.org principalmente porque mucho malware lo utiliza. El plugin de verificación de temas está específicamente orientado a esos estándares.

Dicho esto, en lugar de leer un archivo .json y decodificarlo cada vez, tendría mucho más sentido simplemente decodificarlo una vez e incluir el array de PHP resultante directamente en el código.

Otto Otto
22 oct 2014 21:19:14

No, no es mi tema, y francamente señor, no le creo lo del framework, basado en eventos recientes con él.

kprovance kprovance
22 oct 2014 21:19:26

@kprovance No estoy seguro si ha desarrollado un odio, ha hablado en términos generales.

Otto, entonces ¿cómo sugieres que tengamos una solución permanente más allá de lo que hemos hecho? Intentamos usar WP_Filesystem, pero si falla usamos file_get_contents. ¿Es esto aceptable? Parece que ha funcionado bien hasta ahora.

Dovy Dovy
22 oct 2014 21:22:16

La gente de Redux es libre de estar en desacuerdo conmigo y usar lo que funcione mejor para ellos y sus usuarios. No me molesta en absoluto.

Otto Otto
22 oct 2014 21:22:57

Otto, por favor envíame un correo o escríbeme por Skype. dovy@reduxframework.com. Skype: DovyDigital

Me gustaría resolver todas las preocupaciones y obtener tu consejo honesto.

Dovy Dovy
22 oct 2014 21:24:18

Por favor, lleva esto a otro lugar. Stack Exchange no es un foro por naturaleza, mucho menos para conflictos interpersonales.

Rarst Rarst
22 oct 2014 21:51:04
Mostrar los 3 comentarios restantes