Perché l'API WP Filesystem non riesce a leggere googlefonts.json?

22 ott 2014, 18:49:25
Visualizzazioni: 1.76K
Voti: 2

Ho ereditato un sito costruito con un tema di Highgrade (southcentral) che utilizza il framework Redux.

Sto ricevendo il seguente errore sia nel frontend che nel pannello di amministrazione:

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

Ho provato a modificare permessi e proprietario del file googlefonts.json senza successo.

Il problema sembra essere all'interno del framework Redux - vedi questa discussione su github

Sto eseguendo il debug nella classe 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
        );
    }
}

Qualcuno ha idea di cosa potrebbe causare questo problema? Il file esiste ed è nel percorso specificato. L'ambiente di sviluppo è OSX Mavericks.

AGGIORNAMENTO:

Cambiare la proprietà dell'intera directory wordpress a _www:_www risolve il problema ma ovviamente non è una soluzione ideale.

4
Commenti

Perché stai cercando di usare $wp_filesystem->get_contents qui? Usa semplicemente il normale file_get_contents di PHP invece.

Otto Otto
22 ott 2014 20:34:32

Non sono io. È l'autore del tema. Voglio capire il problema, non aggirarlo con hack.

codecowboy codecowboy
22 ott 2014 20:35:01

Beh, dì all'autore che sta sbagliando e di sostituire quelle chiamate con file_get_contents. Scriverò una risposta più dettagliata qui.

Otto Otto
22 ott 2014 20:35:41

La risposta di Otto dovrebbe essere selezionata come risposta a questa domanda. Tuttavia, probabilmente ci sarebbe altro contesto da aggiungere su cosa fare quando non è possibile utilizzare file_get_contents() a causa delle regole di WordPress.

Tim Malone Tim Malone
8 mar 2018 00:14:55
Tutte le risposte alla domanda 4
8

Non è necessario utilizzare il WP_Filesystem per ogni piccola cosa, e in questo caso, la soluzione corretta è utilizzare il normale file_get_contents.

Il WP_Filesystem è un wrapper attorno a vari metodi per interagire con il filesystem in modo sicuro... ma non è pensato per ogni utilizzo.

Fondamentalmente, il codice di WP_Filesystem è stato creato per permettere a WordPress di aggiornarsi autonomamente.

In un'operazione del genere, la proprietà dei file è un aspetto cruciale. Molti server girano come "www" (ad esempio) invece che come il vero proprietario dei file PHP. Se WordPress scrivesse un file direttamente in un caso del genere, il file risultante sarebbe di proprietà di "www", non del proprietario reale e corretto. Questo può portare a problemi di sicurezza, specialmente in ambienti di hosting condiviso.

Quindi, il WP_Filesystem astrae le operazioni sui file. Può leggere e scrivere file in modi che preservano la proprietà dei file. Se può scrivere direttamente e la proprietà rimane invariata, lo farà, ma se non può, allora avrà bisogno di credenziali per qualche metodo come FTP. Utilizzando credenziali, può accedere tramite quella via e scrivere file con il proprietario corretto.

Ciò significa che prima di utilizzare il WP_Filesystem, deve essere configurato. Deve essere eseguito un test, e se il test fallisce, allora devono essere ottenute credenziali dall'utente. Senza quelle credenziali, non può funzionare.

Nel tuo caso, dato che "cambiare la proprietà dell'intera directory di wordpress a _www:_www" ha risolto il problema, questo è ciò che ti sta succedendo. Il test di scrittura di un file con la proprietà corretta fallisce. Cambiando il proprietario dei file esistenti, stai modificando le condizioni per quel test.

Ora, la verità è che in questo caso, non c'è alcuna ragione di utilizzare il WP_Filesystem. Stai leggendo un file. Puoi leggerlo direttamente. La proprietà non ha importanza qui. Quindi, in realtà, basta usare file_get_contents. Utilizzare il WP_Filesystem per questo non ha senso.

