Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Merge a2d6b4a into e6ae441
Browse files Browse the repository at this point in the history
  • Loading branch information
weierophinney committed Jan 5, 2017
2 parents e6ae441 + a2d6b4a commit 59e2a2b
Show file tree
Hide file tree
Showing 30 changed files with 598 additions and 69 deletions.
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ matrix:
- php: 7
env:
- DEPS=latest
- php: 7.1
env:
- DEPS=lowest
- php: 7.1
env:
- DEPS=locked
- php: 7.1
env:
- DEPS=latest
- php: hhvm
env:
- DEPS=lowest
Expand Down
12 changes: 9 additions & 3 deletions src/ConfigDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ class ConfigDiscovery
'dist' => ConfigDiscovery\DevelopmentConfig::class,
'work' => ConfigDiscovery\DevelopmentWorkConfig::class,
],
'config/config.php' => ConfigDiscovery\ExpressiveConfig::class,
'config/config.php' => [
'aggregator' => ConfigDiscovery\ConfigAggregator::class,
'manager' => ConfigDiscovery\ExpressiveConfig::class,
],
];

/**
Expand All @@ -35,7 +38,10 @@ class ConfigDiscovery
'dist' => Injector\DevelopmentConfigInjector::class,
'work' => Injector\DevelopmentWorkConfigInjector::class,
],
'config/config.php' => Injector\ExpressiveConfigInjector::class,
'config/config.php' => [
'aggregator' => Injector\ConfigAggregatorInjector::class,
'manager' => Injector\ExpressiveConfigInjector::class,
]
];

/**
Expand All @@ -56,7 +62,7 @@ public function getAvailableConfigOptions(Collection $availableTypes, $projectRo
]);

Collection::create($this->discovery)
// Create a discovery class for the dicovery type
// Create a discovery class for the discovery type
->map(function ($discoveryClass) use ($projectRoot) {
if (is_array($discoveryClass)) {
return new ConfigDiscovery\DiscoveryChain($discoveryClass, $projectRoot);
Expand Down
37 changes: 37 additions & 0 deletions src/ConfigDiscovery/ConfigAggregator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php
/**
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
* @copyright Copyright (c) 2016 Zend Technologies Ltd (http://www.zend.com)
*/

namespace Zend\ComponentInstaller\ConfigDiscovery;

class ConfigAggregator extends AbstractDiscovery
{
/**
* Configuration file to look for.
*
* @var string
*/
protected $configFile = 'config/config.php';

/**
* Expected pattern to match if the configuration file exists.
*
* Pattern is set in constructor to ensure PCRE quoting is correct.
*
* @var string
*/
protected $expected = '';

public function __construct($projectDirectory = '')
{
$this->expected = sprintf(
'/new (?:%s?%s)?ConfigAggregator\(\s*(?:array\(|\[)/s',
preg_quote('\\'),
preg_quote('Zend\ConfigAggregator\\')
);

parent::__construct($projectDirectory);
}
}
67 changes: 67 additions & 0 deletions src/Injector/ConditionalDiscoveryTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
/**
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
* @copyright Copyright (c) 2016 Zend Technologies Ltd (http://www.zend.com)
*/

namespace Zend\ComponentInstaller\Injector;

use Composer\IO\IOInterface;

trait ConditionalDiscoveryTrait
{
/**
* {@inheritDoc}
*
* Prepends the package with a `\\` in order to ensure it is fully
* qualified, preventing issues in config files that are namespaced.
*/
public function inject($package, $type, IOInterface $io)
{
if (! $this->validConfigAggregatorConfig()) {
return;
}

parent::inject('\\' . $package, $type, $io);
}

/**
* {@inheritDoc}
*
* Prepends the package with a `\\` in order to ensure it is fully
* qualified, preventing issues in config files that are namespaced.
*/
public function remove($package, IOInterface $io)
{
if (! $this->validConfigAggregatorConfig()) {
return;
}

parent::remove('\\' . $package, $io);
}

/**
* Does the config file hold valid ConfigAggregator configuration?
*
* @return bool
*/
private function validConfigAggregatorConfig()
{
$discoveryClass = $this->discoveryClass;
$discovery = new $discoveryClass($this->getProjectRoot());
return $discovery->locate();
}

/**
* Calculate the project root from the config file
*
* @return string
*/
private function getProjectRoot()
{
if (static::DEFAULT_CONFIG_FILE === $this->configFile) {
return '';
}
return str_replace('/' . static::DEFAULT_CONFIG_FILE, '', $this->configFile);
}
}
94 changes: 94 additions & 0 deletions src/Injector/ConfigAggregatorInjector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php
/**
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
* @copyright Copyright (c) 2016 Zend Technologies Ltd (http://www.zend.com)
*/

namespace Zend\ComponentInstaller\Injector;

use Zend\ComponentInstaller\ConfigDiscovery\ConfigAggregator as ConfigAggregatorDiscovery;

