Skip to content

Commit

Permalink
Merged validation and parsing functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Sjustein committed May 5, 2024
1 parent 98b48a5 commit 15436a9
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 168 deletions.
58 changes: 58 additions & 0 deletions src/Datatype/FilterClause.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace GlobyApp\OdataQueryParser\Datatype;

use GlobyApp\OdataQueryParser\Enum\FilterOperator;

/**
* @api Public get methods exposed to retrieve data from the result
*/
class FilterClause
{
private string $property;

private FilterOperator $operator;

/**
* @var int|float|string|bool|null|array<int|float|string|bool|null> $value
*/
private int|float|string|bool|null|array $value;

/**
* A filter clause with a field, an operator and the value to filter with
*
* @param string $property The property that should be filtered
* @param FilterOperator $operator The filter operator used
* @param int|float|string|bool|null|array<int|float|string|bool|null> $value The value to filter the property on with the operator
*/
public function __construct(string $property, FilterOperator $operator, int|float|string|bool|null|array $value)
{
$this->property = $property;
$this->operator = $operator;
$this->value = $value;
}

/**
* @return string The property on which to filter
*/
public function getProperty(): string
{
return $this->property;
}

/**
* @return FilterOperator The operator with which to filter
*/
public function getOperator(): FilterOperator
{
return $this->operator;
}

/**
* @return int|float|string|bool|null|array<int|float|string|bool|null> The value to filter the property on with the operator
*/
public function getValue(): int|float|string|bool|null|array
{
return $this->value;
}
}
202 changes: 89 additions & 113 deletions src/OdataQueryParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,43 +58,12 @@ public static function parse(string $url, bool $withDollar = true): ?OdataQuery
self::setKeyConstants($withDollar);

// Extract the different odata keys and store them in the output array
$select = [];
if (self::selectQueryParameterIsValid($parsedQueryString)) {
$select = self::getSelect($parsedQueryString);
}

$count = null;
if (self::countQueryParameterIsValid($parsedQueryString)) {
$count = boolval(trim($parsedQueryString[self::$count]));
}

$top = null;
if (self::topQueryParameterIsValid($parsedQueryString)) {
$top = intval(trim($parsedQueryString[self::$top]));

if ($top < 0) {
throw new InvalidArgumentException('Top should be greater or equal to zero');
}
}

$skip = null;
if (self::skipQueryParameterIsValid($parsedQueryString)) {
$skip = intval(trim($parsedQueryString[self::$skip]));

if ($skip < 0) {
throw new InvalidArgumentException('Skip should be greater or equal to zero');
}
}

$orderBy = [];
if (self::orderByQueryParameterIsValid($parsedQueryString)) {
$orderBy = self::getOrderBy($parsedQueryString);
}

$filter = [];
if (self::filterQueryParameterIsValid($parsedQueryString)) {
$filter = self::getFilterValue($parsedQueryString);
}
$select = self::getSelect($parsedQueryString);
$count = self::getCount($parsedQueryString);
$top = self::getTop($parsedQueryString);
$skip = self::getSkip($parsedQueryString);
$orderBy = self::getOrderBy($parsedQueryString);
$filter = self::getFilter($parsedQueryString);

return new OdataQuery($select, $count, $top, $skip, $orderBy, $filter);
}
Expand Down Expand Up @@ -189,81 +158,6 @@ private static function hasKey(string $key, array $queryString): bool
return array_key_exists($key, $queryString);
}

/**
* Function to determine whether a select clause is present and valid in a query string
*
* @param array<string, string> $queryString The query string to find the select key in
*
* @return bool Whether the select key exists in the query string and is valid
*/
private static function selectQueryParameterIsValid(array $queryString): bool
{
return self::hasKey(self::$select, $queryString)
&& !empty(trim($queryString[self::$select]));
}

/**
* Function to determine whether a count key is present and valid in a query string
*
* @param array<string, string> $queryString The query string to find the count key in
*
* @return bool Whether the count key exists in the query string and is valid
*/
private static function countQueryParameterIsValid(array $queryString): bool
{
return self::validateWithFilterValidate($queryString, self::$count, FILTER_VALIDATE_BOOLEAN);
}

/**
* Function to determine whether a top key is present and valid in a query string
*
* @param array<string, string> $queryString The query string to find the top key in
*
* @return bool Whether the top key exists in the query string and is valid
*/
private static function topQueryParameterIsValid(array $queryString): bool
{
return self::validateWithFilterValidate($queryString, self::$top, FILTER_VALIDATE_INT);
}

/**
* Function to determine whether a skip key is present and valid in a query string
*
* @param array<string, string> $queryString The query string to find the skip key in
*
* @return bool Whether the skip key exists in the query string and is valid
*/
private static function skipQueryParameterIsValid(array $queryString): bool
{
return self::validateWithFilterValidate($queryString, self::$skip, FILTER_VALIDATE_INT);
}

