Add json template validation

This commit is contained in:
Dennis Eichhorn 2018-12-20 23:22:44 +01:00
parent 4ed4caf55b
commit 6cc59da699
9 changed files with 562 additions and 1 deletions

35
Module/infoLayout.json Normal file
View File

@ -0,0 +1,35 @@
{
"name": {
"id": "^[1-9]\\d*",
"internal": "[a-zA-Z0-9]+",
"external": "[a-zA-Z0-9]+"
},
"category": "[a-zA-Z0-9]+",
"version": "([0-9]+\\.){2}[0-9]+",
"requirements": {
".*": ".*"
},
"creator": {
"name": ".+",
"website": ".*"
},
"description": ".+",
"directory": "[a-zA-Z0-9]+",
"dependencies": {
".*": ".*"
},
"providing": {
".*": ".*"
},
"load": [
{
"pid": [
".*"
],
"type": "^[1-9]\\d*",
"for": "^([1-9]\\d*)|([a-zA-Z0-9]+)",
"from": "[a-zA-Z0-9]+",
"file": "[a-zA-Z0-9]*"
}
]
}

View File

@ -32,6 +32,6 @@ abstract class DateTime extends ValidatorAbstract
*/
public static function isValid($value, array $constraints = null) : bool
{
return (bool) strtotime($value);
return (bool) \strtotime($value);
}
}

225
Validation/Base/Json.php Normal file
View File

