Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from zfegg/develop
Add DbalRecordExistsFilter
- Loading branch information
Showing
7 changed files
with
184 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?php | ||
|
||
declare(strict_types = 1); | ||
|
||
namespace Zfegg\ContentValidation\Opis\Filter; | ||
|
||
use Opis\JsonSchema\Filter; | ||
use Opis\JsonSchema\Schema; | ||
use Opis\JsonSchema\ValidationContext; | ||
use Psr\Container\ContainerInterface; | ||
|
||
class DbalRecordExistsFilter implements Filter | ||
{ | ||
|
||
private ContainerInterface $container; | ||
private string $defaultId; | ||
|
||
public function __construct(ContainerInterface $container, string $defaultId = 'db') | ||
{ | ||
$this->container = $container; | ||
$this->defaultId = $defaultId; | ||
} | ||
|
||
public function validate(ValidationContext $context, Schema $schema, array $args = []): bool | ||
{ | ||
/** @var \Doctrine\DBAL\Connection $db */ | ||
$db = $this->container->get($args['db'] ?? $this->defaultId); | ||
|
||
if (isset($args['sql'])) { | ||
$sql = $args['sql']; | ||
} elseif (isset($args['table']) && isset($args['field'])) { | ||
$sql = sprintf('SELECT COUNT(*) FROM %s WHERE %s=?', $args['table'], $args['field']); | ||
} else { | ||
throw new \InvalidArgumentException('Invalid args.'); | ||
} | ||
|
||
$exists = $args['exists'] ?? false; | ||
$sth = $db->prepare($sql); | ||
$row = $sth->executeQuery([$context->currentData()])->fetchNumeric(); | ||
|
||
return $row[0] == $exists; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<?php | ||
|
||
declare(strict_types = 1); | ||
|
||
namespace ZfeggTest\ContentValidation\Opis\Filter; | ||
|
||
use Doctrine\DBAL\DriverManager; | ||
use Opis\JsonSchema\Schema; | ||
use Opis\JsonSchema\SchemaLoader; | ||
use Opis\JsonSchema\ValidationContext; | ||
use Opis\JsonSchema\Validator; | ||
use Zfegg\ContentValidation\Opis\Filter\DbalRecordExistsFilter; | ||
use PHPUnit\Framework\TestCase; | ||
use ZfeggTest\ContentValidation\SetupTrait; | ||
|
||
class DbalRecordExistsFilterTest extends TestCase | ||
{ | ||
|
||
use SetupTrait { | ||
setUp as setUpContainer; | ||
} | ||
|
||
const SQL = <<<SQL | ||
create table foo | ||
( | ||
id INTEGER not null primary key autoincrement, | ||
key VARCHAR(32) not null, | ||
value VARCHAR(32) not null | ||
); | ||
SQL; | ||
private $db; | ||
|
||
protected function setUp(): void | ||
{ | ||
$this->setUpContainer(); | ||
$db = DriverManager::getConnection(['url' => 'sqlite:///:memory:']); | ||
$db->executeStatement(self::SQL); | ||
$db->executeStatement('INSERT INTO foo VALUES(NULL, "exists","123")'); | ||
$this->container->setService('db', $db->getWrappedConnection()); | ||
$this->container->setService('dbal', $db); | ||
} | ||
|
||
public function testValidate(): void | ||
{ | ||
$filter = new DbalRecordExistsFilter($this->container, 'dbal'); | ||
|
||
$context = new ValidationContext('test', new SchemaLoader()); | ||
$schema = $this->createMock(Schema::class); | ||
$rs = $filter->validate($context, $schema, ['sql' => 'SELECT count(*) FROM foo where key=?']); | ||
$this->assertTrue($rs); | ||
|
||
$rs = $filter->validate($context, $schema, ['sql' => 'SELECT count(*) FROM foo where key=?', 'exists' => true]); | ||
$this->assertFalse($rs); | ||
|
||
$rs = $filter->validate($context, $schema, ['table' => 'foo', 'field' => 'key']); | ||
$this->assertTrue($rs); | ||
} | ||
|
||
|
||
public function testInValidator(): void | ||
{ | ||
$validator = $this->container->get(Validator::class); | ||
$data = <<<'JSON' | ||
{"key": "exists"} | ||
JSON; | ||
$data = json_decode($data); | ||
$result = $validator->validate($data, 'test:test/test-dbal-filter.json'); | ||
|
||
$this->assertTrue($result->isValid()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"type": "object", | ||
"properties": { | ||
"key": { | ||
"type": "string", | ||
"minLength": 1, | ||
"maxLength": 64, | ||
"$filters": [ | ||
{ | ||
"$func": "dbal-exists", | ||
"$vars": { | ||
"db": "dbal", | ||
"table": "foo", | ||
"field": "key", | ||
"exists": true | ||
} | ||
} | ||
] | ||
} | ||
}, | ||
"required": ["key"], | ||
"additionalProperties": false | ||
} |