概述

文件系统API,添加 WordPress 2.6,最初是为WordPress自己的自动更新功能而创建的。

文件系统API将读取和写入本地文件到要在各种主机类型上安全完成的文件系统所需的功能。

它通过 wp_filesystem_base 类和几个子类,这些子类实现与本地文件系统连接的不同方式,具体取决于单个主机支持。

任何需要在本地编写文件的主题或插件都应使用WP_Filesystem班级家庭。

目的

不同的托管系统在配置其网络服务器的方式方面具有不同的限制。

特别是,许多托管系统具有与WordPress文件所有者不同的用户网络服务器。在这种情况下,从Web服务器用户编写文件的过程将具有Web服务器用户帐户而不是实际用户帐户所产生的文件。这可能会导致共享托管情况的安全问题,其中多个用户正在为不同站点共享同一Web服务器。

WP_Filesystem能够检测书面文件的用户何时无法匹配,并使用FTP或类似方法切换到方法。根据可用的PHP库,wp_filesystem 支持使用FTP的三种不同方法(通过扩展,套接字或SSH),并将自动选择正确的方法。

在这种情况下,实现此代码的插件或主题需要向用户请求FTP凭据。已经添加了功能,以使其易于执行,并标准化凭证条目的外观和感觉。

文件系统API类参考

获得证书

使用WP_FILESYSTEM的第一步是向用户请求凭据。实现这一目标的正常方式是在保存表单输入的结果时,或者您已经确定需要写入文件。

凭据表格可以通过使用以下代码显示在管理页面上:

$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() 呼叫需要五个论点。

  • 应提交表单的URL(在上面的示例中使用了主题页的非压力URL)
  • 一种方法覆盖(通常您应该将其作为空字符串:“”)
  • 错误标志(通常是错误的,除非检测到错误,请参见下文)
  • 上下文目录(false或您要测试的访问的特定目录路径)
  • 表单字段(您希望“通过”产生的凭据表单中的表单字段名称数组

request_filesystem_credentials呼叫将测试以查看它是否能够直接写入本地文件系统,而无需首先凭据。如果是这种情况,那么它将返回真实而不做任何事情。然后,您的代码可以继续使用WP_Filesystem班级。

request_filesystem_credentials呼叫还考虑了硬编码信息,例如主机名或用户名或密码,已插入wp-config.php使用定义的文件。如果这些文件是在该文件中预定的,则此调用将返回该信息,而不是显示表单,绕过用户的表单。

如果确实需要用户的凭据,则将输出FTP信息表格并返回false。在这种情况下,您应该停止进一步处理,以允许用户输入凭据。您指定的任何表单字段名称都将包含在结果表单中为隐藏输入,并且当用户重新提交表单时,这次将返回使用FTP凭据。

注意:请勿使用保留的名称hostnameusernamepasswordpublic_key,或者private_key对于您自己的输入。这些由凭证形式本身使用。或者,如果您使用它们,request_filesystem_credentials功能将假定它们是传入的FTP凭据。

当提交凭据表格时,它将查看这些字段的传入帖子数据,如果找到,它将以适合传递给WP_Filesystem的数组返回,这是下一步。

初始化wp_filesystem_base

在使用WP_FILESYSTEM之前,必须使用适当的凭据初始化它。可以这样做:

if ( ! WP_Filesystem( $creds ) ) {
	request_filesystem_credentials( $url, '', true, false, null );
	return;
}

首先您打电话给WP_Filesystem功能,从之前传递凭证。然后,它将尝试验证凭据。如果它们很好,那么它将返回真实。如果不是,则它将返回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的开发人员来说,最初的挑战之一是您无法在任何地方初始化它。这request_filesystem_credentials()直到之后才能使用功能wp_loaded动作钩,仅包含在管理区域中。您可以使用的最早钩子之一是Admin_Init。

WP文件系统API方法论
打电话的另一个问题request_filesystem_credentials()您无法直接确定您是否可以直接访问文件系统,或者是否将提示用户获得凭据。从UX的角度来看,如果您要在激活插件时对文件进行更改,这将变得有问题。试想一下,用户可以通过其管理区域安装插件,输入FTP详细信息,完成安装并激活您的插件。但是,一旦他们这样做,他们就会再次提示他们再次输入FTP细节,并抓住他们的原因。

一个更好的解决方案是添加通知(例如,使用admin_notice)向用户解释您的插件需要写入文件系统以完成安装。除此通知外,您还将添加一个按钮或链接,该按钮将您的功能调用触发到request_filesystem_credentials()

但是,让我们进一步扩展这种情况,并说该插件每次更新插件时都需要访问文件系统。如果您定期发布更新和错误修复,那么每次升级时,用户很快就可以单击可操作的按钮。很好的是确定我们是否有直接的写入访问request_filesystem_credentials()并默默地进行安装。那就是get_filesystem_method()功能发挥作用。

$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__ ) ); 

使用文件系统API时需要考虑的是文件的途径并不总是相同的。使用直接方法时,您可以安全地使用MY_PLUGIN_DIR恒定,但是如果您使用FTP或SSH方法时尝试执行相同的操作,那么您可能会遇到问题。这是因为FTP和SSH通常扎根于沿绝对路径的某个地方的目录。现在,文件系统API为我们提供了通过诸如此类的方法克服这个问题的方法$wp_filesystem->wp_content_dir()$wp_filesystem->wp_plugins_dir(),但两次定义插件的路径是不切实际的。

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

虽然此功能需要初始化文件系统API,但它不是$wp_filesystem对象,这可能就是为什么其参数相互矛盾的原因。第一个参数,$file,必须是文件的绝对“直接”路径,而$toparameter需要指向文件系统的绝对路径。

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 );

外部参考

By zhuon

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注