/**
* Function to determine whether an order by clause is present and valid in a query string
*
* @param array<string, string> $queryString The query string to find the order by key in
*
* @return bool Whether the order by key exists in the query string and is valid
*/
private static function orderByQueryParameterIsValid(array $queryString): bool
{
return self::hasKey(self::$orderBy, $queryString)
&& !empty(trim($queryString[self::$orderBy]));
}

/**
* Function to determine whether a filter clause is present and valid in a query string
*
* @param array<string, string> $queryString The query string to find the filter key in
*
* @return bool Whether the filter key exists in the query string and is valid
*/
private static function filterQueryParameterIsValid(array $queryString): bool
{
return self::hasKey(self::$filter, $queryString)
&& !empty(trim($queryString[self::$filter]));
}

/**
* Function to easily validate that an array key exists in a query string and adheres to a specified filter_var filter
*
Expand All @@ -272,6 +166,7 @@ private static function filterQueryParameterIsValid(array $queryString): bool
* @param int $filter The filter to validate the value against, if it exists in the query string
*
* @return bool Whether the key exists in the query string and adheres to the specified filter
* @throws InvalidArgumentException If the input value doesn't pass the given filter
*/
private static function validateWithFilterValidate(array $queryString, string $key, int $filter): bool
{
Expand Down Expand Up @@ -301,6 +196,12 @@ private static function validateWithFilterValidate(array $queryString, string $k
*/
private static function getSelect(array $queryString): array
{
// If the original query string doesn't include a select part, return an empty array
if (!(self::hasKey(self::$select, $queryString)
&& !empty(trim($queryString[self::$select])))) {
return [];
}

// Split the select string into an array, as it's just a csv string
$csvSplit = explode(",", $queryString[self::$select]);

Expand All @@ -309,6 +210,71 @@ private static function getSelect(array $queryString): array
}, $csvSplit);
}

/**
* Function to determine whether a count key is present and return a parsed version of the value
*
* @param array<string, string> $queryString The query string to find the count key in
*
* @return bool|null The value of the count key, or null, if no count key is present in the query string
* @throws InvalidArgumentException If the input value doesn't pass the given filter
*/
private static function getCount(array $queryString): ?bool
{
if (!self::validateWithFilterValidate($queryString, self::$count, FILTER_VALIDATE_BOOLEAN)) {
return null;
}

return boolval(trim($queryString[self::$count]));
}

/**
* Function to determine whether a top key is present and return a parsed version of the value
*
* @param array<string, string> $queryString The query string to find the top key in
*
* @return int|null The value of the top key, or null, if no top key is present in the query string
* @throws InvalidArgumentException If the input value is not a valid integer
*/
private static function getTop(array $queryString): ?int
{
if (!self::validateWithFilterValidate($queryString, self::$top, FILTER_VALIDATE_INT)) {
return null;
}

// Parse skip and ensure it's larger than 0, as negative values don't make sense in this context
$top = intval(trim($queryString[self::$top]));

if ($top < 0) {
throw new InvalidArgumentException('Top should be greater or equal to zero');
}

return $top;
}

/**
* Function to determine whether a skip key is present and return a parsed version of the value
*
* @param array<string, string> $queryString The query string to find the skip key in
*
* @return int|null The value of the skip key, or null, if no skip key is present in the query string
* @throws InvalidArgumentException If the input value is not a valid integer
*/
private static function getSkip(array $queryString): ?int
{
if (!self::validateWithFilterValidate($queryString, self::$skip, FILTER_VALIDATE_INT)) {
return null;
}

// Parse skip and ensure it's larger than 0, as negative values don't make sense in this context
$skip = intval(trim($queryString[self::$skip]));

if ($skip < 0) {
throw new InvalidArgumentException('Skip should be greater or equal to zero');
}

return $skip;
}

/**
* Function to split the orderBy part of a query string and return a list of order by clauses
*
Expand All @@ -319,6 +285,11 @@ private static function getSelect(array $queryString): array
*/
private static function getOrderBy(array $queryString): array
{
if (!(self::hasKey(self::$orderBy, $queryString)
&& !empty(trim($queryString[self::$orderBy])))) {
return [];
}

$csvSplit = explode(",", $queryString[self::$orderBy]);

return array_map(function (string $clause): OrderByClause {
Expand Down Expand Up @@ -366,8 +337,13 @@ private static function parseDirection(string $direction): OrderDirection
* @return FilterClause[] The parsed list of filter clauses
* @throws InvalidArgumentException If an invalid operator is found, or the clause split found a clause that was incorrectly formed
*/
private static function getFilterValue(array $queryString): array
private static function getFilter(array $queryString): array
{
if (!(self::hasKey(self::$filter, $queryString)
&& !empty(trim($queryString[self::$filter])))) {
return [];
}

$filterParts = explode("and", $queryString[self::$filter]);

return array_map(function (string $clause): FilterClause {
Expand Down
55 changes: 0 additions & 55 deletions src/OdataQueryParser/Datatype/FilterClause.php

This file was deleted.

0 comments on commit 15436a9

Please sign in to comment.