Utvecklingen av WordPress från en bloggplattform till ett heltäckande CMS, samtidigt som det blir en solid ram för utvecklare att bygga utestående projekt och applikationer på.

WordPress-kärnan driver inte bara användarnas förlagsmotor utan ger också utvecklare en robust uppsättning klasser, API och hjälpare, utformade för att tillgodose ett brett utbud av behov.

En av de dolda pärlorna i WordPress som tillåter utvecklare att utföra operationer med det lokala filsystemet på ett säkert och robust sätt är WordPress Filesystem API. Den sammanfattar filmanipuleringsfunktionalitet i en uppsättning vanligt förekommande metoder så att de kan användas säkert i olika värdmiljöer.

Problemets omfattning

Det kan finnas flera skäl att vilja skriva lokala filer i kod:

  • Registrering av händelser eller utförda åtgärder
  • Datautbyte med icke-WordPress-drivna system
  • Säkerhetskopiering

Oavsett motivationen kan det vara en riskabel skrivning av lokala filer från PHP-kod. Minst två väldigt viktiga fallgropar bör beaktas vid implementering av detta för ett WordPress-tema, plugin eller anpassad installation:

  1. Säkerhet. Det finns risk för felaktigt filägande när du skriver lokala filer med kod (av webbservern). Det här problemet uppstår i dåligt konfigurerade delade värdmiljöer och kan leda till förlust av kontroll över filer.
  2. Kompatibilitet. På grund av de olika hostingföretagen där ute är den speciella användarens serverkonfiguration vanligtvis okänd för utvecklaren. Således kan utvecklaren inte vara säker på att behörigheter som krävs för en skrivoperation uppnås av användaren av plugin eller tema.

Om ett WordPress-plugin eller ett tema som behöver skriva lokala filer är avsett för offentliggörande, bör utvecklaren ständigt bära dessa problem i åtanke. Den goda nyheten är att WordPress själv redan har ett verktyg för att lösa dessa problem: Filsystem API.

Introduktion till WordPress Filesystem API

Filsystemet API läggs till i WordPress i version 2.6 för att aktivera WordPress egna uppdateringsfunktion. Den sammanfattar den funktionalitet som behövs för att utföra läs- / skrivoperationer på ett säkert sätt och på en mängd olika värdtyper. Den består av en uppsättning klasser och låter dig automatiskt välja rätt sätt att ansluta till det lokala filsystemet, beroende på individuell värdinställning.

Logiken bakom API: n är ganska enkel; Det försöker skriva lokala filer direkt och om det är felaktigt filinnehåll växlar det till en annan FTP-baserad metod. Beroende på tillgängliga PHP-bibliotek hittar den ett lämpligt sätt att konfigurera en FTP-anslutning (via uttagskontakter eller över SSH). Vanligtvis krävs följande steg för att arbeta med lokala filer:

Steg 1. Upptäck vilken anslutningsmetod som är tillgänglig

WordPress använder get_filesystem_method för att upptäcka tillgängligheten av följande metoder (från högsta prioritet till lägsta) Direkt, SSH2, FTP PHP Extension, FTP Sockets.

Steg 2. Hämta referenser som krävs för den upptäckta metoden

Om den upptäckta transporten behöver legitimationsuppgifter från en användare använder WordPress funktionen request_filesystem_credentials för att visa ett förfrågningsformulär. Funktionen har ett antal parametrar som gör det möjligt att bevara data mellan formulärinsändningar, be om inloggningsuppgifter flera gånger om anslutningen misslyckades och rikta in på en viss katalog i WordPress-installationen:

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

Genom att leverera en tom $ typparameter till funktionen kunde vi tvinga den att utföra detektering av tillgängliga anslutningsmetoder, så det skulle kallas get_filesystem_method för oss. Samtidigt kan vi tvinga funktionen att använda en viss anslutningstyp genom att ange den med argumentet $ type.

När anslutningsdata som krävs enligt den valda metoden inte anges, skriver funktionen formuläret för att begära det:

Conneciton information

Efter den första förfrågan lagrar WordPress FTP-värdnamnet och användarnamnet i databasen för framtida användning, men det lagrar inte lösenordet. Alternativt kan FTP-uppgifter anges i wp-config.php-filen med hjälp av följande konstanter:

  • FTP_HOST - värdnamnet på servern för att ansluta till
  • FTP_USER - användarnamnet att ansluta till
  • FTP_PASS - lösenordet att ansluta till
  • FTP_PUBKEY - sökvägen till den allmänna nyckeln som ska användas för SSH2-anslutning
  • FTP_PRIKEY - sökvägen till den privata nyckeln som ska användas för SSH2-anslutning

När denna data lagras i wp-config.php-filen visas inte formuläret för inlämningsuppgifter, men säkerhetsnätena är signifikanta och säkerhetsförfarandena ska triple-checkas med den högsta uppmärksamhet som är möjlig bör betalas till säkerheten för den här filen.

