underpin / decision-list-loader
Underpin 的决策列表加载器
This package is auto-updated.
Last update: 2024-09-11 23:13:45 UTC
README
助助于向 WordPress 网站添加决策列表的加载器。
安装
使用 Composer
composer require underpin/decision-list-loader
手动
此插件使用内置的自动加载器,因此只要它在 Underpin 之前被要求,就应该按预期工作。
require_once(__DIR__ . '/underpin-decision-lists/decision-lists.php');
设置
- 安装 Underpin。请参阅 Underpin 文档
- 根据需要注册新的决策列表。
决策列表
通常,WordPress 插件仅依赖 WordPress 钩子来确定扩展逻辑。这对于简单解决方案来说是可以的,但一旦几个插件试图相互覆盖,就会变得非常麻烦。最大的问题是确定决策的实际逻辑是 分散的。由于没有单一的真实来源来规定逻辑的顺序,更不用说实际的 选择是什么,因此您没有简单的方法来理解 为什么 插件决定这样做。
决策列表旨在通过将所有扩展集中在一个注册表中来使工作更容易。当启用 WP_DEBUG
时,此注册表会导出到 Underpin 控制台,因此可以清楚地了解此网站的逻辑层次结构。
如果您正在调试实时站点,可以使用 PHP 控制台工具(如调试栏控制台)输出决策列表。
var_dump(plugin_name_replace_me()->decision_lists()->get('email'));
设置
本质上,决策列表不过是一个加载器类,可以以相同的方式处理。
假设我们想要创建一个决策列表,允许人们覆盖插件中的电子邮件地址。这需要检查电子邮件地址的选项值,并回退到硬编码的地址。它还需要可能由其他插件覆盖此值。
在传统的 WordPress 中,您可能会看到在函数末尾使用 apply_filters
来完成此操作,如下所示
function get_email_address(){ return apply_filters('plugin_name_replace_me_email_address',get_option('email_address', 'admin@webmaster.com')); }
然而,使用决策列表,这被放在一个类中,并且该类可以被扩展。如下所示
/** * Class Email To * Class Email to list * * @since 1.1.0 * @package DFS_Monitor\Factories */ class Email_To extends Decision_List { public $dedecision listion = 'Determines which email address this plugin should use.'; public $name = 'Email Address'; /** * @inheritDoc */ protected function set_default_items() { $this->add( 'option', new class extends Integration_Frequency_Decision { public $id = 'option'; public $name = 'Option Value'; public $dedecision listion = 'Uses the value of the db option, if it is set.'; public $priority = 100; public function is_valid( $params = [] ) { if(!is_email(get_option('email_address'))){ return plugin_name_replace_me()->logger()->log( 'notice', 'email_address_option_invalid', 'A decision tree did not use the option value because it is not set.' ); } else{ return true; } } /** * @inheritDoc */ public function valid_actions( $params = [] ) { return get_option('email_address'); } } ); $this->add( 'hard_coded', new class extends Integration_Frequency_Decision { public $id = 'hard_coded'; public $name = 'Hard coded email'; public $dedecision listion = 'Uses a hard-coded email address for this site.'; public $priority = 1000; public function is_valid( $params = [] ) { return true; } public function valid_actions( $params = [] ) { return 'admin@webmaster.com'; } } ); } }
请注意,我这里使用匿名类只是为了将所有内容保持在单个文件中。您绝对 不需要 使用匿名类。事实上,在大多数情况下您不应该这样做。如果您将类引用作为字符串传递,它将不会实例化类,除非它被显式调用。这节省了资源并使事物保持快速。
每个类内部的 $priority
值告诉决策树首先尝试使用哪个选项。如果它返回一个 WP_Error
,则将其移动到下一个。一旦找到返回 true
的选项,它就会从 valid_actions
方法获取值,然后继续。
像自定义记录器类一样,需要在 Service_Locator
中注册。
/** * Set up active loader classes. * * This is where you can add anything that needs "registered" to WordPress, * such as shortcodes, rest endpoints, blocks, and cron jobs. * * All supported loaders come pre-packaged with this plugin, they just need un-commented here * to begin using. * * @since 1.0.0 */ protected function _setup() { plugin_name_replace_me()->decision_lists()->add('email', '\Plugin_Name_Replace_Me\Decision_Lists\Email_To'); }
最后,我们可以在我们的 get_email_address
函数中直接使用此决策列表
function get_email_address(){ // Decide which action we should take. $decide = plugin_name_replace_me()->decision_lists()->get('email')->decide(); // Return the valid decision. if(!is_wp_error($decide) && $decide['decision'] instanceof Decision){ return $decide['decision']->valid_actions(); } // Bubble up the error, otherwise. return $decide; }
现在我们已经设置了,它可以由其他插件使用 add
方法扩展。下面的示例将强制决策列表在运行其他任何选项之前运行。
plugin_name_replace_me()->decision_lists()->get('email')->add('custom_option',new class extends \Underpin\Abstracts\Decision{ // Force this to run before all other options public $priority = 50; public $name = 'Custom Option Name'; public $dedecision listion = 'This custom name is used in an extension, and overrides the default'; public function is_valid($params = []){ // TODO: Implement is_valid() method. } public function valid_actions($params = []){ // TODO: Implement valid_actions() method. } });
示例
一个非常基本的例子可能看起来像这样。
\Underpin\underpin()->decision_lists()->add( 'example_decision_list', [ // Decision one [ 'valid_callback' => '__return_true', 'valid_actions_callback' => '__return_empty_string', 'name' => 'Test Decision', 'description' => 'A single decision', 'priority' => 500, ], // Decision two [ 'valid_callback' => '__return_true', 'valid_actions_callback' => '__return_empty_array', 'name' => 'Test Decision Two', 'description' => 'A single decision', 'priority' => 1000, ], ] );
或者,您可以直接扩展 决策列表
并直接引用扩展的类,如下所示
underpin()->decision_lists()->add('key','Namespace\To\Class');
这对于使用决策列表特别有用,因为它们往往很长且嵌套很深。
获取决策结果
当决策列表确定一个操作时,它会做三件事
- 按照优先级对所有决策进行排序,数值越小优先级越高。
- 遍历每个项目,并在第一个通过相应测试的决定处停止。
- 返回决定的
valid_actions
回调的结果。
上面的示例将返回 ''
,因为第一个通过的项目将是具有最低优先级并通过的项目。
underpin()->decision_lists()->decide('example_decision_list', [] );
第二个参数,$params
是一个数组,包含传递给 valid_callback
和 valid_actions_callback
的参数。