Skip to content

Commit

Permalink
WIP: solution based on CompilerExtension
Browse files Browse the repository at this point in the history
  • Loading branch information
JanTvrdik committed May 8, 2016
1 parent 526c8e4 commit b004f3a
Show file tree
Hide file tree
Showing 9 changed files with 351 additions and 340 deletions.
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
"nette/utils": "~2.2"
},
"require-dev": {
"nette/di": "~2.2",
"nette/robot-loader": "~2.2",
"nette/tester": "~1.3",
"tracy/tracy": "~2.2",
"mockery/mockery": "~0.9"
},
"extra": {
Expand Down
75 changes: 0 additions & 75 deletions src/SecuredLinksControlTrait.php

This file was deleted.

135 changes: 135 additions & 0 deletions src/SecuredLinksExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php

namespace Nextras\Application\UI;

use Generator;
use Nette;
use Nette\Application\IRouter;
use Nette\Application\UI\Presenter;
use Nette\DI\PhpReflection;
use Nette\Neon\Neon;
use Nette\Utils\Strings;
use ReflectionClass;
use ReflectionMethod;


class SecuredLinksExtension extends Nette\DI\CompilerExtension
{
/**
* @inheritdoc
*/
public function beforeCompile()
{
$builder = $this->getContainerBuilder();
$builder->addDefinition($this->prefix('routerFactory'))
->setImplement(SecuredRouterFactory::class)
->setParameters(['Nette\Application\IRouter innerRouter'])
->setArguments([
$builder->literal('$innerRouter'),
'@Nette\Application\IPresenterFactory',
'@Nette\Http\Session',
$this->findSecuredPresentersMeta()
]);

$innerRouter = $builder->getByType(IRouter::class);
$builder->getDefinition($innerRouter)
->setAutowired(FALSE);

$builder->addDefinition($this->prefix('router'))
->setClass(IRouter::class)
->setFactory("@{$this->name}.routerFactory::create", ["@$innerRouter"])
->setAutowired(TRUE);
}


/**
* @return array
*/
private function findSecuredPresentersMeta()
{
$builder = $this->getContainerBuilder();
$presenters = $builder->findByType(Presenter::class);
$secured = [];

foreach ($presenters as $presenterDef) {
$presenterClass = $presenterDef->getClass();
$presenterRef = new \ReflectionClass($presenterClass);

foreach ($this->findSecuredDestinations($presenterRef) as $destination => $params) {
if (Strings::endsWith($destination, '!')) {
$key = 'do';
$value = Strings::substring($destination, 0, -1);

} else {
$key = 'action';
$value = $destination;
}

$secured[$presenterClass][$key][$value] = $params;
}
}
return $secured;
}


/**
* @param ReflectionClass $classRef
* @return Generator
*/
private function findSecuredDestinations(ReflectionClass $classRef)
{
foreach ($this->findTargetMethods($classRef) as $destination => $methodRef) {
if ($this->isSecured($methodRef, $ignoredParams)) {
yield $destination => $ignoredParams;
}
}
}


/**
* @param ReflectionClass $classRef
* @return Generator|ReflectionMethod[]
*/
private function findTargetMethods(ReflectionClass $classRef)
{
foreach ($classRef->getMethods() as $methodRef) {
$methodName = $methodRef->getName();

if (Strings::startsWith($methodName, 'action') && $classRef->isSubclassOf(Presenter::class)) {
$destination = Strings::firstLower(Strings::after($methodName, 'action'));
yield $destination => $methodRef;

} elseif (Strings::startsWith($methodName, 'handle')) {
$destination = Strings::firstLower(Strings::after($methodName, 'handle')) . '!';
yield $destination => $methodRef;

} elseif (Strings::startsWith($methodName, 'createComponent')) {
$returnType = PhpReflection::getReturnType($methodRef);
if ($returnType !== NULL) {
$returnTypeRef = new ReflectionClass($returnType);
$componentName = Strings::firstLower(Strings::after($methodName, 'createComponent'));
foreach ($this->findTargetMethods($returnTypeRef) as $innerDestination => $innerRef) {
yield "$componentName-$innerDestination" => $innerRef;
}
}
}
}
}


/**
* @param ReflectionMethod $ref
* @param array|bool $params
* @return bool
*/
private function isSecured(ReflectionMethod $ref, & $params)
{
if (preg_match('#^[ \t/*]*@secured(?:[ \t]+(\[.*?\])?|$)#m', $ref->getDocComment(), $matches)) {
$params = !empty($matches[1]) ? Neon::decode($matches[1]) : TRUE;
return TRUE;

} else {
return FALSE;
}
}
}
127 changes: 0 additions & 127 deletions src/SecuredLinksPresenterTrait.php

This file was deleted.

Loading

0 comments on commit b004f3a

Please sign in to comment.