false, ]; public function __construct($path=null, array $opts=[]) { if (!$path) { $path = getcwd(); } if (!file_exists($path."/composer.json")) { throw new \RuntimeException("Could not find a composer.json in {$path}"); } $this->opts = array_merge( self::$default_options, $opts ); } private function readComposer() { print_info("Parsing composer.json..."); $json = file_get_contents("composer.json"); $composer = json_decode($json); if (!isset($composer->bin) || !is_array($composer->bin)) { print_warn("No executable defined, building a library phar..."); } elseif (count($composer->bin)>1) { print_info("More than one executable defined, using the first one as default"); print_info(" → Using executable %s", $composer->bin[0]); $this->bins = $composer->bin; } else { print_info(" → Using executable %s", $composer->bin[0]); $this->bins = $composer->bin; } if (isset($composer->extra) && isset($composer->extra->phar)) { print_info(" → Found extra phar configuration"); $this->pharOpts = (array)$composer->extra->phar; } if ($this->index) { $this->pharType = self::PHAR_TYPE_WEB; $this->output = basename($this->index,".php").".phar"; } else { if (isset($composer->bin) && is_array($composer->bin)) { $this->pharType = self::PHAR_TYPE_APP; } $this->output = "output.phar"; } print_info("Generating output %s", $this->output); $this->composer = $composer; } private function installComposer() { print_info("Installing dependencies..."); passthru("composer install --no-interaction --optimize-autoloader"); } private function buildManifest() { print_info("Creating manifest..."); $manifest = new Manifest($this->path); // Always include the vendor directory print_info(" ← vendor/"); $manifest->addDirectory("vendor"); // Include everything from the autoload if (isset($this->composer->autoload)) { foreach ((array)$this->composer->autoload as $type=>$autoloaders) { if ($type == "files") { foreach ($autoloaders as $file) { print_info(" ← %s", $file); $manifest->addFile($file); } continue; } foreach ($autoloaders as $prefix=>$path) { print_info(" ← %s", $path); $manifest->addDirectory($path); } } } if (array_key_exists('include', $this->pharOpts)) { foreach ((array)$this->pharOpts['include'] as $path) { print_info(" ← %s", $path); if (substr($path,-1,1)==DIRECTORY_SEPARATOR) { $manifest->addDirectory($path); } else { $manifest->addFile($path); } } } $this->manifest = $manifest; } private function generateBootstrap(\Phar $phar, $type, $index=null, array $bins=[]) { print_info("Generating bootstrap stub..."); if (!$index && count($bins)==0) { $indexFile = '1) { $indexFile = 'stripShebang($str); $phar->addFromString($bin, $str); } } else { if (count($bins)) { $index = array_shift($bins); } $indexFile = file_get_contents($index); $indexFile = $this->stripShebang($indexFile); $index = "bootstrap.php"; } $stub = "#!/usr/bin/env php\n".$phar->createDefaultStub($index); $phar->addFromString($index, $indexFile); $phar->setStub($stub); } private function stripShebang($str) { if (strpos($str, '#!') === 0) { if (strpos($str, '#!/usr/bin/env php') === 0) { $str = substr($str,strpos($str, " "PharLite/".PHARLITE_VERSION." (PHP/".PHP_VERSION.")", 'phar.type' => $this->pharType, 'package.name' => isset($this->composer->name)?$this->composer->name:null, 'package.version' => isset($this->composer->version)?$this->composer->version:null, ], $metadata); print_info("Writing metadata:\n%s", json_encode($metadata, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT)); $phar->setMetadata($metadata); } public function build() { $this->readComposer(); if ($this->opts['install']) { $this->installComposer(); } $this->buildManifest(); print_info("Adding files..."); $phar = new \Phar($this->output); $total = count($this->manifest); $pcf = 100 / $total; $bw = 40; $pbf = $bw / $total; $index = 0; foreach ($this->manifest as $object) { // printf(" %s: %s\n", $object->getFilename(), $object->getLocalName()); $object->addToPhar($phar); if (posix_isatty(STDOUT) && ($index++ % 25 == 0)) { $pc = $pcf * $index; $pb = round($pbf * $index); printf("\r[%s%s] %.1f%%", str_repeat("=",$pb), str_repeat(" ",$bw-$pb), $pc); } } if (posix_isatty(STDOUT)) { printf("\r\e[2K"); } print_info("Added %d files!", $index); $this->generateBootstrap($phar, $this->pharType, $this->index, $this->bins); $this->writeMetadata($phar, (array)(array_key_exists('metadata',$this->pharOpts)?$this->pharOpts['metadata']:[])); chmod($this->output, 0777); } }