De ce nu poate API-ul WP Filesystem să citească googlefonts.json?

22 oct. 2014, 18:49:25
Vizualizări: 1.76K
Voturi: 2

Am preluat un site construit cu un temă de la Highgrade (southcentral) care folosește cadrul Redux.

Văd următoarea eroare în frontend și panoul de administrare:

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

Am încercat să modific permisiunile și ownership-ul pentru googlefonts.json dar fără succes.

Problema pare să fie în cadrul Redux - vezi acest thread pe github

Depanez în clasa 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
                );
            }
        }
    }

Are cineva vreo idee ce ar putea cauza asta? Fișierul există și se află la calea specificată. Mediul de dezvoltare este OSX Mavericks.

ACTUALIZARE:

Schimbarea ownership-ului întregului director wordpress la _www:_www rezolvă problema dar evident nu este o soluție ideală.

4
Comentarii

De ce încerci să folosești $wp_filesystem->get_contents aici? Mai bine folosește funcția PHP normală file_get_contents.

Otto Otto
22 oct. 2014 20:34:32

Nu eu o fac. Autorul temei o face. Vreau să înțeleg problema, nu să o rezolv prin hack-uri.

codecowboy codecowboy
22 oct. 2014 20:35:01

Păi spune-i autorului că face greșit și să schimbe acele apeluri cu file_get_contents. Voi scrie un răspuns mai detaliat aici.

Otto Otto
22 oct. 2014 20:35:41

Răspunsul lui Otto ar trebui selectat ca răspuns la această întrebare. Totuși, probabil ar mai fi de adăugat și alte detalii despre ce să faci atunci când nu poți folosi file_get_contents() din cauza regulilor WordPress.

Tim Malone Tim Malone
8 mar. 2018 00:14:55
Toate răspunsurile la întrebare 4
8

Nu este necesar să folosiți WP_Filesystem pentru orice lucru minor, iar în acest caz, soluția corectă este să utilizați funcția normală file_get_contents.

WP_Filesystem este un wrapper în jurul diferitelor metode de a interacționa cu sistemul de fișiere într-un mod sigur... dar nu este destinat pentru orice situație.

În esență, codul WP_Filesystem a fost creat pentru a permite WordPress să se actualizeze singur.

Când faceți astfel de operații, proprietatea fișierelor este o problemă destul de importantă. Multe servere rulează sub utilizatorul "www" (de exemplu) în loc să ruleze sub proprietarul real al fișierelor PHP. Dacă WordPress ar scrie direct un fișier în astfel de cazuri, fișierul rezultat ar fi deținut de "www", nu de adevăratul proprietar. Acest lucru poate duce la probleme de securitate, în special în cazul hostingului partajat.

Deci, WP_Filesystem abstractizează operațiunile cu fișiere. Poate citi și scrie fișiere în modalități care vor păstra proprietatea acestora. Dacă poate scrie direct și proprietatea rămâne neschimbată, atunci va face acest lucru, dar dacă nu poate, atunci va avea nevoie de credențiale pentru o metodă precum FTP. Folosind aceste credențiale, se poate conecta prin acea rută și poate scrie fișiere folosind proprietarul corect.

Ce înseamnă acest lucru este că înainte de a utiliza WP_Filesystem, acesta trebuie configurat. Trebuie efectuat un test, iar dacă testul eșuează, atunci trebuie obținute credențiale de la utilizator. Fără aceste credențiale, nu poate funcționa.

În cazul dumneavoastră, deoarece "schimbarea proprietarului întregului director WordPress la _www:_www" a rezolvat problema, aceasta este situația care vă afectează. Testul prin care încercă să scrie un fișier și să obțină proprietatea corectă eșuează. Prin schimbarea proprietarului fișierelor existente, modificați condițiile pentru acel test.

În realitate, în acest caz, nu există niciun motiv să utilizați WP_Filesystem deloc. Utilizatorul citește un fișier. Poate citi acel fișier direct. Proprietatea nu contează aici. Așadar, pur și simplu folosiți file_get_contents. Utilizarea WP_Filesystem pentru această operație nu are sens.

Mai multe informații despre WP_Filesystem, din perspectiva utilizării: http://ottopress.com/2011/tutorial-using-the-wp_filesystem/

22 oct. 2014 20:43:23
Comentarii

Mi se pare un pic contradictoriu să susții folosirea file_get_contents(), în timp ce aceasta este interzisă de regulile repo-ului. Ce se întâmplă dacă acesta ar fi un theme public în repo? Înțeleg că temele care nu sunt în repo pot pur și simplu (și o fac, inclusiv eu) să ignore această regulă, dar cred că este un context important pentru răspuns, iar cazul unui theme din repo nu este acoperit prin recomandarea acestuia.

