public function execute($pharFile = 'output.phar') { if (!extension_loaded('json')) { throw new RuntimeException('json extension is required.'); } // $composerConfigFile is a SplFileInfo object since wuse ->isa('file') $composerConfigFile = $this->options->{'composer'} ?: 'composer.json'; if (!file_exists($composerConfigFile)) { throw new Exception("composer config '{$composerConfigFile}' doesn't exist."); } $composerConfigFile = new SplFileInfo(realpath($composerConfigFile)); $this->logger->debug("Found composer config at {$composerConfigFile}"); // workingDir is a SplFileInfo object since we use ->isa('Dir') $workingDir = $this->options->{'working-dir'} ?: new SplFileInfo($composerConfigFile->getPath()); if (!file_exists($workingDir)) { throw new Exception("working directory '{$workingDir}' doesn't exist."); } $this->logger->debug('Working directory: ' . $workingDir->getPathname()); $vendorDirName = $this->options->vendor ?: 'vendor'; $pharGenerator = new PharGenerator($this->logger, $this->options, $pharFile); $phar = $pharGenerator->getPhar(); ini_set('phar.readonly', 0); $this->logger->info("Creating phar file {$pharFile}..."); $phar->startBuffering(); $stubs = new Block(); if ($this->options->executable) { $this->logger->debug('Adding shell bang...'); $stubs[] = '#!/usr/bin/env php'; } // prepend open tag $stubs[] = '<?php'; $this->logger->info('Setting up stub...'); $stubs[] = "Phar::mapPhar('{$pharFile}');"; // $workingDir = dirname(realpath($composerConfigFile)); // Get class paths by ReflectionClass, they should be relative path. // However the class path might be in another directory because the // classes are loaded from vendor/autoload.php $classPaths = array(Utils::getClassPath('Universal\\ClassLoader\\ClassLoader'), Utils::getClassPath('Universal\\ClassLoader\\Psr0ClassLoader'), Utils::getClassPath('Universal\\ClassLoader\\Psr4ClassLoader'), Utils::getClassPath('Universal\\ClassLoader\\MapClassLoader')); // Generate class loader stub $this->logger->debug('Adding class loader files...'); foreach ($classPaths as $classPath) { $phar->addFile($classPath, basename($classPath)); } /* $classDir = dirname($classPaths[0]); $phar->buildFromIterator( new RecursiveIteratorIterator(new RecursiveDirectoryIterator($classDir)), $workingDir ); */ foreach ($classPaths as $classPath) { $this->logger->debug('Adding require statment for class loader: ' . basename($classPath)); $stubs[] = new RequireStatement(new PharURI($pharFile, basename($classPath))); } if (!$this->options->{'no-classloader'}) { $this->logger->info('Generating classLoader stubs'); $autoloadGenerator = new ComposerAutoloadGenerator($this->logger); $autoloadGenerator->setVendorDir('vendor'); $autoloadGenerator->setWorkingDir($workingDir->getPathname()); $autoloadGenerator->scanComposerJsonFiles($workingDir . DIRECTORY_SEPARATOR . $vendorDirName); $autoloads = $autoloadGenerator->traceAutoloadsWithComposerJson($composerConfigFile, $workingDir . DIRECTORY_SEPARATOR . $vendorDirName, true); foreach ($autoloads as $packageName => $config) { if (!isset($config['autoload'])) { continue; } $autoload = $config['autoload']; if (!isset($config['root'])) { $autoload = $autoloadGenerator->prependAutoloadPathPrefix($autoload, $vendorDirName . DIRECTORY_SEPARATOR . $packageName . DIRECTORY_SEPARATOR); } foreach ($autoload as $type => $map) { foreach ($map as $mapPaths) { $paths = (array) $mapPaths; foreach ($paths as $path) { $absolutePath = $workingDir . DIRECTORY_SEPARATOR . $path; if (is_dir($absolutePath)) { $this->logger->debug("Add files from directory {$absolutePath} under {$workingDir}"); $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($absolutePath, FilesystemIterator::SKIP_DOTS)); foreach ($it as $fileinfo) { $pathName = $fileinfo->getPathname(); if (preg_match('/(\\.(?:git|svn|hg)|Tests|Test\\.php)/', $pathName)) { continue; } $localPath = str_replace($workingDir . DIRECTORY_SEPARATOR, '', $pathName); $this->logger->debug("Adding {$localPath}"); $phar->addFile($pathName, $localPath); } /* $builtFiles = $phar->buildFromIterator( new RecursiveIteratorIterator( new RecursiveDirectoryIterator($absolutePath, FilesystemIterator::SKIP_DOTS) ), $workingDir ); */ } elseif (is_file($absolutePath)) { $this->logger->debug("Add file {$absolutePath} under {$path}"); $phar->addFile($absolutePath, $path); } else { $this->logger->error("File '{$absolutePath}' is not found."); } } } } } $classloaderStub = $autoloadGenerator->generate($composerConfigFile, $pharFile); $this->logger->debug('ClassLoader stub:'); $this->logger->debug($classloaderStub); $stubs[] = $autoloadGenerator->generate($composerConfigFile, $pharFile); } if ($bootstraps = $this->options->bootstrap) { foreach ($bootstraps as $bootstrap) { $this->logger->info("Adding bootstrap: {$bootstrap}"); $content = php_strip_whitespace($bootstrap); $content = preg_replace('{^#!/usr/bin/env\\s+php\\s*}', '', $content); $localPath = str_replace($workingDir->getPathname(), '', $bootstrap->getRealPath()); $phar->addFromString($localPath, $content); $stubs[] = new RequireStatement(new PharURI($pharFile, $localPath)); } } if ($this->options->{'app-bootstrap'}) { $app = $this->getApplication(); $refObject = new ReflectionObject($app); $appClassName = $refObject->getName(); $block = new Block(); $block[] = new AssignStatement('$app', new NewObjectExpr($appClassName)); $block[] = new MethodCallStatement('$app', 'run', array('$argv')); $stubs[] = $block; } $stubs[] = '__HALT_COMPILER();'; $stubstr = $stubs->render(); $this->logger->debug($stubstr); $phar->setStub($stubstr); // Add some extra files in phar's root if ($adds = $this->options->add) { foreach ($adds as $add) { $phar->buildFromIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($add)), $workingDir); } } $pharGenerator->generate(); $this->logger->info('Done'); }
public function testGetClassPath() { $path = Utils::getClassPath('Universal\\ClassLoader\\ClassLoader', getcwd()); $this->assertEquals('vendor/corneltek/universal/src/Universal/ClassLoader/ClassLoader.php', $path); $this->assertFileExists($path); }