diff --git a/.scrutinizer.yml b/.scrutinizer.yml
index c6eb21b..ef2824c 100644
--- a/.scrutinizer.yml
+++ b/.scrutinizer.yml
@@ -3,6 +3,7 @@ filter:
- src/*
excluded_paths:
- tests/*
+ - src/data/*
tools:
php_code_sniffer:
config:
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1c58f27
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Yuuki Takezawa
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/README.md b/README.md
index 927e764..748fb63 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# Laravel-Aspect
-for laravel framework(use Go!Aop Framework)
+for laravel framework
[![Build Status](http://img.shields.io/travis/ytake/Laravel-Aspect/master.svg?style=flat-square)](https://travis-ci.org/ytake/Laravel-Aspect)
[![Coverage Status](http://img.shields.io/coveralls/ytake/Laravel-Aspect/master.svg?style=flat-square)](https://coveralls.io/r/ytake/Laravel-Aspect?branch=master)
@@ -13,7 +13,7 @@ for laravel framework(use Go!Aop Framework)
[![Latest Version](http://img.shields.io/packagist/v/ytake/laravel-aspect.svg?style=flat-square)](https://packagist.org/packages/ytake/laravel-aspect)
[![Total Downloads](http://img.shields.io/packagist/dt/ytake/laravel-aspect.svg?style=flat-square)](https://packagist.org/packages/ytake/laravel-aspect)
-## usage
+## usage
### install
@@ -41,6 +41,33 @@ $ composer require ytake/laravel-aspect
]
```
+### publish aspect module class
+
+```bash
+$ php artisan ytake:aspect-module-publish
+```
+more command options [--help]
+
+### aspect kernel boot
+
+added serviceProvider Class
+
+```php
+class AppServiceProvider extends ServiceProvider
+{
+ /**
+ * @return void
+ */
+ public function boot()
+ {
+ /** @var \Ytake\LaravelAspect\AspectManager $aspect */
+ $aspect = $this->app['aspect.manager'];
+ $aspect->register(\App\Modules\CacheableModule::class);
+ }
+
+}
+```
+
### publish configure
* basic
@@ -69,7 +96,7 @@ $ php artisan ytake:aspect-clear-cache
## Annotations
-### @Transactional(Around Advice)
+### @Transactional
for database transaction(illuminate/database)
* option
@@ -90,7 +117,7 @@ public function save(array $params)
}
```
-### @Cacheable(After Advice)
+### @Cacheable
for cache(illuminate/cache)
* option
@@ -118,7 +145,7 @@ public function namedMultipleKey($id, $value)
}
```
-### @CacheEvict(After Advice)
+### @CacheEvict
for cache(illuminate/cache) / remove cache
* option
@@ -144,7 +171,7 @@ public function removeCache()
}
```
-### @CachePut(After Advice)
+### @CachePut
for cache(illuminate/cache) / cache put
* option
@@ -169,23 +196,38 @@ public function throwExceptionCache()
}
```
-## add Interceptors
+### @Loggable
+
+soon
-your service provider's
+### Annotation Cache Driver
+
+chose array driver or file cache driver
+
+use config/ytake-laravel-aspect.php file
```php
-public function boot()
-{
- $this->app['aspect.annotation.register']->registerAnnotations([
- app_path() . '/Annotation/Finder.php',
- ]);
-
- $this->app['aspect.manager']->setAspects([
- \App\Interceptor\SampleInterceptor::class
- ]);
-}
+ 'annotation' => [
+ /**
+ * choose annotation reader
+ * 'array'(default), 'file'(file cache)
+ */
+ 'default' => env('ASPECT_ANNOTATION_DRIVER', 'array'),
+
+ 'drivers' => [
+ 'file' => [
+ 'cache_dir' => storage_path('framework/annotation'),
+ //
+ 'debug' => env('ASPECT_ANNOTATION_DEBUG', true),
+ ],
+ ],
+ ],
```
+## add Interceptors
+
+soon
+
## for testing
use none driver
diff --git a/composer.json b/composer.json
index e0e590e..57203d8 100644
--- a/composer.json
+++ b/composer.json
@@ -18,12 +18,14 @@
],
"require": {
"php": ">=5.5.9",
- "goaop/framework": "~0.0",
"illuminate/console": "~5.0",
"illuminate/filesystem": "~5.0",
"illuminate/support": "~5.0",
"illuminate/config": "~5.0",
- "doctrine/annotations": "~1.0"
+ "illuminate/contracts": "~5.0",
+ "ray/aop": "~2.0",
+ "doctrine/annotations": "~1.0",
+ "doctrine/cache": "~1.0"
},
"require-dev": {
"symfony/framework-bundle": "2.*",
@@ -41,7 +43,8 @@
},
"autoload-dev": {
"files": [
- "tests/TestCase.php"
+ "tests/TestCase.php",
+ "tests/helper.php"
],
"psr-4": {
"__Test\\": "tests/src"
diff --git a/phpunit.xml b/phpunit.xml
index 8ad538a..24e3cc5 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -20,6 +20,7 @@
./src
./src/config
+ ./src/data
./src/AspectServiceProvider.php
./src/CompileServiceProvider.php
./src/ConsoleServiceProvider.php
diff --git a/src/Annotation.php b/src/Annotation.php
index 423c9b2..6268c10 100644
--- a/src/Annotation.php
+++ b/src/Annotation.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
*/
class Annotation
{
@@ -34,16 +42,15 @@ public function registerAnnotations(array $files)
}
/**
- * use annotations
- *
- * @return void
+ * @throws FileNotFoundException
*/
public function registerAspectAnnotations()
{
foreach ($this->files as $file) {
- if (file_exists($file)) {
- AnnotationRegistry::registerFile($file);
+ if (!file_exists($file)) {
+ throw new FileNotFoundException($file);
}
+ AnnotationRegistry::registerFile($file);
}
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Transactional.php');
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Cacheable.php');
diff --git a/src/Annotation/AnnotationReaderTrait.php b/src/Annotation/AnnotationReaderTrait.php
new file mode 100644
index 0000000..5226dab
--- /dev/null
+++ b/src/Annotation/AnnotationReaderTrait.php
@@ -0,0 +1,53 @@
+reader = $reader;
+ }
+
+ /**
+ * @param string $annotation
+ */
+ public function setAnnotation($annotation)
+ {
+ $this->annotation = $annotation;
+ }
+}
diff --git a/src/Annotation/CacheEvict.php b/src/Annotation/CacheEvict.php
index 60dc77d..be39dcc 100644
--- a/src/Annotation/CacheEvict.php
+++ b/src/Annotation/CacheEvict.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
*/
final class CacheEvict extends Annotation
{
diff --git a/src/Annotation/CachePut.php b/src/Annotation/CachePut.php
index e7a0e52..bdd64e7 100644
--- a/src/Annotation/CachePut.php
+++ b/src/Annotation/CachePut.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
*/
final class CachePut extends Annotation
{
diff --git a/src/Annotation/Cacheable.php b/src/Annotation/Cacheable.php
index 6760e8d..7c89b48 100644
--- a/src/Annotation/Cacheable.php
+++ b/src/Annotation/Cacheable.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
*/
final class Cacheable extends Annotation
{
diff --git a/src/Annotation/Transactional.php b/src/Annotation/Transactional.php
index 63b0400..5b4aff6 100644
--- a/src/Annotation/Transactional.php
+++ b/src/Annotation/Transactional.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
*/
final class Transactional extends Annotation
{
diff --git a/src/AnnotationManager.php b/src/AnnotationManager.php
new file mode 100644
index 0000000..15de135
--- /dev/null
+++ b/src/AnnotationManager.php
@@ -0,0 +1,68 @@
+app['config']->get('ytake-laravel-aop.annotation.default');
+ }
+
+ /**
+ * @return ArrayReader
+ */
+ protected function createArrayDriver()
+ {
+ return new ArrayReader();
+ }
+
+ /**
+ * @return FileReader
+ */
+ protected function createFileDriver()
+ {
+ return new FileReader($this->getConfigure('file'));
+ }
+
+ /**
+ * @param string $driver
+ * @return string[]
+ */
+ protected function getConfigure($driver)
+ {
+ $annotationConfigure = $this->app['config']->get('ytake-laravel-aop.annotation.drivers');
+
+ return $annotationConfigure[$driver];
+ }
+}
diff --git a/src/NullAspect.php b/src/AnnotationReadable.php
similarity index 53%
rename from src/NullAspect.php
rename to src/AnnotationReadable.php
index 1b9b079..64164f5 100644
--- a/src/NullAspect.php
+++ b/src/AnnotationReadable.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
+ * Interface AnnotationReadable
*/
-class NullAspect implements AspectDriverInterface
+interface AnnotationReadable
{
/**
- * initialize aspect kernel
- *
- * @return void
- */
- public function register()
- {
- return;
- }
-
- /**
- * @param array $classes
+ * @return Reader
*/
- public function setAspects(array $classes)
- {
- return;
- }
+ public function getReader();
}
diff --git a/src/ArrayReader.php b/src/ArrayReader.php
new file mode 100644
index 0000000..d4b8bb9
--- /dev/null
+++ b/src/ArrayReader.php
@@ -0,0 +1,39 @@
+
- * @license http://opensource.org/licenses/MIT MIT
- */
-final class AspectKernel extends LaravelKernel
-{
- /** @var array */
- protected $aspects;
-
- /**
- * @param array $classes
- */
- public function setAop(array $classes)
- {
- $this->aspects = $classes;
- }
-
- /**
- * @inheritdoc
- */
- protected function configureAop(AspectContainer $container)
- {
- if ($this->aspects) {
- foreach ($this->aspects as $aspect) {
- $container->registerAspect($this->laravel->make($aspect));
- }
- }
- $container->registerAspect(new TransactionalAspect($this->laravel['db']));
- $container->registerAspect(new CacheableAspect($this->laravel['cache']));
- $container->registerAspect(new CacheEvictAspect($this->laravel['cache']));
- $container->registerAspect(new CachePutAspect($this->laravel['cache']));
- }
-}
diff --git a/src/Aspect/LaravelKernel.php b/src/Aspect/LaravelKernel.php
deleted file mode 100644
index 6584369..0000000
--- a/src/Aspect/LaravelKernel.php
+++ /dev/null
@@ -1,36 +0,0 @@
-
- * @license http://opensource.org/licenses/MIT MIT
- */
-abstract class LaravelKernel extends CoreKernel
-{
- /** @var LaravelApplication */
- protected $laravel;
-
- /**
- * @param LaravelApplication $laravel
- */
- public function setLaravel(LaravelApplication $laravel)
- {
- $this->laravel = $laravel;
- }
-}
diff --git a/src/Aspect/TransactionalAspect.php b/src/Aspect/TransactionalAspect.php
deleted file mode 100644
index cfb9381..0000000
--- a/src/Aspect/TransactionalAspect.php
+++ /dev/null
@@ -1,61 +0,0 @@
-
- * @license http://opensource.org/licenses/MIT MIT
- */
-class TransactionalAspect implements Aspect
-{
- /** @var ConnectionResolverInterface */
- protected $db;
-
- /**
- * @param ConnectionResolverInterface $db
- */
- public function __construct(ConnectionResolverInterface $db)
- {
- $this->db = $db;
- }
-
- /**
- * @Around("@annotation(Ytake\LaravelAspect\Annotation\Transactional)")
- * @param MethodInvocation $invocation
- * @return mixed
- */
- public function aroundMethodExecution(MethodInvocation $invocation)
- {
- $connection = $invocation->getMethod()
- ->getAnnotation('Ytake\LaravelAspect\Annotation\Transactional')->value;
- $database = $this->db->connection($connection);
- $database->beginTransaction();
- try {
- $result = $invocation->proceed();
- $database->commit();
-
- return $result;
- } catch (QueryException $exception) {
- $database->rollBack();
- throw $exception;
- }
- }
-}
diff --git a/src/AspectDriverInterface.php b/src/AspectDriverInterface.php
index 8fefcbd..12ec52a 100644
--- a/src/AspectDriverInterface.php
+++ b/src/AspectDriverInterface.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
*/
interface AspectDriverInterface
{
/**
- * @return mixed
- */
- public function register();
-
- /**
- * add user aspect script
+ * @param null $module
+ * @return void
*/
- public function setAspects(array $classes);
+ public function register($module = null);
}
diff --git a/src/AspectManager.php b/src/AspectManager.php
index 37df790..1b18c3f 100644
--- a/src/AspectManager.php
+++ b/src/AspectManager.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
+ * @method void register() register(string $module)
*/
class AspectManager extends Manager
{
/**
* for go-aop driver
*
- * @return GoAspect
+ * @return RayAspectKernel
*/
- protected function createGoDriver()
+ protected function createRayDriver()
{
- return new GoAspect(
+ return new RayAspectKernel(
$this->app,
- $this->getConfigure('go')
+ new Bind(),
+ $this->getConfigure('ray')
);
}
+ /**
+ * @return NullAspectKernel
+ */
protected function createNoneDriver()
{
- return new NullAspect();
+ return new NullAspectKernel();
}
/**
- * @inheritdoc
+ * {@inheritdoc}
*/
public function getDefaultDriver()
{
- return $this->app['config']->get('ytake-laravel-aop.default');
+ return $this->app['config']->get('ytake-laravel-aop.aspect.default');
}
/**
- * @param $driver
- * @return mixed
+ * @param string $driver
+ * @return string[]
*/
protected function getConfigure($driver)
{
- $aspectConfigure = $this->app['config']->get('ytake-laravel-aop.aop');
+ $aspectConfigure = $this->app['config']->get('ytake-laravel-aop.aspect.drivers');
return $aspectConfigure[$driver];
}
diff --git a/src/AspectServiceProvider.php b/src/AspectServiceProvider.php
index 5472ace..0634f64 100644
--- a/src/AspectServiceProvider.php
+++ b/src/AspectServiceProvider.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
*/
class AspectServiceProvider extends ServiceProvider
{
+ /** @var bool */
+ protected $defer = true;
+
/**
- * @inheritdoc
+ * boot serivce
*/
public function boot()
{
// register annotation
- $this->app->make('aspect.annotation.register')->registerAspectAnnotations();
- // annotation driver
- $this->app->make('aspect.manager')->register();
+ $this->app['aspect.annotation.register']->registerAspectAnnotations();
}
/**
- * @inheritdoc
+ * {@inheritdoc}
*/
public function register()
{
@@ -45,7 +53,13 @@ public function register()
$this->mergeConfigFrom($configPath, 'ytake-laravel-aop');
$this->publishes([$configPath => config_path('ytake-laravel-aop.php')], 'aspect');
- $this->registerAspectAnnotations();
+ $this->app->singleton('aspect.annotation.register', function () {
+ return new Annotation();
+ });
+
+ $this->app->singleton('aspect.annotation.reader', function ($app) {
+ return (new AnnotationManager($app))->getReader();
+ });
$this->app->singleton('aspect.manager', function ($app) {
return new AspectManager($app);
@@ -53,12 +67,14 @@ public function register()
}
/**
- * @return void
+ * {@inheritdoc}
*/
- protected function registerAspectAnnotations()
+ public function provides()
{
- $this->app->singleton('aspect.annotation.register', function () {
- return new Annotation();
- });
+ return [
+ 'aspect.annotation.register',
+ 'aspect.annotation.reader',
+ 'aspect.manager'
+ ];
}
}
diff --git a/src/CodeGen.php b/src/CodeGen.php
new file mode 100644
index 0000000..0f67ee5
--- /dev/null
+++ b/src/CodeGen.php
@@ -0,0 +1,158 @@
+parser = $parser;
+ $this->factory = $factory;
+ $this->printer = $printer;
+ $this->codeGenMethod = new CodeGenMethod($parser, $factory, $printer);
+ }
+
+ /**
+ * @param string $class
+ * @param \ReflectionClass $sourceClass
+ *
+ * @return string
+ */
+ public function generate($class, \ReflectionClass $sourceClass, BindInterface $bind)
+ {
+ $methods = $this->codeGenMethod->getMethods($sourceClass, $bind);
+ $stmt = $this
+ ->getClass($class, $sourceClass)
+ ->addStmts($methods)
+ ->getNode();
+ $stmt = $this->addClassDocComment($stmt, $sourceClass);
+ $code = $this->printer->prettyPrint([$stmt]);
+ $statements = $this->getUseStatements($sourceClass);
+
+ return $statements . $code;
+ }
+
+ /**
+ * @param \ReflectionClass $class
+ *
+ * @return string
+ */
+ private function getUseStatements(\ReflectionClass $class)
+ {
+ $traverser = new NodeTraverser();
+ $useStmtsVisitor = new CodeGenVisitor();
+ $traverser->addVisitor($useStmtsVisitor);
+ // parse
+ $stmts = $this->parser->parse(file_get_contents($class->getFileName()));
+ // traverse
+ $traverser->traverse($stmts);
+ // pretty print
+ $code = $this->printer->prettyPrint($useStmtsVisitor());
+
+ return (string)$code;
+ }
+
+ /**
+ * Return class statement
+ *
+ * @param string $newClassName
+ * @param \ReflectionClass $class
+ *
+ * @return \PhpParser\Builder\Class_
+ */
+ private function getClass($newClassName, \ReflectionClass $class)
+ {
+ $parentClass = $class->name;
+ $builder = $this->factory
+ ->class($newClassName)
+ ->extend($parentClass)
+ ->implement('Ray\Aop\WeavedInterface')
+ ->addStmt(
+ $this->factory->property('isIntercepting')->makePrivate()->setDefault(true)
+ )->addStmt(
+ $this->factory->property('bind')->makePublic()
+ );
+
+ return $builder;
+ }
+
+ /**
+ * Add class doc comment
+ *
+ * @param Class_ $node
+ * @param \ReflectionClass $class
+ *
+ * @return \PHPParser\Node\Stmt\Class_
+ */
+ private function addClassDocComment(Class_ $node, \ReflectionClass $class)
+ {
+ $docComment = $class->getDocComment();
+ if ($docComment) {
+ $node->setAttribute('comments', [new Doc($docComment)]);
+ }
+
+ return $node;
+ }
+}
diff --git a/src/CodeGenMethod.php b/src/CodeGenMethod.php
new file mode 100644
index 0000000..3a7e68d
--- /dev/null
+++ b/src/CodeGenMethod.php
@@ -0,0 +1,191 @@
+parser = $parser;
+ $this->factory = $factory;
+ $this->printer = $printer;
+ }
+
+ /**
+ * @param \ReflectionClass $class
+ * @param BindInterface $bind
+ *
+ * @return array
+ */
+ public function getMethods(\ReflectionClass $class, BindInterface $bind)
+ {
+ $bindingMethods = array_keys($bind->getBindings());
+ $stmts = [];
+ $methods = $class->getMethods();
+ foreach ($methods as $method) {
+ $isBindingMethod = in_array($method->getName(), $bindingMethods);
+ /* @var $method \ReflectionMethod */
+ if ($isBindingMethod && $method->isPublic()) {
+ $stmts[] = $this->getMethod($method);
+ }
+ }
+
+ return $stmts;
+ }
+
+ /**
+ * Return method statement
+ *
+ * @param \ReflectionMethod $method
+ *
+ * @return \PhpParser\Node\Stmt\ClassMethod
+ */
+ private function getMethod(\ReflectionMethod $method)
+ {
+ $methodStmt = $this->factory->method($method->name);
+ $params = $method->getParameters();
+ foreach ($params as $param) {
+ $methodStmt = $this->getMethodStatement($param, $methodStmt);
+ }
+ $methodInsideStatements = $this->getMethodInsideStatement();
+ $methodStmt->addStmts($methodInsideStatements);
+ $node = $this->addMethodDocComment($methodStmt, $method);
+
+ return $node;
+ }
+
+ /**
+ * Return parameter reflection
+ *
+ * @param \ReflectionParameter $param
+ * @param \PHPParser\Builder\Method $methodStmt
+ *
+ * @return \PHPParser\Builder\Method
+ */
+ private function getMethodStatement(\ReflectionParameter $param, Method $methodStmt)
+ {
+ /** @var $paramStmt Param */
+ $paramStmt = $this->factory->param($param->name);
+ /* @var $param \ReflectionParameter */
+ $typeHint = $param->getClass();
+ $this->setTypeHint($param, $paramStmt, $typeHint);
+ $this->setDefault($param, $paramStmt);
+ $methodStmt->addParam($paramStmt);
+
+ return $methodStmt;
+ }
+
+ /**
+ * @param Method $methodStmt
+ * @param \ReflectionMethod $method
+ *
+ * @return \PhpParser\Node\Stmt\ClassMethod
+ */
+ private function addMethodDocComment(Method $methodStmt, \ReflectionMethod $method)
+ {
+ $node = $methodStmt->getNode();
+ $docComment = $method->getDocComment();
+ if ($docComment) {
+ $node->setAttribute('comments', [new Doc($docComment)]);
+ }
+
+ return $node;
+ }
+
+ /**
+ * @return \PHPParser\Node[]
+ */
+ private function getMethodInsideStatement()
+ {
+ // fixed call parent method
+ $code = file_get_contents(__DIR__ . '/data/CodeTemplate.php');
+ $node = $this->parser->parse($code)[0];
+ /** @var $node \PHPParser\Node\Stmt\Class_ */
+ $node = $node->getMethods()[0];
+
+ return $node->stmts;
+ }
+
+ /**
+ * @param \ReflectionParameter $param
+ * @param Param $paramStmt
+ * @param \ReflectionClass $typeHint
+ */
+ private function setTypeHint(\ReflectionParameter $param, Param $paramStmt, \ReflectionClass $typeHint = null)
+ {
+ if ($typeHint) {
+ $paramStmt->setTypeHint($typeHint->name);
+ }
+ if ($param->isArray()) {
+ $paramStmt->setTypeHint('array');
+ }
+ if ($param->isCallable()) {
+ $paramStmt->setTypeHint('callable');
+ }
+ }
+
+ /**
+ * @param \ReflectionParameter $param
+ * @param Param $paramStmt
+ */
+ private function setDefault(\ReflectionParameter $param, $paramStmt)
+ {
+ if ($param->isDefaultValueAvailable()) {
+ $paramStmt->setDefault($param->getDefaultValue());
+ }
+ }
+}
diff --git a/src/Console/ClearAnnotationCacheCommand.php b/src/Console/ClearAnnotationCacheCommand.php
new file mode 100644
index 0000000..6d0bfc0
--- /dev/null
+++ b/src/Console/ClearAnnotationCacheCommand.php
@@ -0,0 +1,72 @@
+config = $config;
+ $this->filesystem = $filesystem;
+ }
+
+ /**
+ * @return void
+ */
+ public function fire()
+ {
+ $configure = $this->config->get('ytake-laravel-aop.annotation');
+ if ($configure['default'] === 'file') {
+ $driverConfig = $configure['drivers']['file'];
+ $directories = $this->filesystem->glob($driverConfig['cache_dir'] . '/*');
+ foreach ($directories as $directory) {
+ $this->filesystem->deleteDirectory($directory);
+ }
+ }
+ $this->info('annotation cache clear!');
+ }
+}
diff --git a/src/Console/ClearCacheCommand.php b/src/Console/ClearCacheCommand.php
index 03d3328..0b6853a 100644
--- a/src/Console/ClearCacheCommand.php
+++ b/src/Console/ClearCacheCommand.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
*/
class ClearCacheCommand extends Command
{
@@ -28,7 +35,7 @@ class ClearCacheCommand extends Command
protected $name = 'ytake:aspect-clear-cache';
/** @var string */
- protected $description = 'compiles all known templates';
+ protected $description = 'Flush the application aspect code cache';
/** @var ConfigRepository */
protected $config;
@@ -52,12 +59,14 @@ public function __construct(ConfigRepository $config, Filesystem $filesystem)
*/
public function fire()
{
- $configure = $this->config->get('ytake-laravel-aop');
-
- $driverConfig = $configure['aop'][$configure['default']];
- if (isset($driverConfig['cacheDir'])) {
- $this->filesystem->cleanDirectory($driverConfig['cacheDir']);
+ $configure = $this->config->get('ytake-laravel-aop.aspect');
+ $driverConfig = $configure['drivers'][$configure['default']];
+ if (isset($driverConfig['cache_dir'])) {
+ $files = $this->filesystem->glob($driverConfig['cache_dir'] . '/*');
+ foreach ($files as $file) {
+ $this->filesystem->delete($file);
+ }
}
- $this->info('aspect/annotation cache clear!');
+ $this->info('aspect code cache clear!');
}
}
diff --git a/src/Console/ModulePublishCommand.php b/src/Console/ModulePublishCommand.php
new file mode 100644
index 0000000..f3c01eb
--- /dev/null
+++ b/src/Console/ModulePublishCommand.php
@@ -0,0 +1,180 @@
+ \Ytake\LaravelAspect\Modules\CacheableModule::class,
+ 'CacheEvictModule' => \Ytake\LaravelAspect\Modules\CacheEvictModule::class,
+ 'CachePutModule' => \Ytake\LaravelAspect\Modules\CachePutModule::class,
+ 'TransactionalModule' => \Ytake\LaravelAspect\Modules\TransactionalModule::class,
+ ];
+
+ /**
+ * @param Filesystem $filesystem
+ */
+ public function __construct(Filesystem $filesystem)
+ {
+ parent::__construct();
+ $this->filesystem = $filesystem;
+ }
+
+ /**
+ * @return void
+ */
+ public function fire()
+ {
+ foreach ($this->modules as $className => $module) {
+ $path = $this->getPath($this->parseClassName($className, $this->argument('module_dir')));
+
+ if ($this->filesystem->exists($path)) {
+ continue;
+ }
+ $stub = $this->filesystem->get($this->stub);
+ $extendClassName = $this->getExtendsClassName($module);
+ $source = str_replace(
+ [
+ 'DummyNamespace',
+ 'DummyClass',
+ 'DummyAspectModuleClass',
+ 'DummyModuleClass'
+ ],
+ [
+ $this->laravel->getNamespace() . $this->argument('module_dir'),
+ $className,
+ $module . ' as ' . $extendClassName,
+ $extendClassName
+ ], $stub);
+ $this->makeDirectory($path);
+ $this->filesystem->put($path, $source);
+ $this->info($path . ' created successfully.');
+ }
+ }
+
+ /**
+ * @return array
+ */
+ protected function getArguments()
+ {
+ return [
+ ['module_dir', InputArgument::OPTIONAL, 'The name of the class directory', $this->classPath],
+ ];
+ }
+
+ /**
+ * @param string $name
+ * @return string
+ */
+ protected function getPath($name)
+ {
+ $name = str_replace($this->laravel->getNamespace(), '', $name);
+
+ return $this->laravel['path'] . '/' . str_replace('\\', '/', $name) . '.php';
+ }
+
+ /**
+ * Parse the name and format according to the root namespace.
+ *
+ * @param string $name
+ * @return string
+ */
+ protected function parseClassName($name, $moduleDirectory = null)
+ {
+ $rootNamespace = $this->laravel->getNamespace();
+
+ if (Str::startsWith($name, $rootNamespace)) {
+ return $name;
+ }
+
+ if (Str::contains($name, '/')) {
+ $name = str_replace('/', '\\', $name);
+ }
+
+ return $this->parseClassName(
+ trim($rootNamespace, '\\') . '\\' . $moduleDirectory . '\\' . $name
+ );
+ }
+
+ /**
+ * added custom aspect module, override package modules
+ *
+ * @param $module
+ * @return $this
+ */
+ protected function addModule($module)
+ {
+ $this->modules[$module];
+
+ return $this;
+ }
+
+ /**
+ * Build the directory for the class if necessary.
+ *
+ * @param string $path
+ * @return string
+ */
+ protected function makeDirectory($path)
+ {
+ if (!$this->filesystem->isDirectory(dirname($path))) {
+ $this->filesystem->makeDirectory(dirname($path), 0777, true, true);
+ }
+ }
+
+ /**
+ * @param $module
+ * @return string
+ */
+ protected function getExtendsClassName($module)
+ {
+ $shortName = (new \ReflectionClass($module))->getShortName();
+ $extendClassName = "Package{$shortName}";
+
+ return $extendClassName;
+ }
+}
diff --git a/src/Console/stub/ModuleStub.stub b/src/Console/stub/ModuleStub.stub
new file mode 100644
index 0000000..04381e6
--- /dev/null
+++ b/src/Console/stub/ModuleStub.stub
@@ -0,0 +1,17 @@
+
- * @license http://opensource.org/licenses/MIT MIT
*/
class ConsoleServiceProvider extends ServiceProvider
{
/** @var bool */
protected $defer = true;
- /**
- * @inheritdoc
- */
public function boot()
{
$this->registerCommands();
}
/**
- * @inheritdoc
+ * {@inheritdoc}
*/
public function register()
{
@@ -50,16 +56,28 @@ protected function registerCommands()
$this->app->singleton('command.ytake.aspect.clear-cache', function ($app) {
return new ClearCacheCommand($app['config'], $app['files']);
});
- $this->commands(['command.ytake.aspect.clear-cache']);
+ $this->app->singleton('command.ytake.aspect.annotation.clear-cache', function ($app) {
+ return new ClearAnnotationCacheCommand($app['config'], $app['files']);
+ });
+ $this->app->singleton('command.ytake.aspect.module-publish', function ($app) {
+ return new ModulePublishCommand($app['files']);
+ });
+ $this->commands([
+ 'command.ytake.aspect.clear-cache',
+ 'command.ytake.aspect.annotation.clear-cache',
+ 'command.ytake.aspect.module-publish'
+ ]);
}
/**
- * @inheritdoc
+ * {@inheritdoc}
*/
public function provides()
{
return [
- 'command.ytake.aspect.clear-cache'
+ 'command.ytake.aspect.clear-cache',
+ 'command.ytake.aspect.annotation.clear-cache',
+ 'command.ytake.aspect.module-publish'
];
}
}
diff --git a/src/Exception/ClassNotFoundException.php b/src/Exception/ClassNotFoundException.php
new file mode 100644
index 0000000..e136880
--- /dev/null
+++ b/src/Exception/ClassNotFoundException.php
@@ -0,0 +1,39 @@
+config = $config;
+ }
+
+ /**
+ * @return CachedReader
+ */
+ public function getReader()
+ {
+ return new CachedReader(
+ new AnnotationReader(),
+ new FilesystemCache($this->config['cache_dir']),
+ (bool) $this->config['debug']
+ );
+ }
+}
diff --git a/src/GoAspect.php b/src/GoAspect.php
deleted file mode 100644
index 8358e9c..0000000
--- a/src/GoAspect.php
+++ /dev/null
@@ -1,66 +0,0 @@
-
- * @license http://opensource.org/licenses/MIT MIT
- */
-class GoAspect implements AspectDriverInterface
-{
- /** @var array */
- protected $configure;
-
- /** @var LaravelApplication */
- protected $laravel;
-
- /** @var AspectKernel */
- protected $kernel;
-
- /**
- * @param LaravelApplication $laravel
- * @param array $configure
- */
- public function __construct(LaravelApplication $laravel, array $configure)
- {
- $this->laravel = $laravel;
- $this->configure = $configure;
- $this->kernel = AspectKernel::getInstance();
- }
-
- /**
- * initialize aspect kernel
- *
- * @return void
- */
- public function register()
- {
- if (!defined('AOP_CACHE_DIR')) {
- $this->kernel->setLaravel($this->laravel);
- $this->kernel->init($this->configure);
- }
- }
-
- /**
- * @param array $classes
- */
- public function setAspects(array $classes)
- {
- $this->kernel->setAop($classes);
- }
-}
diff --git a/src/Aspect/AbstractCache.php b/src/Interceptor/AbstractCache.php
similarity index 76%
rename from src/Aspect/AbstractCache.php
rename to src/Interceptor/AbstractCache.php
index 41a3fe9..77ffbe7 100644
--- a/src/Aspect/AbstractCache.php
+++ b/src/Interceptor/AbstractCache.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
*/
-abstract class AbstractCache implements Aspect
+abstract class AbstractCache implements MethodInterceptor
{
+ use AnnotationReaderTrait;
+
/** @var string */
protected $join = ":";
- /** @var CacheFactory */
- protected $cache;
-
- /**
- * @param CacheFactory $cache
- */
- public function __construct(CacheFactory $cache)
- {
- $this->cache = $cache;
- }
-
/**
* @param $name
* @param MethodInvocation $invocation
@@ -85,7 +83,7 @@ protected function detectCacheKeys(MethodInvocation $invocation, $annotation, $k
*/
protected function detectCacheRepository($annotation)
{
- $cache = $this->cache->store($annotation->driver);
+ $cache = app('cache')->store($annotation->driver);
if (count($annotation->tags)) {
$cache = $cache->tags($annotation->tags);
diff --git a/src/Aspect/CacheEvictAspect.php b/src/Interceptor/CacheEvictInterceptor.php
similarity index 58%
rename from src/Aspect/CacheEvictAspect.php
rename to src/Interceptor/CacheEvictInterceptor.php
index 76b81eb..321de88 100644
--- a/src/Aspect/CacheEvictAspect.php
+++ b/src/Interceptor/CacheEvictInterceptor.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
+ * Class CacheEvictInterceptor
*/
-class CacheEvictAspect extends AbstractCache
+class CacheEvictInterceptor extends AbstractCache
{
/**
- * @After("@annotation(Ytake\LaravelAspect\Annotation\CacheEvict)")
* @param MethodInvocation $invocation
*
* @return mixed
*/
- public function afterMethodExecution(MethodInvocation $invocation)
+ public function invoke(MethodInvocation $invocation)
{
- $annotation = $invocation->getMethod()->getAnnotation('Ytake\LaravelAspect\Annotation\CacheEvict');
+ $result = $invocation->proceed();
+
+ $annotation = $this->reader
+ ->getMethodAnnotation($invocation->getMethod(), $this->annotation);
$keys = $this->generateCacheName($annotation->cacheName, $invocation);
if (!is_array($annotation->key)) {
$annotation->key = [$annotation->key];
}
$keys = $this->detectCacheKeys($invocation, $annotation, $keys);
+
// detect use cache driver
$cache = $this->detectCacheRepository($annotation);
+
if ($annotation->allEntries) {
- return $cache->flush();
+ $cache->flush();
}
+
$cache->forget(implode($this->join, $keys));
+ return $result;
}
}
diff --git a/src/Aspect/CachePutAspect.php b/src/Interceptor/CachePutInterceptor.php
similarity index 63%
rename from src/Aspect/CachePutAspect.php
rename to src/Interceptor/CachePutInterceptor.php
index 169989f..fb48edc 100644
--- a/src/Aspect/CachePutAspect.php
+++ b/src/Interceptor/CachePutInterceptor.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
+ * Class AroundCachePutAspect
*/
-class CachePutAspect extends AbstractCache
+class CachePutInterceptor extends AbstractCache
{
/**
- * @Around("@annotation(Ytake\LaravelAspect\Annotation\CachePut)")
* @param MethodInvocation $invocation
+ *
* @return mixed
*/
- public function afterMethodExecution(MethodInvocation $invocation)
+ public function invoke(MethodInvocation $invocation)
{
- $annotation = $invocation->getMethod()->getAnnotation('Ytake\LaravelAspect\Annotation\CachePut');
+ $annotation = $this->reader
+ ->getMethodAnnotation($invocation->getMethod(), $this->annotation);
$keys = $this->generateCacheName($annotation->cacheName, $invocation);
if (!is_array($annotation->key)) {
diff --git a/src/Aspect/CacheableAspect.php b/src/Interceptor/CacheableInterceptor.php
similarity index 65%
rename from src/Aspect/CacheableAspect.php
rename to src/Interceptor/CacheableInterceptor.php
index 5694e92..a33ec1e 100644
--- a/src/Aspect/CacheableAspect.php
+++ b/src/Interceptor/CacheableInterceptor.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
+ * Class CacheableInterceptor
*/
-class CacheableAspect extends AbstractCache
+class CacheableInterceptor extends AbstractCache
{
/**
- * @Around("@annotation(Ytake\LaravelAspect\Annotation\Cacheable)")
* @param MethodInvocation $invocation
* @return mixed
*/
- public function aroundMethodExecution(MethodInvocation $invocation)
+ public function invoke(MethodInvocation $invocation)
{
- $annotation = $invocation->getMethod()->getAnnotation('Ytake\LaravelAspect\Annotation\Cacheable');
+ $annotation = $this->reader
+ ->getMethodAnnotation($invocation->getMethod(), $this->annotation);
+
$keys = $this->generateCacheName($annotation->cacheName, $invocation);
if (!is_array($annotation->key)) {
$annotation->key = [$annotation->key];
@@ -45,7 +52,6 @@ public function aroundMethodExecution(MethodInvocation $invocation)
if ($result = $invocation->proceed()) {
$cache->add($key, $result, $annotation->lifetime);
}
-
return $result;
}
}
diff --git a/src/Interceptor/TransactionalInterceptor.php b/src/Interceptor/TransactionalInterceptor.php
new file mode 100644
index 0000000..cee2ede
--- /dev/null
+++ b/src/Interceptor/TransactionalInterceptor.php
@@ -0,0 +1,61 @@
+reader
+ ->getMethodAnnotation($invocation->getMethod(), $this->annotation);
+
+ $connection = $annotation->value;
+ /** @var $database */
+ $database = app('db')->connection($connection);
+ $database->beginTransaction();
+ try {
+ $result = $invocation->proceed();
+ $database->commit();
+
+ return $result;
+ } catch (QueryException $exception) {
+ $database->rollBack();
+ throw $exception;
+ }
+ }
+}
diff --git a/src/Modules/AspectModule.php b/src/Modules/AspectModule.php
new file mode 100644
index 0000000..fa93840
--- /dev/null
+++ b/src/Modules/AspectModule.php
@@ -0,0 +1,83 @@
+app = $app;
+ $this->bind = $bind;
+ }
+
+ /**
+ * @return void
+ */
+ abstract public function attach();
+
+ /**
+ * @param CompilerInterface $compiler
+ *
+ * @return $this
+ */
+ public function setCompiler(CompilerInterface $compiler)
+ {
+ $this->compiler = $compiler;
+ return $this;
+ }
+
+ /**
+ * @param $class
+ * @param array $pointcuts
+ */
+ protected function instanceResolver($class, array $pointcuts)
+ {
+ $bind = $this->bind->bind($class, $pointcuts);
+ $compiledClass = $this->compiler->compile($class, $bind);
+ $this->app->bind($class, function ($app) use ($bind, $compiledClass) {
+ $instance = $app->make($compiledClass);
+ $instance->bindings = $bind->getBindings();
+ return $instance;
+ });
+ }
+}
diff --git a/src/Modules/CacheEvictModule.php b/src/Modules/CacheEvictModule.php
new file mode 100644
index 0000000..59eb927
--- /dev/null
+++ b/src/Modules/CacheEvictModule.php
@@ -0,0 +1,42 @@
+app->call([new CacheEvictPointCut, 'configure']);
+ foreach ($this->classes as $class) {
+ $this->instanceResolver($class, [$pointcut]);
+ }
+ }
+}
diff --git a/src/Modules/CachePutModule.php b/src/Modules/CachePutModule.php
new file mode 100644
index 0000000..1003f10
--- /dev/null
+++ b/src/Modules/CachePutModule.php
@@ -0,0 +1,42 @@
+app->call([new CachePutPointCut, 'configure']);
+ foreach ($this->classes as $class) {
+ $this->instanceResolver($class, [$pointcut]);
+ }
+ }
+}
diff --git a/src/Modules/CacheableModule.php b/src/Modules/CacheableModule.php
new file mode 100644
index 0000000..8b50ab0
--- /dev/null
+++ b/src/Modules/CacheableModule.php
@@ -0,0 +1,42 @@
+app->call([new CacheablePointCut, 'configure']);
+ foreach ($this->classes as $class) {
+ $this->instanceResolver($class, [$pointcut]);
+ }
+ }
+}
diff --git a/src/Modules/TransactionalModule.php b/src/Modules/TransactionalModule.php
new file mode 100644
index 0000000..8f73aa2
--- /dev/null
+++ b/src/Modules/TransactionalModule.php
@@ -0,0 +1,42 @@
+app->call([new TransactionalPointCut, 'configure']);
+ foreach ($this->classes as $class) {
+ $this->instanceResolver($class, [$pointcut]);
+ }
+ }
+}
diff --git a/src/NullAspectKernel.php b/src/NullAspectKernel.php
new file mode 100644
index 0000000..5611ad3
--- /dev/null
+++ b/src/NullAspectKernel.php
@@ -0,0 +1,37 @@
+setInterceptor(new CacheEvictInterceptor);
+
+ return $this->withAnnotatedAnyInterceptor($app);
+ }
+}
diff --git a/src/PointCut/CachePutPointCut.php b/src/PointCut/CachePutPointCut.php
new file mode 100644
index 0000000..cadc6a8
--- /dev/null
+++ b/src/PointCut/CachePutPointCut.php
@@ -0,0 +1,49 @@
+setInterceptor(new CachePutInterceptor);
+
+ return $this->withAnnotatedAnyInterceptor($app);
+ }
+}
diff --git a/src/PointCut/CacheablePointCut.php b/src/PointCut/CacheablePointCut.php
new file mode 100644
index 0000000..5db6890
--- /dev/null
+++ b/src/PointCut/CacheablePointCut.php
@@ -0,0 +1,49 @@
+setInterceptor(new CacheableInterceptor);
+
+ return $this->withAnnotatedAnyInterceptor($app);
+ }
+}
diff --git a/src/PointCut/CommonPointCut.php b/src/PointCut/CommonPointCut.php
new file mode 100644
index 0000000..aaa712e
--- /dev/null
+++ b/src/PointCut/CommonPointCut.php
@@ -0,0 +1,63 @@
+interceptor = $interceptor;
+ }
+
+ /**
+ * @param Container $app
+ * @return Pointcut
+ */
+ protected function withAnnotatedAnyInterceptor(Container $app)
+ {
+ $this->interceptor->setReader($app['aspect.annotation.reader']);
+ $this->interceptor->setAnnotation($this->annotation);
+ return new Pointcut(
+ (new Matcher)->any(),
+ (new Matcher)->annotatedWith($this->annotation),
+ [$this->interceptor]
+ );
+ }
+}
diff --git a/src/PointCut/PointCutable.php b/src/PointCut/PointCutable.php
new file mode 100644
index 0000000..d372ebc
--- /dev/null
+++ b/src/PointCut/PointCutable.php
@@ -0,0 +1,37 @@
+setInterceptor(new TransactionalInterceptor);
+
+ return $this->withAnnotatedAnyInterceptor($app);
+ }
+}
diff --git a/src/RayAspectKernel.php b/src/RayAspectKernel.php
new file mode 100644
index 0000000..28e0670
--- /dev/null
+++ b/src/RayAspectKernel.php
@@ -0,0 +1,88 @@
+app = $app;
+ $this->configure = $configure;
+ $this->compiler = $this->getCompiler();
+ $this->bind = $bind;
+ }
+
+ /**
+ * @param null $module
+ * @throws ClassNotFoundException
+ */
+ public function register($module = null)
+ {
+ if (!class_exists($module)) {
+ throw new ClassNotFoundException($module);
+ }
+ (new $module($this->app, $this->bind))->setCompiler($this->compiler)->attach();
+ }
+
+ /**
+ * @return Compiler
+ */
+ protected function getCompiler()
+ {
+ return new Compiler($this->configure['cache_dir'], new CodeGen(
+ new Parser(new Lexer()),
+ new BuilderFactory(),
+ new Standard()
+ ));
+ }
+}
diff --git a/src/config/ytake-laravel-aop.php b/src/config/ytake-laravel-aop.php
index acbfde0..f1cda6d 100644
--- a/src/config/ytake-laravel-aop.php
+++ b/src/config/ytake-laravel-aop.php
@@ -1,4 +1,5 @@
- * @license http://opensource.org/licenses/MIT MIT
- */
return [
- /**
- * choose aop library
- * "go"(go-aop), "none"(for testing)
- *
- * @see https://github.com/goaop/framework
- */
- 'default' => env('ASPECT_DRIVER', 'go'),
+ 'aspect' => [
+ /**
+ * choose aop library
+ * "ray"(Ray.Aop), "none"(for testing)
+ */
+ 'default' => env('ASPECT_DRIVER', 'ray'),
+
+ /**
+ *
+ */
+ 'drivers' => [
+ 'ray' => [
+ // string Path to the cache directory where compiled classes will be stored
+ 'cache_dir' => storage_path('framework/aop'),
+ ],
+ 'none' => [
+ // for testing driver
+ // no use aspect
+ ]
+ ],
+ ],
+
+ 'annotation' => [
+ /**
+ * choose annotation reader
+ * 'array'(default), 'file'(file cache)
+ */
+ 'default' => env('ASPECT_ANNOTATION_DRIVER', 'array'),
- /**
- *
- */
- 'aop' => [
- 'go' => [
- // boolean Determines whether or not kernel is in debug mode
- 'debug' => env('ASPECT_DEBUG', true),
- // string Path to the application root directory.
- 'appDir' => app_path(),
- // string Path to the cache directory where compiled classes will be stored
- 'cacheDir' => storage_path('framework/aop'),
- // integer Binary mask of features
- // 'features' => 0,
- // array WhiteList of directories where aspects should be applied. Empty for everywhere.
- 'includePaths' => [
- app_path()
+ 'drivers' => [
+ 'file' => [
+ 'cache_dir' => storage_path('framework/annotation'),
+ //
+ 'debug' => env('ASPECT_ANNOTATION_DEBUG', true),
],
- // array BlackList of directories or files where aspects shouldn't be applied.
- // 'excludePaths' => []
],
- 'none' => [
- // for testing driver
- // no use aspect
- ]
],
];
diff --git a/src/data/CodeTemplate.php b/src/data/CodeTemplate.php
new file mode 100644
index 0000000..6936a5a
--- /dev/null
+++ b/src/data/CodeTemplate.php
@@ -0,0 +1,53 @@
+ [$interceptorA[]][]
+ */
+ public $bindings;
+
+ /**
+ * Method Template
+ */
+ public function returnSame($a)
+ {
+ if (isset($this->bindings[__FUNCTION__]) === false) {
+ return call_user_func_array([$this, 'parent::' . __FUNCTION__], func_get_args());
+ }
+
+ if ($this->isIntercepting === false) {
+ $this->isIntercepting = true;
+ return call_user_func_array([$this, 'parent::' . __FUNCTION__], func_get_args());
+ }
+
+ $this->isIntercepting = false;
+ $invocationResult = (new \Ray\Aop\ReflectiveMethodInvocation(
+ $this,
+ new \ReflectionMethod($this, __FUNCTION__),
+ new \Ray\Aop\Arguments(func_get_args()),
+ $this->bindings[__FUNCTION__]
+ ))->proceed();
+ $this->isIntercepting = true;
+
+ return $invocationResult;
+ }
+}
diff --git a/tests/AnnotationManagerTest.php b/tests/AnnotationManagerTest.php
new file mode 100644
index 0000000..7d2c058
--- /dev/null
+++ b/tests/AnnotationManagerTest.php
@@ -0,0 +1,52 @@
+manager = new \Ytake\LaravelAspect\AnnotationManager($this->app);
+ }
+
+ public function testReturnDefaultDriverName()
+ {
+ $this->assertInternalType('string', $this->manager->getDefaultDriver());
+ }
+
+ public function testDefaultDriverInstance()
+ {
+ $this->assertInstanceOf(
+ \Ytake\LaravelAspect\ArrayReader::class,
+ $this->manager->driver()
+ );
+ }
+
+ public function testAnnotationDriverInstance()
+ {
+ $this->assertInstanceOf(
+ \Ytake\LaravelAspect\ArrayReader::class,
+ $this->manager->driver('array')
+ );
+ $this->assertInstanceOf(
+ \Ytake\LaravelAspect\FileReader::class,
+ $this->manager->driver('file')
+ );
+ }
+
+ public function testAnnotationDriverImplementsAccessor()
+ {
+ $fileReader = $this->manager->driver('file');
+ $this->assertInstanceOf(
+ \Doctrine\Common\Annotations\CachedReader::class,
+ $fileReader->getReader()
+ );
+ $arrayReader = $this->manager->driver('array');
+ $this->assertInstanceOf(
+ \Doctrine\Common\Annotations\AnnotationReader::class,
+ $arrayReader->getReader()
+ );
+ }
+}
diff --git a/tests/AspectManagerTest.php b/tests/AspectManagerTest.php
index 6cc91c2..a18c539 100644
--- a/tests/AspectManagerTest.php
+++ b/tests/AspectManagerTest.php
@@ -19,15 +19,14 @@ public function testCreateDriverInstance()
public function testCreateGoDriverInstance()
{
$this->assertInstanceOf(
- \Ytake\LaravelAspect\GoAspect::class, $this->manager->driver('go')
+ \Ytake\LaravelAspect\RayAspectKernel::class, $this->manager->driver('ray')
);
}
public function testCreateNullDriverInstance()
{
$driver = $this->manager->driver('none');
- $this->assertInstanceOf(\Ytake\LaravelAspect\NullAspect::class, $driver);
- $this->assertNull($driver->setAspects([]));
+ $this->assertInstanceOf(\Ytake\LaravelAspect\NullAspectKernel::class, $driver);
$this->assertNull($driver->register());
$class = new \ReflectionClass($driver);
$this->assertSame(0, count($class->getProperties()));
diff --git a/tests/CacheEvictTest.php b/tests/CacheEvictTest.php
index f2ba557..9f8a8ff 100644
--- a/tests/CacheEvictTest.php
+++ b/tests/CacheEvictTest.php
@@ -5,8 +5,6 @@ class CacheEvictTest extends \TestCase
/** @var \Ytake\LaravelAspect\AspectManager $manager */
protected $manager;
- protected static $instance;
-
protected function setUp()
{
parent::setUp();
@@ -14,22 +12,16 @@ protected function setUp()
$this->resolveManager();
}
- /**
- * @runInSeparateProcess
- */
public function testGenerateCacheNameRemoveNullKey()
{
- $cache = new \__Test\AspectCacheEvict();
+ $cache = $this->app->make(\__Test\AspectCacheEvict::class);
$cache->singleCacheDelete();
$this->assertNull($this->app['cache']->get('singleCacheDelete'));
}
- /**
- * @runInSeparateProcess
- */
public function testCacheableAndRemove()
{
- $cache = new \__Test\AspectCacheEvict();
+ $cache = $this->app->make(\__Test\AspectCacheEvict::class);
$cache->cached(1, 2);
$this->assertNotNull($this->app['cache']->tags(['testing1'])->get('testing:1:2'));
@@ -45,8 +37,8 @@ protected function resolveManager()
{
$annotation = new \Ytake\LaravelAspect\Annotation;
$annotation->registerAspectAnnotations();
- /** @var \Ytake\LaravelAspect\GoAspect $aspect */
- $aspect = $this->manager->driver('go');
- $aspect->register();
+ $aspect = $this->app['aspect.manager']->driver('ray');
+ $aspect->register(\__Test\CacheEvictModule::class);
+ $aspect->register(\__Test\CacheableModule::class);
}
}
diff --git a/tests/CachePutTest.php b/tests/CachePutTest.php
index ddf80f9..3846988 100644
--- a/tests/CachePutTest.php
+++ b/tests/CachePutTest.php
@@ -14,12 +14,9 @@ protected function setUp()
$this->resolveManager();
}
- /**
- * @runInSeparateProcess
- */
public function testCachePutReturnUpdatedValue()
{
- $cache = new \__Test\AspectCachePut;
+ $cache = $this->app->make(\__Test\AspectCachePut::class);
$this->app['cache']->add('singleKey:1000', 1, 120);
$result = $cache->singleKey(1000);
$this->assertSame(1000, $result);
@@ -27,12 +24,11 @@ public function testCachePutReturnUpdatedValue()
}
/**
- * @runInSeparateProcess
* @expectedException \InvalidArgumentException
*/
public function testCacheableGenerateCacheNameSingleKey()
{
- $cache = new \__Test\AspectCachePut;
+ $cache = $this->app->make(\__Test\AspectCachePut::class);
$cache->throwExceptionCache();
}
@@ -43,8 +39,7 @@ protected function resolveManager()
{
$annotation = new \Ytake\LaravelAspect\Annotation;
$annotation->registerAspectAnnotations();
- /** @var \Ytake\LaravelAop\GoAspect $aspect */
- $aspect = $this->manager->driver('go');
- $aspect->register();
+ $aspect = $this->manager->driver('ray');
+ $aspect->register(\__Test\CachePutModule::class);
}
}
diff --git a/tests/CacheableTest.php b/tests/CacheableTest.php
index 42e6335..f9553a7 100644
--- a/tests/CacheableTest.php
+++ b/tests/CacheableTest.php
@@ -14,56 +14,41 @@ protected function setUp()
$this->resolveManager();
}
- /**
- * @runInSeparateProcess
- */
public function testCacheableGenerateCacheNameSingleKey()
{
- $cache = new \__Test\AspectCacheable;
+ $cache = $this->app->make(\__Test\AspectCacheable::class);
$result = $cache->singleKey(1000);
$this->assertSame(1000, $result);
$this->assertSame(1000, $this->app['cache']->get('singleKey:1000'));
}
- /**
- * @runInSeparateProcess
- */
public function testCacheableGenerateCacheNameMultipleKey()
{
- $cache = new \__Test\AspectCacheable;
+ $cache = $this->app->make(\__Test\AspectCacheable::class);
$result = $cache->multipleKey(1000, 'testing');
$this->assertSame(1000, $result);
$this->assertSame(1000, $this->app['cache']->get('multipleKey:1000:testing'));
}
- /**
- * @runInSeparateProcess
- */
public function testCacheableCacheNameMultipleKey()
{
- $cache = new \__Test\AspectCacheable;
+ $cache = $this->app->make(\__Test\AspectCacheable::class);
$result = $cache->namedMultipleKey(1000, 'testing');
$this->assertSame(1000, $result);
$this->assertSame(1000, $this->app['cache']->get('testing1:1000:testing'));
}
- /**
- * @runInSeparateProcess
- */
public function testCacheableCacheNameMultipleNameAndKey()
{
- $cache = new \__Test\AspectCacheable;
+ $cache = $this->app->make(\__Test\AspectCacheable::class);
$result = $cache->namedMultipleNameAndKey(1000, 'testing');
$this->assertSame(1000, $result);
$this->assertSame(1000, $this->app['cache']->tags(['testing1', 'testing2'])->get('namedMultipleNameAndKey:1000:testing'));
}
- /**
- * @runInSeparateProcess
- */
public function testCacheableCacheObject()
{
- $cache = new \__Test\AspectCacheable;
+ $cache = $this->app->make(\__Test\AspectCacheable::class);
$class = new \stdClass;
$class->title = 'testing';
$result = $cache->cachingKeyObject(1000, $class);
@@ -77,7 +62,7 @@ protected function resolveManager()
{
$annotation = new \Ytake\LaravelAspect\Annotation;
$annotation->registerAspectAnnotations();
- $aspect = $this->manager->driver('go');
- $aspect->register();
+ $aspect = $this->manager->driver('ray');
+ $aspect->register(\__Test\CacheableModule::class);
}
}
diff --git a/tests/Commands/AspectClearCacheCommandTest.php b/tests/Commands/AspectClearCacheCommandTest.php
index c49050b..7f4b24f 100644
--- a/tests/Commands/AspectClearCacheCommandTest.php
+++ b/tests/Commands/AspectClearCacheCommandTest.php
@@ -21,12 +21,9 @@ protected function setUp()
$this->command->setLaravel(new MockApplication());
}
- /**
- * @runInSeparateProcess
- */
public function testCacheClearFile()
{
- $cache = new \__Test\AspectCacheable;
+ $cache = $this->app->make(\__Test\AspectCacheable::class);
$cache->namedMultipleNameAndKey(1000, 'testing');
$output = new \Symfony\Component\Console\Output\BufferedOutput();
@@ -34,12 +31,12 @@ public function testCacheClearFile()
new \Symfony\Component\Console\Input\ArrayInput([]),
$output
);
- $this->assertSame('aspect/annotation cache clear!', trim($output->fetch()));
+ $this->assertSame('aspect code cache clear!', trim($output->fetch()));
$configure = $this->app['config']->get('ytake-laravel-aop');
- $driverConfig = $configure['aop'][$configure['default']];
- if(isset($driverConfig['cacheDir'])) {
- $files = $this->app['filesystem']->files($driverConfig['cacheDir']);
+ $driverConfig = $configure['aspect']['drivers'][$configure['aspect']['default']];
+ if (isset($driverConfig['cache_dir'])) {
+ $files = $this->app['filesystem']->files($driverConfig['cache_dir']);
$this->assertCount(0, $files);
}
}
@@ -51,9 +48,8 @@ protected function resolveManager()
{
$annotation = new \Ytake\LaravelAspect\Annotation;
$annotation->registerAspectAnnotations();
- /** @var \Ytake\LaravelAspect\GoAspect $aspect */
- $aspect = $this->manager->driver('go');
- $aspect->register();
+ $aspect = $this->manager->driver('ray');
+ $aspect->register(\__Test\CacheableModule::class);
}
protected function tearDown()
@@ -78,6 +74,7 @@ public function version()
* Get or check the current application environment.
*
* @param mixed
+ *
* @return string
*/
public function environment()
@@ -111,6 +108,7 @@ public function registerConfiguredProviders()
* @param \Illuminate\Support\ServiceProvider|string $provider
* @param array $options
* @param bool $force
+ *
* @return \Illuminate\Support\ServiceProvider
*/
public function register($provider, $options = [], $force = false)
@@ -123,6 +121,7 @@ public function register($provider, $options = [], $force = false)
*
* @param string $provider
* @param string $service
+ *
* @return void
*/
public function registerDeferredProvider($provider, $service = null)
@@ -144,6 +143,7 @@ public function boot()
* Register a new boot listener.
*
* @param mixed $callback
+ *
* @return void
*/
public function booting($callback)
@@ -155,6 +155,7 @@ public function booting($callback)
* Register a new "booted" listener.
*
* @param mixed $callback
+ *
* @return void
*/
public function booted($callback)
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 220c4b1..226b5bc 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -2,9 +2,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\DatabaseManager;
-use Illuminate\Database\Eloquent\QueueEntityResolver;
use Illuminate\Database\Connectors\ConnectionFactory;
-use Illuminate\Database\Eloquent\Factory as EloquentFactory;
class TestCase extends \PHPUnit_Framework_TestCase
{
@@ -61,6 +59,13 @@ protected function registerCache()
});
}
+ protected function registerAnnotationReader()
+ {
+ $this->app->singleton('aspect.annotation.reader', function ($app) {
+ return (new \Ytake\LaravelAspect\AnnotationManager($app))->getReader();
+ });
+ }
+
protected function createApplicationContainer()
{
$this->app = new \Illuminate\Container\Container;
@@ -70,11 +75,23 @@ protected function createApplicationContainer()
$this->registerConfigure();
$this->registerDatabase();
$this->registerCache();
+ $this->registerAnnotationReader();
+ $this->app->singleton('aspect.manager', function ($app) {
+ return new \Ytake\LaravelAspect\AspectManager($app);
+ });
+ $this->app->bind(
+ \Illuminate\Container\Container::class,
+ function () {
+ return $this->app;
+ }
+ );
+ \Illuminate\Container\Container::setInstance($this->app);
}
protected function tearDown()
{
- $this->app['filesystem']->deleteDirectory(__DIR__ . '/storage');
+ // $this->app['filesystem']->cleanDirectory(__DIR__ . '/storage/aop');
+ // $this->app['filesystem']->cleanDirectory(__DIR__ . '/storage/annotation');
$this->app = null;
}
}
diff --git a/tests/TransactionalTest.php b/tests/TransactionalTest.php
index 960517c..a748451 100644
--- a/tests/TransactionalTest.php
+++ b/tests/TransactionalTest.php
@@ -15,24 +15,20 @@ protected function setUp()
$this->resolveManager();
}
- /**
- * @runInSeparateProcess
- */
public function testTransactionalAssertString()
{
- $transactional = new \__Test\AspectTransactionalString;
+ $transactional = $this->app->make(\__Test\AspectTransactionalString::class);
$this->assertContains('testing', $transactional->start());
}
- /**
- * @runInSeparateProcess
- */
public function testTransactionalDatabase()
{
- $transactional = new \__Test\AspectTransactionalDatabase($this->app['db']);
+ $this->app->bind(\__Test\AspectTransactionalDatabase::class, function () {
+ return new \__Test\AspectTransactionalDatabase($this->app['db']);
+ });
+ $transactional = $this->app->make(\__Test\AspectTransactionalDatabase::class);
$this->assertInternalType('array', $transactional->start());
$this->assertInstanceOf('stdClass', $transactional->start()[0]);
-
}
/**
@@ -42,8 +38,7 @@ protected function resolveManager()
{
$annotation = new \Ytake\LaravelAspect\Annotation;
$annotation->registerAspectAnnotations();
- /** @var \Ytake\LaravelAspect\GoAspect $aspect */
- $aspect = $this->manager->driver('go');
- $aspect->register();
+ $aspect = $this->manager->driver('ray');
+ $aspect->register(\__Test\TransactionalModule::class);
}
}
diff --git a/tests/config/ytake-laravel-aop.php b/tests/config/ytake-laravel-aop.php
index 10f55db..1abc946 100644
--- a/tests/config/ytake-laravel-aop.php
+++ b/tests/config/ytake-laravel-aop.php
@@ -1,50 +1,42 @@
- * @license http://opensource.org/licenses/MIT MIT
- */
return [
- /**
- * choose aop library
- * "go"(go-aop), "none"(for testing)
- *
- * @see https://github.com/goaop/framework
- */
- 'default' => 'go',
- /**
- *
- */
- 'aop' => [
- 'go' => [
- // boolean Determines whether or not kernel is in debug mode
- 'debug' => true,
- // string Path to the application root directory.
- 'appDir' => __DIR__ . '/../src',
- // string Path to the cache directory where compiled classes will be stored
- 'cacheDir' => __DIR__ . '/../storage',
- // integer Binary mask of features
- // 'features' => 0,
- // array WhiteList of directories where aspects should be applied. Empty for everywhere.
- 'includePaths' => [
- __DIR__ . '/../src',
+ 'aspect' => [
+ /**
+ * choose aop library
+ * "ray"(Ray.Aop), "none"(for testing)
+ */
+ 'default' => 'ray',
+
+ /**
+ *
+ */
+ 'drivers' => [
+ 'ray' => [
+ // string Path to the cache directory where compiled classes will be stored
+ 'cache_dir' => __DIR__ . '/../storage/aop',
+ ],
+ 'none' => [
+ // for testing driver
+ // no use aspect
+ ]
+ ],
+ ],
+
+ 'annotation' => [
+ /**
+ * choose annotation reader
+ * 'array'(default), 'file'(file cache)
+ */
+ 'default' => 'array',
+
+ 'drivers' => [
+ 'file' => [
+ 'cache_dir' => __DIR__ . '/../storage/annotation',
+ //
+ 'debug' => true,
],
- // array BlackList of directories or files where aspects shouldn't be applied.
- // 'excludePaths' => []
],
- 'none' => [
- // for testing driver
- // no use aspect
- ]
],
];
diff --git a/tests/helper.php b/tests/helper.php
new file mode 100644
index 0000000..c64cd1b
--- /dev/null
+++ b/tests/helper.php
@@ -0,0 +1,21 @@
+make($make, $parameters);
+ }
+}
diff --git a/tests/src/AspectTransactionalString.php b/tests/src/AspectTransactionalString.php
index c2c56de..1b9207b 100644
--- a/tests/src/AspectTransactionalString.php
+++ b/tests/src/AspectTransactionalString.php
@@ -5,12 +5,10 @@
namespace __Test;
-use Ytake\Lom\Meta\NoArgsConstructor;
use Ytake\LaravelAspect\Annotation\Transactional;
/**
* Class AspectTransactional
- * @NoArgsConstructor
* @package Test
*/
class AspectTransactionalString
diff --git a/tests/src/CacheEvictModule.php b/tests/src/CacheEvictModule.php
new file mode 100644
index 0000000..b977c7d
--- /dev/null
+++ b/tests/src/CacheEvictModule.php
@@ -0,0 +1,13 @@
+