Utviklingen av WordPress fra en blogging-plattform til et fullverdig CMS, gjør det samtidig til et solid rammeverk for utviklere å bygge utestående prosjekter og applikasjoner på.

WordPress-kjerne, styrer ikke bare brukerens publiseringsmotor, men gir også utviklere et robust sett med klasser, APIer og hjelpere, designet for å møte et bredt spekter av behov.

En av skjulte perler av WordPress som gjør det mulig for utviklere å utføre operasjoner med det lokale filsystemet på en sikker og robust måte, er WordPress Filesystem API. Den abstraherer filmanipuleringsfunksjonalitet til et sett med ofte etterlyste metoder, slik at de kan brukes sikkert i forskjellige vertsmiljøer.

Omfanget av problemet

Det kan være flere grunner til at du vil skrive lokale filer i kode:

  • Logging av hendelser eller operasjoner utført
  • Datautveksling med ikke-WordPress-drevne systemer
  • backup

Uavhengig av motivasjonene, kan det være en risikabel operasjon å skrive lokale filer fra PHP-kode. Minst to svært viktige fallgruver bør tas i betraktning når du implementerer dette for et WordPress-tema, plugin eller egendefinert installasjon:

  1. Sikkerhet. Det er fare for feil fileierskap når du skriver lokale filer med kode (av webserveren). Dette problemet oppstår i dårlig konfigurert delt hosting miljøer og kan føre til tap av kontroll over filer.
  2. Kompatibilitet. På grunn av det mangfoldige hostingfirmaet der ute, er den spesielle brukerens serverkonfigurasjon vanligvis ukjent for utvikleren. Dermed kan utvikleren ikke være sikker på at tillatelser som kreves for en skriveoperasjon, kan oppnås av brukeren av plugin eller tema.

Hvis en WordPress-plugin eller et tema som trenger å skrive lokale filer, er ment for offentlig utgivelse, bør utvikleren hele tiden bære disse problemene i tankene. Den gode nyheten er at WordPress selv allerede har et verktøy for å løse disse problemene: Filsystemet API.

Introduksjon til WordPress Filesystem API

Filsystemet API ble lagt til i WordPress i versjon 2.6 for å aktivere WordPress 'egen oppdateringsfunksjon. Den abstraherer funksjonaliteten som trengs for å utføre lese / skrive operasjoner sikkert og på en rekke vertstyper. Den består av et sett med klasser og lar deg automatisk velge riktig måte å koble til det lokale filsystemet, avhengig av individuell vertoppsett.

Logikken bak APIen er ganske enkel; det prøver å skrive lokale filer direkte, og i tilfelle feil fil-eierskap skifter det til en annen FTP-basert metode. Avhengig av tilgjengelige PHP-biblioteker, finner den en passende måte å konfigurere en FTP-tilkobling (via utgangskontakter eller over-SSH). Vanligvis er følgende trinn kreves for å arbeide med lokale filer:

Trinn 1. Oppdag hvilken tilkoblingsmetode som er tilgjengelig

WordPress bruker get_filesystem_method til å oppdage tilgjengeligheten av følgende metoder (fra høyeste prioritet til laveste) Direkte, SSH2, FTP PHP Extension, FTP Sockets.

Trinn 2. Hent legitimasjon som kreves for den oppdagede metoden

Hvis den oppdagede transporten trenger legitimasjon fra en bruker, bruker WordPress request_filesystem_credentials-funksjonen til å vise et forespørselsskjema. Funksjonen har en rekke parametere som gjør det mulig å bevare data mellom skjemainnlegg, be om legitimasjon flere ganger hvis tilkoblingen mislyktes og målrette mot en bestemt katalog inne i WordPress-installasjonen:

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

Ved å levere en tom $ type parameter til funksjonen kunne vi tvinge den til å utføre deteksjon av tilgjengelige tilkoblingsmetoder, så det ville kalle get_filesystem_method for oss. Samtidig kan vi tvinge funksjonen til å bruke en bestemt tilkoblingstype ved å spesifisere den ved hjelp av argumentet for $ type.

Når tilkoblingsdataene som kreves av den valgte metoden, ikke er oppgitt, skriver funksjonen skjemaet for å be om det:

Conneciton information

Etter den første forespørselen lagrer WordPress FTP-vertsnavnet og brukernavnet i databasen for fremtidig bruk, men det lagrer ikke passordet. Alternativt kan FTP-legitimasjon angis i wp-config.php-filen ved å bruke følgende konstanter:

  • FTP_HOST - vertsnavnet til serveren for å koble til
  • FTP_USER - Brukernavnet for å koble til
  • FTP_PASS - Passordet for å koble til
  • FTP_PUBKEY - banen til offentlig nøkkel for bruk for SSH2-tilkobling
  • FTP_PRIKEY - banen til privatnøkkelen til bruk for SSH2-tilkobling