Maggiori informazioni su WP_Filesystem, da un punto di vista pratico: http://ottopress.com/2011/tutorial-using-the-wp_filesystem/

22 ott 2014 20:43:23
Commenti

Trovo un po' contraddittorio sostenere l'uso di file_get_contents() mentre contemporaneamente viene vietato dalle regole del repository. E se fosse un tema pubblico nel repository? Capisco che i temi fuori dal repository possono (e lo fanno, me compreso) ignorare questa regola, ma penso che sia un contesto importante per la risposta e un caso all'interno del repository non è coperto dal consigliarlo.

Rarst Rarst
22 ott 2014 21:58:02

@Otto quindi WP Filesystem esegue un test per scrivere un file prima di fare $wp_filesystem->get_contents(ReduxFramework::$_dir . 'inc/fields/typography/googlefonts.json') nel mio caso? Se sapessi dove prova a scrivere un file potrei semplicemente cambiare i permessi di quella directory, quindi sarebbe un'informazione utile

codecowboy codecowboy
22 ott 2014 22:05:21

Inoltre, tutto ciò che WP_Filesystem_Direct::file_get_contents sembra fare è incapsulare e sopprimere gli errori di file_get_contents() di PHP

codecowboy codecowboy
22 ott 2014 22:23:00

@codecowboy La variabile global $wp_filesystem non viene impostata finché non chiami la funzione WP_Filesystem(), che effettivamente esegue quel test per ciascuno dei vari metodi. Se il metodo diretto funziona, allora viene assegnato a quella variabile. Quindi non puoi chiamare $wp_filesystem->get_contents() finché non hai chiamato WP_Filesystem() almeno una volta.

Otto Otto
22 ott 2014 23:30:53

@Rarst Se questo fosse per un tema nel repository, consiglierei di riscrivere completamente il codice per evitare di dover leggere e analizzare quel file .json ogni volta. Invece di lasciarlo come file json, lo leggi una volta, lo passi attraverso json_decode, stampi il risultato con print_r e lo inserisci in un file PHP, che poi puoi semplicemente includere per impostare qualsiasi variabile contenga. Perché complicarsi la vita leggendo e analizzando un file ogni volta quando puoi farlo una sola volta?

Otto Otto
22 ott 2014 23:32:45

@Rarst Per il caso più generale di "leggere un file in un tema", non riesco a pensare a una buona ragione per cui un tema dovrebbe farlo. Consentiamo l'uso di file() specificamente per quei casi, ma realisticamente, si è presentato solo poche volte e in quei casi era relativamente semplice usare un approccio alternativo che eliminava del tutto la necessità di leggere il file.

Otto Otto
22 ott 2014 23:34:34

@Otto il mio punto era principalmente che nella forma di "usare il normale file_get_contents()" la risposta manca di contesto, come le regole del repository. Se qualcuno lo usa semplicemente e poi viene bloccato cercando di inviare al repository — considererebbero tale risposta un cattivo consiglio.

Rarst Rarst
22 ott 2014 23:36:28

@Rarst capisco il tuo punto di vista, ma non sono d'accordo. Ha posto una domanda su un pezzo specifico di codice. La mia risposta riflette solo quello. Non ha chiesto una domanda che richiederebbe una risposta molto più complessa coinvolgendo la revisione del tema, il plugin theme check e il repository ufficiale gratuito. Vuole risolvere il suo problema e imparare qualcosa su WP_Filesystem, non imparare come funziona l'intera struttura.

Otto Otto
22 ott 2014 23:42:44
Mostra i restanti 3 commenti
3

@codecowboy, quale versione di Redux stai utilizzando? Nelle versioni più recenti non utilizziamo nemmeno il file googlefonts.json in questo modo.

