Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions src/Database/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,40 @@ public function getValue($default = null)
return $this->values[0] ?? $default;
}

/**
* Create a query string from this Query instance
* This method is the opposide of 'parse' method.
*
* @return string
*/
public function toString(): string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to implement __toString()?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Meldiron I think this is a pretty cool suggestion, can we have the same thing for Role and Permission?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__toString() would only be used in the case where the object is contextually expected to be a string, e.g.

echo Query::limit(1);

For the case in the description, we would have to call the magic method:

'queries' => [ Query::limit(1)->__toString() ]

I think it's cleaner to implement an instance method toString() instead

{
$method = static::getMethodFromAlias($this->getMethod());
$values = $this->getValues();
$attribute = $this->getAttribute();

switch ($method) {
case self::TYPE_EQUAL:
case self::TYPE_NOTEQUAL:
case self::TYPE_LESSER:
case self::TYPE_LESSEREQUAL:
case self::TYPE_GREATER:
case self::TYPE_GREATEREQUAL:
case self::TYPE_CONTAINS:
case self::TYPE_SEARCH:
$values = \array_map(fn($value) => static::toStringValue($value), $values);
return $method . '("' . $attribute . '", [' . \implode(",", $values) . '])';
case self::TYPE_ORDERASC:
case self::TYPE_ORDERDESC:
case self::TYPE_CURSORAFTER:
case self::TYPE_CURSORBEFORE:
return $method . '("' . $attribute . '")';
case self::TYPE_LIMIT:
case self::TYPE_OFFSET:
return $method . '(' . $values[0] . ')';
}
}

/**
* Sets Method.
* @param string $method
Expand Down Expand Up @@ -407,6 +441,34 @@ protected static function parseValue(string $value): mixed
return $value;
}

/**
* Convert value into properly stringified version.
* This method is opposide of 'parseValue' method
*
* @param mixed $value
* @return mixed
*/
protected static function toStringValue(mixed $value): string
{
if ($value === false) { // Boolean value
return 'false';
} else if ($value === true) {
return 'true';
} else if ($value === null) { // Null value
return 'null';
} else if (\is_numeric($value)) { // Numeric value
// Cast to number
return $value . '';
} else if (\is_string($value)) { // String param
$value = \str_replace('"', '\\"', $value);

return '"' . $value . '"';
}

// Unknown format
return $value;
}

/**
* Returns Method from Alias.
*
Expand Down
26 changes: 26 additions & 0 deletions tests/Database/QueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,30 @@ public function testisMethod()
$this->assertFalse(Query::isMethod('invalid'));
$this->assertFalse(Query::isMethod('lte '));
}


public function testToString(): void
{
$queries = [
'equal("title", ["Iron Man"])',
'equal("title", ["Iron Man"])',
'equal("title", ["Iro\'n Man"])',
'equal("title", ["Iro\"n Man"])',
'lessThan("year", [2001])',
'equal("published", [true])',
'equal("published", [false])',
'equal("actors", [" Johnny Depp "," Brad Pitt","Al Pacino "])',
'equal("actors", ["Brad Pitt","Johnny Depp"])',
'contains("writers", ["Tim O\'Reilly"])',
'greaterThan("score", [8.5])',
'notEqual("director", ["null"])',
'notEqual("director", [null])',
'equal("attr", [1])',
];

foreach ($queries as $query) {
$queryInstance = Query::parse($query);
$this->assertEquals($query, $queryInstance->toString());
}
}
}