Rarst Rarst
22 oct. 2014 21:58:02

@Otto deci WP Filesystem efectuează un test pentru a scrie un fișier înainte de a face $wp_filesystem->get_contents(ReduxFramework::$_dir . 'inc/fields/typography/googlefonts.json') în cazul meu? Dacă aș ști unde încearcă să scrie un fișier, aș putea pur și simplu să schimb permisiunile pe acel director, așa că această informație ar fi utilă

codecowboy codecowboy
22 oct. 2014 22:05:21

De asemenea, tot ce face WP_Filesystem_Direct::file_get_contents pare a fi să încapsuleze și să suprascrie erorile file_get_contents() din PHP

codecowboy codecowboy
22 oct. 2014 22:23:00

@codecowboy Variabila globală global $wp_filesystem nu este setată până când nu apelezi funcția WP_Filesystem(), care de fapt face acel test pentru fiecare dintre metodele disponibile. Dacă metoda directă funcționează, atunci este atribuită acelei variabile. Deci nu poți apela $wp_filesystem->get_contents() până nu ai apelat WP_Filesystem() măcar o dată.

Otto Otto
22 oct. 2014 23:30:53

@Rarst Dacă asta era pentru o temă din repository, aș recomanda rescrierea completă pentru a nu mai fi nevoie să citești și să analizezi acel fișier .json de fiecare dată. În loc să-l lași ca fișier json, îl citești o dată, îl treci prin json_decode, folosești print_r pe rezultat și pui asta într-un fișier PHP, pe care apoi îl poți include pur și simplu pentru a seta orice variabilă conține. De ce să te complici cu citirea și parsarea unui fișier de fiecare dată când poți face asta o singură dată?

Otto Otto
22 oct. 2014 23:32:45

@Rarst Pentru cazul mai general de "citire a unui fișier într-o temă", nu pot să mă gândesc la vreun motiv într-adevăr bun pentru care o temă ar face asta. Permitem file() specific pentru acele cazuri, dar realist vorbind, a apărut doar de câteva ori și în acele cazuri a fost relativ simplu să folosești o alternativă care elimină nevoia de a citi fișierul cu totul.

Otto Otto
22 oct. 2014 23:34:34

@Otto punctul meu principal a fost că în forma "a folosi normal file_get_contents()" răspunsul lipsește context, cum ar fi regulile repository-ului. Dacă cineva pur și simplu îl folosește și apoi este respins încercând să trimită la repository - ei ar considera un astfel de răspuns ca fiind un sfat prost.

Rarst Rarst
22 oct. 2014 23:36:28

@Rarst Înțeleg punctul tău, dar nu sunt de acord cu el. El a pus o întrebare despre o bucată specifică de cod. Răspunsul meu reflectă doar asta. El nu a pus o întrebare care să necesite un răspuns mult mai complex care să implice review-ul temei, pluginul de verificare a temei și repository-ul oficial gratuit. El vrea să-și rezolve problema și să învețe puțin despre WP_Filesystem, nu să învețe cum funcționează întreaga structură.

Otto Otto
22 oct. 2014 23:42:44
Arată celelalte 3 comentarii
3

@codecowboy, ce versiune de Redux folosești? În versiunile mai noi nici măcar nu mai folosim googlefonts.json în acest fel.

