Permalink
Browse files

Merge branch 'release-0.2'

  • Loading branch information...
zyxist committed Jun 12, 2011
2 parents 23e5ed9 + 3e701a1 commit 6f44438cc0d4ca584ae6ad3d752b63bb27988341
View
@@ -1,4 +1,4 @@
-Open Power Autoloader 3.0.1.0
+Open Power Autoloader 3.0.2.0
=============================
This is a collection of universal class loaders for PHP 5.3+ compatible with
@@ -9,7 +9,7 @@ naming rules.
Version information
-------------------
-This is a development version of Open Power Autoloader 3.0.1.0
+This is a development version of Open Power Autoloader 3.0.2.0
Requirements
------------
@@ -33,8 +33,12 @@ The package provides the following class loaders:
Extra classes:
* `\Opl\Autoloader\ClassMapBuilder` - class map builder for the map-based autoloaders.
+* `\Opl\Autoloader\CoreTracker` - an autoloader decorator that allows to find the common application
+ core loaded every time.
* `\Opl\Autoloader\Command\ClassMapBuild` - Symfony 2 Console command that builds
the class maps for the map-based autoloaders.
+* `\Opl\Autoloader\Command\CoreDump` - Symfony 2 Console command that generates the
+ application core loading code from the `CoreTracker` dump.
Documentation can be found [here](http://static.invenzzia.org/docs/opl/3_0/book/en/autoloader.html).
View
@@ -1,7 +1,7 @@
# Configure the project definitions here
project.name=Open Power Autoloader
project.filename=opl-autoloader
-project.version=3.0.1.0
+project.version=3.0.2.x
project.stability.release=devel
project.stability.api=devel
project.license=New BSD
View
@@ -36,9 +36,11 @@ http://pear.php.net/dtd/package-2.0.xsd">
<contents>
<dir baseinstalldir="/" name="/">
<file baseinstalldir="/" name="Opl/Autoloader/Command/ClassMapBuild.php" role="php" />
+ <file baseinstalldir="/" name="Opl/Autoloader/Command/CoreDump.php" role="php" />
<file baseinstalldir="/" name="Opl/Autoloader/PHARLoader.php" role="php" />
<file baseinstalldir="/" name="Opl/Autoloader/ClassMapLoader.php" role="php" />
<file baseinstalldir="/" name="Opl/Autoloader/ClassMapBuilder.php" role="php" />
+ <file baseinstalldir="/" name="Opl/Autoloader/CoreTracker.php" role="php" />
<file baseinstalldir="/" name="Opl/Autoloader/GenericLoader.php" role="php" />
</dir>
</contents>
View
@@ -15,5 +15,6 @@
$cli->addCommands(array(
new \Opl\Autoloader\Command\ClassMapBuild(),
+ new \Opl\Autoloader\Command\CoreDump(),
));
$cli->run();
@@ -107,6 +107,13 @@ public function addNamespace($namespaceName, $path, $extension = '.php')
*/
protected function _processSingleFile($file)
{
+ // PHP 5.3 does not have this token, so we add it in order not to get
+ // warnings.
+ if(!defined('T_TRAIT'))
+ {
+ define('T_TRAIT', 65536);
+ }
+
$code = '';
$namespace = '';
$className = '';
@@ -135,7 +142,7 @@ protected function _processSingleFile($file)
$state = 1;
}
- elseif($tokenName == T_CLASS || $tokenName == T_INTERFACE)
+ elseif($tokenName == T_CLASS || $tokenName == T_INTERFACE || $tokenName == T_TRAIT)
{
$state = 2;
}
@@ -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;
@@ -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;
@@ -18,6 +18,7 @@ public static function suite()
$suite->addTestSuite('TestSuite\\GenericLoaderTest');
$suite->addTestSuite('TestSuite\\ClassMapLoaderTest');
$suite->addTestSuite('TestSuite\\PHARLoaderTest');
+ $suite->addTestSuite('TestSuite\\CoreTrackerTest');
return $suite;
} // end suite();
Oops, something went wrong.

0 comments on commit 6f44438

Please sign in to comment.