Merge remote-tracking branch 'origin/master'

# Conflicts:
#	composer.json
#	composer.lock
master
Sipachev Igor 3 years ago
commit 453b918a6b
  1. 3
      composer.json
  2. 510
      composer.lock
  3. 4
      src/Annotation/PropertyPath.php
  4. 31
      src/EventListener/RequestListener.php
  5. 46
      tests/_support/Helper/Unit.php
  6. 43
      tests/unit/Listener/FillTest.php

@ -11,7 +11,8 @@
"jms/serializer": "^3.13",
"symfony/validator": "^5.3",
"symfony/cache": "^5.3",
"rinsvent/attribute-extractor": "^0.0.1"
"symfony/string": "^5.3",
"rinsvent/attribute-extractor": "^0.0.2"
},
"require-dev": {
"codeception/codeception": "^4.1",

510
composer.lock generated

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "8bebb837cbbc196ec3ac49c24e16dc37",
"content-hash": "6f29c92495f5e5045ad725f6a287b947",
"packages": [
{
"name": "doctrine/annotations",
@ -582,16 +582,16 @@
},
{
"name": "rinsvent/attribute-extractor",
"version": "v0.0.1",
"version": "v0.0.2",
"source": {
"type": "git",
"url": "https://github.com/Rinsvent/attribute-extractor.git",
"reference": "f63bcb263ff17ed03bcaa87ab4b5c50e246d842e"
"reference": "081b9f18c2fa4305e8acbe63fff873ae59928c9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Rinsvent/attribute-extractor/zipball/f63bcb263ff17ed03bcaa87ab4b5c50e246d842e",
"reference": "f63bcb263ff17ed03bcaa87ab4b5c50e246d842e",
"url": "https://api.github.com/repos/Rinsvent/attribute-extractor/zipball/081b9f18c2fa4305e8acbe63fff873ae59928c9d",
"reference": "081b9f18c2fa4305e8acbe63fff873ae59928c9d",
"shasum": ""
},
"require": {
@ -615,9 +615,9 @@
"description": "PHP 8 attribute extractor",
"support": {
"issues": "https://github.com/Rinsvent/attribute-extractor/issues",
"source": "https://github.com/Rinsvent/attribute-extractor/tree/v0.0.1"
"source": "https://github.com/Rinsvent/attribute-extractor/tree/v0.0.2"
},
"time": "2021-07-27T16:37:22+00:00"
"time": "2021-07-28T13:37:17+00:00"
},
{
"name": "symfony/cache",
@ -940,6 +940,171 @@
],
"time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/24b72c6baa32c746a4d0840147c9715e42bb68ab",
"reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"grapheme",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-05-27T09:17:38+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"files": [
"bootstrap.php"
],
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.23.0",
@ -1261,6 +1426,89 @@
],
"time": "2021-04-01T10:43:52+00:00"
},
{
"name": "symfony/string",
"version": "v5.3.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1",
"reference": "bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "~1.15"
},
"require-dev": {
"symfony/error-handler": "^4.4|^5.0",
"symfony/http-client": "^4.4|^5.0",
"symfony/translation-contracts": "^1.1|^2",
"symfony/var-exporter": "^4.4|^5.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\String\\": ""
},
"files": [
"Resources/functions.php"
],
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
"grapheme",
"i18n",
"string",
"unicode",
"utf-8",
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v5.3.3"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-06-27T11:44:38+00:00"
},
{
"name": "symfony/translation-contracts",
"version": "v2.4.0",
@ -5131,171 +5379,6 @@
],
"time": "2021-06-30T08:27:49+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/24b72c6baa32c746a4d0840147c9715e42bb68ab",
"reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"grapheme",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-05-27T09:17:38+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"files": [
"bootstrap.php"
],
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/routing",
"version": "v5.3.0",
@ -5386,89 +5469,6 @@
],
"time": "2021-05-26T17:43:10+00:00"
},
{
"name": "symfony/string",
"version": "v5.3.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1",
"reference": "bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "~1.15"
},
"require-dev": {
"symfony/error-handler": "^4.4|^5.0",
"symfony/http-client": "^4.4|^5.0",
"symfony/translation-contracts": "^1.1|^2",
"symfony/var-exporter": "^4.4|^5.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\String\\": ""
},
"files": [
"Resources/functions.php"
],
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
"grapheme",
"i18n",
"string",
"unicode",
"utf-8",
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v5.3.3"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-06-27T11:44:38+00:00"
},
{
"name": "symfony/var-dumper",
"version": "v5.3.3",

@ -3,9 +3,9 @@
namespace Rinsvent\RequestBundle\Annotation;
#[\Attribute]
class HeaderKey
class PropertyPath
{
public function __construct(
public string $key
public string $path
) {}
}

@ -3,12 +3,13 @@
namespace Rinsvent\RequestBundle\EventListener;
use JMS\Serializer\SerializerBuilder;
use ReflectionMethod;
use ReflectionObject;
use Rinsvent\AttributeExtractor\PropertyExtractor;
use Rinsvent\RequestBundle\Annotation\PropertyPath;
use Rinsvent\RequestBundle\Annotation\RequestDTO;
use Rinsvent\RequestBundle\Annotation\HeaderKey;
use Rinsvent\RequestBundle\DTO\Error;
use Rinsvent\RequestBundle\DTO\ErrorCollection;
use Rinsvent\AttributeExtractor\MethodExtractor;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
@ -25,20 +26,16 @@ class RequestListener
$controller = $request->get('_controller');
if (is_string($controller)) {
$controller = explode('::', $controller);
$method = new ReflectionMethod($controller[0], $controller[1]);
}
if (is_callable($controller)) {
$method = new ReflectionMethod($controller[0], $controller[1]);
}
if (!isset($method)) {
return;
if (is_object($controller[0])) {
$controller[0] = get_class($controller[0]);
}
$methodExtractor = new MethodExtractor($controller[0], $controller[1]);
}
$attributes = $method->getAttributes(RequestDTO::class);
$attribute = $attributes[0] ?? null;
if ($attribute) {
/** @var RequestDTO $requestDTO */
$requestDTO = $attribute->newInstance();
/** @var RequestDTO $requestDTO */
if ($requestDTO = $methodExtractor->fetch(RequestDTO::class)) {
$requestDTOInstance = $this->grabRequestDTO($requestDTO->className, $request->getContent(), $request->query->all(), $request->request->all(), $request->headers->all());
$errorCollection = $this->validate($requestDTOInstance);
@ -92,12 +89,10 @@ class RequestListener
$reflectionObject = new ReflectionObject($object);
$properties = $reflectionObject->getProperties();
foreach ($properties as $property) {
$attributes = $property->getAttributes(HeaderKey::class);
$attribute = $attributes[0] ?? null;
if ($attribute) {
/** @var HeaderKey $headerKey */
$headerKey = $attribute->newInstance();
$value = $data[strtolower($headerKey->key)][0] ?? null;
$propertyExtractor = new PropertyExtractor($object::class, $property->getName());
/** @var PropertyPath $propertyPath */
if ($propertyPath = $propertyExtractor->fetch(PropertyPath::class)) {
$value = $data[strtolower($propertyPath->path)][0] ?? null;
} else {
$value = $data[$property->getName()] ?? null;
}

@ -4,21 +4,43 @@ namespace Rinsvent\RequestBundle\Tests\Helper;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
use Rinsvent\ApiSDKGenerator\DTO\Writer\Config;
use Rinsvent\ApiSDKGenerator\Service\Writer;
use Rinsvent\RequestBundle\EventListener\RequestListener;
use Rinsvent\RequestBundle\Tests\unit\Listener\fixtures\FillTest\Controller;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
use Symfony\Component\HttpKernel\EventListener\RouterListener;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
class Unit extends \Codeception\Module
{
public function getWriter(string $lang = 'php'): Writer
public function send(Request $request): Response
{
return new Writer(
new Config(
dirname(dirname(dirname(__DIR__))) . DIRECTORY_SEPARATOR . 'templates',
dirname(dirname(dirname(__DIR__))) . DIRECTORY_SEPARATOR . 'var/tests/cache',
$lang,
dirname(dirname(dirname(__DIR__))) . DIRECTORY_SEPARATOR . 'var/tests/result',
'Rinsvent\\AuthSDK'
)
);
$routes = new RouteCollection();
$controller = new Controller();
$routes->add('hello', new Route('/hello/{name}', [
'_controller' => [$controller, 'hello']
]
));
$matcher = new UrlMatcher($routes, new RequestContext());
$dispatcher = new EventDispatcher();
$dispatcher->addSubscriber(new RouterListener($matcher, new RequestStack()));
$listener = new RequestListener();
$dispatcher->addListener('kernel.request', [$listener, 'onKernelRequest']);
$controllerResolver = new ControllerResolver();
$argumentResolver = new ArgumentResolver();
$kernel = new HttpKernel($dispatcher, $controllerResolver, new RequestStack(), $argumentResolver);
$response = $kernel->handle($request);
$response->send();
return $response;
}
}

@ -2,19 +2,7 @@
namespace Rinsvent\RequestBundle\Tests\Listener;
use Rinsvent\RequestBundle\Tests\unit\Listener\fixtures\FillTest\Controller;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
use Symfony\Component\HttpKernel\EventListener\RouterListener;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Rinsvent\RequestBundle\EventListener\RequestListener;
@ -39,31 +27,22 @@ class FillTest extends \Codeception\Test\Unit
$request = Request::create('/hello/igor', 'GET', [
'surname' => 'Surname'
]);
$response = $this->send($request);
$response = $this->tester->send($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('Surname', $request->get(RequestListener::REQUEST_DATA)->surname);
$this->assertEquals('Hello igor', $response->getContent());
}
private function send(Request $request): Response
public function testFailRequestData()
{
$routes = new RouteCollection();
$controller = new Controller();
$routes->add('hello', new Route('/hello/{name}', [
'_controller' => [$controller, 'hello']
]
));
$matcher = new UrlMatcher($routes, new RequestContext());
$dispatcher = new EventDispatcher();
$dispatcher->addSubscriber(new RouterListener($matcher, new RequestStack()));
$listener = new RequestListener();
$dispatcher->addListener('kernel.request', [$listener, 'onKernelRequest']);
$request = Request::create('/hello/igor', 'GET', [
'surname' => ''
]);
$response = $this->tester->send($request);
$controllerResolver = new ControllerResolver();
$argumentResolver = new ArgumentResolver();
$kernel = new HttpKernel($dispatcher, $controllerResolver, new RequestStack(), $argumentResolver);
$response = $kernel->handle($request);
$response->send();
return $response;
$this->assertEquals(400, $response->getStatusCode());
$this->assertEquals('{"errors":[{"message":"This value should not be blank.","path":"surname"}]}', $response->getContent());
}
}

Loading…
Cancel
Save