@ -0,0 +1,225 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package phpOMS\Validation\Base
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace phpOMS\Validation\Base;
use phpOMS\Validation\ValidatorAbstract;
use phpOMS\Utils\ArrayUtils;
/**
* Validate date.
*
* @package phpOMS\Validation\Base
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
abstract class Json extends ValidatorAbstract
{
/**
* {@inheritdoc}
*/
public static function isValid($value, array $constraints = null) : bool
{
return true;
}
/**
* Validate array against a template array.
*
* @param array $template Template structure
* @param array $source Source structure
* @param bool $perfect No additional elements in source allowed
*
* @return bool
*
* @since 1.0.0
*/
public static function validateTemplate(array $template, array $source, bool $perfect = false) : bool
{
$templatePaths = self::createAllViablePaths($template, '');
$sourcePaths = self::createAllViablePaths($source, '');
$isComplete = self::isCompleteSource($templatePaths, $sourcePaths);
if (!$isComplete) {
return false;
}
if ($perfect) {
$perfectFit = self::hasTemplateDefinition($templatePaths, $sourcePaths);
if (!$perfectFit) {
return false;
}
}
$isValid = self::isValidSource($templatePaths, $sourcePaths);
if (!$isValid) {
return false;
}
return true;
}
/**
* Create all viable paths and their values
*
* @param array $arr Array
* @param string $path Current path
*
* @return array
*
* @since 1.0.0
*/
private static function createAllViablePaths(array $arr, string $path = '') : array
{
$paths = [];
foreach ($arr as $key => $value) {
$tempPath = $path . '/' . $key;
if (\is_array($value)) {
$paths += self::createAllViablePaths($value, $tempPath);
} else {
$paths[$tempPath] = $value;
}
}
return $paths;
}
/**
* Check if source array has additional elements.
*
* @param array $template Template structure
* @param array $source Source structure
*
* @return bool Returns false in case of undefined elements
*
* @since 1.0.0
*/
private static function hasTemplateDefinition(array $template, array $source) : bool
{
$completePaths = [];
foreach ($template as $key => $value) {
$key = \str_replace('/0', '/.*', $key);
$completePaths[$key] = $value;
}
foreach ($source as $sPath => $sValue) {
$hasDefinition = false;
foreach ($completePaths as $tPath => $tValue) {
if ($tPath === $sPath
|| \preg_match('~' . \str_replace('/', '\\/', $tPath) . '~', $sPath) === 1
) {
$hasDefinition = true;
break;
}
}
if (!$hasDefinition) {
return false;
}
}
return true;
}
/**
* Check if source array is complete
*
* @param array $template Template structure
* @param array $source Source structure
*
* @return bool
*
* @since 1.0.0
*/
private static function isCompleteSource(array $template, array $source) : bool
{
$completePaths = [];
foreach ($template as $key => $value) {
$key = \str_replace('/0', '/.*', $key);
if (\stripos($key, '/.*') !== false) {
continue;
}
$completePaths[$key] = $value;
}
foreach ($completePaths as $tPath => $tValue) {
$sourceIsComplete = false;
foreach ($source as $sPath => $sValue) {
if ($tPath === $sPath
|| \preg_match('~' . \str_replace('/', '\\/', $tPath) . '~', $sPath) === 1
) {
unset($completePaths[$tPath]);
break;
}
}
}
return count($completePaths) === 0;
}
/**
* Check if source array is correct
*
* @param array $template Template structure
* @param array $source Source structure
*
* @return bool
*
* @since 1.0.0
*/
private static function isValidSource(array $template, array $source) : bool
{
$validPaths = [];
foreach ($template as $key => $value) {
$key = \str_replace('/0', '/\d*', $key);
$validPaths[$key] = $value;
}
foreach ($source as $sPath => $sValue) {
$sourceIsValid = false;
$foundPath = false;
foreach ($validPaths as $tPath => $tValue) {
if (!$foundPath
&& ($tPath === $sPath
|| \preg_match('~' . \str_replace('/', '\\/', $tPath) . '~', $sPath) === 1)
) {
$foundPath = true;
}
if (($tPath === $sPath
|| \preg_match('~' . \str_replace('/', '\\/', $tPath) . '~', $sPath) === 1)
&& ($tValue === $sValue
|| \preg_match('~' . ((string) $tValue) . '~', (string) $sValue) === 1)
) {
$sourceIsValid = true;
break;
}
}
if (!$sourceIsValid && $foundPath) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,38 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package tests
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
namespace phpOMS\tests\Validation\Base;
use phpOMS\Validation\Base\Json;
class JsonTest extends \PHPUnit\Framework\TestCase
{
public function testJson()
{
$template = \json_decode(file_get_contents(__DIR__ . '/json/template.json'), true);
$valid = \json_decode(file_get_contents(__DIR__ . '/json/valid.json'), true);
self::assertTrue(Json::validateTemplate($template, $valid));
self::assertTrue(Json::validateTemplate($template, $valid, true));
$additional = \json_decode(file_get_contents(__DIR__ . '/json/additional.json'), true);
self::assertTrue(Json::validateTemplate($template, $additional));
self::assertFalse(Json::validateTemplate($template, $additional, true));
$incomplete = \json_decode(file_get_contents(__DIR__ . '/json/incomplete.json'), true);
self::assertFalse(Json::validateTemplate($template, $incomplete));
$invalid = \json_decode(file_get_contents(__DIR__ . '/json/invalid.json'), true);
self::assertFalse(Json::validateTemplate($template, $invalid));
}
}

View File

@ -0,0 +1,58 @@
{
"name": {
"id": 1001100000,
"internal": "Tasks",
"external": "Tasks"
},
"category": "Tools",
"version": "1.0.0",
"requirements": {
"phpOMS": "1.0.0",
"phpOMS-db": "1.0.0"
},
"creator": {
"name": "Orange Management",
"website": "www.spl1nes.com"
},
"tooMuch": 1,
"description": "Tasks module.",
"directory": "Tasks",
"dependencies": {
"Admin": "1.0.0",
"Calendar": "1.0.0",
"Media": "1.0.0",
"Editor": "1.0.0"
},
"providing": {
"Navigation": "*"
},
"load": [
{
"pid": [
"/backend/task"
],
"type": 4,
"for": 0,
"from": "Tasks",
"file": "Tasks"
},
{
"pid": [
"/backend"
],
"type": 4,
"from": "Tasks",
"for": "Navigation",
"file": "Tasks"
},
{
"pid": [
"/backend"
],
"type": 5,
"from": "Tasks",
"for": "Navigation",
"file": "Navigation"
}
]
}

View File

@ -0,0 +1,56 @@
{
"name": {
"id": 1001100000,
"internal": "Tasks",
"external": "Tasks"
},
"category": "Tools",
"requirements": {
"phpOMS": "1.0.0",
"phpOMS-db": "1.0.0"
},
"creator": {
"name": "Orange Management",
"website": "www.spl1nes.com"
},
"description": "Tasks module.",
"directory": "Tasks",
"dependencies": {
"Admin": "1.0.0",
"Calendar": "1.0.0",
"Media": "1.0.0",
"Editor": "1.0.0"
},
"providing": {
"Navigation": "*"
},
"load": [
{
"pid": [
"/backend/task"
],
"type": 4,
"for": 0,
"from": "Tasks",
"file": "Tasks"
},
{
"pid": [
"/backend"
],
"type": 4,
"from": "Tasks",
"for": "Navigation",
"file": "Tasks"
},
{
"pid": [
"/backend"
],
"type": 5,
"from": "Tasks",
"for": "Navigation",
"file": "Navigation"
}
]
}

View File

@ -0,0 +1,57 @@
{
"name": {
"id": "abc",
"internal": "Tasks",
"external": "Tasks"
},
"category": "Tools",
"version": "1.0.0",
"requirements": {
"phpOMS": "1.0.0",
"phpOMS-db": "1.0.0"
},
"creator": {
"name": "Orange Management",
"website": "www.spl1nes.com"
},
"description": "Tasks module.",
"directory": "Tasks",
"dependencies": {
"Admin": "1.0.0",
"Calendar": "1.0.0",
"Media": "1.0.0",
"Editor": "1.0.0"
},
"providing": {
"Navigation": "*"
},
"load": [
{
"pid": [
"/backend/task"
],
"type": 4,
"for": 0,
"from": "Tasks",
"file": "Tasks"
},
{
"pid": [
"/backend"
],
"type": 4,
"from": "Tasks",
"for": "Navigation",
"file": "Tasks"
},
{
"pid": [
"/backend"
],
"type": 5,
"from": "Tasks",
"for": "Navigation",
"file": "Navigation"
}
]
}

View File

@ -0,0 +1,35 @@
{
"name": {
"id": "^[1-9]\\d*",
"internal": "[a-zA-Z0-9]+",
"external": "[a-zA-Z0-9]+"
},
"category": "[a-zA-Z0-9]+",
"version": "([0-9]+\\.){2}[0-9]+",
"requirements": {
".*": ".*"
},
"creator": {
"name": ".+",
"website": ".*"
},
"description": ".+",
"directory": "[a-zA-Z0-9]+",
"dependencies": {
".*": ".*"
},
"providing": {
".*": ".*"
},
"load": [
{
"pid": [
".*"
],
"type": "^[1-9]\\d*",
"for": "^([1-9]\\d*)|([a-zA-Z0-9]+)",
"from": "[a-zA-Z0-9]+",
"file": "[a-zA-Z0-9]*"
}
]
}

View File

@ -0,0 +1,57 @@
{
"name": {
"id": 1001100000,
"internal": "Tasks",
"external": "Tasks"
},
"category": "Tools",
"version": "1.0.0",
"requirements": {
"phpOMS": "1.0.0",
"phpOMS-db": "1.0.0"
},
"creator": {
"name": "Orange Management",
"website": "www.spl1nes.com"
},
"description": "Tasks module.",
"directory": "Tasks",
"dependencies": {
"Admin": "1.0.0",
"Calendar": "1.0.0",
"Media": "1.0.0",
"Editor": "1.0.0"
},
"providing": {
"Navigation": "*"
},
"load": [
{
"pid": [
"/backend/task"
],
"type": 4,
"for": 0,
"from": "Tasks",
"file": "Tasks"
},
{
"pid": [
"/backend"
],
"type": 4,
"from": "Tasks",
"for": "Navigation",
"file": "Tasks"
},
{
"pid": [
"/backend"
],
"type": 5,
"from": "Tasks",
"for": "Navigation",
"file": "Navigation"
}
]
}