Steg 3. Initiera WordPress Filesystem-klassen och anslut till filsystemet

Hjärtat i WordPress Filesystem API är funktionen WP_Filesystem. Den laddar och initialiserar lämplig transportklass, lagrar en erhållen instans i det globala $ wp_filesystemobjektet för vidare användning och försöker ansluta till filsystemet med de angivna referenserna:

WP_Filesystem($args, $context);

Steg 4. Använd WordPress-filsystemmetoderna för att utföra läs- / skrivoperationer

Ett korrekt initierat $ wp_filesystemobjekt har en uppsättning metoder för att kommunicera med det lokala filsystemet som kan användas utan ytterligare ångest om anslutningstyp. I synnerhet följer följande vanliga metoder:

  • get_contents - läser filen i en sträng
  • put_contents - skriver en sträng till en fil
  • mkdir - skapar en katalog
  • mdir - tar bort en katalog
  • wp_content_dir - returnerar sökvägen på det lokala filsystemet till mappen wp-innehåll
  • wp_plugins_dir - returnerar sökvägen på det lokala filsystemet till plugin-mappen
  • wp_themes_dir - returnerar sökvägen på det lokala filsystemet till teman mappen

Om vi ​​sammanfattar det, låt oss komma fram med ett exempel som utför ovanstående steg i en enkel situation - vi kommer att skriva lite text som skickas i en textarea till en vanlig .txt-fil.

Observera att det här exemplet är för demonstrationsändamål, i en verklig situation skulle du inte lagra enkel textdata i en .txt-fil, det skulle vara en mycket mer robust lösning för att lagra den i databasen istället.

WordPress Filesystem API i åtgärd

Låt oss paketera vår kod i en separat plugin, som kommer att tilldelas en egen filsystem-demo-mapp. Det ger oss en målmapp för att lagra .txt-filen och kontrollera skrivbehörigheter.

Låt oss först skapa demoversidan för att visa vår form under Verktyg-menyn:

/*** 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 ($ output)) {$error = $output->get_error_message();$output = '';}  } annat {// läs från filenif (false === ($ output = filesystem_demo_text_read ($ form_url))) {return;  // vi visar uppgiften bildar inget behov av vidare bearbetning} elseif (is_wp_error ($ output)) {$error = $output->get_error_message();$output = '';}  } $ output = esc_textarea ($ output);  // flyr för utskrift?> 

Demosidan för filsystem API

När vi visar vår sida (filesystem_demo_screen) kontrollerar vi om det finns tillgång till textinsändning. Om det existerar försöker vi skriva det i en test.txt-fil, annars försöker vi hitta en sådan fil i plugin-mappen och läsa innehållet som ska ingå i textområdet. Slutligen skriver vi ut en grundläggande form för att skriva in text. För läsbarhetens skull separerades dessa skriv- och läsoperationer i sina egna funktioner.

Filesystem API demo

För att undvika dubbelarbete av samma initialiseringssteg har den delade hjälpen skapats. Det kallar request_filesystem_credentials först för att upptäcka den tillgängliga anslutningsmetoden och få inloggningsuppgifter. Om det lyckades kallas då WP_Filesystem för att initiera $ wp_filesystem med givna data.

/*** 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}

Skrivning till filkod ser så här ut:

/*** 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;}

I denna del definierade vi några nödvändiga parametrar:

  • $ demotext - skickad text att skriva
  • $ form_fields - objekt i $ _POST-arrayen som lagrar vår text och bör bevaras
  • $ metod - transportmetod, lämnar vi den tom för att upptäcka automatiskt
  • $ context - målmapp (pluginens en)

Därefter initierade vi det globala $ wp_filesystemobjektet med hjälp av hjälparfunktionen som jag beskrivit tidigare. I händelse av framgång upptäcker vi den korrekta sökvägen till målmappen och skriver in den inlämnade texten i den med hjälp av put_contents-metoden för $ wp_filesystem-objektet.

Koden för läsning från filen ser så här ut:

/*** 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;}

Den här funktionen fungerar på samma sätt som tidigare beskrivits, men den använder get_contents för att läsa från målfilen.

Slutsats

När du arbetar med lokala filer kommer en WordPress-teman eller plugins-utvecklare att komma i kontakt med säkerhets- och kompatibilitetsproblem, vilket ger enorm stress på laget och lägger till långa timmar i projektets livscykel. Genom att förlita sig på Filsystem API kan dessa problem sidoprovas på ett effektivt sätt. Så nästa gång du befinner dig skriva in i pluginens kod, anser du att det här alternativet är ett hälsosammare alternativ.

Du kan ladda ner en demo av den här koden här , och anpassa det till dina behov.