Skip to content

Commit

Permalink
refactor: add factory for creating resource queries to pass to low le…
Browse files Browse the repository at this point in the history
  • Loading branch information
ThorstenSuckow committed Oct 19, 2022
1 parent cf87631 commit 0962331
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 0 deletions.
96 changes: 96 additions & 0 deletions lib/src/Http/V0/JsonApi/ResourceQueryFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

/**
* conjoon
* lumen-app-email
* Copyright (C) 2022 Thorsten Suckow-Homberg https://github.com/conjoon/lumen-app-email
*
* 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.
*/

declare(strict_types=1);

namespace App\Http\V0\JsonApi;

use Conjoon\Core\Util\ClassLoader;
use App\Http\V0\JsonApi\Resource\Query as QueryPool;
use Conjoon\Data\ParameterBag;
use Conjoon\Data\Resource\ResourceQuery;
use Conjoon\JsonApi\Request\Request as JsonApiRequest;
use Conjoon\MailClient\Data\Resource\Query as QueryParent;

/**
* ResourceQueryFactory responsible for dynamically loading ResourceQueries based on the
* JsonApiRequest-$request submitted to #createQueryFromRequest().
*/
class ResourceQueryFactory
{
/**
* @var ClassLoader
*/
protected readonly ClassLoader $classLoader;

/**
* @param ClassLoader $classLoader
*/
public function __construct(ClassLoader $classLoader)
{
$this->classLoader = $classLoader;
}


/**
* Returns the ResourceQuery that can be used for forwarding to sub-systems
* expecting a declarative API.
*
* @param JsonApiRequest $request
*
* @return ResourceQuery|null
*/
public function createQueryFromRequest(JsonApiRequest $request): ?ResourceQuery
{
$loader = $this->getClassLoader();

$target = $request->getResourceTarget();
$resourceType = $target->getType();
$targetsResourceCollection = $request->targetsResourceCollection();

$parameters = $request->getUrl()->getQuery()->getParameterBag() ?? new ParameterBag();

$type = $targetsResourceCollection ? "collection" : "single";
$loadList = [
"MessageItem" => [
"single" => [QueryPool\MessageItemQuery::class, QueryParent\MessageItemQuery::class],
"collection" => [QueryPool\MessageItemListQuery::class, QueryParent\MessageItemListQuery::class]
]
];

return $loader->load(...array_merge($loadList[$resourceType][$type], [[$parameters]]));
}


/**
* @return ClassLoader
*/
public function getClassLoader(): ClassLoader
{
return $this->classLoader;
}
}
135 changes: 135 additions & 0 deletions lib/tests/Http/V0/JsonApi/ResourceQueryFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php

/**
* conjoon
* lumen-app-email
* Copyright (C) 2022 Thorsten Suckow-Homberg https://github.com/conjoon/lumen-app-email
*
* 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.
*/

declare(strict_types=1);

namespace Tests\App\Http\V0\JsonApi;

;

use Conjoon\Core\Util\ClassLoader;
use App\Http\V0\JsonApi\Resource\Query as QueryPool;
use Conjoon\Data\ParameterBag;
use Conjoon\JsonApi\Request\Request as JsonApiRequest;
use Conjoon\MailClient\Data\Resource\Query as QueryParent;
use App\Http\V0\JsonApi\ResourceQueryFactory;
use Conjoon\Data\Resource\ObjectDescription;
use Conjoon\JsonApi\Query\Query as JsonApiQuery;
use Conjoon\JsonApi\Request\Url as JsonApiUrl;
use ReflectionException;
use Tests\TestCase;

/**
* Test ResourceQueryFactory
*/
class ResourceQueryFactoryTest extends TestCase
{

/**
* Tests class functionality
* @return void
*/
public function testClass()
{
$classLoader = new ClassLoader();
$resourceQueryFactory = new ResourceQueryFactory($classLoader);
$this->assertSame($classLoader, $resourceQueryFactory->getClassLoader());
}


/**
* Tests createQueryFromRequest()
*
* @return void
* @throws ReflectionException
*/
public function testCreateQueryFromRequest()
{
$loadList = [
"MessageItem_single" => [
QueryPool\MessageItemQuery::class, QueryParent\MessageItemQuery::class, new ParameterBag()
],
"MessageItem_collection" => [
QueryPool\MessageItemListQuery::class, QueryParent\MessageItemListQuery::class, new ParameterBag()
]
];
$runs = count(array_keys($loadList));
$currentKey = "";

$query = $this->getMockBuilder(JsonApiQuery::class)
->disableOriginalConstructor()
->onlyMethods(["getParameterBag"])->getMock();

$query->expects($this->any())->method("getParameterBag")->willReturnCallback(
function () use ($loadList, &$currentKey) {
return $loadList[$currentKey][2];
}
);

$url = $this->getMockBuilder(JsonApiUrl::class)
->disableOriginalConstructor()
->onlyMethods(["getQuery"])
->getMock();
$url->expects($this->any())->method("getQuery")
->willReturn($query);


$request = $this->getMockBuilder(JsonApiRequest::class)
->disableOriginalConstructor()
->onlyMethods(["getUrl", "getResourceTarget", "targetsResourceCollection"])
->getMock();


$request->expects($this->exactly($runs))->method("getUrl")->willReturn($url);

$request->expects($this->exactly($runs))->method("getResourceTarget")->willReturnCallback(
function () use (&$currentKey) {
$resourceTarget = $this->createMockForAbstract(ObjectDescription::class, ["getType"]);
$resourceTarget->expects($this->once())->method("getType")->willReturn(
explode("_", $currentKey)[0]
);
return $resourceTarget;
}
);
$request->expects($this->exactly($runs))->method("targetsResourceCollection")->willReturnCallback(
function () use (&$currentKey) {
return str_contains($currentKey, "collection");
}
);


$resourceQueryFactory = new ResourceQueryFactory(new ClassLoader());
foreach ($loadList as $index => $item) {
$currentKey = $index;
$result = $resourceQueryFactory->createQueryFromRequest($request);
$this->assertInstanceOf($item[0], $result);
$this->assertInstanceOf($item[1], $result);
$pb = $this->makeAccessible($result, "parameterBag", true);
$this->assertSame($item[2], $pb->getValue($result));
}
}
}

0 comments on commit 0962331

Please sign in to comment.