Når disse dataene er lagret i wp-config.php-filen, vises ikke skjemaet for legitimasjon, men sikkerhetsnaklene er signifikante og sikkerhetsprosedyrene skal tredobles med den høyeste oppmerksomheten som er mulig, bør betales til sikkerheten til denne filen.

Trinn 3. Initialiser WordPress Filesystem-klassen og koble til filsystemet

Hjertet i WordPress Filesystem API er WP_Filesystem-funksjonen. Den laster og initialiserer riktig transportklasse, lagrer en oppnådd forekomst i det globale $ wp_filesystem objektet for videre bruk, og forsøker å koble til filsystemet med de oppgitte legitimasjonene:

WP_Filesystem($args, $context);

Trinn 4. Bruk WordPress-filsystemmetodene til å utføre lese / skrive-operasjoner

En riktig initialisert $ wp_filesystem objekt har et sett med metoder for å kommunisere med det lokale filsystemet som kan brukes uten ytterligere angst for tilkoblingstype. Spesielt er det følgende vanlige metoder:

  • get_contents - leser filen i en streng
  • put_contents - skriver en streng til en fil
  • mkdir - lager en katalog
  • mdir - fjerner en katalog
  • wp_content_dir - returnerer banen på det lokale filsystemet til wp-innholdmappen
  • wp_plugins_dir - returnerer banen på det lokale filsystemet til plugin-mappen
  • wp_themes_dir - returnerer banen på det lokale filsystemet til tema-mappen

Når vi setter det sammen, la oss komme opp med et eksempel som utfører de ovennevnte trinnene i en enkel situasjon - vi vil skrive noen tekst som sendes inn i en tekstarea til en vanlig .txt-fil.

Vær oppmerksom på at dette eksemplet er til demonstrasjonsformål, i en ekte situasjon ville du ikke lagre enkle tekstdata i en .txt-fil, det ville være en langt mer robust løsning for å lagre den i databasen i stedet.

WordPress Filesystem API i handling

La oss pakke inn koden vår i et eget plugin, som vil tilordnes sin egen filsystem-demo-mappe. Det gir oss målmappe for å lagre .txt-filen og sjekke skrivetillatelser.

Først av alt, la oss lage demo siden for å vise skjemaet under Verktøy-menyen:

/*** 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 = '';}  } ellers {// les fra filif (false === ($ output = filesystem_demo_text_read ($ form_url))) {return;  // vi viser legitimasjonsbeskrivelser danner ikke behov for videre behandling} elseif (is_wp_error ($ output)) {$error = $output->get_error_message();$output = '';}  } $ output = esc_textarea ($ output);  // escape for utskrift?> 

Demo-side for filsystem-API

Når vi viser vår side (filesystem_demo_screen), ser vi etter tilgjengeligheten av tekstinnlevering. Hvis det eksisterer prøver vi å skrive det i en test.txt-fil, ellers prøver vi å finne en slik fil i plugin-mappen og lese innholdet som skal inkluderes i tekstområdet. Endelig skriver vi ut et grunnskjema for å skrive inn tekst. For lesbarhets skyld ble disse skrift- og leseoperasjonene skilt i egne funksjoner.

Filesystem API demo

For å unngå duplisering av de samme initialiseringstrinnene, har den delte hjelperen blitt opprettet. Det kaller request_filesystem_credentials først for å oppdage den tilgjengelige tilkoblingsmetoden og oppnå legitimasjon. Hvis det var vellykket, kalles det WP_Filesystem for å starte $ wp_filesystem med gitt 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}

Skrive til filkode ser slik 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 denne delen definerte vi noen nødvendige parametere:

  • $ demotext - sendt inn tekst for å skrive
  • $ form_fields - element i $ _POST-gruppen som lagrer vår tekst og skal bevare
  • $ metode - transportmetode, la vi den stå tom for å oppdage automatisk
  • $ kontekst - målmappe (pluginens en)

Deretter startet vi det globale $ wp_filesystem objektet ved hjelp av hjelperfunksjonen jeg beskrev tidligere. I tilfelle suksess oppdager vi den riktige banen til målmappen og skriver den innleverte teksten inn i den ved hjelp av put_contents-metoden for $ wp_filesystem-objektet.

Koden for lesing fra filen ser slik 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;}

Denne funksjonen fungerer på samme måte som tidligere beskrevet, men det bruker get_contents å lese fra målfilen.

Konklusjon

Når du arbeider med lokale filer, kommer et WordPress-tema eller en plugin-utvikler i kontakt med sikkerhets- og kompatibilitetsproblemer, og legger stor stress på teamet og legger til lange timer i prosjektets livssyklus. Ved å stole på Filsystem-API kan disse problemene bli sidestegt på en effektiv måte. Så neste gang du finner deg selv å skrive fwrite i pluginens kode, kan du vurdere dette alternativet sunnere alternativet.

Du kan last ned en demonstrasjon av denne koden her , og tilpass det til dine behov.