diff --git a/src/Action/ActionAbstract.php b/src/Action/ActionAbstract.php index 43dc73c..91289b1 100644 --- a/src/Action/ActionAbstract.php +++ b/src/Action/ActionAbstract.php @@ -33,9 +33,7 @@ abstract class ActionAbstract implements ActionInterface public function __construct(ContainerInterface $c) { $this->container = $c; - if ($c->has('request')) { - $this->request = $c['request']; - } + if ($c->has('response')) { $this->response = $c['response']; } diff --git a/src/Config/Config.php b/src/Config/Config.php index 5869c28..6a48c65 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -33,7 +33,7 @@ public function export() */ public function isEnvironment($environment) { - return in_array($this->get('app.environment'), (array)$environment); + return strtolower($this->get('app.environment')) === strtolower($environment); } /** diff --git a/src/Container/Container.php b/src/Container/Container.php index 3755772..30b3f0f 100644 --- a/src/Container/Container.php +++ b/src/Container/Container.php @@ -74,8 +74,8 @@ public function __construct(array $values = []) # Default Request Query Modifier (Do nothing), # Use your own implementation of RequestQueryModifierInterface if (!isset($values[self::ENTITY_FACTORY])) { - $this[self::ENTITY_FACTORY] = function () { - return new EntityFactory(); + $this[self::ENTITY_FACTORY] = function (ContainerInterface $c) { + return new EntityFactory($c); }; } diff --git a/src/Entity/EntityFactory.php b/src/Entity/EntityFactory.php index ffe548d..f9ed9c0 100644 --- a/src/Entity/EntityFactory.php +++ b/src/Entity/EntityFactory.php @@ -9,6 +9,8 @@ namespace Eukles\Entity; use Eukles\Action\ActionInterface; +use Eukles\Container\ContainerInterface; +use Eukles\Container\ContainerTrait; use Eukles\Util\PksFinder; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -17,6 +19,18 @@ class EntityFactory implements EntityFactoryInterface { + use ContainerTrait; + + /** + * EntityFactoryInterface constructor. + * + * @param ContainerInterface $c + */ + public function __construct(ContainerInterface $c) + { + $this->container = $c; + } + /** * Create a new instance of activeRecord and add it to Request attributes * @@ -33,7 +47,7 @@ public function create( ResponseInterface $response, callable $next ): ResponseInterface { - $entityRequest = $config->getEntityRequest(); + $entityRequest = $config->createEntityRequest($this->container); # make a new empty record $obj = $entityRequest->instantiateActiveRecord(); @@ -77,13 +91,11 @@ public function fetch( ResponseInterface $response, callable $next ): ResponseInterface { - $entityRequest = $config->getEntityRequest(); + $entityRequest = $config->createEntityRequest($this->container); # First, we try to determine PK in request path (most common case) if (isset($request->getAttribute('routeInfo')[2][$config->getRequestParameterName()])) { - $config->getEntityRequest()->setPrimaryKey( - $request->getAttribute('routeInfo')[2][$config->getRequestParameterName()] - ); + $entityRequest->setPrimaryKey($request->getAttribute('routeInfo')[2][$config->getRequestParameterName()]); } # Next, we create the query (ModelCriteria), based on Action class (which can alter the query) diff --git a/src/Entity/EntityFactoryConfig.php b/src/Entity/EntityFactoryConfig.php index f3ea809..4c9b39b 100644 --- a/src/Entity/EntityFactoryConfig.php +++ b/src/Entity/EntityFactoryConfig.php @@ -8,6 +8,7 @@ namespace Eukles\Entity; +use Eukles\Container\ContainerInterface; class EntityFactoryConfig { @@ -44,13 +45,11 @@ class EntityFactoryConfig * @var string */ protected $requestParameterName = "id"; - /** * @var string */ protected $type; - /** * Constructor wrapper * @@ -62,19 +61,29 @@ public static function create() } /** - * @return EntityRequestInterface + * @return string */ - public function getEntityRequest(): EntityRequestInterface + public function getEntityRequest(): string { return $this->entityRequest; } /** - * @param EntityRequestInterface $entityRequestClass + * @param ContainerInterface $container + * + * @return EntityRequestInterface + */ + public function createEntityRequest(ContainerInterface $container): EntityRequestInterface + { + return new $this->entityRequest($container); + } + + /** + * @param string $entityRequestClass Name * * @return EntityFactoryConfig */ - public function setEntityRequest(EntityRequestInterface $entityRequestClass): EntityFactoryConfig + public function setEntityRequest(string $entityRequestClass): EntityFactoryConfig { $this->entityRequest = $entityRequestClass; @@ -121,7 +130,6 @@ public function setRequestParameterName(string $requestParameterName): EntityFac return $this; } - /** * @return string */ diff --git a/src/Entity/EntityFactoryInterface.php b/src/Entity/EntityFactoryInterface.php index ce87b57..e045bf2 100644 --- a/src/Entity/EntityFactoryInterface.php +++ b/src/Entity/EntityFactoryInterface.php @@ -2,6 +2,7 @@ namespace Eukles\Entity; +use Eukles\Container\ContainerInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -13,6 +14,13 @@ interface EntityFactoryInterface { + /** + * EntityFactoryInterface constructor. + * + * @param ContainerInterface $c + */ + public function __construct(ContainerInterface $c); + /** * Create a new instance of activeRecord and add it to Request attributes * diff --git a/src/Service/QueryModifier/Util/EasyFilter.php b/src/Service/QueryModifier/Util/EasyFilter.php new file mode 100644 index 0000000..e6d3c17 --- /dev/null +++ b/src/Service/QueryModifier/Util/EasyFilter.php @@ -0,0 +1,123 @@ + $value[0]]; + if (!empty($value[1])) { + $valueTmp['max'] = $value[1]; + } + $value = $valueTmp; + } + } # Handle > operators + elseif ($firstChar === '>') { + $value = substr($value, 1); + $operator = Criteria::GREATER_THAN; + if (mb_substr($value, 0, 1) === '=') { + $value = substr($value, 1); + $operator = Criteria::GREATER_EQUAL; + } + } # Handle < operators + elseif ($firstChar === '<') { + $value = substr($value, 1); + $operator = Criteria::LESS_THAN; + if (strpos($value, '=') === 0) { + $value = substr($value, 1); + $operator = Criteria::LESS_EQUAL; + } + } elseif ($firstChar === '"' || $firstChar === "'") { + $value = trim($value, "\"'"); + } # Handle IN operator when comma is present + elseif (strpos($value, ',') !== false) { + # IN operator is handled by propel + $operator = $negate ? Criteria::NOT_IN : null; + $value = explode(',', $value); + } + + return [$operator, $value]; + } + + /** + * @param $property + * @param $value + * + * @return bool + */ + public function apply($property, $value): bool + { + $this->value = $value; + $this->property = $property; + if ($this->isAutoUseRelationQuery()) { + return $this->useRelationQuery(); + } else { + return $this->filter(); + } + } + + /** + * @return bool + */ + protected function filter() + { + # Determine if method is callable in Query class + $method = 'filterBy' . ucfirst($this->property); + if (!method_exists($this->query, $method)) { + return false; + } + + list($value, $operator) = $this->build($this->value); + + $this->query = call_user_func([$this->query, $method], $value, $operator); + + return true; + } +} diff --git a/src/Service/QueryModifier/Util/EasySort.php b/src/Service/QueryModifier/Util/EasySort.php new file mode 100644 index 0000000..3deb673 --- /dev/null +++ b/src/Service/QueryModifier/Util/EasySort.php @@ -0,0 +1,67 @@ +property, $this->direction) = self::build($sort); + if ($this->isAutoUseRelationQuery()) { + return $this->useRelationQuery(); + } else { + return $this->filter(); + } + } + + /** + * @return bool + */ + protected function filter() + { + # Try to call method in Query class + try { + $this->query = $this->query->orderBy(ucfirst($this->property), $this->direction); + } catch (UnknownColumnException $e) { + return false; + } catch (UnknownModelException $e) { + return false; + } + + return true; + } +} diff --git a/src/Service/QueryModifier/Util/EasyUtil.php b/src/Service/QueryModifier/Util/EasyUtil.php new file mode 100644 index 0000000..c118e8b --- /dev/null +++ b/src/Service/QueryModifier/Util/EasyUtil.php @@ -0,0 +1,114 @@ +query = $query; + } + + abstract protected function filter(); + + + /** + * @param ModelCriteria $query + * + * @return EasyUtil + */ + public static function create(ModelCriteria $query): EasyUtil + { + return new static($query); + } + + /** + * @return ModelCriteria + */ + public function getQuery(): ModelCriteria + { + return $this->query; + } + + /** + * @return bool + */ + public function isAutoUseRelationQuery(): bool + { + return $this->autoUseRelationQuery; + } + + /** + * @param bool $autoUseRelationQuery + * + * @return static + */ + public function setAutoUseRelationQuery(bool $autoUseRelationQuery): EasyUtil + { + $this->autoUseRelationQuery = $autoUseRelationQuery; + + return $this; + } + + /** + * @return bool + */ + protected function useRelationQuery() + { + $map = explode(self::RELATION_SEP, $this->property); + $this->property = array_pop($map); + + if (count($map) > 0) { + $this->relations = $map; + foreach ($this->relations as $relation) { + $method = sprintf('use%sQuery', ucfirst($relation)); + if (!method_exists($this->query, $method)) { + return false; + } + $this->query = call_user_func([$this->query, $method]); + } + + $result = $this->filter(); + + foreach ($this->relations as $null) { + $this->query = $this->query->endUse(); + } + } else { + return $this->filter(); + } + + return $result; + } +} diff --git a/src/Service/Request/QueryModifier/Modifier/EasyFilter.php b/src/Service/Request/QueryModifier/Modifier/EasyFilter.php new file mode 100644 index 0000000..1774660 --- /dev/null +++ b/src/Service/Request/QueryModifier/Modifier/EasyFilter.php @@ -0,0 +1,54 @@ +ignoredParams = $ignoredParams; + $this->request = $request; + } + + /** + * @param ModelCriteria $query + */ + public function apply(ModelCriteria $query) + { + $filter = new \Eukles\Service\QueryModifier\Util\EasyFilter($query); + $filter->setAutoUseRelationQuery(true); + + foreach ($this->request->getQueryParams() as $column => $value) { + # Ignored params + if (in_array($column, $this->ignoredParams)) { + continue; + } + $filter->apply($column, $value); + } + } +} diff --git a/src/Service/Request/QueryModifier/Modifier/EasySorter.php b/src/Service/Request/QueryModifier/Modifier/EasySorter.php deleted file mode 100644 index cf9865d..0000000 --- a/src/Service/Request/QueryModifier/Modifier/EasySorter.php +++ /dev/null @@ -1,95 +0,0 @@ -ignoredParams = $ignoredParams; - $this->request = $request; - } - - /** - * @param ModelCriteria $query - */ - public function apply(ModelCriteria $query) - { - foreach ($this->request->getQueryParams() as $column => $value) { - # Ignored params - if (in_array($column, $this->ignoredParams)) { - continue; - } - - # Determine if method is callable in Query class - $method = 'filterBy' . ucfirst($column); - if (!method_exists($query, $method)) { - continue; - } - - # Use default operator - $operator = Criteria::EQUAL; - - # Handle negate operator - $negate = strpos($value, '!') === 0; - if ($negate) { - $value = substr($value, 1); - $operator = Criteria::NOT_EQUAL; - } - - # Handle LIKE operator when % is present in value - if (strpos($value, '%') === 0 || strpos($value, '%') === strlen($value) - 1) { - $operator = $negate ? Criteria::NOT_LIKE : Criteria::LIKE; - }# Handle IN operator when comma is present - elseif (strpos($value, ',') !== false) { - # IN operator is handled by propel - $operator = null; - $value = explode(',', $value); - } # Handle > operators - elseif (strpos($value, '>') === 0) { - $value = substr($value, 1); - $operator = Criteria::GREATER_THAN; - if (strpos($value, '=') === 0) { - $value = substr($value, 1); - $operator = Criteria::GREATER_EQUAL; - } - } # Handle < operators - elseif (strpos($value, '<') === 0) { - $value = substr($value, 1); - $operator = Criteria::LESS_THAN; - if (strpos($value, '=') === 0) { - $value = substr($value, 1); - $operator = Criteria::LESS_EQUAL; - } - } - - call_user_func([$query, $method], $value, $operator); - } - } -} diff --git a/src/Service/Request/QueryModifier/Modifier/SortModifier.php b/src/Service/Request/QueryModifier/Modifier/SortModifier.php index 2b81d66..8a01e9f 100644 --- a/src/Service/Request/QueryModifier/Modifier/SortModifier.php +++ b/src/Service/Request/QueryModifier/Modifier/SortModifier.php @@ -11,6 +11,7 @@ namespace Eukles\Service\Request\QueryModifier\Modifier; +use Eukles\Service\QueryModifier\Util\EasySort; use Eukles\Service\Request\QueryModifier\Modifier\Base\ModifierBase; use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\Exception\UnknownColumnException; @@ -43,14 +44,7 @@ public function setModifierFromRequest(ServerRequestInterface $request) if (is_string($modifiers) && null === json_decode($modifiers)) { $sorters = explode(',', $modifiers); foreach ($sorters as $sorter) { - $direction = Criteria::ASC; - if (strpos($sorter, '+') === 0) { - $sorter = substr($sorter, 1); - } elseif (strpos($sorter, '-') === 0) { - $sorter = substr($sorter, 1); - $direction = Criteria::DESC; - } - + list($sorter, $direction) = EasySort::build($sorter); $this->modifiers[] = [ 'property' => $sorter, 'direction' => $direction, diff --git a/src/Service/Request/QueryModifier/RequestQueryModifier.php b/src/Service/Request/QueryModifier/RequestQueryModifier.php index d3559f9..60f979a 100644 --- a/src/Service/Request/QueryModifier/RequestQueryModifier.php +++ b/src/Service/Request/QueryModifier/RequestQueryModifier.php @@ -9,7 +9,7 @@ namespace Eukles\Service\Request\QueryModifier; use Eukles\Service\QueryModifier\QueryModifierInterface; -use Eukles\Service\Request\QueryModifier\Modifier\EasySorter; +use Eukles\Service\Request\QueryModifier\Modifier\EasyFilter; use Eukles\Service\Request\QueryModifier\Modifier\FilterModifier; use Eukles\Service\Request\QueryModifier\Modifier\SortModifier; use Propel\Runtime\ActiveQuery\ModelCriteria; @@ -66,7 +66,7 @@ public function apply(ModelCriteria $query) $sorters = new SortModifier($this->request); $sorters->apply($query); - $easySorters = new EasySorter($this->request, ["sort", "filter"]); + $easySorters = new EasyFilter($this->request, ["sort", "filter"]); $easySorters->apply($query); return $query; diff --git a/src/Service/Router/Route.php b/src/Service/Router/Route.php index e0d4a62..f303643 100644 --- a/src/Service/Router/Route.php +++ b/src/Service/Router/Route.php @@ -198,11 +198,13 @@ public function createEntity(EntityFactoryConfig $config): RouteInterface } # Auto add EntityRequest if not specified if (!$config->issetEntityRequest()) { - $config->setEntityRequest(new $this->requestClass($this->getContainer())); + $config->setEntityRequest($this->requestClass); } # Auto determine name of parameter to add if (!$config->issetParameterToInjectInto()) { - $config->setParameterToInjectInto($config->getEntityRequest()->getNameOfParameterToAdd(false)); + $config->setParameterToInjectInto( + $config->createEntityRequest($this->container)->getNameOfParameterToAdd(false) + ); } # Make sure config is clean @@ -228,6 +230,7 @@ public function deprecated(): RouteInterface * @param EntityFactoryConfig $config * * @return RouteInterface + * @throws \Eukles\Entity\EntityFactoryConfigException */ public function fetchEntity(EntityFactoryConfig $config): RouteInterface { @@ -240,11 +243,13 @@ public function fetchEntity(EntityFactoryConfig $config): RouteInterface } # Auto add EntityRequest if not specified if (!$config->issetEntityRequest()) { - $config->setEntityRequest(new $this->requestClass($this->getContainer())); + $config->setEntityRequest($this->requestClass); } # Auto determine name of parameter to add if (!$config->issetParameterToInjectInto()) { - $config->setParameterToInjectInto($config->getEntityRequest()->getNameOfParameterToAdd(false)); + $config->setParameterToInjectInto( + $config->createEntityRequest($this->container)->getNameOfParameterToAdd(false) + ); } # Make sure config is clean diff --git a/tests/Action/ActionTest.php b/tests/Action/ActionTest.php index f14341b..f0956d4 100644 --- a/tests/Action/ActionTest.php +++ b/tests/Action/ActionTest.php @@ -32,6 +32,11 @@ public function testConstructWithContainer() public function testResponse() { + $c = new \Slim\Container(["response" => function () { return new \Slim\Http\Response(); }]); + /** @var ActionInterface $a */ + $a = $this->getMockForAbstractClass(ActionAbstract::class, [$c]); + $this->assertSame($c["response"], $a->getResponse()); + /** @var ActionInterface $a */ $a = $this->getMockForAbstractClass(ActionAbstract::class, [], "", false); $r = new Response(); diff --git a/tests/Config/ConfigTest.php b/tests/Config/ConfigTest.php index a37f0b8..43bbe80 100644 --- a/tests/Config/ConfigTest.php +++ b/tests/Config/ConfigTest.php @@ -13,7 +13,7 @@ class ConfigTest extends TestCase { - + public function testExport() { $configArray = [ @@ -22,12 +22,28 @@ public function testExport() 'key2' => "value2", ], ]; - + $config = new Config($configArray); - + $configString = $config->export(); $newConfigArray = eval("return " . $configString . ";"); - + $this->assertSame($newConfigArray, $configArray); } + + public function testIsEnvironment() + { + $config = new Config(['app' => ['environment' => "DEV"]]); + + $this->assertTrue($config->isEnvironment('dev')); + $this->assertTrue($config->isEnvironment('DEV')); + $this->assertFalse($config->isEnvironment('foo')); + } + + public function testIsNotProduction() + { + $config = new Config(['app' => ['environment' => "DEV"]]); + + $this->assertTrue($config->isNotProduction()); + } } diff --git a/tests/Service/QueryModifier/Util/EasyFilterTest.php b/tests/Service/QueryModifier/Util/EasyFilterTest.php new file mode 100644 index 0000000..7d00698 --- /dev/null +++ b/tests/Service/QueryModifier/Util/EasyFilterTest.php @@ -0,0 +1,169 @@ +assertSame(null, $operator); + $this->assertSame("foo", $value); + + list($operator, $value) = EasyFilter::build("!foo"); + $this->assertSame(Criteria::NOT_EQUAL, $operator); + $this->assertSame("foo", $value); + + list($operator, $value) = EasyFilter::build("foo,bar"); + $this->assertSame(null, $operator); + $this->assertSame(["foo", "bar"], $value); + + list($operator, $value) = EasyFilter::build("!foo,bar"); + $this->assertSame(Criteria::NOT_IN, $operator); + $this->assertSame(["foo", "bar"], $value); + + list($operator, $value) = EasyFilter::build("%foo,bar"); + $this->assertSame(Criteria::LIKE, $operator); + $this->assertSame("%foo,bar", $value); + + list($operator, $value) = EasyFilter::build("foo%"); + $this->assertSame(Criteria::LIKE, $operator); + $this->assertSame("foo%", $value); + + list($operator, $value) = EasyFilter::build(">1"); + $this->assertSame(Criteria::GREATER_THAN, $operator); + $this->assertSame("1", $value); + + list($operator, $value) = EasyFilter::build("<1"); + $this->assertSame(Criteria::LESS_THAN, $operator); + $this->assertSame("1", $value); + + list($operator, $value) = EasyFilter::build(">=1"); + $this->assertSame(Criteria::GREATER_EQUAL, $operator); + $this->assertSame("1", $value); + + list($operator, $value) = EasyFilter::build("<=1"); + $this->assertSame(Criteria::LESS_EQUAL, $operator); + $this->assertSame("1", $value); + + list($operator, $value) = EasyFilter::build("!%foo,bar"); + $this->assertSame(Criteria::NOT_LIKE, $operator); + $this->assertSame("%foo,bar", $value); + + list($operator, $value) = EasyFilter::build("[1,5]"); + $this->assertSame(null, $operator); + $this->assertSame(["min" => "1", "max" => "5"], $value); + list($operator, $value) = EasyFilter::build("[1,5"); + $this->assertSame(null, $operator); + $this->assertSame(["min" => "1", "max" => "5"], $value); + + list($operator, $value) = EasyFilter::build("[1,5]"); + $this->assertSame(null, $operator); + $this->assertSame(["min" => "1", "max" => "5"], $value); + + list($operator, $value) = EasyFilter::build("[1,5"); + $this->assertSame(null, $operator); + $this->assertSame(["min" => "1", "max" => "5"], $value); + + list($operator, $value) = EasyFilter::build("[1"); + $this->assertSame(null, $operator); + $this->assertSame(["min" => "1"], $value); + + list($operator, $value) = EasyFilter::build("[1,"); + $this->assertSame(null, $operator); + $this->assertSame(["min" => "1"], $value); + + list($operator, $value) = EasyFilter::build("[]"); + $this->assertSame(null, $operator); + $this->assertSame(null, $value); + + list($operator, $value) = EasyFilter::build("["); + $this->assertSame(null, $operator); + $this->assertSame(null, $value); + + list($operator, $value) = EasyFilter::build("'test,quoted'"); + $this->assertSame(null, $operator); + $this->assertSame("test,quoted", $value); + } + + public function testCreate() + { + $this->assertInstanceOf(EasyFilter::class, EasyFilter::create(new ModelCriteria())); + } + + public function testApplySimpleFailure() + { + $f = new EasyFilter($this->mockQueryInstance()); + + # FALSE when relation and no use query + $this->assertFalse($f->apply('baz', "foo")); + } + + public function testApplySimpleSuccess() + { + $f = new EasyFilter($this->mockQueryInstance()); + + # TRUE when no relation + $this->assertTrue($f->apply('aName', "foo")); + } + + public function testApplyUseRelationQueryFailures() + { + $f = new EasyFilter($this->mockQueryInstance()); + + # FALSE when relation and no use query + $this->assertFalse($f->apply('b.bName', "foo")); + + # FALSE when relation and unknown property + $f->setAutoUseRelationQuery(true); + $this->assertFalse($f->apply('b.foo', "foo")); + } + + public function testApplyUseRelationQuerySuccess() + { + $f = new EasyFilter($this->mockQueryInstance()); + + # TRUE when no relation and unknown property + $this->assertTrue($f->apply('aName', "foo")); + + # TRUE when relation and no use query + $f->setAutoUseRelationQuery(true); + $this->assertTrue($f->apply('b.bName', "foo")); + $this->assertTrue($f->apply('b.c.cName', "foo")); + $this->assertTrue($f->apply('b.c.id', 0)); + } + + public static function setUpBeforeClass() + { + if (!class_exists("\\A")) { + $schema = file_get_contents(__DIR__ . '/../../../schema-small.xml'); + $builder = new QuickBuilder(); + $builder->setSchema($schema); + $builder->buildClasses(); + } + } + + /** + * @return ModelCriteria $query + */ + protected function mockQueryInstance() + { + + /** @var ModelCriteria $query */ + $query = new \AQuery; + + return $query; + } +} diff --git a/tests/Service/QueryModifier/Util/EasySortTest.php b/tests/Service/QueryModifier/Util/EasySortTest.php new file mode 100644 index 0000000..5f2a637 --- /dev/null +++ b/tests/Service/QueryModifier/Util/EasySortTest.php @@ -0,0 +1,114 @@ +setSchema($schema); + $builder->buildClasses(); + } + } + + public function testApplySimpleFailure() + { + $f = new EasySort($this->mockQueryInstance()); + + # FALSE when relation and no use query + $this->assertFalse($f->apply('baz')); + } + + public function testApplySimpleSuccess() + { + $f = new EasySort($this->mockQueryInstance()); + + # TRUE when relation and no use query + $this->assertTrue($f->apply('-aName')); + } + + public function testApplyUseRelationQueryFailures() + { + $f = new EasySort($this->mockQueryInstance()); + + # FALSE when relation and no use query + $this->assertFalse($f->apply('-b.bName')); + + # FALSE when relation and unknown property + $f->setAutoUseRelationQuery(true); + $this->assertFalse($f->apply('b.foo')); + + # FALSE when relation and bad placement of direction + $f->setAutoUseRelationQuery(true); + $this->assertFalse($f->apply('b.-foo')); + + # FALSE when bad relation + $f->setAutoUseRelationQuery(true); + $this->assertFalse($f->apply('bad.foo')); + } + + public function testApplyUseRelationQuerySuccess() + { + $f = new EasySort($this->mockQueryInstance()); + $f->setAutoUseRelationQuery(true); + + $this->assertTrue($f->apply('-aName')); + $this->assertTrue($f->apply('-b.bName')); + $this->assertTrue($f->apply('-b.c.cName')); + $this->assertTrue($f->apply('-b.c.id')); + + $this->assertSame([ + 0 => 'a.a_name DESC', + 1 => 'b.b_name DESC', + 2 => 'c.c_name DESC', + 3 => 'c.id DESC', + ], $f->getQuery()->getOrderByColumns()); + } + + public function testBuild() + { + list($property, $direction) = EasySort::build("foo"); + $this->assertSame("foo", $property); + $this->assertSame($direction, Criteria::ASC); + + list($property, $direction) = EasySort::build("+foo"); + $this->assertSame("foo", $property); + $this->assertSame($direction, Criteria::ASC); + + list($property, $direction) = EasySort::build("-foo"); + $this->assertSame("foo", $property); + $this->assertSame($direction, Criteria::DESC); + } + + public function testCreate() + { + $this->assertInstanceOf(EasySort::class, EasySort::create(new ModelCriteria())); + } + + /** + * @return ModelCriteria $query + */ + protected function mockQueryInstance() + { + + /** @var ModelCriteria $query */ + $query = new \AQuery; + + return $query; + } +} diff --git a/tests/Service/QueryModifier/Util/EasyUtilTest.php b/tests/Service/QueryModifier/Util/EasyUtilTest.php new file mode 100644 index 0000000..473af7f --- /dev/null +++ b/tests/Service/QueryModifier/Util/EasyUtilTest.php @@ -0,0 +1,39 @@ +getMockForAbstractClass(EasyUtil::class, [$query]); + $this->assertSame($query, $t->getQuery()); + } + + public function testIsAutoUseRelationQuery() + { + /** @var EasyUtil $t */ + $t = $this->getMockForAbstractClass(EasyUtil::class, [new ModelCriteria]); + $this->assertFalse($t->isAutoUseRelationQuery()); + } + + public function testSetAutoUseRelationQuery() + { + /** @var EasyUtil $t */ + $t = $this->getMockForAbstractClass(EasyUtil::class, [new ModelCriteria]); + $t->setAutoUseRelationQuery(true); + $this->assertTrue($t->isAutoUseRelationQuery()); + } +} diff --git a/tests/schema-small.xml b/tests/schema-small.xml new file mode 100644 index 0000000..00eedfe --- /dev/null +++ b/tests/schema-small.xml @@ -0,0 +1,25 @@ + + + + +
+ + + + + + + + +
+ + + + + + + + + +
+