概要
Filesystem APIは、WordPress 2.6で追加され、WordPress自身の自動更新機能のために最初に作成されました。
Filesystem APIは、さまざまなホストタイプでローカルファイルを安全に読み書きするために必要な機能を抽象化します。
これは、WP_Filesystem_Baseクラスと、個々のホストのサポートに応じてローカルファイルシステムに接続するさまざまな方法を実装するいくつかのサブクラスを通じて行われます。
ローカルにファイルを書き込む必要があるテーマやプラグインは、WP_Filesystem
ファミリーのクラスを使用するべきです。
目的
異なるホスティングシステムは、ウェブサーバーの設定方法において異なる制限があります。
特に、多くのホスティングシステムでは、ウェブサーバーがWordPressファイルの所有者とは異なるユーザーとして実行されています。この場合、ウェブサーバーユーザーからファイルを書き込むプロセスは、実際のユーザーアカウントではなく、ウェブサーバーのユーザーアカウントが所有する結果のファイルを生成します。これは、複数のユーザーが異なるサイトのために同じウェブサーバーを共有している共有ホスティングの状況で、セキュリティ上の問題を引き起こす可能性があります。
そのような場合、これを実装するプラグインまたはテーマは、ユーザーからFTP資格情報を要求する必要があります。この操作を簡単に行うための関数が追加され、資格情報入力フォームの外観と感触を標準化します。
<a name="filesystem-api-class-reference"></a>
## Filesystem API クラスリファレンス
- クラス: [WP_Filesystem_Base](https://developer.wordpress.org/reference/classes/wp_filesystem_base/)
- クラス: [WP_Filesystem_Direct](https://developer.wordpress.org/reference/classes/wp_filesystem_direct/)
- クラス: [WP_Filesystem_FTPext](https://developer.wordpress.org/reference/classes/wp_filesystem_ftpext/)
- クラス: [WP_Filesystem_ftpsocket](https://developer.wordpress.org/reference/classes/wp_filesystem_ftpsockets/)
- クラス: [WP_Filesystem_SSH2](https://developer.wordpress.org/reference/classes/wp_filesystem_ssh2/)
- 関数: [request_filesystem_credentials()](https://developer.wordpress.org/reference/functions/request_filesystem_credentials/)
<a name="getting-credentials"></a>
## 資格情報の取得
WP_Filesystemを使用する最初のステップは、ユーザーから資格情報を要求することです。通常、これはフォーム入力の結果を保存する際、またはファイルに書き込む必要があることを判断したときに行われます。
資格情報フォームは、次のコードを使用して管理ページに表示できます:
``````bash
$url = wp_nonce_url( 'themes.php?page=example', 'example-theme-options' );
if ( false === ( $creds = request_filesystem_credentials( $url, '', false, false, null ) ) ) {
return; // stop processing here
}
`
request_filesystem_credentials()呼び出しは、5つの引数を取ります。
- フォームが送信されるURL(上記の例ではテーマページへの非公開URLが使用されました)
- メソッドのオーバーライド(通常は空の文字列: “”のままにします)
- エラーフラグ(通常はfalse、エラーが検出された場合は下記参照)
- コンテキストディレクトリ(false、またはアクセスをテストしたい特定のディレクトリパス)
- フォームフィールド(以前のフォームから「パススルー」したいフォームフィールド名の配列、またはない場合はnull)
`````request_filesystem_credentials`````呼び出しは、ホスト名やユーザー名、パスワードなどのハードコーディングされた情報も考慮します。これらが定義を使用して`````wp-config.php`````ファイルに挿入されている場合、この呼び出しはフォームを表示する代わりにその情報を返します。
ユーザーから資格情報が必要な場合、FTP情報フォームを出力し、falseを返します。この場合、ユーザーが資格情報を入力できるように、処理を停止する必要があります。指定したフォームフィールド名は、結果のフォームに隠し入力として含まれ、ユーザーが再度フォームを送信する際に、今度はFTP資格情報と共に返されます。
注意: `````hostname`````、`````username`````、`````password`````、`````public_key`````、または`````private_key`````の予約名を自分の入力に使用しないでください。これらは資格情報フォーム自体によって使用されます。代わりに、これらを使用する場合、`````request_filesystem_credentials`````関数はそれらが受信したFTP資格情報であると仮定します。
資格情報フォームが送信されると、受信したPOSTデータ内でこれらのフィールドを探し、見つかった場合は、WP_Filesystemに渡すのに適した配列で返します。これが次のステップです。
<a name="initializing-wp_filesystem_base"></a>
## WP_Filesystem_Baseの初期化
WP_Filesystemを使用する前に、適切な資格情報で初期化する必要があります。これは次のように行うことができます:
``````bash
if ( ! WP_Filesystem( $creds ) ) {
request_filesystem_credentials( $url, '', true, false, null );
return;
}
`
最初にWP_Filesystem
関数を呼び出し、前述の資格情報を渡します。その後、資格情報を検証しようとします。資格情報が正しければ、trueを返します。そうでなければ、falseを返します。
資格情報が不正な場合、上記のコードはrequest_filesystem_credentials()
にもう一度呼び出しますが、今回はエラーフラグをtrueに設定します。これにより、関数は再度フォームを表示し、ユーザーに情報が不正であるというエラーメッセージを表示します。ユーザーはその後、情報を再入力して再試行できます。
WP_Filesystem_Baseクラスの使用
クラスが初期化されると、グローバル$wp_filesystem
変数が定義され、使用可能になります。WP_Filesystem_Base
クラスは、ローカルファイルを読み書きするために使用できるいくつかのメソッドを定義しています。たとえば、ファイルを書き込むには、次のようにできます:
global $wp_filesystem;
$wp_filesystem->put_contents(
'/tmp/example.txt',
'Example contents of a file',
FS_CHMOD_FILE // predefined mode settings for WP files
);
他に利用可能なメソッドには、ファイルを読み取るためのget_contents()
とget_contents_array()
、それらのディレクトリへのファイルシステムパスを返すwp_content_dir()
、wp_plugins_dir()
、wp_themes_dir()
、ディレクトリを作成および削除するためのmkdir()
、rmdir()
、およびその他の便利なファイルシステム関連の関数が含まれます。
ヒントとコツ
request_filesystem_credentials()
をいつ呼び出せますか?
WP Filesystem APIを使用する開発者にとっての最初の課題の1つは、どこでも初期化できないことです。request_filesystem_credentials()
関数はwp_loaded
アクションフックの後でのみ利用可能で、管理エリアにのみ含まれています。利用できる最も早いフックの1つはadmin_initです。
WP Filesystem APIの方法論
より良い解決策は、ユーザーにプラグインがインストールを完了するためにファイルシステムに書き込む必要があることを説明する通知を追加することです(たとえばadmin_noticeを使用)。その通知に加えて、`````request_filesystem_credentials()`````への関数呼び出しをトリガーするボタンまたはリンクを追加します。
しかし、このシナリオをさらに拡張し、このプラグインがプラグインが更新されるたびにファイルシステムにアクセスする必要があるとしましょう。定期的に更新やバグ修正をリリースしている場合、ユーザーがアップグレードするたびにアクションボタンをクリックするのは次第に厄介になります。`````request_filesystem_credentials()`````を呼び出す前に直接書き込みアクセスがあるかどうかを判断し、静かにインストールを行うことができれば素晴らしいでしょう。これが`````get_filesystem_method()`````関数の出番です。
``````bash
$access_type = get_filesystem_method();
if ( $access_type === 'direct' )
{
/* you can safely run request_filesystem_credentials() without any issues and don't need to worry about passing in a URL */
$creds = request_filesystem_credentials( site_url() . '/wp-admin/', '', false, false, array() );
/* initialize the API */
if ( ! WP_Filesystem( $creds ) ) {
/* any problems and we exit */
return false;
}
global $wp_filesystem;
/* do our file manipulations below */
}
else
{
/* don't have direct write access. Prompt user with our notice */
add_action( 'admin_notices', 'you_admin_notice_function' );
}
`
このアプローチは、すべての関係者にとってうまく機能します。直接書き込み権限を持たないユーザーは、ファイルシステムに変更を加えるように促され、プラグインはファイルシステムに直接書き込むことができるサイトでは目立たない(良い意味で)ままです。
パスの取り扱い
WordPress開発者は、プラグインのパスにアクセスするための定数や変数を設定することに慣れているべきです。通常、次のようになります:
define( 'MY_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
Filesystem APIを使用する際に考慮すべきことは、ファイルへのパスが常に同じではないということです。直接メソッドを使用する場合、MY_PLUGIN_DIR
定数を安全に使用できますが、FTPまたはSSHメソッドを使用する場合に同じことを試みると問題が発生する可能性があります。これは、FTPとSSHが通常、絶対パスのどこかにルートされているためです。現在、Filesystem APIは$wp_filesystem->wp_content_dir()
や$wp_filesystem->wp_plugins_dir()
のようなメソッドを使用してこの問題を克服する方法を提供しますが、プラグインへのパスを2回定義するのは実用的ではありません。
/* replace the 'direct' absolute path with the Filesystem API path */
$plugin_path = str_replace( ABSPATH, $wp_filesystem->abspath(), MY_PLUGIN_DIR );
/* Now we can use $plugin_path in all our Filesystem API method calls */
if ( ! $wp_filesystem->is_dir( $plugin_path . '/config/' ) ) {
/* directory didn't exist, so let's create it */
$wp_filesystem->mkdir( $plugin_path . '/config/' );
}
unzip_file($file, $to);
この関数はFilesystem APIが初期化されることを必要としますが、$wp_filesystem
オブジェクトのメソッドではないため、その引数が互いに矛盾している可能性があります。最初のパラメータ$file
は、ファイルへの絶対的な「直接」パスである必要があり、$toparameter
はFilesystemの絶対パスを指す必要があります。
define( 'MY_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
global $wp_filesystem; // already initialised the Filesystem API previously
$plugin_path = str_replace( ABSPATH, $wp_filesystem->abspath(), MY_PLUGIN_DIR ); // get remote system absolute path
/* Acceptable way to use the function */
$file = MY_PLUGIN_DIR . '/plugin-file.zip';
$to = $plugin_path;
$result = unzip_file( $file, $to );
if ( $result !== true ) {
// unzip failed. Handle Error
}
/* Not acceptable */
$file = MY_PLUGIN_DIR . '/plugin-file.zip';
$to = MY_PLUGIN_DIR; // $to cannot be the 'direct' absolute path to the folder otherwise FTP and SSH methods are left in the cold
unzip_file( $file, $to );
$file = $plugin_path . '/plugin-file.zip'; // If $file isn't the 'direct' absolute path then users not using FTP and SSH methods are left in the cold
$to = $plugin_path;
unzip_file( $file, $to );