Skip to content

Commit

Permalink
Refactor vendor root configuration
Browse files Browse the repository at this point in the history
 - allow for ENV variable as well as constant
 - remove `abstract_composer.php` shell "helper"
 - increase test coverage of Autoload.php
 - update README to reflect changes

Should close #5, gets #4 closer
  • Loading branch information
mattwellss committed Jan 5, 2016
1 parent e651f58 commit d6cf067
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 30 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,20 @@ This should only be a temporary solution until the project is listed on a real c

## Configuration

Post install, the new `Varien_Autoload` class needs one more setting to use Composer instead of Magento to autoload: The `VENDOR_ROOT` constant. Generally it's best to configure this in your index file as well as any other entrypoints, such as `cron.php`, `api.php` and others.
Post install, the new `Varien_Autoload` class needs to know where `vendor/autoload.php` is hiding. This must be configured.

### `VENDOR_ROOT`
### Defining the vendor root directory

The `VENDOR_ROOT` constant is the absolute path to your project's `vendor` directory, such that `VENDOR_ROOT . '/autoload.php'` resolves correctly to Composer autoload file. It'd be real nice to not put this config on you our users, but there's no known way around it.
Regardless of how the vendor dir is defined, it **must not end with a trailing slash**.

The two methods of describing the vendor root directory are:
- `VENDOR_ROOT` constant. Must be defined _in all entry points_.
- `MAGE_VENDOR_ROOT` env variable. Be sure it's defined for **all** PHP environments (cli and fpm/mod_php).

## Optimizing the Autoloader

**WARNING: WIP**

Aside from `composer dump -o`, running `php shell/classmap_generator.php` when deploying new code to production is recommended. That script generates a classmap file to be used by composer to speed autoloading of files in Magento's code pools.

To enable use of the generated classmap, include `define('OPTIMIZED_COMPOSER', true)` in `includes/config.php`.
54 changes: 44 additions & 10 deletions src/Autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,28 +68,62 @@ static public function instance()
}

/**
* Register SPL autoload function
* Returns vendor root directory
* @return string|false
*/
static public function register()
public static function getVendorRootDir()
{
if (!defined('VENDOR_ROOT')) {
spl_autoload_register(array(self::instance(), 'autoload'));
return;
if (isset($_ENV['MAGE_VENDOR_ROOT'])) {
return $_ENV['MAGE_VENDOR_ROOT'];
}

self::registerComposerAutoloader();
if (defined('VENDOR_ROOT')) {
return VENDOR_ROOT;
}

return false;
}

public static function registerComposerAutoloader()
/**
* Get an instance of the Composer Autoloader
*
* @return Composer\Autoload\ClassLoader
* @throws Exception
*/
private static function getComposerAutoloader()
{
$autoloadFilename = VENDOR_ROOT . '/autoload.php';
$vendorDir = self::getVendorRootDir();

$autoloadFilename = $vendorDir . '/autoload.php';
if (!file_exists($autoloadFilename)) {
throw new Exception(
$autoloadFilename . " was not found. Is \"VENDOR_ROOT\" correctly defined?");
'The composer autoload.php file was not found. See README for more information');
}

return require $autoloadFilename;
}

/**
* Register SPL autoload function
*/
static public function register()
{
if (!self::getVendorRootDir()) {
spl_autoload_register(array(self::instance(), 'autoload'));
return;
}

$autoloader = require $autoloadFilename;
self::registerComposerAutoloader();
}

/**
* Add Magento's paths to the Composer autoload directory fallback
* @return void
* @throws Exception
*/
private static function registerComposerAutoloader()
{
$autoloader = self::getComposerAutoloader();

if (defined('OPTIMIZED_COMPOSER')) {
self::registerClassMap($autoloader);
Expand Down
9 changes: 0 additions & 9 deletions src/abstract_composer.php

This file was deleted.

2 changes: 1 addition & 1 deletion src/classmap_generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use Composer\Autoload\ClassMapGenerator;

require_once 'abstract_composer.php';
require_once 'abstract.php';

/**
* Magento Compiler Shell Script
Expand Down
59 changes: 52 additions & 7 deletions tests/AutoloadTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ class AutoloadTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
if (!defined('VENDOR_ROOT')) {
define('VENDOR_ROOT', __DIR__ . '/../vendor');
}

if (!defined('BP')) {
define('BP', __DIR__);
}
Expand All @@ -17,16 +13,60 @@ public function setUp()

public function testInstance()
{
// This method is used later on, so we should be sure it works
$this->assertInstanceOf('Varien_Autoload', Varien_Autoload::instance());
}

public function testRegisterStandard()
{
Varien_Autoload::register();
$functions = spl_autoload_functions();

$matches = array_filter($functions, function ($function) {
return $function == [Varien_Autoload::instance(), 'autoload'];
});

$this->assertNotCount(0, $matches);

// TODO: find a way to use assertArraySubset
// $this->assertArraySubset(
// [Varien_Autoload::instance(), 'autoload'], $functions);

spl_autoload_unregister([Varien_Autoload::instance(), 'autoload']);
}

public function testRegisterWithEnv()
{
$_ENV['MAGE_VENDOR_ROOT'] = __DIR__ . '/../vendor';

Varien_Autoload::register();

$loader = require __DIR__ . '/../vendor/autoload.php';

$expectedPaths = [
BP . '/app/code/local/',
BP . '/app/code/community/',
BP . '/app/code/core/',
BP . '/lib/',
];

// Ensure that by registering the autoloader
// The expected paths are in the "fallback dirs"
// For autoloading
$this->assertArraySubset(
$expectedPaths, $loader->getFallbackDirs());
}

public function testNotFoundAutoload()
{
$exceptionMessage = VENDOR_ROOT . '/autoload.php was not found. Is "VENDOR_ROOT" correctly defined?';
if (!defined('VENDOR_ROOT')) {
define('VENDOR_ROOT', __DIR__ . '/../vendor');
}
$exceptionMessage = 'The composer autoload.php file was not found. See README for more information';

rename(VENDOR_ROOT . '/autoload.php', VENDOR_ROOT . '/autoload.php.bak');
try {
Varien_Autoload::registerComposerAutoloader();
Varien_Autoload::register();
} catch (Exception $e) {
$this->assertInstanceOf('Exception', $e);
$this->assertEquals($e->getMessage(), $exceptionMessage);
Expand All @@ -36,7 +76,11 @@ public function testNotFoundAutoload()

public function testRegisterComposer()
{
Varien_Autoload::registerComposerAutoloader();
if (!defined('VENDOR_ROOT')) {
define('VENDOR_ROOT', __DIR__ . '/../vendor');
}

Varien_Autoload::register();
$loader = require __DIR__ . '/../vendor/autoload.php';

$expectedPaths = [
Expand All @@ -52,4 +96,5 @@ public function testRegisterComposer()
$this->assertArraySubset(
$expectedPaths, $loader->getFallbackDirs());
}

}

0 comments on commit d6cf067

Please sign in to comment.