Ti suggerisco di installare semplicemente Redux Framework dal repository dei plugin di WordPress (http://wordpress.org/plugins/redux-framework/), e questo problema sarà risolto per te in quanto il plugin sovrascriverà la versione di Redux incorporata nel tuo tema.

22 ott 2014 21:20:42
Commenti

Grazie per questo. Proverò questa soluzione rapida che non causerà problemi con eventuali aggiornamenti futuri del tema.

codecowboy codecowboy
22 ott 2014 21:59:59

La versione di redux sembra essere la 3.2.8.1

codecowboy codecowboy
22 ott 2014 22:00:36

Lavoriamo duramente per assicurarci che gli aggiornamenti non danneggino i temi e, se succede, inseriamo una soluzione temporanea. Pensiamo che installare il plugin sia la scelta migliore.

Dovy Dovy
2 nov 2014 17:39:07
0

Dopo qualche debug sembra che quello che sta realmente succedendo è che WP_Filesystem cerca di aprire una connessione FTP al file temporaneo mentre sta effettuando i suoi controlli:

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; //false è restituito e quindi ottengo un array vuoto di Google Fonts

        fseek( $temp, 0 ); // Torna all'inizio del file in scrittura
        $contents = '';

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

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

Sul mio computer locale con OSX questo fallisce mentre sul server di destinazione funziona. Non sono sicuro del perché cambiare la proprietà dell'intera directory di WordPress a _www:_www permetta a questo ftp_fget di passare dato che sta cercando di leggere un file temporaneo in /var/tmp

23 ott 2014 09:15:46
8
-2

Per la cronaca, l'ultima versione di Redux non utilizza più questo specifico metodo per caricare i font Google. In secondo luogo, Otto ha una certa avversione per le persone di Redux, quindi prendi ciò che dice qui con le pinze. Vediamo errori di controllo del tema COSTANTEMENTE che dicono:

AVVISO: file_put_contents è stato trovato nel file class.redux_filesystem.php Le operazioni sui file dovrebbero utilizzare i metodi WP_Filesystem invece delle chiamate dirette al filesystem PHP.

Davvero? Quindi, Otto? Stai inventando standard e linee guida man mano che procedi? Ha senso, in realtà, poiché l'intera base di $wp_filesystem sembra sia stata messa insieme pezzo per pezzo da ragazzini che non avevano idea di cosa stessero facendo. Standard, davvero!

22 ott 2014 21:13:38
Commenti

Non mi stavo riferendo direttamente al tuo tema, solo al codice fornito. Non conosco nulla del tuo framework, di per sé. Non l'ho mai analizzato in profondità.

Otto Otto
22 ott 2014 21:17:40

Inoltre, l'uso di file_get_contents non è permesso per i temi nella directory di WordPress.org principalmente perché molto malware lo utilizza. Il plugin theme check è specificamente orientato a quegli standard.

Detto questo, invece di leggere un file .json e decodificarlo ogni volta, avrebbe molto più senso decodificarlo una sola volta e includere direttamente nell'array PHP risultante nel codice.

Otto Otto
22 ott 2014 21:19:14

No, non è il mio tema, e francamente signore, non credo alla sua storia sul framework, basandomi su eventi recenti a riguardo.

kprovance kprovance
22 ott 2014 21:19:26

@kprovance Non sono sicuro se abbia preso un'avversione, ha parlato in termini generici.

Otto, quindi come suggerisci di avere una soluzione permanente oltre a quello che abbiamo fatto? Tentiamo di usare il WP_Filesystem, ma se fallisce usiamo file_get_contents. È accettabile? Sembrava funzionare bene finora.

Dovy Dovy
22 ott 2014 21:22:16

Le persone di Redux sono libere di dissentire con me e usare ciò che funziona meglio per loro e i loro utenti. Non mi dà alcun fastidio.

Otto Otto
22 ott 2014 21:22:57

Otto, per favore inviami un'email o contattami su Skype. dovy@reduxframework.com. Skype: DovyDigital

Vorrei risolvere tutte le preoccupazioni e ottenere il tuo onesto consiglio.

Dovy Dovy
22 ott 2014 21:24:18

Per favore, porta questa discussione altrove. Stack Exchange non è un forum per sua natura, tanto meno per conflitti interpersonali.

Rarst Rarst
22 ott 2014 21:51:04
Mostra i restanti 3 commenti