Composer 跳过脚本中的提示
Composer skips prompt in scripts
我正在使用 composer 和 phing 来初始化我制作的样板文件。
基本上我正在使用这个 post-create-project 挂钩来调用我的 phing 构建文件。
"scripts": {
"post-create-project-cmd": "bin/phing -f boilerplate.xml"
}
我的 phing 文件看起来像这样:
<?xml version="1.0"?>
<project name="boilerplate" default="build">
<target name="build">
<propertyprompt propertyname="APP_NAME" promptcharacter=":" defaultValue="Example">Enter a name for the app</propertyprompt>
<propertyprompt propertyname="APP_NS" promptcharacter=":" defaultValue="Example">Enter a desired namespace for the app</propertyprompt>
<php expression="strtolower('${APP_NAME}');" returnProperty="APP_KEY" />
<php expression="str_replace(' ', '_', '${APP_KEY}');" returnProperty="APP_KEY" />
<php expression="preg_replace('/[^a-z0-9_-]/i', '', '${APP_KEY}');" returnProperty="APP_KEY" />
<php expression="preg_replace('/[_-]/', '', '${APP_KEY}');" returnProperty="APP_KEY_PHING" />
<php expression="str_replace(' ', '', '${APP_NS}');" returnProperty="APP_NS" />
<echo msg="Your chosen app name is '${APP_NAME}'" />
<echo msg="Your generated namespace is '${APP_NS}'" />
<echo msg="Your generated app key is '${APP_KEY}'" />
<echo msg="Your generated phing key is '${APP_KEY_PHING}'" />
<copy file="composer.json.tpl" tofile="composer.json"
overwrite="true">
<filterchain>
<replacetokens begintoken="%%" endtoken="%%">
<token key="APP_NAME" value="${APP_NAME}"/>
<token key="APP_KEY" value="${APP_KEY}"/>
<token key="APP_NS" value="${APP_NS}"/>
</replacetokens>
</filterchain>
</copy>
<delete>
<fileset dir=".">
<include name="composer.json.tpl" />
</fileset>
</delete>
<reflexive>
<fileset dir=".">
<include pattern="*.*" />
<include pattern="build/**/*" />
<include pattern="app/**/*" />
</fileset>
<filterchain>
<replacetokens begintoken="%%" endtoken="%%">
<token key="APP_NAME" value="${APP_NAME}"/>
<token key="APP_KEY" value="${APP_KEY}"/>
<token key="APP_KEY_PHING" value="${APP_KEY_PHING}"/>
<token key="APP_NS" value="${APP_NS}"/>
</replacetokens>
</filterchain>
</reflexive>
<echo msg="Project successfully prepared." />
</target>
</project>
当我执行我的 phing 文件时,一切正常。
当我通过作曲家执行它时,它会跳过属性提示并使用默认值。
如何禁止这种行为?
经过一些逆向工程,我发现了为什么会这样。
Composer 在内部使用 Symfony Process class 在您使用脚本的命令行时生成一个进程。这个 Process 组件获取输入和输出流,以某种方式将其重定向到 composer。但是,这不允许用户输入并跳过它们。
我解决这个问题的方法是围绕 Phing 编写一个包装器,以便将其用于作曲家。
您可以根据需要使用它,但它确实很基础,而且可以更加灵活。
<?php
use Composer\Script\Event;
class BoilerplateInstaller {
public static function install(Event $event) {
$phingPath = __DIR__ . "/vendor/phing/phing/classes";
set_include_path(
$phingPath .
PATH_SEPARATOR .
get_include_path()
);
require_once($phingPath.'/phing/Phing.php');
Phing::startup();
$args = array(
'-f',
'boilerplate.xml',
);
Phing::fire($args);
Phing::shutdown();
}
}
这是我的composer.json
改变的部分
"scripts": {
"post-create-project-cmd": "BoilerplateInstaller::install"
},
"autoload": {
"psr-0": {
"": "./"
}
}
我正在使用 composer 和 phing 来初始化我制作的样板文件。 基本上我正在使用这个 post-create-project 挂钩来调用我的 phing 构建文件。
"scripts": {
"post-create-project-cmd": "bin/phing -f boilerplate.xml"
}
我的 phing 文件看起来像这样:
<?xml version="1.0"?>
<project name="boilerplate" default="build">
<target name="build">
<propertyprompt propertyname="APP_NAME" promptcharacter=":" defaultValue="Example">Enter a name for the app</propertyprompt>
<propertyprompt propertyname="APP_NS" promptcharacter=":" defaultValue="Example">Enter a desired namespace for the app</propertyprompt>
<php expression="strtolower('${APP_NAME}');" returnProperty="APP_KEY" />
<php expression="str_replace(' ', '_', '${APP_KEY}');" returnProperty="APP_KEY" />
<php expression="preg_replace('/[^a-z0-9_-]/i', '', '${APP_KEY}');" returnProperty="APP_KEY" />
<php expression="preg_replace('/[_-]/', '', '${APP_KEY}');" returnProperty="APP_KEY_PHING" />
<php expression="str_replace(' ', '', '${APP_NS}');" returnProperty="APP_NS" />
<echo msg="Your chosen app name is '${APP_NAME}'" />
<echo msg="Your generated namespace is '${APP_NS}'" />
<echo msg="Your generated app key is '${APP_KEY}'" />
<echo msg="Your generated phing key is '${APP_KEY_PHING}'" />
<copy file="composer.json.tpl" tofile="composer.json"
overwrite="true">
<filterchain>
<replacetokens begintoken="%%" endtoken="%%">
<token key="APP_NAME" value="${APP_NAME}"/>
<token key="APP_KEY" value="${APP_KEY}"/>
<token key="APP_NS" value="${APP_NS}"/>
</replacetokens>
</filterchain>
</copy>
<delete>
<fileset dir=".">
<include name="composer.json.tpl" />
</fileset>
</delete>
<reflexive>
<fileset dir=".">
<include pattern="*.*" />
<include pattern="build/**/*" />
<include pattern="app/**/*" />
</fileset>
<filterchain>
<replacetokens begintoken="%%" endtoken="%%">
<token key="APP_NAME" value="${APP_NAME}"/>
<token key="APP_KEY" value="${APP_KEY}"/>
<token key="APP_KEY_PHING" value="${APP_KEY_PHING}"/>
<token key="APP_NS" value="${APP_NS}"/>
</replacetokens>
</filterchain>
</reflexive>
<echo msg="Project successfully prepared." />
</target>
</project>
当我执行我的 phing 文件时,一切正常。 当我通过作曲家执行它时,它会跳过属性提示并使用默认值。
如何禁止这种行为?
经过一些逆向工程,我发现了为什么会这样。 Composer 在内部使用 Symfony Process class 在您使用脚本的命令行时生成一个进程。这个 Process 组件获取输入和输出流,以某种方式将其重定向到 composer。但是,这不允许用户输入并跳过它们。
我解决这个问题的方法是围绕 Phing 编写一个包装器,以便将其用于作曲家。 您可以根据需要使用它,但它确实很基础,而且可以更加灵活。
<?php
use Composer\Script\Event;
class BoilerplateInstaller {
public static function install(Event $event) {
$phingPath = __DIR__ . "/vendor/phing/phing/classes";
set_include_path(
$phingPath .
PATH_SEPARATOR .
get_include_path()
);
require_once($phingPath.'/phing/Phing.php');
Phing::startup();
$args = array(
'-f',
'boilerplate.xml',
);
Phing::fire($args);
Phing::shutdown();
}
}
这是我的composer.json
改变的部分"scripts": {
"post-create-project-cmd": "BoilerplateInstaller::install"
},
"autoload": {
"psr-0": {
"": "./"
}
}