public function build() { $this->log('[' . $this->step . '/' . $this->step . '] Creating phar <info>' . $this->getTarget() . '</info>'); $time = microtime(true); $pathVendor = $this->getPathVendor(); if (!is_dir($pathVendor)) { throw new RuntimeException('Directory "' . $pathVendor . '" not properly installed, did you run "composer install"?'); } $target = $this->getTarget(); if (file_exists($target)) { $this->log(' - Remove existing file <info>' . $target . '</info> (' . $this->getSize($target) . ')'); if (unlink($target) === false) { throw new UnexpectedValueException('Unable to remove existing phar archive "' . $target . '"'); } } $targetPhar = TargetPhar::create($target, $this); $this->log(' - Adding main package'); $targetPhar->addBundle(Bundle::from($this->getPackageRoot(), $this->logger)); $this->log(' - Adding composer base files'); // explicitly add composer autoloader $targetPhar->addFile($pathVendor . 'autoload.php'); // TODO: check for vendor/bin ! // only add composer base directory (no sub-directories!) $targetPhar->buildFromIterator(new \GlobIterator($pathVendor . 'composer/*.*', \FilesystemIterator::KEY_AS_FILENAME)); foreach ($this->getPackagesDependencies() as $package) { $this->log(' - Adding dependency "' . $package->getName() . '" from "' . $this->getPathLocalToBase($package->getDirectory()) . '"'); $targetPhar->addBundle(Bundle::from($package, $this->logger)); } $this->log(' - Setting main/stub'); $chmod = 0755; $main = $this->getMain(); if ($main === null) { $this->log(' WARNING: No main bin file defined! Resulting phar will NOT be executable'); } else { $generator = StubGenerator::create()->index($this->getPathLocalToBase($main))->extract(true)->banner("Bundled by phar-composer with the help of php-box.\n\n@link https://github.com/clue/phar-composer"); $lines = file($main, FILE_IGNORE_NEW_LINES); if (substr($lines[0], 0, 2) === '#!') { $this->log(' Using referenced shebang "' . $lines[0] . '"'); $generator->shebang($lines[0]); // remove shebang from main file and add (overwrite) unset($lines[0]); $targetPhar->addFromString($this->getPathLocalToBase($main), implode("\n", $lines)); } $targetPhar->setStub($generator->generate()); $chmod = octdec(substr(decoct(fileperms($main)), -4)); $this->log(' Using referenced chmod ' . sprintf('%04o', $chmod)); } $targetPhar->finalize(); if ($chmod !== null) { $this->log(' Applying chmod ' . sprintf('%04o', $chmod)); if (chmod($target, $chmod) === false) { throw new UnexpectedValueException('Unable to chmod target file "' . $target . '"'); } } $time = max(microtime(true) - $time, 0); $this->log(''); $this->log(' <info>OK</info> - Creating <info>' . $this->getTarget() . '</info> (' . $this->getSize($this->getTarget()) . ') completed after ' . round($time, 1) . 's'); }
/** * @override */ protected function execute(InputInterface $input, OutputInterface $output) { $this->config = $this->getConfig($input); $path = $this->config->getOutputPath(); // load bootstrap file if (null !== ($bootstrap = $this->config->getBootstrapFile())) { $this->config->loadBootstrap(); $this->putln('?', "Loading bootstrap file: {$bootstrap}"); unset($bootstrap); } // remove any previous work if (file_exists($path)) { $this->putln('?', 'Removing previously built Phar...'); unlink($path); } // set up Box if ($this->isVerbose()) { $this->putln('*', 'Building...'); } else { $output->writeln('Building...'); } $this->putln('?', "Output path: {$path}"); $this->box = Box::create($path); // set replacement values, if any if (array() !== ($values = $this->config->getProcessedReplacements())) { $this->putln('?', 'Setting replacement values...'); if ($this->isVerbose()) { foreach ($values as $key => $value) { $this->putln('+', "{$key}: {$value}"); } } $this->box->setValues($values); unset($values, $key, $value); } // register configured compactors if (array() !== ($compactors = $this->config->getCompactors())) { $this->putln('?', 'Registering compactors...'); foreach ($compactors as $compactor) { $this->putln('+', get_class($compactor)); $this->box->addCompactor($compactor); } } // alert about mapped paths if (array() !== ($map = $this->config->getMap())) { $this->putln('?', 'Mapping paths:'); foreach ($map as $item) { foreach ($item as $match => $replace) { if (empty($match)) { $match = "(all)"; } $this->putln('-', "{$match} <info>></info> {$replace}"); } } } // start adding files if (array() !== ($iterators = $this->config->getFinders())) { $this->putln('?', 'Adding Finder files...'); foreach ($iterators as $iterator) { $this->add($iterator, null); } } if (array() !== ($iterators = $this->config->getBinaryFinders())) { $this->putln('?', 'Adding binary Finder files...'); foreach ($iterators as $iterator) { $this->add($iterator, null, true); } } $this->add($this->config->getDirectoriesIterator(), 'Adding directories...'); $this->add($this->config->getBinaryDirectoriesIterator(), 'Adding binary directories...', true); $this->add($this->config->getFilesIterator(), 'Adding files...'); $this->add($this->config->getBinaryFilesIterator(), 'Adding binary files...', true); if (null !== ($main = $this->config->getMainScriptPath())) { $this->putln('?', 'Adding main file: ' . $this->config->getBasePath() . DIRECTORY_SEPARATOR . $main); $mapper = $this->config->getMapper(); $pharPath = $mapper($main); if (null !== $pharPath) { $this->putln('>', $pharPath); $main = $pharPath; } $this->box->addFromString($main, $this->config->getMainScriptContents()); } // set the appropriate stub if (true === $this->config->isStubGenerated()) { $this->putln('?', 'Generating new stub...'); $stub = StubGenerator::create()->alias($this->config->getAlias())->extract($this->config->isExtractable())->index($main)->intercept($this->config->isInterceptFileFuncs())->mimetypes($this->config->getMimetypeMapping())->mung($this->config->getMungVariables())->notFound($this->config->getNotFoundScriptPath())->web($this->config->isWebPhar()); if (null !== ($shebang = $this->config->getShebang())) { $this->putln('-', 'Using custom shebang line: ' . $shebang); $stub->shebang($shebang); } if (null !== ($banner = $this->config->getStubBanner())) { $this->putln('-', 'Using custom banner.'); $stub->banner($banner); } elseif (null !== ($banner = $this->config->getStubBannerFromFile())) { $this->putln('-', 'Using custom banner from file: ' . $this->config->getBasePath() . DIRECTORY_SEPARATOR . $this->config->getStubBannerPath()); $stub->banner($banner); } $this->box->getPhar()->setStub($stub->generate()); } elseif (null !== ($stub = $this->config->getStubPath())) { $stub = $this->config->getBasePath() . DIRECTORY_SEPARATOR . $stub; $this->putln('?', "Using stub file: {$stub}"); $this->box->setStubUsingFile($stub); } else { $this->putln('?', 'Using default stub.'); } // set metadata, if any if (null !== ($metadata = $this->config->getMetadata())) { $this->putln('?', 'Setting metadata...'); $this->box->getPhar()->setMetadata($metadata); } // compress, if algorithm set if (null !== ($algorithm = $this->config->getCompressionAlgorithm())) { $this->putln('?', 'Compressing...'); $this->box->getPhar()->compressFiles($algorithm); } $this->box->getPhar()->stopBuffering(); // sign using private key, if applicable if (file_exists($path . '.pubkey')) { unlink($path . '.pubkey'); } if (null !== ($key = $this->config->getPrivateKeyPath())) { $this->putln('?', 'Signing using a private key...'); $passphrase = $this->config->getPrivateKeyPassphrase(); if ($this->config->isPrivateKeyPrompt()) { /** @var $dialog DialogHelper */ $dialog = $this->getHelper('dialog'); $passphrase = $dialog->askHiddenResponse($output, 'Private key passphrase:'); } $this->box->signUsingFile($key, $passphrase); // set the signature algorithm if no key is used } elseif (null !== ($algorithm = $this->config->getSigningAlgorithm())) { $this->box->getPhar()->setSignatureAlgorithm($algorithm); } unset($this->box); // chmod, if configured if (null !== ($chmod = $this->config->getFileMode())) { $this->putln('?', 'Setting file permissions...'); chmod($path, $chmod); } $this->putln('*', 'Done.'); }
public function testCreate() { $this->assertInstanceOf('Herrera\\Box\\StubGenerator', StubGenerator::create()); }
private function preparePhar() { touch('bootstrap.php'); file_put_contents('box.json', json_encode(array('bootstrap' => 'bootstrap.php', 'compactors' => 'Herrera\\Box\\Compactor\\Php', 'main' => 'bin/run', 'replacements' => array('name' => 'world'), 'stub' => true))); $box = Box::create('test.phar'); $box->addCompactor(new Php()); $box->setValues(array('name' => 'world')); $box->addFromString('bin/run', <<<CODE #!/usr/bin/run php <?php require __DIR__ . '/../src/hello.php'; CODE ); $box->addFromString('src/hello.php', <<<CODE <?php /** * Just saying hello! */ echo "Hello, @name@! "; CODE ); $box->getPhar()->setStub(StubGenerator::create()->index('bin/run')->generate()); unset($box); }
/** * @depends testSign */ public function testSignUsingFile() { if (false === extension_loaded('openssl')) { $this->markTestSkipped('The "openssl" extension is not available.'); } list($key, $password) = $this->getPrivateKey(); $file = $this->createFile(); file_put_contents($file, $key); $this->box->getPhar()->addFromString('test.php', '<?php echo "Hello, world!\\n";'); $this->box->getPhar()->setStub(StubGenerator::create()->index('test.php')->generate()); $this->box->signUsingFile($file, $password); $this->assertEquals('Hello, world!', exec('php test.phar')); }
/** * Set the stub to use * * @return string */ protected function setStub() { $this->box->getPhar()->setStub(StubGenerator::create()->index('bin/rocketeer')->generate()); }