cmpayments / crate-lib
一个简化PHAR构建过程的库。
Requires
- php: >=5.3.3
- ext-phar: *
- phine/path: ~1.0
- tedivm/jshrink: ~1.0
Requires (Dev)
- herrera-io/annotations: ~1.0
- herrera-io/phpunit-test-case: 1.*
- mikey179/vfsstream: 1.1.0
- phpseclib/phpseclib: ~0.3
- phpunit/phpunit: 3.7.*
Suggests
- herrera-io/annotations: For compacting annotated docblocks.
- phpseclib/phpseclib: For verifying OpenSSL signed phars without the phar extension.
This package is auto-updated.
Last update: 2024-08-27 19:00:35 UTC
README
Crate 是一个从 Box 项目 分支出来的库,并且基于 Phar
类构建。它旨在简化创建新PHAR和修改现有PHAR的过程。功能包括压缩源文件、更好的自定义存根生成和更好的OpenSSL签名处理。
示例
use CmPayments\Crate\Crate; use CmPayments\Crate\StubGenerator; $crate = Crate::create('test.phar'); $crate->buildFromDirectory('/path/to/dir'); $crate->getPhar()->setStub( StubGenerator::create() ->index('path/to/script.php') ->generate() );
安装
将其添加到您的Composer依赖列表中
$ composer require cmpayments/crate=1.*
用法
Crate 库包含许多功能,其中一些功能设计为可以独立使用。这是为了使PHAR构建器更好地控制PHAR构建过程。
压缩源文件
Crate 使用源文件 "压缩器"。压缩器是一个简单的类,它会检查给定的文件是否受支持,然后操作其内容以使其更小。我将在 最后,构建PHAR 中介绍如何实际使用它们。
创建压缩器类有两种方式:实现 CompactorInterface
接口,或扩展 Compactor
抽象类。
实现 CompactorInterface
CompactorInterface
接口只要求你在你的类中实现两个方法: compact($contents)
和 support($file)
。 $contents
参数是源文件的内容,而 $file
参数是文件的完整路径。如何确定哪些文件类型受支持完全取决于你自己。
在这个例子中,这个自定义压缩器将只修改以 .php
结尾的文件,并从每一行的末尾删除空白字符
namespace Example\Compactor; use CmPayments\Crate\Compactor\CompactorInterface; /** * My example compactor. */ class RemoveWhitespace implements CompactorInterface { /** * Seek and destroy (whitespaces). * * @param string $source The source code. * * @return string The compacted source code. */ public function compact($source) { return preg_replace('/[ \t]+$/m', '', $source); } /** * Make sure we support it. * * @param string $file The file path. * * @return boolean Returns TRUE if supported, FALSE if not. */ public function supports($file) { return ('php' === pathinfo($file, PATHINFO_EXTENSION)); } }
扩展 Compactor
包含了一个抽象压缩器类,它可以为你处理文件类型检查。你只需要提供默认支持的文件扩展名列表。如果需要,开发者可以通过调用 Compactor->setExtensions()
方法覆盖这些扩展名。
这个例子是前面例子压缩器的一个变体
namespace Example\Compactor; use CmPayments\Crate\Compactor\Compactor; /** * My example compactor. */ class RemoveWhitespace extends Compactor { /** * The default supported file extensions. * * @var array */ protected $extensions = array('php'); /** * Seek and destroy (whitespaces). * * @param string $source The source code. * * @return string The compacted source code. */ public function compact($source) { return preg_replace('/[ \t]+$/m', '', $source); } }
开发者可以通过调用 Compactor->setExtensions()
方法来更改支持的文件扩展名
$example = new Example\Compactor\RemoveWhitespace(); $example->setExtensions( array( 'inc', 'php' ) );
捆绑压缩器
该库捆绑了两个压缩器,方便您使用。
压缩JavaScript
JavaScript
压缩器会压缩JavaScript文件,但需要 tedivm/jshrink
包才能工作。当你安装Crate库时,它会包含在内。
use CmPayments\Crate\Compactor\Javascript; $compactor = new Javascript();
压缩JSON
JSON
压缩器非常简单易用,因为它没有配置选项。然而,需要 json
扩展才能使用它。从所有 .json
文件中删除所有额外空白。
use CmPayments\Crate\Compactor\Json; $compactor = new Json();
压缩PHP
PHP
压缩器将从 .php
文件中删除所有注释空白。删除的注释将使用与原始注释相同数量的换行符删除。这是为了在PHAR中发生错误时保留报告的行号。
use CmPayments\Crate\Compactor\Php; $compactor = new Php();
如果您使用Doctrine格式的注释,您还可以在Php
压缩器中使用一个特殊功能。为了压缩注释并保留注释,您需要安装herrera-io/annotations
库,并创建一个Tokenizer
实例。
use Herrera\Annotations\Tokenizer; $compactor->setTokenizer(new Tokenizer());
行数和注释数据都得到了保留。
管理签名
Phar
类提供了一个简单的方法来提取和验证phar的签名。简单实例化该类即可验证指定的phar。然而,执行这些任务需要phar
扩展。Crate库包含了一种方法,可以在不使用扩展的情况下提取和验证签名。
use CmPayments\Crate\Exception\SignatureException; use CmPayments\Crate\Signature; $sig = new Signature('/path/to/my.phar'); // same output as Phar->getSignature() $signature = $sig->get(); try { // TRUE if passed, FALSE if failed $result = $sig->verify(); } catch (SignatureException $exception) { // the signature could not be verified }
Signature::create()
方法是对Signature::__construct()
的别名,允许您使用上面示例的简写版本。
if (Signature::create('/path/to/my.phar')->verify()) { // do the do }
在没有扩展的情况下能够验证phar的目的是更加谨慎的。在没有扩展的敏感环境中,开发人员或系统管理员在将phar发布到系统之前,可能想要验证他们所使用的phar的完整性。
提取Phars
除了能够在不使用扩展的情况下验证phar的签名外,您还可以提取其内容。此功能主要设计为作为自定义存根的一部分嵌入,但它也可以用于提取任何phar。
use CmPayments\Crate\Extract; $extract = new Extract('/path/to/my.phar', 65538); $extract->go('/path/to/extract/dir');
构造函数的第一个参数是现有phar的路径。第二个参数是存根的长度。这个参数是必须的,因为Extract
类需要知道phar的清单从哪里开始。通常,这个值是由使用默认存根时Phar
类生成的。
如果这个值未知,可以使用Extract::findStubLength()
方法来尝试最佳猜测。如果存根长度猜测错误,Extract
类将在提取过程中某个时刻抛出异常。
默认情况下,Extract->go()
方法将创建一个临时目录路径,并将phar的内容提取到那里。示例中指定的目录路径是可选的。
为了减少开销,如果目标目录中存在特殊文件,Extract
类将不会重新提取phar。这是为了加快没有使用phar扩展执行的phar的执行速度。
请注意,如果phar中的任何文件使用了gzip或bzip2进行压缩,将需要相应的扩展来解压缩。如果未安装所需的扩展,则Extract
类将抛出异常。
生成存根
如果项目需要,Crate库可以生成自定义存根。您将能够控制存根中的以下功能
- 设置别名。
- 设置“标语”注释(例如版权声明)。
- 嵌入
Extract
类以支持自提取。 - 设置CLI索引脚本。
- 启用使用
Phar::interceptFileFuncs()
。 - 设置文件MIME类型。
- 设置要“mung”的服务器变量列表。
- 设置404脚本。
- 设置“shebang”行。
- 选择使用
Phar::webPhar()
而不是Phar::mapPhar()
。
以下是使用所有设置生成的存根示例
use CmPayments\Crate\StubGenerator; $generator = new StubGenerator(); $banner = <<<BANNER Copyright (c) 2013 Some Dude Some license text here. BANNER; $mimetypes = array( 'phps' => Phar::PHP ); $rewrite = <<<REWRITE function rewrite_url(\$uri) { return \$rewritten; } REWRITE; $stub = $generator ->alias('test.phar') ->banner($banner) ->extract(true) ->index('bin/cli.php') ->intercept(true) ->mimetypes($mimetypes) ->mung(array('REQUEST_URI')) ->notFound('lib/404.php') ->rewrite($rewrite) ->shebang('/home/dude/.local/php/bin/php') ->web(true) ->generate();
以及生成的存根
<?php /** * Copyright (c) 2013 Some Dude * * Some license text here. */ define('CRATE_EXTRACT_PATTERN_DEFAULT', '__HALT' . '_COMPILER(); ?>'); define('CRATE_EXTRACT_PATTERN_OPEN', "__HALT" . "_COMPILER(); ?>\r\n"); if (class_exists('Phar')) { Phar::webPhar('test.phar', 'bin/cli.php', 'lib/404.php', array ( 'phps' => 0, ), 'function rewrite_url($uri) { return $rewritten; }'); Phar::interceptFileFuncs(); Phar::mungServer(array ( 0 => 'REQUEST_URI', )); } else { $extract = new Extract(__FILE__, Extract::findStubLength(__FILE__)); $dir = $extract->go(); set_include_path($dir . PATH_SEPARATOR . get_include_path()); require "$dir/bin/cli.php"; } // ... snip ... __HALT_COMPILER();
为了简洁起见,嵌入的
Extract
类被替换为“...省略...”。
示例存根可能比您需要的更复杂。通过不使用extract()
方法,您可以轻松地从存根中删除几百行代码,减小其大小,但您将失去在没有phar
扩展的环境中执行phar的能力。
最后,构建Phars
所有这些功能都非常出色,但将它们在Crate
类中一起使用时则更加出色。Crate
类旨在通过一个(希望)简单易用的接口自动集成所有这些功能。
有两种方式可以实例化这个类
use CmPayments\Crate\Crate; // use an existing Phar instance $crate = new Crate($phar); // or create one $crate = Crate::create('/path/to/my.phar');
请注意,
Crate::create()
方法接受与Phar::__construct()
方法相同的参数。
注册压缩器
无论您使用的是捆绑的压缩器还是您自己的压缩器,您都需要调用Crate->addCompactor()
方法来将您的类注册到Crate
中。使用Crate
添加到phar的所有文件都将自动通过支持的压缩器进行处理。
use CmPayments\Crate\Compactor\Json; use CmPayments\Crate\Compactor\Php; $crate->addCompactor(new Json()); $crate->addCompactor(new Php()); $crate->addCompactor($custom);
使用占位符值
Crate
类提供了在添加的文件中搜索和替换占位符值的功能。请注意,任何替换都只支持标量值。
$crate->setValues( array( 'match' => 'replace' ) );
使用上述值进行匹配,以下代码
$myCode = 'This @match@ is now "replace".';
将被添加到phar中
$myCode = 'This replace is now "replace".';
添加文件
要实际使用注册的压缩器和设置占位符值替换,您需要使用Crate
类的方法来添加文件。这些方法与Phar
类的方法相同,但会自动应用适当的压缩器和替换。
Crate->addFile()
Crate->addFromString()
Crate->buildFromDirectory()
Crate->buildFromIterator()
请注意,如果您需要添加一个没有任何更改的文件(例如二进制文件),您可能需要直接使用Phar
实例添加该文件。
$phar = $crate->getPhar(); $phar->addFile('...');
设置Stub
Crate
类提供了一个简单的方法来添加来自文件的stub,并同时应用占位符替换。
$crate->setStubUsingFile('/path/to/stub.php', true);
第二个参数表示应在stub上执行替换。如果您省略了它,则默认为false
,这意味着不会执行任何替换,并且将直接使用stub。
私钥签名
Crate
类提供了两种简单的方法来使用私钥对phar进行签名。然而,任何一种方法都需要openssl
扩展可用。
使用字符串
如果您已经将私钥作为字符串变量加载,您可以使用Crate->sign()
方法。
$crate->sign($key, $pass);
如果密钥是带密码生成的,则需要密码。
使用文件
您还可以使用包含在文件中的私钥对phar进行签名。
$crate->signUsingFile($file, $pass);