Vývoj aplikace WordPress z blogovací platformy do plnohodnotného CMS současně přetváří do pevného rámce, v němž mohou vývojáři vytvářet vynikající projekty a aplikace.

Jádro WordPress nese nejen publikační engine uživatelů, ale také poskytuje vývojářům robustní množinu tříd, rozhraní API a pomocníků, které jsou navrženy tak, aby řešily širokou škálu potřeb.

Jeden ze skrytých skvostů WordPress, který umožňuje vývojářům provádět operace s lokálním systémem souborů bezpečným a robustním způsobem, je rozhraní API WordPress Filesystem. Funkce manipulace s soubory abstrahuje do souboru běžně požadovaných metod, takže je lze bezpečně používat v různých hostitelských prostředích.

Rozsah problému

Mohlo by existovat několik důvodů, proč chtít psát místní soubory v kódu:

  • Protokolování událostí nebo prováděných operací
  • Výměna dat s systémy nepodporujícími systém WordPress
  • Zálohování

Bez ohledu na motivace může být psaní lokálních souborů z PHP kódu rizikovou operací. Nejméně dvě velmi důležité úskalí by měly být brány v úvahu při implementaci tohoto tématu, plugin nebo vlastní instalace WordPress:

  1. Bezpečnostní. Při psaní místních souborů s kódem (webovým serverem) existuje riziko nesprávného vlastnictví souborů. Tento problém vzniká v nesprávně nakonfigurovaných sdílených hostitelských prostředích a může vést ke ztrátě kontroly nad soubory.
  2. Kompatibilita. Vzhledem k rozmanitosti hostingových společností tam, konfigurace konkrétního uživatele serveru je obvykle neznámé vývojáři. Vývojář tedy nemůže si být jisti, že oprávnění potřebná pro psaní jsou dosažitelná uživatelem pluginu nebo tématu.

Pokud je plugin WordPress nebo téma, který potřebuje psát místní soubory, určen pro veřejné uvolnění, měl by vývojář neustále tyto problémy vzít v úvahu. Dobrou zprávou je, že WordPress sám již má k řešení těchto problémů nástroj: FileSystem API.

Úvod do rozhraní API WordPress Filesystem

Aplikační systém Filesystem API byl přidán do WordPress ve verzi 2.6 a umožnil vlastní funkci aktualizace WordPress. Abstrahuje funkce potřebné pro bezpečné a rychlé provádění operací čtení a zápisu na různých typech hostitelů. Obsahuje sadu tříd a umožňuje vám automaticky zvolit správný způsob připojení k místnímu systému souborů, v závislosti na nastavení jednotlivých hostitelů.

Logika API je poměrně jednoduchá; pokusí se psát místní soubory přímo a v případě nesprávného vlastnictví souboru přepne na jinou metodu založenou na protokolu FTP. V závislosti na dostupných knihovnách PHP zjistí vhodný způsob, jak nastavit připojení FTP (přes rozšiřující sokety nebo přes SSH). Obvykle jsou pro práci s místními soubory vyžadovány následující kroky:

Krok 1. Zjistěte, jaká metoda připojení je k dispozici

WordPress používá metodu get_filesystem_method ke zjištění dostupnosti následujících metod (od nejvyšší priority k nejnižší) Přímý, SSH2, FTP PHP Extension, FTP Sockets.

Krok 2. Získat pověření vyžadovaná pro zjištěnou metodu

Pokud zjištěné dopravní potřeby vyžadují pověření od uživatele, aplikace WordPress používá funkci request_filesystem_credentials k zobrazení formuláře žádosti. Funkce má několik parametrů, které jí umožňují uchovat data mezi odesláním formuláře, několikrát požádat o pověření, pokud spojení selhalo, a cílit na konkrétní adresář uvnitř instalace WordPress:

request_filesystem_credentials($form_post, $type, $error, $context, $extra_fields);

Přidáním prázdného parametru typu $ na funkci jsme jej mohli přinutit provést zjištění dostupných metod připojení, proto by pro nás nazval metodu get_filesystem_method. Současně můžeme funkci přinutit k použití jakéhokoli konkrétního typu připojení tím, že jej specifikuje pomocí argumentu typu $.

Pokud nejsou k dispozici údaje o připojení požadované zvolenou metodou, funkce vytiskne formulář a vyžádá si ji:

Conneciton information

