Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added module class map cache ability.

- ModuleAutoloader uses now Exception\InvalidArgumentException instead of the built-in InvalidArgumentException
  • Loading branch information...
commit c7c559127c7217fc1bd8d521cfbad07f11f9f851 1 parent f30ec3f
Eric Boh coss authored
34 library/Zend/Loader/ModuleAutoloader.php
View
@@ -95,6 +95,29 @@ public function setOptions($options)
}
/**
+ * Retrieves the class map for all loaded modules.
+ *
+ * @return array
+ */
+ public function getModuleClassMap()
+ {
+ return $this->moduleClassMap;
+ }
+
+ /**
+ * Sets the class map used to speed up the module autoloading.
+ *
+ * @param array $classmap
+ * @return ModuleLoader
+ */
+ public function setModuleClassMap(array $classmap)
+ {
+ $this->moduleClassMap = $classmap;
+
+ return $this;
+ }
+
+ /**
* Autoload a class
*
* @param $class
@@ -109,6 +132,11 @@ public function autoload($class)
return false;
}
+ if (isset($this->moduleClassMap[$class])) {
+ require_once $this->moduleClassMap[$class];
+ return $class;
+ }
+
$moduleName = substr($class, 0, -7);
if (isset($this->explicitPaths[$moduleName])) {
$classLoaded = $this->loadModuleFromDir($this->explicitPaths[$moduleName], $class);
@@ -268,7 +296,8 @@ public function unregister()
public function registerPaths($paths)
{
if (!is_array($paths) && !$paths instanceof Traversable) {
- throw new \InvalidArgumentException(
+ require_once __DIR__ . '/Exception/InvalidArgumentException.php';
+ throw new Exception\InvalidArgumentException(
'Parameter to \\Zend\\Loader\\ModuleAutoloader\'s '
. 'registerPaths method must be an array or '
. 'implement the \\Traversable interface'
@@ -296,7 +325,8 @@ public function registerPaths($paths)
public function registerPath($path, $moduleName = false)
{
if (!is_string($path)) {
- throw new \InvalidArgumentException(sprintf(
+ require_once __DIR__ . '/Exception/InvalidArgumentException.php';
+ throw new Exception\InvalidArgumentException(sprintf(
'Invalid path provided; must be a string, received %s',
gettype($path)
));
22 library/Zend/ModuleManager/Listener/ConfigListener.php
View
@@ -171,8 +171,12 @@ public function onLoadModulesPost(ModuleEvent $e)
}
// If enabled, update the config cache
- if ($this->getOptions()->getConfigCacheEnabled()) {
- $this->updateCache();
+ if (
+ $this->getOptions()->getConfigCacheEnabled()
+ && false === $this->skipConfig
+ ) {
+ $configFile = $this->getOptions()->getConfigCacheFile();
+ $this->writeArrayToFile($configFile, $this->getMergedConfig(false));
}
return $this;
@@ -386,18 +390,4 @@ protected function getCachedConfig()
{
return include $this->getOptions()->getConfigCacheFile();
}
-
- /**
- * @return ConfigListener
- */
- protected function updateCache()
- {
- if (($this->getOptions()->getConfigCacheEnabled())
- && (false === $this->skipConfig)
- ) {
- $configFile = $this->getOptions()->getConfigCacheFile();
- $this->writeArrayToFile($configFile, $this->getMergedConfig(false));
- }
- return $this;
- }
}
4 library/Zend/ModuleManager/Listener/DefaultListenerAggregate.php
View
@@ -12,7 +12,6 @@
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\ListenerAggregateInterface;
-use Zend\Loader\ModuleAutoloader;
use Zend\ModuleManager\ModuleEvent;
use Zend\Stdlib\CallbackHandler;
@@ -47,10 +46,9 @@ public function attach(EventManagerInterface $events)
$options = $this->getOptions();
$configListener = $this->getConfigListener();
$locatorRegistrationListener = new LocatorRegistrationListener($options);
- $moduleAutoloader = new ModuleAutoloader($options->getModulePaths());
// High priority, we assume module autoloading (for FooNamespace\Module classes) should be available before anything else
- $this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULES, array($moduleAutoloader, 'register'), 9000);
+ $this->listeners[] = $events->attach(new ModuleLoaderListener($options));
$this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULE_RESOLVE, new ModuleResolverListener);
// High priority, because most other loadModule listeners will assume the module's classes are available via autoloading
$this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULE, new AutoloaderListener($options), 9000);
64 library/Zend/ModuleManager/Listener/ListenerOptions.php
View
@@ -58,6 +58,16 @@ class ListenerOptions extends AbstractOptions
protected $cacheDir;
/**
+ * @var string
+ */
+ protected $moduleMapCacheEnabled = false;
+
+ /**
+ * @var string
+ */
+ protected $moduleMapCacheKey;
+
+ /**
* Get an array of paths where modules reside
*
* @return array
@@ -262,6 +272,60 @@ public function setCacheDir($cacheDir)
}
/**
+ * Check if the module class map cache is enabled
+ *
+ * @return bool
+ */
+ public function getModuleMapCacheEnabled()
+ {
+ return $this->moduleMapCacheEnabled;
+ }
+
+ /**
+ * Set if the module class map cache should be enabled or not
+ *
+ * @param bool $enabled
+ * @return ListenerOptions
+ */
+ public function setModuleMapCacheEnabled($enabled)
+ {
+ $this->moduleMapCacheEnabled = (bool) $enabled;
+ return $this;
+ }
+
+ /**
+ * Get key used to create the cache file name
+ *
+ * @return string
+ */
+ public function getModuleMapCacheKey()
+ {
+ return (string) $this->moduleMapCacheKey;
+ }
+
+ /**
+ * Set key used to create the cache file name
+ *
+ * @param string $moduleMapCacheKey the value to be set
+ * @return ListenerOptions
+ */
+ public function setModuleMapCacheKey($moduleMapCacheKey)
+ {
+ $this->moduleMapCacheKey = $moduleMapCacheKey;
+ return $this;
+ }
+
+ /**
+ * Get the path to the module class map cache
+ *
+ * @return string
+ */
+ public function getModuleMapCacheFile()
+ {
+ return $this->getCacheDir() . '/module-classmap-cache.'.$this->getModuleMapCacheKey().'.php';
+ }
+
+ /**
* Normalize a path for insertion in the stack
*
* @param string $path
140 library/Zend/ModuleManager/Listener/ModuleLoaderListener.php
View
@@ -0,0 +1,140 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_ModuleManager
+ */
+
+namespace Zend\ModuleManager\Listener;
+
+use Zend\Loader\ModuleAutoloader;
+use Zend\ModuleManager\ModuleEvent;
+use Zend\EventManager\EventManagerInterface;
+use Zend\EventManager\ListenerAggregateInterface;
+
+/**
+ * Module loader listener
+ *
+ * @category Zend
+ * @package Zend_ModuleManager
+ * @subpackage Listener
+ */
+class ModuleLoaderListener extends AbstractListener implements ListenerAggregateInterface
+{
+ /**
+ * @var array
+ */
+ protected $moduleLoader;
+
+ /**
+ * @var bool
+ */
+ protected $generateCache;
+
+ /**
+ * @var array
+ */
+ protected $listeners = array();
+
+ /**
+ * Constructor.
+ *
+ * Creates an instance of the ModuleAutoloader and injects the module paths
+ * into it.
+ *
+ * @param ListenerOptions $options
+ */
+ public function __construct(ListenerOptions $options = null)
+ {
+ parent::__construct($options);
+
+ $this->generateCache = $this->options->getModuleMapCacheEnabled();
+ $this->moduleLoader = new ModuleAutoloader($this->options->getModulePaths());
+
+ if ($this->hasCachedClassMap()) {
+ $this->generateCache = false;
+ $this->moduleLoader->setModuleClassMap($this->getCachedConfig());
+ }
+ }
+
+ /**
+ * Attach one or more listeners
+ *
+ * @param EventManagerInterface $events
+ * @return LocatorRegistrationListener
+ */
+ public function attach(EventManagerInterface $events)
+ {
+ $this->listeners[] = $events->attach(
+ ModuleEvent::EVENT_LOAD_MODULES,
+ array($this->moduleLoader, 'register'),
+ 9000
+ );
+
+ if ($this->generateCache) {
+ $this->listeners[] = $events->attach(
+ ModuleEvent::EVENT_LOAD_MODULES_POST,
+ array($this, 'onLoadModulesPost')
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Detach all previously attached listeners
+ *
+ * @param EventManagerInterface $events
+ * @return void
+ */
+ public function detach(EventManagerInterface $events)
+ {
+ foreach ($this->listeners as $key => $listener) {
+ if ($events->detach($listener)) {
+ unset($this->listeners[$key]);
+ }
+ }
+ }
+
+ /**
+ * @return bool
+ */
+ protected function hasCachedClassMap()
+ {
+ if (
+ $this->options->getModuleMapCacheEnabled()
+ && file_exists($this->options->getConfigCacheFile())
+ ) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @return array
+ */
+ protected function getCachedConfig()
+ {
+ return include $this->options->getModuleMapCacheFile();
+ }
+
+ /**
+ * loadModulesPost
+ *
+ * Unregisters the ModuleLoader and generates the module class map cache.
+ *
+ * @param ModuleEvent $e
+ */
+ public function onLoadModulesPost(ModuleEvent $event)
+ {
+ $this->moduleLoader->unregister();
+ $this->writeArrayToFile(
+ $this->options->getModuleMapCacheFile(),
+ $this->moduleLoader->getModuleClassMap()
+ );
+ }
+}
12 tests/Zend/Loader/ModuleAutoloaderTest.php
View
@@ -197,4 +197,16 @@ public function testCanLoadModulesFromExplicitLocation()
$this->assertTrue(class_exists('PharModuleExplicit\Module'));
}
+ public function testCanLoadModulesFromClassMap()
+ {
+ $loader = new ModuleAutoloader();
+ $loader->setModuleClassMap(array(
+ 'BarModule\Module' => __DIR__ . '/_files/BarModule/Module.php',
+ 'PharModuleMap\Module' => __DIR__ . '/_files/PharModuleMap.phar',
+ ));
+ $loader->register();
+
+ $this->assertTrue(class_exists('BarModule\Module'));
+ $this->assertTrue(class_exists('PharModuleMap\Module'));
+ }
}
15 tests/Zend/Loader/_files/BarModule/Module.php
View
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_Loader
+ */
+
+namespace BarModule;
+
+class Module
+{
+}
BIN  tests/Zend/Loader/_files/PharModuleMap.phar
View
Binary file not shown
1  tests/Zend/Loader/_files/_buildPhars.php
View
@@ -4,6 +4,7 @@
// Executable
// .phar
buildModulePhar('PharModule');
+buildModulePhar('PharModuleMap');
// .phar.gz
buildModulePhar('PharModuleGz', Phar::PHAR, Phar::GZ);
// .phar.bz2
96 tests/Zend/ModuleManager/Listener/ModuleLoaderListenerTest.php
View
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_ModuleManager
+ */
+
+namespace ZendTest\ModuleManager\Listener;
+
+use ArrayObject;
+use InvalidArgumentException;
+use PHPUnit_Framework_TestCase as TestCase;
+use Zend\ModuleManager\Listener\ModuleResolverListener;
+use Zend\ModuleManager\Listener\ModuleLoaderListener;
+use Zend\ModuleManager\Listener\ListenerOptions;
+use Zend\ModuleManager\ModuleManager;
+use Zend\ModuleManager\ModuleEvent;
+
+class ModuleLoaderListenerTest extends TestCase
+{
+ public function setUp()
+ {
+ $this->tmpdir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'zend_module_cache_dir';
+ @mkdir($this->tmpdir);
+
+ $this->moduleManager = new ModuleManager(array());
+ $this->moduleManager->getEventManager()->attach('loadModule.resolve', new ModuleResolverListener, 1000);
+ }
+
+ public function tearDown()
+ {
+ $file = glob($this->tmpdir . DIRECTORY_SEPARATOR . '*');
+ @unlink($file[0]); // change this if there's ever > 1 file
+ @rmdir($this->tmpdir);
+ }
+
+ public function testModuleLoaderListenerFunctionsAsAggregateListenerEnabledCache()
+ {
+ $options = new ListenerOptions(array(
+ 'cache_dir' => $this->tmpdir,
+ 'module_map_cache_enabled' => true,
+ 'module_map_cache_key' => 'foo',
+ ));
+
+ $configListener = new ModuleLoaderListener($options);
+
+ $moduleManager = $this->moduleManager;
+ $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES)));
+ $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST)));
+
+ $configListener->attach($moduleManager->getEventManager());
+ $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES)));
+ $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST)));
+ }
+
+ public function testModuleLoaderListenerFunctionsAsAggregateListenerDisabledCache()
+ {
+ $options = new ListenerOptions(array(
+ 'cache_dir' => $this->tmpdir,
+ ));
+
+ $configListener = new ModuleLoaderListener($options);
+
+ $moduleManager = $this->moduleManager;
+ $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES)));
+ $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST)));
+
+ $configListener->attach($moduleManager->getEventManager());
+ $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES)));
+ $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST)));
+ }
+
+ public function testModuleLoaderListenerFunctionsAsAggregateListenerHasCache()
+ {
+ $options = new ListenerOptions(array(
+ 'cache_dir' => $this->tmpdir,
+ 'module_map_cache_enabled' => true,
+ 'module_map_cache_key' => 'foo',
+ ));
+
+ file_put_contents($options->getModuleMapCacheFile(), '<?php return array();');
+
+ $configListener = new ModuleLoaderListener($options);
+
+ $moduleManager = $this->moduleManager;
+ $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES)));
+ $this->assertEquals(0, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST)));
+
+ $configListener->attach($moduleManager->getEventManager());
+ $this->assertEquals(2, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES)));
+ $this->assertEquals(1, count($moduleManager->getEventManager()->getListeners(ModuleEvent::EVENT_LOAD_MODULES_POST)));
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.