This repository has been archived by the owner on Feb 18, 2020. It is now read-only.
-
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.
- Loading branch information
0 parents
commit c7fc888
Showing
18 changed files
with
756 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,7 @@ | ||
vendor | ||
tests/**/*.actual | ||
tests/**/*.expected | ||
tests/**/coverage.* | ||
composer.lock | ||
tests/tmp | ||
!.gitkeep |
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,29 @@ | ||
{ | ||
"name": "librette/setup", | ||
"keywords": ["nette", "librette", "di"], | ||
"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"], | ||
"authors": [ | ||
{ | ||
"name": "David Matějka", | ||
"homepage": "http://www.matej21.cz" | ||
} | ||
], | ||
"require": { | ||
"nette/di": "~2.2@dev", | ||
"nette/utils": "~2.2@dev", | ||
"nette/reflection": "~2.2@dev" | ||
}, | ||
"require-dev": { | ||
"nette/bootstrap": "~2.2@dev", | ||
"nette/neon": "~2.2@dev", | ||
"nette/php-generator": "~2.2@dev", | ||
"nette/tester": "@dev", | ||
"tracy/tracy": "~2.2@dev", | ||
"mockery/mockery": "@stable" | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"Librette\\Setup\\": "src/" | ||
} | ||
} | ||
} |
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,18 @@ | ||
<?php | ||
namespace Librette\Setup; | ||
|
||
use Nette\DI\ServiceDefinition; | ||
|
||
/** | ||
* @author David Matejka | ||
*/ | ||
interface IProcessor | ||
{ | ||
|
||
/** | ||
* @param ServiceDefinition | ||
* @param mixed | ||
* @return void | ||
*/ | ||
public function process(ServiceDefinition $definition, $args); | ||
} |
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,22 @@ | ||
<?php | ||
namespace Librette\Setup\Processors; | ||
|
||
use Librette\Setup\IProcessor; | ||
use Nette\DI\ServiceDefinition; | ||
use Nette\Object; | ||
|
||
/** | ||
* @author David Matejka | ||
*/ | ||
class InjectProcessor extends Object implements IProcessor | ||
{ | ||
|
||
|
||
public function process(ServiceDefinition $definition, $args) | ||
{ | ||
if ($args === TRUE) { | ||
$definition->setInject(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,36 @@ | ||
<?php | ||
namespace Librette\Setup\Processors; | ||
|
||
use Librette\Setup\IProcessor; | ||
use Nette\DI\ServiceDefinition; | ||
use Nette\DI\Statement; | ||
use Nette\Object; | ||
use Nette\Utils\Validators; | ||
|
||
/** | ||
* @author David Matejka | ||
*/ | ||
class SetupProcessor extends Object implements IProcessor | ||
{ | ||
|
||
|
||
public function process(ServiceDefinition $definition, $methods) | ||
{ | ||
$currentSetupMethods = array_map(function (Statement $statement) { | ||
return $statement->getEntity(); | ||
}, $definition->getSetup()); | ||
Validators::assert($methods, 'array'); | ||
foreach ($methods as $setup) { | ||
$method = $setup; | ||
$args = array(); | ||
if ($method instanceof Statement) { | ||
$args = $method->arguments; | ||
$method = $method->getEntity(); | ||
} | ||
if (!in_array($method, $currentSetupMethods)) { | ||
$definition->addSetup($method, $args); | ||
} | ||
} | ||
} | ||
|
||
} |
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,33 @@ | ||
<?php | ||
namespace Librette\Setup\Processors; | ||
|
||
use Librette\Setup\IProcessor; | ||
use Nette\DI\ServiceDefinition; | ||
use Nette\Object; | ||
|
||
/** | ||
* @author David Matejka | ||
*/ | ||
class TagsProcessor extends Object implements IProcessor | ||
{ | ||
|
||
|
||
public function process(ServiceDefinition $definition, $tags) | ||
{ | ||
if (is_string($tags)) { | ||
$tags = array($tags); | ||
} | ||
|
||
$currentTags = $definition->getTags(); | ||
foreach ((array) $tags as $tag => $attrs) { | ||
if (is_int($tag) && is_string($attrs)) { | ||
$tag = $attrs; | ||
$attrs = TRUE; | ||
} | ||
if (!isset($currentTags[$tag])) { | ||
$definition->addTag($tag, $attrs); | ||
} | ||
} | ||
} | ||
|
||
} |
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,125 @@ | ||
<?php | ||
namespace Librette\Setup; | ||
|
||
use Nette\DI\CompilerExtension; | ||
use Nette\DI\ServiceDefinition; | ||
use Nette\Reflection; | ||
|
||
|
||
/** | ||
* @author David Matejka | ||
*/ | ||
class SetupExtension extends CompilerExtension | ||
{ | ||
|
||
public $defaults = array( | ||
'processors' => array( | ||
'setup' => 'Librette\Setup\Processors\SetupProcessor', | ||
'inject' => 'Librette\Setup\Processors\InjectProcessor', | ||
'tags' => 'Librette\Setup\Processors\TagsProcessor', | ||
), | ||
'targets' => array(), | ||
); | ||
|
||
|
||
public function beforeCompile() | ||
{ | ||
$builder = $this->getContainerBuilder(); | ||
$config = $this->getConfig($this->defaults); | ||
$processors = $config['processors']; | ||
/** @var IProcessor[] $initializedProcessors */ | ||
$initializedProcessors = array(); | ||
$targets = $this->getTargets($config); | ||
/** @var ServiceDefinition $definition */ | ||
foreach ($builder->getDefinitions() as $definition) { | ||
if (!($class = $this->detectClass($definition))) { | ||
continue; | ||
} | ||
$types = self::getAllClassTypes($class); | ||
foreach ($targets as $target) { | ||
if (count(array_intersect($target['type'], $types)) === 0) { | ||
continue; | ||
} | ||
unset($target['type']); | ||
foreach ($target as $processor => $args) { | ||
if (is_int($processor)) { | ||
$processor = $args; | ||
$args = TRUE; | ||
} | ||
if (!isset($processors[$processor])) { | ||
throw new \RuntimeException("Setup processor \"{$processor}\" not exists."); | ||
} | ||
if (!isset($initializedProcessors[$processor])) { | ||
$initializedProcessors[$processor] = new $processors[$processor]($builder); | ||
} | ||
$initializedProcessors[$processor]->process($definition, $args); | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
|
||
/** | ||
* @param ServiceDefinition | ||
* @return string|null | ||
*/ | ||
protected static function detectClass(ServiceDefinition $def) | ||
{ | ||
if ($def->getClass()) { | ||
return $def->getClass(); | ||
} elseif ($interface = $def->getImplement()) { | ||
$rc = Reflection\ClassType::from($interface); | ||
$method = $rc->hasMethod('create') ? 'create' : ($rc->hasMethod('get') ? 'get' : NULL); | ||
if ($method === NULL) { | ||
return NULL; | ||
} | ||
if (!($returnType = $rc->getMethod($method)->getAnnotation('return'))) { | ||
return NULL; | ||
} | ||
|
||
return Reflection\AnnotationsParser::expandClassName(preg_replace('#[|\s].*#', '', $returnType), $rc); | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
|
||
/** | ||
* @param string | ||
* @return array | ||
*/ | ||
protected static function getAllClassTypes($class) | ||
{ | ||
$rc = Reflection\ClassType::from($class); | ||
$classTypes = array_merge(array($class), class_parents($class), class_implements($class)); | ||
if(PHP_VERSION_ID >= 50400) { | ||
do { | ||
$classTypes = array_merge($classTypes, $rc->getTraitNames()); | ||
} while ($rc = $rc->getParentClass()); | ||
} | ||
|
||
return array_map(function ($val) { | ||
return ltrim(strtolower($val), '\\'); | ||
}, $classTypes); | ||
} | ||
|
||
|
||
/** | ||
* @param array | ||
* @return array | ||
*/ | ||
protected function getTargets($config) | ||
{ | ||
$targets = $config['targets']; | ||
unset($config['processors'], $config['targets']); | ||
$targets = array_merge($targets, $config); | ||
foreach ($targets as &$target) { | ||
$target['type'] = array_map(function ($val) { | ||
return ltrim(strtolower($val), '\\'); | ||
}, (array) $target['type']); | ||
} | ||
|
||
return $targets; | ||
} | ||
} |
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,36 @@ | ||
<?php | ||
namespace LibretteTests\Setup; | ||
|
||
use Librette; | ||
use Nette; | ||
use Tester\TestCase; | ||
|
||
require __DIR__ . '/mocks.php'; | ||
|
||
|
||
abstract class CompilerExtensionTestCase extends TestCase | ||
{ | ||
|
||
|
||
protected function createExtension($targets) | ||
{ | ||
$config = array( | ||
'processors' => array( | ||
'test' => 'LibretteTests\Setup\TestProcessor', | ||
), | ||
'targets' => $targets, | ||
); | ||
$compiler = \Mockery::mock('Nette\DI\Compiler'); | ||
$builder = new Nette\DI\ContainerBuilder(); | ||
$compiler->shouldReceive('getContainerBuilder')->andReturn($builder); | ||
$compiler->shouldReceive('getConfig')->andReturn(array('setup' => $config)); | ||
$builder->addDefinition('foo')->setClass('LibretteTests\Setup\Foo'); | ||
$builder->addDefinition('bar')->setClass('LibretteTests\Setup\Bar'); | ||
$extension = new Librette\Setup\SetupExtension(); | ||
$extension->setCompiler($compiler, 'setup'); | ||
|
||
return $extension; | ||
|
||
} | ||
|
||
} |
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,41 @@ | ||
<?php | ||
namespace LibretteTests\Setup; | ||
|
||
use Librette; | ||
use Nette; | ||
use Tester; | ||
|
||
require_once __DIR__ . '/../bootstrap.php'; | ||
require_once __DIR__ . '/mocks.php'; | ||
|
||
|
||
/** | ||
* @author David Matějka | ||
*/ | ||
class ConfiguratorTestCase extends Tester\TestCase | ||
{ | ||
|
||
public function setUp() | ||
{ | ||
} | ||
|
||
|
||
public function testConfigurator() | ||
{ | ||
$configurator = new Nette\Configurator(); | ||
$configurator->defaultExtensions = array_intersect_key($configurator->defaultExtensions, array('extensions' => TRUE)); | ||
$configurator->autowireExcludedClasses = array(); | ||
$configurator->setTempDirectory(TEMP_DIR); | ||
$configurator->addConfig(__DIR__ . '/config/basic.neon'); | ||
|
||
/** @var Nette\DI\Container $container */ | ||
$container = $configurator->createContainer(); | ||
/** @var Bar $bar */ | ||
$bar = $container->getService('bar'); | ||
Tester\Assert::same($container->getService('foo'), $bar->foo); | ||
Tester\Assert::same($container->getService('lorem'), $bar->lorem); | ||
} | ||
} | ||
|
||
|
||
\run(new ConfiguratorTestCase()); |
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,38 @@ | ||
<?php | ||
namespace LibretteTests\Setup; | ||
|
||
use Librette; | ||
use Nette; | ||
use Tester; | ||
|
||
require_once __DIR__ . '/../bootstrap.php'; | ||
|
||
|
||
/** | ||
* @author David Matějka | ||
*/ | ||
class InjectProcessorTestCase extends CompilerExtensionTestCase | ||
{ | ||
|
||
public function setUp() | ||
{ | ||
} | ||
|
||
|
||
public function testInject() | ||
{ | ||
$extension = $this->createExtension(array( | ||
array( | ||
'type' => 'LibretteTests\Setup\Bar', | ||
'inject' => TRUE, | ||
) | ||
)); | ||
$builder = $extension->getContainerBuilder(); | ||
$extension->beforeCompile(); | ||
Tester\Assert::false($builder->getDefinition('foo')->getInject()); | ||
Tester\Assert::true($builder->getDefinition('bar')->getInject()); | ||
} | ||
} | ||
|
||
|
||
\run(new InjectProcessorTestCase()); |
Oops, something went wrong.