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.
Mohlo by existovat několik důvodů, proč chtít psát místní soubory v kódu:
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:
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.
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:
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.
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:
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.
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);
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:
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.
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í.
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:
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.
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.