cerys
6 months ago
24 changed files with 2451 additions and 25 deletions
@ -0,0 +1,4 @@ |
|||||
|
.idea/ |
||||
|
composer.phar |
||||
|
vendor/ |
||||
|
*.cache |
@ -1,3 +1,4 @@ |
|||||
# DeegraphPHP |
# DeegraphPHP |
||||
|
|
||||
Documentation is available at https://wiki.darksparrow.uk/en/Packages/PHP/DeegraphPHP. |
- Package is available at https://packagist.org/packages/darksparrow/deegraph-php |
||||
|
- Documentation is available at https://wiki.darksparrow.uk/en/Packages/PHP/DeegraphPHP. |
||||
|
@ -1,20 +1,33 @@ |
|||||
{ |
{ |
||||
"name": "darksparrow/deegraph-php", |
"name": "darksparrow/deegraph-php", |
||||
"description": "Deegraph Interactions Wrapper", |
"description": "Deegraph Interactions Wrapper", |
||||
"type": "library", |
"type": "library", |
||||
"license": "MPL-2.0", |
"license": "MPL-2.0", |
||||
"authors": [ |
"authors": [ |
||||
{ |
{ |
||||
"name": "Cerys Lewis", |
"name": "Cerys Lewis", |
||||
"email": "cerys@darksparrow.uk", |
"email": "cerys@darksparrow.uk", |
||||
"homepage": "https://ceryslewis.dev", |
"homepage": "https://ceryslewis.dev", |
||||
"role": "Lead Developer" |
"role": "Lead Developer" |
||||
} |
} |
||||
], |
], |
||||
"support": { |
"minimum-stability": "dev", |
||||
"email": "cerys@darksparrow.uk" |
"support": { |
||||
}, |
"email": "cerys@darksparrow.uk" |
||||
"require": { |
}, |
||||
"php": ">=8.1" |
"autoload": { |
||||
} |
"psr-4": { |
||||
} |
"Darksparrow\\DeegraphPHP\\": "src/" |
||||
|
} |
||||
|
}, |
||||
|
"require": { |
||||
|
"php": ">=8.1", |
||||
|
"ext-curl": "*" |
||||
|
}, |
||||
|
"require-dev": { |
||||
|
"phpunit/phpunit": "^9.5" |
||||
|
}, |
||||
|
"scripts": { |
||||
|
"test": "phpunit" |
||||
|
} |
||||
|
} |
||||
|
File diff suppressed because it is too large
@ -0,0 +1,10 @@ |
|||||
|
<phpunit |
||||
|
colors="true" |
||||
|
bootstrap="tests/bootstrap.php" |
||||
|
> |
||||
|
<testsuites> |
||||
|
<testsuite name="DeegraphPHP Tests"> |
||||
|
<directory>tests</directory> |
||||
|
</testsuite> |
||||
|
</testsuites> |
||||
|
</phpunit> |
@ -0,0 +1,46 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\Attributes; |
||||
|
|
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders\InsertQuery; |
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders\PutQuery; |
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders\SelectQuery; |
||||
|
use PhpParser\Node\Attribute; |
||||
|
use PhpParser\Node\Name; |
||||
|
use ReflectionClass; |
||||
|
|
||||
|
#[\Attribute] class QueryBuilderQuery extends Attribute |
||||
|
{ |
||||
|
public function __construct() |
||||
|
{ |
||||
|
parent::__construct(new Name("QueryBuilderQuery", []), [], []); |
||||
|
} |
||||
|
|
||||
|
public function ValidateValues( |
||||
|
InsertQuery|PutQuery|SelectQuery $target |
||||
|
): void |
||||
|
{ |
||||
|
$nameBase = "Darksparrow\\DeegraphPHP\\Attributes"; |
||||
|
$reflection = new ReflectionClass($target); |
||||
|
$properties = $reflection->getProperties(); |
||||
|
|
||||
|
foreach ($properties as $property) |
||||
|
{ |
||||
|
$attributes = $property->getAttributes(); |
||||
|
$propertyName = $property->getName(); |
||||
|
$propertyValue = $property->getValue($target); |
||||
|
|
||||
|
if(sizeof($attributes) == 0) continue; |
||||
|
|
||||
|
foreach ($attributes as $attribute) |
||||
|
{ |
||||
|
if($attribute->getName() == "$nameBase\\QueryBuilderRequiredField") |
||||
|
{ |
||||
|
if($propertyValue == "") |
||||
|
throw new \Exception(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,20 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\Attributes; |
||||
|
|
||||
|
use PhpParser\Node\Attribute; |
||||
|
use PhpParser\Node\Name; |
||||
|
use ReflectionClass; |
||||
|
|
||||
|
#[\Attribute] class QueryBuilderRequiredField extends Attribute |
||||
|
{ |
||||
|
public bool $Required; |
||||
|
|
||||
|
public function __construct( |
||||
|
bool $required = false |
||||
|
) |
||||
|
{ |
||||
|
$this->Required = $required; |
||||
|
parent::__construct(new Name("QueryBuilderRequiredField", []), [], []); |
||||
|
} |
||||
|
} |
@ -0,0 +1,88 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\Core; |
||||
|
|
||||
|
use Darksparrow\DeegraphPHP\DataStructures\QueryResponseWrapper; |
||||
|
use Darksparrow\DeegraphPHP\DataStructures\ServerInfo; |
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders\InsertQuery; |
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders\PutQuery; |
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders\SelectQuery; |
||||
|
|
||||
|
class DeegraphServer |
||||
|
{ |
||||
|
private string $ServerDomain; |
||||
|
private int $Port; |
||||
|
private string $Token; |
||||
|
private string $Actor; |
||||
|
private bool $AllowSelfSignedCerts; |
||||
|
|
||||
|
public function __construct( |
||||
|
string $token, |
||||
|
string $actor, |
||||
|
string $server = "localhost", |
||||
|
int $port = 8088, |
||||
|
bool $allowSelfSignedCerts = false) |
||||
|
{ |
||||
|
$this->ServerDomain = $server; |
||||
|
$this->Port = $port; |
||||
|
$this->Token = $token; |
||||
|
$this->Actor = $actor; |
||||
|
$this->AllowSelfSignedCerts = $allowSelfSignedCerts; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Runs an API request against the Deegraph Server, and returns back information about the Deegraph Server. |
||||
|
* @return ServerInfo |
||||
|
*/ |
||||
|
public function ServerInfo(): ServerInfo |
||||
|
{ |
||||
|
$response = $this->RunRawRequest(endpoint: "/api/v1/@server_info"); |
||||
|
return ServerInfo::FromAPIResponse(response: $response); |
||||
|
} |
||||
|
|
||||
|
private function RunRawRequest(string $endpoint, string $method = "GET", string $body = null): string |
||||
|
{ |
||||
|
$ch = curl_init("https://{$this->ServerDomain}:{$this->Port}{$endpoint}"); |
||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [ |
||||
|
'Content-Type: application/json', |
||||
|
"Authorization: Bearer {$this->Token}", |
||||
|
"X-Auxilium-Actor: {$this->Actor}", |
||||
|
]); |
||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||||
|
|
||||
|
if ($method == "POST") { |
||||
|
curl_setopt($ch, CURLOPT_POST, 1); |
||||
|
} |
||||
|
if($this->AllowSelfSignedCerts) |
||||
|
{ |
||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); |
||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); |
||||
|
} |
||||
|
|
||||
|
if ($method == "POST" || $method == "PUT") { |
||||
|
if ($body != null) { |
||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $body); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
$result = curl_exec($ch); |
||||
|
curl_close($ch); |
||||
|
|
||||
|
return $result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param InsertQuery|PutQuery|SelectQuery $query Takes in a Query Builder object. |
||||
|
* @return QueryResponseWrapper |
||||
|
*/ |
||||
|
public function RunQuery(InsertQuery|PutQuery|SelectQuery $query): QueryResponseWrapper |
||||
|
{ |
||||
|
$response = $this->RunRawRequest( |
||||
|
endpoint: "/api/v1/@query", |
||||
|
method: "POST", |
||||
|
body: $query |
||||
|
); |
||||
|
return QueryResponseWrapper::FromAPIResponse($response); |
||||
|
} |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\DataStructures; |
||||
|
|
||||
|
class QueryResponseWrapper |
||||
|
{ |
||||
|
public array $Rows; |
||||
|
public string $RowFormat; |
||||
|
|
||||
|
public static function FromAPIResponse(string $response): QueryResponseWrapper |
||||
|
{ |
||||
|
$temp = json_decode($response, true); |
||||
|
|
||||
|
$builder = new QueryResponseWrapper(); |
||||
|
|
||||
|
$builder->Rows = $temp["@rows"]; |
||||
|
$builder->RowFormat = $temp["@row_format"]; |
||||
|
|
||||
|
return $builder; |
||||
|
} |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\DataStructures; |
||||
|
|
||||
|
class ServerInfo |
||||
|
{ |
||||
|
public string $InstanceID; |
||||
|
public string $InstanceFQDN; |
||||
|
public array $PublicKeys; |
||||
|
|
||||
|
public static function FromAPIResponse(string $response): ServerInfo |
||||
|
{ |
||||
|
$temp = json_decode($response, true); |
||||
|
|
||||
|
$builder = new ServerInfo(); |
||||
|
|
||||
|
$builder->InstanceID = $temp["@instance_id"]; |
||||
|
$builder->InstanceFQDN = $temp["@instance_fqdn"]; |
||||
|
$builder->PublicKeys = $temp["@public_keys"]; |
||||
|
|
||||
|
return $builder; |
||||
|
} |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\Enumerators; |
||||
|
|
||||
|
enum DeegraphEqualityOperator: string |
||||
|
{ |
||||
|
case EQUALS = "="; |
||||
|
case IDENTICAL = "=="; |
||||
|
case IS = "==="; |
||||
|
|
||||
|
case DIFFERENT = "!="; |
||||
|
case ISNT = "ISNT"; |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\Enumerators; |
||||
|
|
||||
|
enum DeegraphLogicalOperators: string |
||||
|
{ |
||||
|
case NOT = "!"; |
||||
|
case AND = "&&"; |
||||
|
case OR = "||"; |
||||
|
case XOR = "^|"; |
||||
|
} |
@ -0,0 +1,12 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\Enumerators; |
||||
|
|
||||
|
enum DeegraphNumericalComparitor: string |
||||
|
{ |
||||
|
case LESS_THAN = "<"; |
||||
|
case MORE_THAN = ">"; |
||||
|
case LESS_THAN_OR_EQUAL_TO = "<="; |
||||
|
case MORE_THAN_OR_EQUAL_TO = ">="; |
||||
|
} |
||||
|
|
@ -0,0 +1,17 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\Exceptions; |
||||
|
|
||||
|
use Exception; |
||||
|
|
||||
|
class QueryBuilderConflictingFieldAlreadyExistsException extends Exception |
||||
|
{ |
||||
|
public function __construct( |
||||
|
string $message = "You have tried to set a field which would nullify a field you've previously set.", |
||||
|
int $code = 422 |
||||
|
) { |
||||
|
parent::__construct($message, $code); |
||||
|
$this->message = "$message"; |
||||
|
$this->code = $code; |
||||
|
} |
||||
|
} |
@ -0,0 +1,17 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\Exceptions; |
||||
|
|
||||
|
use Exception; |
||||
|
|
||||
|
class QueryBuilderInvalidDeegraphPathException extends Exception |
||||
|
{ |
||||
|
public function __construct( |
||||
|
string $message = "The Deegraph path you have entered is not valid.", |
||||
|
int $code = 422 |
||||
|
) { |
||||
|
parent::__construct($message, $code); |
||||
|
$this->message = "$message"; |
||||
|
$this->code = $code; |
||||
|
} |
||||
|
} |
@ -0,0 +1,17 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\Exceptions; |
||||
|
|
||||
|
use Exception; |
||||
|
|
||||
|
class QueryBuilderInvalidInputException extends Exception |
||||
|
{ |
||||
|
public function __construct( |
||||
|
string $message = "The value you have entered doesn't pass regex validation.", |
||||
|
int $code = 422 |
||||
|
) { |
||||
|
parent::__construct($message, $code); |
||||
|
$this->message = "$message"; |
||||
|
$this->code = $code; |
||||
|
} |
||||
|
} |
@ -0,0 +1,17 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\Exceptions; |
||||
|
|
||||
|
use Exception; |
||||
|
|
||||
|
class QueryBuilderRequiredFieldIsNotSetException extends Exception |
||||
|
{ |
||||
|
public function __construct( |
||||
|
string $message = "A field that is required for this operation has not been set.", |
||||
|
int $code = 422 |
||||
|
) { |
||||
|
parent::__construct($message, $code); |
||||
|
$this->message = "$message"; |
||||
|
$this->code = $code; |
||||
|
} |
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\QueryBuilder; |
||||
|
|
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders\InsertQuery; |
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders\PutQuery; |
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders\SelectQuery; |
||||
|
|
||||
|
class QueryBuilder |
||||
|
{ |
||||
|
|
||||
|
public static function Insert(): InsertQuery |
||||
|
{ |
||||
|
return new InsertQuery(); |
||||
|
} |
||||
|
public static function Put(): PutQuery |
||||
|
{ |
||||
|
return new PutQuery(); |
||||
|
} |
||||
|
public static function Select(): SelectQuery |
||||
|
{ |
||||
|
return new SelectQuery(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\QueryBuilder; |
||||
|
|
||||
|
use Darksparrow\DeegraphPHP\Exceptions\QueryBuilderConflictingFieldAlreadyExistsException; |
||||
|
use Darksparrow\DeegraphPHP\Exceptions\QueryBuilderException; |
||||
|
use Darksparrow\DeegraphPHP\Exceptions\QueryBuilderInvalidInputException; |
||||
|
|
||||
|
trait QueryBuilderTrait |
||||
|
{ |
||||
|
protected function RegexValidate(string $target, string $pattern): string |
||||
|
{ |
||||
|
if (!preg_match(pattern: $pattern, subject: $target)) |
||||
|
throw new QueryBuilderInvalidInputException(); |
||||
|
return $target; |
||||
|
} |
||||
|
|
||||
|
protected function EnsureNotSet(string $target): void |
||||
|
{ |
||||
|
if ($target != "") |
||||
|
throw new QueryBuilderConflictingFieldAlreadyExistsException(); |
||||
|
} |
||||
|
|
||||
|
protected function ValidateDeegraphPath(string $target): string |
||||
|
{ |
||||
|
if (!preg_match(pattern: "(^(\{[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}\})$)|(^\{[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}\}(\/([a-z][a-z0-9]*|[0-9]+|#|\*))+$)|(^(([a-z][a-z0-9]*|[0-9]+|#|\*))(\/([a-z][a-z0-9]*|[0-9]+|#|\*))*$)", subject: $target)) |
||||
|
throw new QueryBuilderInvalidInputException(); |
||||
|
return $target; |
||||
|
} |
||||
|
} |
@ -0,0 +1,84 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders; |
||||
|
|
||||
|
use Darksparrow\DeegraphPHP\Attributes\QueryBuilderRequiredField; |
||||
|
use Darksparrow\DeegraphPHP\Attributes\QueryBuilderQuery; |
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilderTrait; |
||||
|
|
||||
|
#[QueryBuilderQuery] |
||||
|
final class InsertQuery |
||||
|
{ |
||||
|
use QueryBuilderTrait; |
||||
|
|
||||
|
#[QueryBuilderRequiredField] |
||||
|
protected string $RelativePath = ""; |
||||
|
|
||||
|
protected array $Keys = []; |
||||
|
|
||||
|
protected array $Schemas = []; |
||||
|
|
||||
|
protected string $Values = ""; |
||||
|
|
||||
|
protected bool $Duplicate = false; |
||||
|
|
||||
|
protected bool $Replace = false; |
||||
|
|
||||
|
|
||||
|
public function __construct() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public function __toString(): string |
||||
|
{ |
||||
|
$instance = new QueryBuilderQuery(); |
||||
|
$instance->ValidateValues($this); |
||||
|
|
||||
|
$builder = "INSERT INTO $this->RelativePath"; |
||||
|
|
||||
|
if(sizeof($this->Keys) > 0) $builder .= "KEYS " . implode(separator: ", ", array: $this->Keys); |
||||
|
if(sizeof($this->Schemas) > 0) $builder .= "SCHEMAS " . implode(separator: ", ", array: $this->Schemas); |
||||
|
if($this->Values != "") $builder .= "VALUES $this->Values"; |
||||
|
if($this->Duplicate) $builder .= "DUPLICATE"; |
||||
|
if($this->Replace) $builder .= "REPLACE"; |
||||
|
|
||||
|
return $builder; |
||||
|
} |
||||
|
|
||||
|
public function RelativePath(string $relativePath): InsertQuery |
||||
|
{ |
||||
|
self::ValidateDeegraphPath(target: $relativePath); |
||||
|
$this->RelativePath = $relativePath; |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
public function Keys(string $keys): InsertQuery |
||||
|
{ |
||||
|
$this->Keys = $keys; |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
public function Schemas(string $schemas): InsertQuery |
||||
|
{ |
||||
|
$this->Schemas = $schemas; |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
public function Values(string $values): InsertQuery |
||||
|
{ |
||||
|
$this->Values .= $values; |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
public function Duplicate(): InsertQuery |
||||
|
{ |
||||
|
$this->Duplicate = true; |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
public function Replace(): InsertQuery |
||||
|
{ |
||||
|
$this->Replace = true; |
||||
|
return $this; |
||||
|
} |
||||
|
} |
@ -0,0 +1,114 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders; |
||||
|
|
||||
|
use Darksparrow\DeegraphPHP\Attributes\QueryBuilderRequiredField; |
||||
|
use Darksparrow\DeegraphPHP\Exceptions\QueryBuilderConflictingFieldAlreadyExistsException; |
||||
|
use Darksparrow\DeegraphPHP\Exceptions\QueryBuilderInvalidInputException; |
||||
|
use Darksparrow\DeegraphPHP\Exceptions\QueryBuilderRequiredFieldIsNotSetException; |
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilderTrait; |
||||
|
|
||||
|
final class PutQuery |
||||
|
{ |
||||
|
use QueryBuilderTrait; |
||||
|
|
||||
|
protected string $PutWhat = ""; |
||||
|
protected string $PutAt = ""; |
||||
|
protected string $PutInto = ""; |
||||
|
protected bool $Safe = false; |
||||
|
|
||||
|
|
||||
|
public function __construct() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @throws QueryBuilderRequiredFieldIsNotSetException |
||||
|
*/ |
||||
|
public function __toString(): string |
||||
|
{ |
||||
|
$builder = "PUT"; |
||||
|
if($this->PutWhat != "") $builder .= " $this->PutWhat"; |
||||
|
|
||||
|
if($this->PutAt != "") $builder .= " $this->PutAt"; |
||||
|
elseif ($this->PutInto != "") $builder .= " $this->PutInto"; |
||||
|
else throw new QueryBuilderRequiredFieldIsNotSetException(); |
||||
|
|
||||
|
if($this->Safe) $builder .= " SAFE"; |
||||
|
return $builder; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* @throws QueryBuilderInvalidInputException |
||||
|
*/ |
||||
|
public function Schema(string $uri): PutQuery |
||||
|
{ |
||||
|
$this->PutWhat = self::RegexValidate( |
||||
|
target: "SCHEMA \"$uri\"", |
||||
|
pattern: "/SCHEMA \".+\"/" |
||||
|
); |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @throws QueryBuilderInvalidInputException |
||||
|
*/ |
||||
|
public function URI(string $uri): PutQuery |
||||
|
{ |
||||
|
$this->PutWhat = self::RegexValidate( |
||||
|
target: "URI \"$uri\"", |
||||
|
pattern: "/URI \".+\"/" |
||||
|
); |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @throws QueryBuilderInvalidInputException |
||||
|
*/ |
||||
|
public function DataURI(string $mimeType, string $data): PutQuery |
||||
|
{ |
||||
|
$this->PutWhat = self::RegexValidate( |
||||
|
target: "URI \"data:$mimeType;$data\"", |
||||
|
pattern: "/URI \"data:[a-zA-Z0-9]/[a-zA-Z0-9];.+\"/" |
||||
|
); |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* @throws QueryBuilderInvalidInputException |
||||
|
* @throws QueryBuilderConflictingFieldAlreadyExistsException |
||||
|
*/ |
||||
|
public function At(string $node, string $uwu): PutQuery |
||||
|
{ |
||||
|
self::EnsureNotSet($this->PutInto); |
||||
|
$this->PutAt = self::RegexValidate( |
||||
|
target: 'AT {' . $node . '}/' . $uwu, |
||||
|
pattern: "/AT {[a-zA-Z0-9\-]+}\/[a-zA-Z0-9]+/" |
||||
|
); |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* @throws QueryBuilderInvalidInputException |
||||
|
* @throws QueryBuilderConflictingFieldAlreadyExistsException |
||||
|
*/ |
||||
|
public function Into(string $relativePath, string $propertyName): PutQuery |
||||
|
{ |
||||
|
self::EnsureNotSet($this->PutAt); |
||||
|
$this->PutInto = self::RegexValidate( |
||||
|
target: "INTO \"$relativePath\" AS \"$propertyName\"", |
||||
|
pattern: "/INTO \"[a-zA-Z0-9\-]+\" AS \"[a-zA-Z0-9]+\"/" |
||||
|
); |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public function Safe(): PutQuery |
||||
|
{ |
||||
|
$this->Safe = true; |
||||
|
return $this; |
||||
|
} |
||||
|
} |
@ -0,0 +1,61 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilders; |
||||
|
|
||||
|
use Darksparrow\DeegraphPHP\Attributes\QueryBuilderQuery; |
||||
|
use Darksparrow\DeegraphPHP\Attributes\QueryBuilderRequiredField; |
||||
|
use Darksparrow\DeegraphPHP\Enumerators\DeegraphEqualityOperator; |
||||
|
use Darksparrow\DeegraphPHP\Exceptions\QueryBuilderRequiredFieldIsNotSetException; |
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilderTrait; |
||||
|
|
||||
|
#[QueryBuilderQuery] |
||||
|
final class SelectQuery |
||||
|
{ |
||||
|
use QueryBuilderTrait; |
||||
|
|
||||
|
#[QueryBuilderRequiredField] |
||||
|
protected array $RelativePaths = []; |
||||
|
protected string $From = ""; |
||||
|
protected string $Where = ""; |
||||
|
protected string $InstanceOf = ""; |
||||
|
|
||||
|
|
||||
|
public function __construct() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @throws QueryBuilderRequiredFieldIsNotSetException |
||||
|
*/ |
||||
|
public function __toString(): string |
||||
|
{ |
||||
|
$builder = "SELECT "; |
||||
|
if(sizeof($this->RelativePaths)) $builder .= " " . implode(separator: ", ", array: $this->RelativePaths); |
||||
|
if($this->From != "") $builder .= " FROM $this->From"; |
||||
|
if($this->Where != "") $builder .= " WHERE $this->Where"; |
||||
|
if($this->InstanceOf != "") $builder .= " INSTANCEOF $this->InstanceOf"; |
||||
|
|
||||
|
return $builder; |
||||
|
} |
||||
|
|
||||
|
public function RelativePaths(array $relativePaths): SelectQuery |
||||
|
{ |
||||
|
$this->RelativePaths = $relativePaths; |
||||
|
return $this; |
||||
|
} |
||||
|
public function From(string $target): SelectQuery |
||||
|
{ |
||||
|
$this->From = "" . $target; |
||||
|
return $this; |
||||
|
} |
||||
|
public function Where(string $target, DeegraphEqualityOperator $operator, string $value): SelectQuery |
||||
|
{ |
||||
|
$this->Where = "" . $target . " " . $operator->value . " " . $value; |
||||
|
return $this; |
||||
|
} |
||||
|
public function InstanceOf(string $target): SelectQuery |
||||
|
{ |
||||
|
$this->InstanceOf = "" . $target; |
||||
|
return $this; |
||||
|
} |
||||
|
} |
@ -0,0 +1,32 @@ |
|||||
|
<?php |
||||
|
|
||||
|
|
||||
|
use Darksparrow\DeegraphPHP\Exceptions\QueryBuilderConflictingFieldAlreadyExistsException; |
||||
|
use Darksparrow\DeegraphPHP\QueryBuilder\QueryBuilder; |
||||
|
use PHPUnit\Framework\TestCase; |
||||
|
|
||||
|
final class QueryBuilderPutTest extends TestCase |
||||
|
{ |
||||
|
public function testPutURIAtSafeWithValidData() |
||||
|
{ |
||||
|
$queryBuilder = new QueryBuilder(); |
||||
|
$query = $queryBuilder->Put() |
||||
|
->URI("https://schemas.auxiliumsoftware.co.uk/v1/collection.json") |
||||
|
->At(node: "970334ed-1f4f-465a-94d7-923a99698786", uwu: "todos") |
||||
|
->Safe(); |
||||
|
self::assertEquals( |
||||
|
expected: 'PUT URI "https://schemas.auxiliumsoftware.co.uk/v1/collection.json" AT {970334ed-1f4f-465a-94d7-923a99698786}/todos SAFE', |
||||
|
actual: $query |
||||
|
); |
||||
|
} |
||||
|
public function testPutWithBothThings() |
||||
|
{ |
||||
|
$this->expectException(QueryBuilderConflictingFieldAlreadyExistsException::class); |
||||
|
$queryBuilder = new QueryBuilder(); |
||||
|
$query = $queryBuilder->Put() |
||||
|
->URI("https://schemas.auxiliumsoftware.co.uk/v1/collection.json") |
||||
|
->At(node: "970334ed-1f4f-465a-94d7-923a99698786", uwu: "todos") |
||||
|
->Into(relativePath: "Relative Path", propertyName: "OwO") |
||||
|
->Safe(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace tests; |
Loading…
Reference in new issue