proximify / cli-actions
带有自定义操作和交互式提示的命令行界面 (CLI)(例如:composer app:action 参数)。
Requires
- php: >=7.1.0
- symfony/yaml: ^5.1
README
带有自定义操作和交互式提示的命令行界面 (CLI)(例如:composer app:action 参数)。
目标
标准的 composer.json
文件允许声明 CLI 脚本。然后可以从终端调用这些脚本。例如,
$ composer action-name arg1 arg2 ...
调用在 composer.json
中注册的 PHP 脚本的静态方法 action-name
。
声明自定义 Composer 脚本 的过程简单但有点重复。《CLI Actions》简化了此过程,并增加了通过 JSON 设置文件定义的丰富交互式 CLI 行为的功能。
入门
将 CLI Actions 添加到您的项目中。
$ composer require proximify/cli-actions
然后,添加您想要从 CLI 启用的脚本。
在您的项目 composer.json
中添加:
"scripts": { "ACTION-NAME-1": "Proximify\\CLIActions::auto", "ACTION-NAME-2": "Proximify\\CLIActions::auto", "...": "..." }
所有操作都可以映射到 CLI Actions 的同一 "auto" 方法。这是 CLI Actions 简化自定义脚本声明的一种方式。
下一步是定义要运行的脚本及其参数。脚本的参数也可以通过 CLI 提供,或者通过提示用户来提供。提示器会检查 CLI 中提供的参数,并只提示用户缺少的参数。
操作定义是 JSON 文件,用于定义每个参数的提示以及它们的可接受值。此外,参数可以基于选择的选项要求子参数。《CLI Actions》允许嵌套定义参数和子参数。
操作及其参数在 JSON 文件中定义。默认情况下,根级 settings/cli
文件夹中的文件被认为是文件。文件名必须与操作名匹配。每个文件定义了一个可能的 CLI 操作及其参数。
MyProject
├── settings
│ └── cli-actions
│ ├── action1.json
│ ├── action1
│ │ └── sub-action1.json
│ └── namespaceA
│ ├── action-1.json
│ └── action-2.json
├── src
│ ├── helpers.php
│ └── MyProjectCLI.php
└── composer.json
操作定义对象
class
String - 可选的完整类名。如果没有提供,则假设方法属于调用 ($this) 对象。method
String - 被选中的类中的一个回调方法,该方法将在执行操作时被调用。该方法可以是静态的或动态的。该方法接收一个包含所有用户选项和一个包含环境选项的数组method-name(array $options, array $env)
。使用 ReflectionMethod 确定如何调用给定类的该方法。如果是动态的,将通过不提供任何参数调用类的构造函数来创建该类的一个对象。askConfirm
Boolean - 是否要求用户确认执行操作。value
String - 可选的 "默认" 值,用于假设参数未给出。当定义了默认值时,如果 CLI 选项中未给出该参数,则不会提示用户输入值。- 根据在
commandKey
中声明的参数执行操作。 arguments
Object - KEY/VALUE 对,包含执行操作所需的所有参数的定义。每个参数项的键是参数的 name,值是一个收集参数信息的对象。参数的有效选项如下prompt
String - 请求参数值的消息。当 CLI 选项中未提供参数值时,该消息会反复显示给用户。即,提示器会检查 CLI 中提供的参数,并只提示用户缺少的参数。该消息指示用户输入值。index
整数 - 可选的 CLI位置 参数。它是相对于在CLI中给出的所有未命名参数的绝对位置(从0开始)。如果提供,则表示可以按名称或位置指定参数。如果没有提供,则只能按名称指定参数。displayType
字符串 - 数组 和 列表 的枚举。预设提示信息的方式。options
数组 - 字符串数组或 选项定义 数组。用户可以从提供的选项中选择值。selectByIndex
布尔值 - 是否允许用户在提示时输入选项的索引而不是其值以选择选项。
commandKey
字符串 - 在arguments
中的可选 参数名称。这是一种高级行为,用于根据用户从给定参数中选择的选项来定义动作的class
和method
。例如,动作create
可能有一个具有选项widget
和plugin
的type
参数。create使用的class和方法取决于用户是想创建widget还是plugin。在这种情况下,commandKey=type
表示类和方法定义将从由widget
或plugin
定义的子动作中读取,一旦用户选择已知。
选项定义
动作参数的选项可以定义为包含键/值对的 选项定义对象,代表从子动作名称到内联定义或在其他文件中定义的嵌套子动作的映射。
- 内联 - 包含嵌套 动作定义 的对象;
- 外部 - 布尔值 true 表示在 config/cli-actions/MAIN-ACTION/SUB-ACTION/.../SUB-ACTION 位置定义的嵌套子动作。
附加属性
除了 动作定义 属性外,选项定义还允许以下属性
label
字符串 - 在提示用户进行选择时使用的选项显示名称。
示例动作定义
{ 'class': 'Proximify\\Glot\\Builder\\BuilderCLI', 'method': 'create', 'commandKey': 'type', 'askConfirm': true, 'arguments': { 'type': { 'options': { 'host': true, 'widget': true, 'plugin': true, 'streamer': true, 'provider': true, 'dataSource': true, }, 'prompt': 'Type of component to create?', 'index': 0, }, 'name': { 'prompt': 'Name of the component?' }, 'verbose': { 'value': true }, }, }
class: Proximify\Glot\Builder\BuilderCLI method: delete commandKey: type askConfirm: true arguments: type: options: host: class: Proximify\Glot\Publisher\Publisher method: deleteHost arguments: label: Delete a host will delete the host folder in you project, delete the related remote in rclone and delete the bucket in the host. widget: label: Delete the widget. plugin: label: Delete the plugin streamer: label: Delete the streamer provider: label: Delete the provider prompt: Type of component to delete? index: 0 name: prompt: Name of the component?
{ "class": "SOME-NAMESPACE\\SOME-CLASS-NAME", "method": "SOME-METHOD-NAME", "askConfirm": true, "arguments": { "type": { "options": ["a", "b"], "prompt": "What dummy type do you want?", "index": 0 }, "name": { "prompt": "Name of the dummy type?" }, "verbose": { "value": true } } }
为您的Composer包创建CLI
假设您有一个名为Publisher的Composer包,并且您想为它创建一个CLI。要这样做,您必须创建一个扩展CLIActions的类。让我们称它为,PublisherCLI。这个类的唯一任务是定义动作定义所在的文件夹。
namespace XYZ; class PublisherCLI extends \Proximify\CLIActions { static public function getActionFolder(): string { // E.g. own settings folder, one level up from __DIR__ return dirname(__DIR__) . '/settings/cli'; } }
就是这样!
祖先类的动作文件夹是递归添加的。也就是说,如果示例PublisherCLI类扩展了另一个也具有CLI动作的类,则将考虑两个路径以搜索动作。子路径在父路径之前考虑。
在项目的 composer.json
中使用您自己的CLI类
"scripts": { "ACTION-NAME-1": "XYZ\\PublisherCLI::auto", "ACTION-NAME-2": "XYZ\\PublisherCLI::auto", "...": "..." }
通过使用您的类,您将添加自己的动作定义以及您类的祖先类的动作定义。
动作命名空间
建议在定义动作时使用命名空间。在命令行中,动作命名空间的形式为A:B,其中A是命名空间,B是动作名称。命名空间被评估为子文件夹。例如,如果命令是
$ composer app:update
CLI动作将尝试在名为 app
的父文件夹中加载名为 update.json
的设置文件。默认情况下,该路径为 settings\cli\app\update.json
。
建议使用 动作命名空间 以避免与标准Composer动作(如 update 和 install)冲突。
Composer事件对象
当CLI动作方法作为Composer 事件的结果被调用时,一个 Composer\Script\Event
对象将被提供给在 composer.json
文件中定义的 脚本回调 作为参数。
在某些情况下,动作回调需要事件对象,因此它作为名为 event
的环境属性传递给它们。事件对象可以用来获取Composer应用对象以及项目信息。
public function someActionCallback(array $options, array $env) { // Note: 'event' exits only for Composer-triggered actions $event = $env['event']; // Get the Composer app object $composer = $event->getComposer(); // Get the path to the project's vendor folder $vendorDir = $composer->getConfig()->get('vendor-dir'); // Get the "extra" property of the composer.json $extra = $composer->getPackage()->getExtra(); // Get the package being installed or updated $installedPackage = $event->getOperation()->getPackage(); // Output a message to the console $event->getIO()->write("Some message"); }
预存储的额外参数
《composer.json》文件的架构允许一个特殊的 extra 属性。
extra: Arbitrary extra data for consumption by scripts.
CLI Actions 会自动将 $env['extra'] 设置为《composer.json》中的 extra
属性。
《composer.json》中的 extra
属性可以用来设置参数的默认值或提供对于特定项目来说是常量的额外参数。
动作方法
除了通过JSON文件提供的动作定义之外,还可以通过扩展CLIActions类来直接定义自定义方法。可以在《composer.json》中通过名称声明该方法。例如,假设PublisherCLI扩展了CLIActions,可以通过以下方式将methodName
作为动作回调
"scripts": { "ACTION-NAME-1": "XYZ\\PublisherCLI::methodName" }
首先检查公共方法 methodName
是否存在,如果不存在,则评估JSON动作文件。
标准Composer事件
Composer在执行过程中会分发多个命名的事件。所有这些事件的回调都可以通过以表示事件命名的JSON动作文件来定义。
例如,为了定义在执行create-project
命令之后发生的 post-create-project-cmd 动作,只需简单地创建一个名为 post-create-project-cmd.json
的JSON文件,并在《composer.json》文件中设置该事件的脚本回调。
在《composer.json》中
"post-create-project-cmd": "Proximify\\CLIActions::auto"
在《settings/cli/post-create-project-cmd.json》中
{ "class": "XYZ\\MyClass", "method": "methodName" }
示例项目
使用 CLI Actions 的项目。
- Uniweb API:默认行为(没有自定义CLI类)。
- Foreign Packages:定义标准Composer事件的动作。
- GLOT Builder:定义CLI类。
- GLOT Publisher:定义两层自定义CLI类。
贡献
本项目欢迎贡献和建议。大多数贡献需要您同意一份贡献者许可协议(CLA),声明您有权并且实际上确实授予我们使用您的贡献的权利。有关详情,请访问我们的 贡献者许可协议。
当您提交pull请求时,我们将确定您是否需要提供CLA,并相应地装饰PR(例如,标签,注释)。只需遵循提供的说明即可。您只需在整个使用我们的CLA的repo中做一次。
本项目采用了 Proximify开源代码行为准则。有关更多信息,请参阅行为准则FAQ或联系 support@proximify.com 以提出任何额外的问题或评论。
许可
版权所有 (c) Proximify Inc。保留所有权利。
在MIT许可证下许可。
CLI Actions 由 Proximify 创建。我们邀请社区参与。