-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial commit of the extenstion driver locator component
- Loading branch information
Tibor Kotosz
committed
Nov 8, 2015
1 parent
21c6ebe
commit 378dc91
Showing
7 changed files
with
381 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Composer packages directory | ||
/vendor | ||
|
||
# Composer executable files directory | ||
/bin |
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,31 @@ | ||
{ | ||
"name": "bex/behat-extension-driver-locator", | ||
"type": "library", | ||
"description": "Driver locator tool for behat extensions", | ||
"keywords": ["tdd","bdd","behat"], | ||
"homepage": "https://github.com/tkotosz/behat-extension-driver-locator", | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "Tibor Kotosz", | ||
"email": "[email protected]", | ||
"homepage": "https://github.com/tkotosz", | ||
"role": "Developer" | ||
} | ||
], | ||
"require": { | ||
"php" : "^5.4", | ||
"behat/behat" : "^3.0.0" | ||
}, | ||
"require-dev": { | ||
"phpspec/phpspec" : "^2.3.0" | ||
}, | ||
"config": { | ||
"bin-dir": "bin" | ||
}, | ||
"autoload": { | ||
"psr-0": { | ||
"": "src" | ||
} | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
src/Bex/Behat/ExtensionDriverLocator/DriverClassNameResolver.php
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,45 @@ | ||
<?php | ||
|
||
namespace Bex\Behat\ExtensionDriverLocator; | ||
|
||
use Bex\Behat\ExtensionDriverLocator\ClassValidator; | ||
use Symfony\Component\DependencyInjection\Container as DIContainer; | ||
|
||
class DriverClassNameResolver | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
private $namespace; | ||
|
||
/** | ||
* @var ClassValidator | ||
*/ | ||
private $classValidator; | ||
|
||
/** | ||
* @param string $namespace | ||
* @param ClassValidator $classValidator | ||
*/ | ||
public function __construct($namespace, ClassValidator $classValidator) | ||
{ | ||
$this->namespace = $namespace; | ||
$this->classValidator = $classValidator; | ||
} | ||
|
||
/** | ||
* @param string $driverKey | ||
* | ||
* @return string | ||
*/ | ||
public function getClassNameByDriverKey($driverKey) | ||
{ | ||
$driverClass = $this->namespace . '\\' . ucfirst(DIContainer::camelize($driverKey)); | ||
|
||
if (!$this->classValidator->isValidDriverClass($driverClass)) { | ||
throw new \Exception(sprintf('Driver %s was not found in %s', $driverKey, $driverClass)); | ||
} | ||
|
||
return $driverClass; | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
src/Bex/Behat/ExtensionDriverLocator/DriverClassValidator.php
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,44 @@ | ||
<?php | ||
|
||
namespace Bex\Behat\ExtensionDriverLocator; | ||
|
||
use Bex\Behat\ExtensionDriverLocator\DriverInterface; | ||
|
||
|
||
class DriverClassValidator | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
private $parent; | ||
|
||
/** | ||
* @param string $parent | ||
*/ | ||
public function __construct($parent = '') | ||
{ | ||
$this->parent = $parent; | ||
} | ||
|
||
/** | ||
* @param string $className | ||
* | ||
* @return boolean | ||
*/ | ||
public function isValidDriverClass($className) | ||
{ | ||
if (!class_exists($className)) { | ||
return false; | ||
} | ||
|
||
if (!is_subclass_of($className, DriverInterface::class)) { | ||
return false; | ||
} | ||
|
||
if (!empty($this->parent) && !is_subclass_of($className, $this->parent)) { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
} |
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,24 @@ | ||
<?php | ||
|
||
namespace Bex\Behat\ExtensionDriverLocator; | ||
|
||
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; | ||
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
|
||
interface DriverInterface | ||
{ | ||
/** | ||
* @param ArrayNodeDefinition $builder | ||
* | ||
* @return void | ||
*/ | ||
public function configure(ArrayNodeDefinition $builder); | ||
|
||
/** | ||
* @param ContainerBuilder $container | ||
* @param array $config | ||
* | ||
* @return void | ||
*/ | ||
public function load(ContainerBuilder $container, array $config); | ||
} |
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,133 @@ | ||
<?php | ||
|
||
namespace Bex\Behat\ExtensionDriverLocator; | ||
|
||
use Bex\Behat\ExtensionDriverLocator\DriverInterface; | ||
use Bex\Behat\ExtensionDriverLocator\ClassNameResolver; | ||
use Bex\Behat\ExtensionDriverLocator\ClassValidator; | ||
use Symfony\Component\Config\Definition\Builder\TreeBuilder; | ||
use Symfony\Component\Config\Definition\NodeInterface; | ||
use Symfony\Component\Config\Definition\Processor; | ||
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
|
||
class DriverLocator | ||
{ | ||
/** | ||
* @var ClassNameResolver | ||
*/ | ||
private $classNameResolver; | ||
|
||
/** | ||
* @var DriverInterface[] | ||
*/ | ||
private $drivers = []; | ||
|
||
/** | ||
* @param ClassNameResolver $classNameResolver | ||
*/ | ||
public function __construct(ClassNameResolver $classNameResolver) | ||
{ | ||
$this->classNameResolver = $classNameResolver; | ||
} | ||
|
||
/** | ||
* @param string $namespace | ||
* @param string $parent | ||
* | ||
* @return Locator | ||
*/ | ||
public static function getInstance($namespace, $parent = '') | ||
{ | ||
return new self(new ClassNameResolver($namespace, new ClassValidator($parent))); | ||
} | ||
|
||
/** | ||
* @param ContainerBuilder $container | ||
* @param array $configs | ||
* | ||
* @return DriverInterface[] | ||
*/ | ||
public function findDrivers(ContainerBuilder $container, array $activeDrivers, array $driverConfigs) | ||
{ | ||
$this->createDrivers($activeDrivers); | ||
$configTree = $this->configureDrivers($driverConfigs); | ||
$driverConfigs = $this->processDriverConfiguration($configTree, $driverConfigs); | ||
$this->loadDrivers($container, $driverConfigs); | ||
|
||
return $this->drivers; | ||
} | ||
|
||
/** | ||
* @return DriverInterface[] | ||
*/ | ||
public function getDrivers() | ||
{ | ||
return $this->drivers; | ||
} | ||
|
||
/** | ||
* @param array $driverKeys | ||
* | ||
* @return DriverInterface[] | ||
*/ | ||
private function createDrivers($driverKeys) | ||
{ | ||
$this->drivers = []; | ||
|
||
foreach ($driverKeys as $driverKey) { | ||
$driverClass = $this->classNameResolver->getClassNameByDriverKey($driverKey); | ||
$this->drivers[$driverKey] = new $driverClass(); | ||
} | ||
|
||
return $this->drivers; | ||
} | ||
|
||
/** | ||
* @param array $driverConfigs | ||
* | ||
* @return NodeInterface | ||
*/ | ||
private function configureDrivers($driverConfigs) | ||
{ | ||
$tree = new TreeBuilder(); | ||
$root = $tree->root('drivers'); | ||
|
||
foreach ($this->drivers as $driverKey => $driver) { | ||
$driver->configure($root->children()->arrayNode($driverKey)); | ||
} | ||
|
||
return $tree->buildTree(); | ||
} | ||
|
||
/** | ||
* @param NodeInterface $configTree | ||
* @param array $configs | ||
* | ||
* @return array The processed configuration | ||
*/ | ||
private function processDriverConfiguration(NodeInterface $configTree, array $configs) | ||
{ | ||
$configProcessor = new Processor(); | ||
|
||
foreach ($this->drivers as $driverKey => $driver) { | ||
$configs[$driverKey] = isset($configs[$driverKey]) ? $configs[$driverKey] : []; | ||
} | ||
|
||
return $configProcessor->process($configTree, ['drivers' => $configs]); | ||
} | ||
|
||
/** | ||
* @param ContainerBuilder $container | ||
* @param array $driverConfigs | ||
* | ||
* @return DriverInterface[] | ||
*/ | ||
private function loadDrivers(ContainerBuilder $container, array $driverConfigs) | ||
{ | ||
foreach ($this->drivers as $driverKey => $driver) { | ||
$driver->load($container, $driverConfigs[$driverKey]); | ||
} | ||
|
||
return $this->drivers; | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
src/Bex/Behat/ExtensionDriverLocator/DriverNodeBuilder.php
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,99 @@ | ||
<?php | ||
|
||
namespace Bex\Behat\ExtensionDriverLocator; | ||
|
||
use Bex\Behat\ExtensionDriverLocator\ClassNameResolver; | ||
use Bex\Behat\ExtensionDriverLocator\ClassValidator; | ||
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; | ||
|
||
class DriverNodeBuilder | ||
{ | ||
/** | ||
* @var ClassNameResolver | ||
*/ | ||
private $driverClassNameResolver; | ||
|
||
/** | ||
* @param ClassNameResolver $driverClassNameResolver | ||
*/ | ||
public function __construct(ClassNameResolver $driverClassNameResolver) | ||
{ | ||
$this->driverClassNameResolver = $driverClassNameResolver; | ||
} | ||
|
||
/** | ||
* @param string $namespace | ||
* @param string $parent | ||
* | ||
* @return NodeBuilder | ||
*/ | ||
public static function getInstance($namespace, $parent = '') | ||
{ | ||
return new self(new ClassNameResolver($namespace, new ClassValidator($parent))); | ||
} | ||
|
||
/** | ||
* @param ArrayNodeDefinition $builder | ||
* @param string $activeDriversNodeName | ||
* @param string $driversNodeName | ||
* @param array $defaultActiveDrivers | ||
* | ||
* @return void | ||
*/ | ||
public function buildDriverNodes( | ||
ArrayNodeDefinition $builder, | ||
$activeDriversNodeName, | ||
$driversNodeName, | ||
$defaultActiveDrivers | ||
) { | ||
$builder | ||
->children() | ||
->arrayNode($activeDriversNodeName) | ||
->defaultValue($defaultActiveDrivers) | ||
->beforeNormalization() | ||
->ifString() | ||
->then($this->getDefaultValueInitializer()) | ||
->end() | ||
->validate() | ||
->ifTrue($this->getDriverKeyValidator()) | ||
->thenInvalid('%s') | ||
->end() | ||
->prototype('scalar')->end() | ||
->end() | ||
->end() | ||
->fixXmlConfig($driversNodeName . '_child', $driversNodeName) | ||
->children() | ||
->arrayNode($driversNodeName) | ||
->prototype('array') | ||
->prototype('scalar')->end() | ||
->end() | ||
->end() | ||
->end(); | ||
} | ||
|
||
/** | ||
* @return \Closure | ||
*/ | ||
private function getDefaultValueInitializer() | ||
{ | ||
return function ($value) { | ||
return [$value]; | ||
}; | ||
} | ||
|
||
/** | ||
* @return \Closure | ||
*/ | ||
private function getDriverKeyValidator() | ||
{ | ||
$classNameResolver = $this->driverClassNameResolver; | ||
|
||
return function ($driverKeys) use ($classNameResolver) { | ||
foreach ($driverKeys as $driverKey) { | ||
$classNameResolver->getClassNameByDriverKey($driverKey); | ||
} | ||
|
||
return false; | ||
}; | ||
} | ||
} |