class ConfigAggregatorInjector extends AbstractInjector
{
use ConditionalDiscoveryTrait;

const DEFAULT_CONFIG_FILE = 'config/config.php';

/**
* {@inheritDoc}
*/
protected $allowedTypes = [
self::TYPE_CONFIG_PROVIDER,
];

/**
* Configuration file to update.
*
* @var string
*/
protected $configFile = self::DEFAULT_CONFIG_FILE;

/**
* Discovery class, for testing if this injector is valid for the given
* configuration.
*
* @var string
*/
protected $discoveryClass = ConfigAggregatorDiscovery::class;

/**
* Patterns and replacements to use when registering a code item.
*
* Pattern is set in constructor due to PCRE quoting issues.
*
* @var string[]
*/
protected $injectionPatterns = [
self::TYPE_CONFIG_PROVIDER => [
'pattern' => '',
'replacement' => "\$1\n\$2%s::class,\n\$2",
],
];

/**
* Pattern to use to determine if the code item is registered.
*
* Set in constructor due to PCRE quoting issues.
*
* @var string
*/
protected $isRegisteredPattern = '';

/**
* Patterns and replacements to use when removing a code item.
*
* @var string[]
*/
protected $removalPatterns = [
'pattern' => '/^\s+%s::class,\s*$/m',
'replacement' => '',
];

/**
* {@inheritDoc}
*
* Sets $isRegisteredPattern and pattern for $injectionPatterns to ensure
* proper PCRE quoting.
*/
public function __construct($projectRoot = '')
{
$this->isRegisteredPattern = '/new (?:'
. preg_quote('\\')
. '?'
. preg_quote('Zend\ConfigAggregator\\')
. ')?ConfigAggregator\(\s*(?:array\(|\[).*\s+%s::class/s';

$this->injectionPatterns[self::TYPE_CONFIG_PROVIDER]['pattern'] = sprintf(
"/(new (?:%s?%s)?ConfigAggregator\(\s*(?:array\(|\[)\s*)(?:\r|\n|\r\n)(\s*)/",
preg_quote('\\'),
preg_quote('Zend\ConfigAggregator\\')
);

parent::__construct($projectRoot);
}
}
38 changes: 14 additions & 24 deletions src/Injector/ExpressiveConfigInjector.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@

namespace Zend\ComponentInstaller\Injector;

use Composer\IO\IOInterface;
use Zend\ComponentInstaller\ConfigDiscovery\ExpressiveConfig as ExpressiveConfigDiscovery;

class ExpressiveConfigInjector extends AbstractInjector
{
use ConditionalDiscoveryTrait;

const DEFAULT_CONFIG_FILE = 'config/config.php';

/**
* {@inheritDoc}
*/
Expand All @@ -22,7 +26,15 @@ class ExpressiveConfigInjector extends AbstractInjector
*
* @var string
*/
protected $configFile = 'config/config.php';
protected $configFile = self::DEFAULT_CONFIG_FILE;

/**
* Discovery class, for testing if this injector is valid for the given
* configuration.
*
* @var string
*/
protected $discoveryClass = ExpressiveConfigDiscovery::class;

/**
* Patterns and replacements to use when registering a code item.
Expand Down Expand Up @@ -79,26 +91,4 @@ public function __construct($projectRoot = '')

parent::__construct($projectRoot);
}

/**
* {@inheritDoc}
*
* Prepends the package with a `\\` in order to ensure it is fully
* qualified, preventing issues in config files that are namespaced.
*/
public function inject($package, $type, IOInterface $io)
{
parent::inject('\\' . $package, $type, $io);
}

/**
* {@inheritDoc}
*
* Prepends the package with a `\\` in order to ensure it is fully
* qualified, preventing issues in config files that are namespaced.
*/
public function remove($package, IOInterface $io)
{
parent::remove('\\' . $package, $io);
}
}
66 changes: 66 additions & 0 deletions test/ConfigDiscovery/ConfigAggregatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php
/**
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
* @copyright Copyright (c) 2016 Zend Technologies Ltd (http://www.zend.com)
*/

namespace ZendTest\ComponentInstaller\ConfigDiscovery;

use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use PHPUnit_Framework_TestCase as TestCase;
use Zend\ComponentInstaller\ConfigDiscovery\ConfigAggregator;

class ConfigAggregatorTest extends TestCase
{
private $configDir;

private $locator;

public function setUp()
{
$this->configDir = vfsStream::setup('project');
$this->locator = new ConfigAggregator(
vfsStream::url('project')
);
}

public function testAbsenceOfFileReturnsFalseOnLocate()
{
$this->assertFalse($this->locator->locate());
}

public function testLocateReturnsFalseWhenFileDoesNotHaveExpectedContents()
{
vfsStream::newFile('config/config.php')
->at($this->configDir)
->setContent('<' . "?php\nreturn [];");
$this->assertFalse($this->locator->locate());
}

public function validExpressiveConfigContents()
{
// @codingStandardsIgnoreStart
return [
'fqcn-short-array' => ['<' . "?php\n\$aggregator = new Zend\ConfigAggregator\ConfigAggregator([\n]);"],
'globally-qualified-short-array' => ['<' . "?php\n\$aggregator = new \Zend\ConfigAggregator\ConfigAggregator([\n]);"],
'imported-short-array' => ['<' . "?php\n\$aggregator = new ConfigAggregator([\n]);"],
'fqcn-long-array' => ['<' . "?php\n\$aggregator = new Zend\ConfigAggregator\ConfigAggregator(array(\n));"],
'globally-qualified-long-array' => ['<' . "?php\n\$aggregator = new \Zend\ConfigAggregator\ConfigAggregator(array(\n));"],
'imported-long-array' => ['<' . "?php\n\$aggregator = new ConfigAggregator(array(\n));"],
];
// @codingStandardsIgnoreEnd
}

/**
* @dataProvider validExpressiveConfigContents
*/
public function testLocateReturnsTrueWhenFileExistsAndHasExpectedContent($contents)
{
vfsStream::newFile('config/config.php')
->at($this->configDir)
->setContent($contents);

$this->assertTrue($this->locator->locate());
}
}
Loading

0 comments on commit 59e2a2b

Please sign in to comment.