Îți sugerez să instalezi pur și simplu Redux Framework din depozitul de plugin-uri WordPress (http://wordpress.org/plugins/redux-framework/), iar această problemă va fi rezolvată pentru tine deoarece plugin-ul va suprascrie versiunea de Redux încorporată în tema ta.

22 oct. 2014 21:20:42
Comentarii

Mulțumesc pentru aceasta. Voi încerca această soluție rapidă care nu va afecta eventualele actualizări viitoare ale temei.

codecowboy codecowboy
22 oct. 2014 21:59:59

versiunea redux pare să fie 3.2.8.1

codecowboy codecowboy
22 oct. 2014 22:00:36

Lucrăm din greu pentru a ne asigura că actualizările nu distrug temele, iar dacă se întâmplă acest lucru, implementăm o soluție de rezervă. Considerăm că instalarea pluginului este cea mai bună alegere.

Dovy Dovy
2 nov. 2014 17:39:07
0

După ce am făcut depanarea, se pare că ceea ce se întâmplă cu adevărat este că WP_Filesystem încearcă să deschidă o conexiune FTP către fișierul temporar în timp ce efectuează verificările:

public function get_contents( $file ) {
        $tempfile = wp_tempnam($file); // Creează un nume de fișier temporar unic
        $temp = fopen($tempfile, 'w+'); // Deschide fișierul temporar pentru scriere/citire

        if ( ! $temp )
            return false; // Dacă nu poate fi deschis, returnează false

        // Încearcă să descarce fișierul prin FTP în fișierul temporar
        if ( ! @ftp_fget($this->link, $temp, $file, FTP_BINARY ) )
            return false; // Dacă eșuează, returnează false și obțin un array gol pentru fonturile Google

        fseek( $temp, 0 ); // Revine la începutul fișierului temporar
        $contents = ''; // Inițializează variabila pentru conținut

        // Citește fișierul în bucăți de 8192 bytes
        while ( ! feof($temp) )
            $contents .= fread($temp, 8192);

        fclose($temp); // Închide fișierul temporar
        unlink($tempfile); // Șterge fișierul temporar
        return $contents; // Returnează conținutul citit
    }

Pe mașina mea locală cu OSX acest cod eșuează, în timp ce pe serverul țintă funcționează. Nu sunt sigur de ce schimbarea drepturilor de proprietate pentru întregul director WordPress la _www:_www permite acestui ftp_fget să funcționeze, având în vedere că încearcă să citească un fișier temporar în /var/tmp.

23 oct. 2014 09:15:46
8
-2

Pentru clarificare, cea mai recentă versiune de Redux nu mai utilizează această metodă specifică pentru încărcarea fonturilor Google. Și în al doilea rând, Otto are o oarecare aversiune față de oamenii de la Redux, așa că luați cu rezerve ceea ce spune el aici. Vedem CONSTANT erori în verificarea temelor care spun:

AVERTIZARE: file_put_contents a fost găsit în fișierul class.redux_filesystem.php Operațiunile cu fișiere ar trebui să folosească metodele WP_Filesystem în loc de apeluri directe la sistemul de fișiere PHP.

Serios? Deci, Otto? Inventezi standarde și linii directoare pe parcurs? Are sens, într-adevăr, având în vedere că întreaga bază $wp_filesystem acționează de parcă a fost asamblată bucată cu bucată de copii care nu aveau nicio idee despre ce făceau. Standarde, într-adevăr!

22 oct. 2014 21:13:38
Comentarii

Nu mă adresam direct temei tale, doar codului dat. Nu știu nimic despre framework-ul tău, per se. Nu l-am studiat în profunzime.

Otto Otto
22 oct. 2014 21:17:40

De asemenea, folosirea file_get_contents nu este permisă pentru teme în directorul WordPress.org în principal pentru că multe programe malware o folosesc. Plugin-ul de verificare a temelor este axat special pe acele standarde.

Cu toate acestea, în loc să citești un fișier .json și să-l decodifici de fiecare dată, ar fi mult mai logic să-l decodifici o singură dată și să incluzi array-ul PHP rezultat direct în cod.

Otto Otto
22 oct. 2014 21:19:14

Nu, nu este tema mea, și sincer domnule, nu te cred în legătură cu framework-ul, bazat pe evenimentele recente cu acesta.

kprovance kprovance
22 oct. 2014 21:19:26

@kprovance Nu sunt sigur dacă a început să urască, a vorbit în termeni generali.

Otto, deci cum sugerezi să avem o soluție permanentă dincolo de ce am făcut. Încercăm să folosim WP_Filesystem, dar dacă nu funcționează, folosim file_get_contents. Este acceptabil acest lucru? Se pare că a funcționat până acum.

Dovy Dovy
22 oct. 2014 21:22:16

Cei de la Redux sunt liberi să nu fie de acord cu mine și să folosească ceea ce funcționează cel mai bine pentru ei și utilizatorii lor. Nu mă deranjează deloc.

Otto Otto
22 oct. 2014 21:22:57

Otto, te rog să îmi trimiți un email sau să mă contactezi pe Skype. dovy@reduxframework.com. Skype: DovyDigital

Aș dori să rezolvăm toate preocupările și să primesc sfatul tău sincer.

Dovy Dovy
22 oct. 2014 21:24:18

Te rog să duci această discuție în altă parte. Stack Exchange nu este un forum prin natura sa, cu atât mai puțin pentru conflicte interpersonale.

Rarst Rarst
22 oct. 2014 21:51:04
Arată celelalte 3 comentarii