Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
470 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
<?php | ||
/* | ||
* OPEN POWER LIBS <http://www.invenzzia.org> | ||
* | ||
* This file is subject to the new BSD license that is bundled | ||
* with this package in the file LICENSE. It is also available through | ||
* WWW at this URL: <http://www.invenzzia.org/license/new-bsd> | ||
* | ||
* Copyright (c) Invenzzia Group <http://www.invenzzia.org> | ||
* and other contributors. See website for details. | ||
*/ | ||
namespace Opl\Autoloader\Command; | ||
use Symfony\Component\Console\Input\InputArgument; | ||
use Symfony\Component\Console\Input\InputOption; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\Console\Output\Output; | ||
use Symfony\Component\Console\Command\Command; | ||
|
||
/** | ||
* This command line interface command is responsible for building | ||
* class maps for the ClassMapLoader. | ||
* | ||
* @author Tomasz Jędrzejewski | ||
* @copyright Invenzzia Group <http://www.invenzzia.org/> and contributors. | ||
* @license http://www.invenzzia.org/license/new-bsd New BSD License | ||
*/ | ||
class CoreDump extends Command | ||
{ | ||
/** | ||
* @see Command | ||
*/ | ||
protected function configure() | ||
{ | ||
$this->ignoreValidationErrors = true; | ||
|
||
$this->setDefinition(array( | ||
new InputArgument('definition', InputArgument::REQUIRED, 'The class location definition INI file'), | ||
new InputArgument('core', InputArgument::OPTIONAL, 'The core file location, unless specified in the INI file.'), | ||
)) | ||
->setName('opl:autoloader:core-dump-load') | ||
->setDescription('Generates a list of require statements that load the common application core.') | ||
->setHelp(<<<EOF | ||
Use the <info>CoreTracker</info> autoloader decorator to find the common application | ||
core by sending some HTTP requests. The more requests you perform, the more precise | ||
the lookup is. The configuration for the command is given as | ||
an INI file, where each entry represents a single top-level namespace and a path to its code: | ||
[config] | ||
coreDump = "./output/core.txt" | ||
coreLoadOutput = "./application/core.php" | ||
namespaceSeparator = "\\" | ||
extension = ".php" | ||
[namespaces] | ||
Opl = "../libs/" | ||
Foo = "../libs/" | ||
Bar = "../other/" | ||
It is recommended for the paths to have the trailing slashes prepended. The coreDump | ||
value can be also provided as a command argument. The INI setting is ignored then. | ||
EOF | ||
); | ||
} // end configure(); | ||
|
||
/** | ||
* @see Command | ||
*/ | ||
protected function execute(InputInterface $input, OutputInterface $output) | ||
{ | ||
$definition = $input->getArgument('definition'); | ||
if(!$definition) | ||
{ | ||
$output->writeln('<error>No definition file specified!</error>'); | ||
return; | ||
} | ||
$data = parse_ini_file($definition, true); | ||
if(!is_array($data)) | ||
{ | ||
$output->writeln('<error>Invalid INI structure in the definition file!</error>'); | ||
return; | ||
} | ||
|
||
$coreDump = $input->getArgument('core'); | ||
if($coreDump) | ||
{ | ||
$data['config']['coreDump'] = $coreDump; | ||
} | ||
|
||
if(!file_exists($data['config']['coreDump'])) | ||
{ | ||
$output->writeln('<error>Cannot open the core dump file!</error>'); | ||
return; | ||
} | ||
$dump = unserialize(file_get_contents($data['config']['coreDump'])); | ||
$outFile = fopen($data['config']['coreLoadOutput'], 'w'); | ||
fwrite($outFile, '<'.'?php'.PHP_EOL); | ||
|
||
foreach($dump as $className) | ||
{ | ||
$fileName = $this->toFilename($data['namespaces'], $data['config']['namespaceSeparator'], $className, $output); | ||
if(false !== $fileName) | ||
{ | ||
fwrite($outFile, 'require(\''.$fileName.$data['config']['extension'].'\');'.PHP_EOL); | ||
} | ||
} | ||
fclose($outFile); | ||
$output->writeln('<info>Core loading file generated.</info>'); | ||
} // end execute(); | ||
|
||
/** | ||
* Returns the file name for the given class name. | ||
* | ||
* @param array $namespaces The list of available namespaces. | ||
* @param string $className The class name to translate. | ||
* @param OutputInterface $output The output interface. | ||
*/ | ||
protected function toFilename(array $namespaces, $namespaceSeparator, $className, OutputInterface $output) | ||
{ | ||
$className = ltrim($className, $namespaceSeparator); | ||
$match = strstr($className, $namespaceSeparator, true); | ||
|
||
if(false === $match || !isset($namespaces[$match])) | ||
{ | ||
return false; | ||
} | ||
$rest = strrchr($className, $namespaceSeparator); | ||
$replacement = | ||
str_replace($namespaceSeparator, '/', substr($className, 0, strlen($className) - strlen($rest))). | ||
str_replace(array('_', $namespaceSeparator), '/', $rest); | ||
|
||
return $namespaces[$match].$replacement; | ||
} // end toFilename(); | ||
} // end CoreDump; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
<?php | ||
/* | ||
* OPEN POWER LIBS <http://www.invenzzia.org> | ||
* | ||
* This file is subject to the new BSD license that is bundled | ||
* with this package in the file LICENSE. It is also available through | ||
* WWW at this URL: <http://www.invenzzia.org/license/new-bsd> | ||
* | ||
* Copyright (c) Invenzzia Group <http://www.invenzzia.org> | ||
* and other contributors. See website for details. | ||
*/ | ||
namespace Opl\Autoloader; | ||
use DomainException; | ||
|
||
/** | ||
* This decorator for any OPL autoloader tracks the loaded classes, attempting | ||
* to find the common core of the entire application that must be always loaded. | ||
* We can skip the autoloading procedure for it by generating a plain list of | ||
* <tt>require</tt> commands. | ||
* | ||
* @author Tomasz Jędrzejewski | ||
* @copyright Invenzzia Group <http://www.invenzzia.org/> and contributors. | ||
* @license http://www.invenzzia.org/license/new-bsd New BSD License | ||
*/ | ||
class CoreTracker | ||
{ | ||
/** | ||
* The decorated autoloader. | ||
* @var object | ||
*/ | ||
protected $autoloader; | ||
/** | ||
* The core file name, where the results should be dumped. | ||
* @var string | ||
*/ | ||
protected $coreFileName; | ||
/** | ||
* The core file resource. | ||
* @var resource | ||
*/ | ||
protected $coreFile; | ||
/** | ||
* The current core layout. | ||
* @var array | ||
*/ | ||
protected $core; | ||
/** | ||
* The current scan. | ||
* @var array | ||
*/ | ||
protected $currentScan; | ||
/** | ||
* Whether we are generating the initial core or reducing the possibilities? | ||
* @var integer | ||
*/ | ||
protected $mode; | ||
|
||
/** | ||
* Creates the core tracker by decorating another autoloader. | ||
* | ||
* @param object $autoloader The decorated autoloader. | ||
*/ | ||
public function __construct($autoloader, $coreFile) | ||
{ | ||
if(!is_object($autoloader) || !method_exists($autoloader, 'loadClass')) | ||
{ | ||
throw new DomainException('The first argument must be an autoloader object with \'loadClass\' method.'); | ||
} | ||
$this->autoloader = $autoloader; | ||
$this->coreFileName = (string)$coreFile; | ||
|
||
if(!file_exists($this->coreFileName)) | ||
{ | ||
touch($this->coreFileName); | ||
} | ||
$this->coreFile = fopen($this->coreFileName, 'r+'); | ||
|
||
$content = ''; | ||
while(!feof($this->coreFile)) | ||
{ | ||
$content .= fread($this->coreFile, 2048); | ||
} | ||
rewind($this->coreFile); | ||
$this->core = unserialize($content); | ||
if(false == $this->core) | ||
{ | ||
$this->core = array(); | ||
$this->mode = 0; | ||
} | ||
else | ||
{ | ||
$this->mode = 1; | ||
} | ||
$this->currentScan = array(); | ||
} // end __construct(); | ||
|
||
/** | ||
* Updates the core dump file. | ||
*/ | ||
public function __destruct() | ||
{ | ||
if(0 == $this->mode) | ||
{ | ||
fwrite($this->coreFile, serialize($this->currentScan)); | ||
} | ||
else | ||
{ | ||
fwrite($this->coreFile, serialize(array_intersect($this->core, $this->currentScan))); | ||
} | ||
fclose($this->coreFile); | ||
} // end __destruct(); | ||
|
||
/** | ||
* Returns the decorated autoloader. | ||
* | ||
* @return object | ||
*/ | ||
public function getAutoloader() | ||
{ | ||
return $this->autoloader; | ||
} // end getAutoloader(); | ||
|
||
/** | ||
* Installs this class loader on the SPL autoload stack. | ||
*/ | ||
public function register() | ||
{ | ||
spl_autoload_register(array($this, 'loadClass')); | ||
} // end register(); | ||
|
||
/** | ||
* Uninstalls this class loader from the SPL autoloader stack. | ||
*/ | ||
public function unregister() | ||
{ | ||
spl_autoload_unregister(array($this, 'loadClass')); | ||
} // end unregister(); | ||
|
||
/** | ||
* Performs the core tracking and delegates the loading to the decorated | ||
* autoloader. | ||
*/ | ||
public function loadClass($className) | ||
{ | ||
// DO NOT CHANGE THE ORDER OR YOU'LL BREAK THE CLASS DEPENDENCIES! | ||
$result = $this->autoloader->loadClass($className); | ||
$this->currentScan[] = $className; | ||
return $result; | ||
} // end loadClass(); | ||
} // end CoreTracker; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.