Po první žádosti WordPress ukládá název hostitele FTP a uživatelské jméno v databázi pro budoucí použití, ale neuloží heslo. Alternativně mohou být pověření FTP zadána v souboru wp-config.php pomocí následujících konstant:

  • FTP_HOST - název hostitele serveru, ke kterému se má připojit
  • FTP_USER - uživatelské jméno pro připojení
  • FTP_PASS - heslo k připojení
  • FTP_PUBKEY - cesta k veřejnému klíči pro připojení SSH2
  • FTP_PRIKEY - cesta k soukromému klíči pro připojení SSH2

Když jsou tato data uložena v souboru wp-config.php, formulář žádosti o pověření se neobjeví, ale bezpečnostní nedostatky jsou významné a bezpečnostní postupy by měly být triple-checked a nejvyšší pozornost by měla být věnována bezpečnosti tohoto souboru.

Krok 3. Inicializujte třídu WordPress Filesystem a připojte se k souborovému systému

Srdcem API programu WordPress Filesystem je funkce WP_Filesystem. Načte a inicializuje příslušnou přepravní třídu, uloží získanou instanci do globálního objektu $ wp_filesystem pro další použití a pokusí se připojit k souborovému systému s uvedenými pověřeními:

WP_Filesystem($args, $context);

Krok 4. Použijte metody WordPress Filesystem k provádění operací čtení a zápisu

Správně inicializovaný objekt $ wp_filesystem má sadu metod pro komunikaci s lokálním systémem souborů, který by mohl být použit bez dalších obav o typu připojení. Zejména existují následující běžně používané metody:

  • get_contents - čte soubor do řetězce
  • put_contents - zapíše řetězec do souboru
  • mkdir - vytvoří adresář
  • mdir - odstraní adresář
  • wp_content_dir - vrací cestu do lokálního souborového systému do složky wp-content
  • wp_plugins_dir - vrací cestu do lokálního souborového systému do složky plugins
  • wp_themes_dir - vrací cestu do místního souborového systému do složky témat

Když to všechno položíme, pojďme s příkladem, který provádí výše uvedené kroky v jednoduché situaci - budeme psát nějaký text předaný v textarea do obyčejného souboru .txt.

Všimněte si, že tento příklad je pro demonstrační účely, v situaci v reálném světě byste neukládali jednoduchá textová data do souboru .txt, bylo by mnohem robustnějším řešením ukládání do databáze.

Aplikace WordPress Filesystem API v akci

Zkompletujme náš kód v samostatném pluginu, kterému bude přidělen vlastní souborový souborový demo. To nám poskytuje cílovou složku pro uložení souboru .txt a kontrolu oprávnění k psaní.

Nejdříve vytvořte ukázkovou stránku a zobrazte náš formulář v nabídce Nástroje:

/*** Create Demo page (under Tools menu)***/add_action('admin_menu', 'filesystem_demo_page');function filesystem_demo_page() {add_submenu_page( 'tools.php', 'Filesystem API Demo page', 'Filesystem Demo', 'upload_files', 'filesystem_demo', 'filesystem_demo_screen' );}function filesystem_demo_screen() {$form_url = "tools.php?page=filesystem_demo";$output = $error = '';/*** write submitted text into file (if any)* or read the text from file - if there is no submission**/if(isset($_POST['demotext'])){//new submissionif(false === ($output = filesystem_demo_text_write($form_url))){return; //we are displaying credentials form - no need for further processing}  elseif (is_wp_error ($ výstup)) {$error = $output->get_error_message();$output = '';}  } else {// přečíst z fileif (false === ($ output = filesystem_demo_text_read ($ form_url))) {return;  // zobrazujeme pověření bez nutnosti dalšího zpracování} elseif (is_wp_error ($ output)) {$error = $output->get_error_message();$output = '';}  } $ výstup = esc_textarea ($ výstup);  // uniká pro tisk?> 

Stránka Demo API souborového systému

Při zobrazování naší stránky (filesystem_demo_screen) zkontrolujeme dostupnost odesílání textu. Pokud existuje, snažíme se jej napsat do souboru test.txt, jinak se pokusíme najít takový soubor v adresáři plug-inu a přečíst jeho obsah, aby byl zahrnut v textarea. Nakonec vytiskneme základní text pro zadávání textu. Kvůli čitelnosti byly tyto psaní a čtení rozděleny do vlastních funkcí.

Filesystem API demo

Aby se předešlo duplicitě stejných inicializačních kroků, byl vytvořen sdílený pomocník. Nejprve volá request_filesystem_credentials, aby zjistila dostupnou metodu připojení a získala pověření. Pokud to bylo úspěšné, pak volá WP_Filesystem iniciovat $ wp_filesystem s danými daty.

/*** Initialize Filesystem object** @param str $form_url - URL of the page to display request form* @param str $method - connection method* @param str $context - destination folder* @param array $fields - fileds of $_POST array that should be preserved between screens* @return bool/str - false on failure, stored text on success**/function filesystem_init($form_url, $method, $context, $fields = null) {global $wp_filesystem;/* first attempt to get credentials */if (false === ($creds = request_filesystem_credentials($form_url, $method, false, $context, $fields))) {/*** if we comes here - we don't have credentials* so the request for them is displaying* no need for further processing**/return false;}/* now we got some credentials - try to use them*/if (!WP_Filesystem($creds)) {/* incorrect connection data - ask for credentials again, now with error message */request_filesystem_credentials($form_url, $method, true, $context);return false;}return true; //filesystem object successfully initiated}

Psaní kódu souboru vypadá takto:

/*** Perform writing into file** @param str $form_url - URL of the page to display request form* @return bool/str - false on failure, stored text on success**/function filesystem_demo_text_write($form_url){global $wp_filesystem;check_admin_referer('filesystem_demo_screen');$demotext = sanitize_text_field($_POST['demotext']); //sanitize the input$form_fields = array('demotext'); //fields that should be preserved across screens$method = ''; //leave this empty to perform test for 'direct' writing$context = WP_PLUGIN_DIR . '/filesystem-demo'; //target folder$form_url = wp_nonce_url($form_url, 'filesystem_demo_screen'); //page url with nonce valueif(!filesystem_init($form_url, $method, $context, $form_fields))return false; //stop further processign when request form is displaying/** now $wp_filesystem could be used* get correct target file first**/$target_dir = $wp_filesystem->find_folder($context);$target_file = trailingslashit($target_dir).'test.txt';/* write into file */if(!$wp_filesystem->put_contents($target_file, $demotext, FS_CHMOD_FILE))return new WP_Error('writing_error', 'Error when writing file'); //return error objectreturn $demotext;}

V této části jsme definovali některé nezbytné parametry:

  • $ demotext - odeslal text pro zápis
  • $ form_fields - položka v poli $ _POST, která ukládá náš text a měla by být zachována
  • $ metoda - způsob dopravy, ponecháme prázdné pro automatické rozpoznání
  • $ context - cílový adresář (plugin je jeden)

Poté jsme iniciovali globální objekt $ wp_filesystem pomocí pomocné funkce, kterou jsem popsal dříve. V případě úspěchu zjistíme správnou cestu k cílové složce a do ní napíšíme zadaný text pomocí metody put_contents objektu $ wp_filesystem.

Kód pro čtení ze souboru vypadá takto:

/*** Read text from file** @param str $form_url - URL of the page where request form will be displayed* @return bool/str - false on failure, stored text on success**/function filesystem_demo_text_read($form_url){global $wp_filesystem;$demotext = '';$form_url = wp_nonce_url($form_url, 'filesystem_demo_screen');$method = ''; //leave this empty to perform test for 'direct' writing$context = WP_PLUGIN_DIR . '/filesystem-demo'; //target folderif(!filesystem_init($form_url, $method, $context))return false; //stop further processing when request forms displaying/** now $wp_filesystem could be used* get correct target file first**/$target_dir = $wp_filesystem->find_folder($context);$target_file = trailingslashit($target_dir).'test.txt';/* read the file */if($wp_filesystem->exists($target_file)){ //check for existence$demotext = $wp_filesystem->get_contents($target_file);if(!$demotext)return new WP_Error('reading_error', 'Error when reading file'); //return error object}return $demotext;}

Tato funkce pracuje stejným způsobem jako dříve popsaná, ale používá k získání informací z cílového souboru použití get_contents.

Závěr

Při práci s lokálními soubory se vývojář WordPress témat nebo pluginů dostane do kontaktu s problémy zabezpečení a kompatibility, kladou obrovský důraz na tým a přidávají dlouhé hodiny do životního cyklu projektu. Tím, že spoléháme na souborové rozhraní API, mohou být tyto problémy účinně provázány bočně. Takže příště, když zjistíte, že píšete fwrite do kódu pluginu, považujte tuto alternativu za zdravější.

Můžeš Zde si stáhněte demo tohoto kódu , a přizpůsobit je vašim potřebám.