Skip to content

Commit

Permalink
simplify casting from scalar
Browse files Browse the repository at this point in the history
  • Loading branch information
frederikbosch committed May 10, 2019
1 parent 4a28111 commit 4f5e1f6
Show file tree
Hide file tree
Showing 17 changed files with 222 additions and 104 deletions.
29 changes: 23 additions & 6 deletions src/Callback/Arguments.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace Genkgo\Xsl\Callback;

use Genkgo\Xsl\Exception\CastException;
use Genkgo\Xsl\Schema\DataTypeParser;
use Genkgo\Xsl\Schema\XmlSchema;

final class Arguments
Expand All @@ -14,11 +15,18 @@ final class Arguments
private $arguments;

/**
* @var DataTypeParser
*/
private $dataTypeParser;

/**
* @param DataTypeParser $dataTypeParser
* @param array $arguments
*/
public function __construct(array $arguments)
public function __construct(DataTypeParser $dataTypeParser, array $arguments)
{
$this->arguments = $arguments;
$this->dataTypeParser = $dataTypeParser;
}

/**
Expand All @@ -38,15 +46,15 @@ public function get(int $number)
* @param int $number
* @return mixed
*/
public function castAsScalar(int $number)
public function castFromSchemaType(int $number)
{
$value = $this->get($number);
if (\is_scalar($value)) {
return $value;
}

if (\is_array($value) && \count($value) === 1) {
return $value[0]->nodeValue;
return $this->convertFromSchemaTypeToPhpType($value[0]);
}

throw new CastException('Cannot convert list of elements to string');
Expand Down Expand Up @@ -101,12 +109,12 @@ function ($deepValue) {
/**
* @return array
*/
public function unpackAsScalar(): array
public function unpackFromSchemaType(): array
{
return \array_map(
function ($value) {
if (\is_array($value) && \count($value) === 1) {
return \reset($value)->textContent;
return $this->convertFromSchemaTypeToPhpType(\reset($value));
}

return $value;
Expand All @@ -119,7 +127,7 @@ function ($value) {
* @param int $number
* @param string $name
*/
public function assertSchema(int $number, string $name): void
public function assertSchemaType(int $number, string $name): void
{
$element = $this->get($number)[0] ?? '';
if ($element instanceof \DOMElement === false) {
Expand All @@ -131,4 +139,13 @@ public function assertSchema(int $number, string $name): void
throw new \InvalidArgumentException("Expected a {$nsSchema}:{$name} object, got {$element->nodeName}");
}
}

private function convertFromSchemaTypeToPhpType(\DOMNode $node)
{
if ($node->namespaceURI === XmlSchema::URI) {
return $this->dataTypeParser->parse($node);
}

return $node->textContent;
}
}
23 changes: 20 additions & 3 deletions src/Callback/PhpCallback.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace Genkgo\Xsl\Callback;

use Genkgo\Xsl\Schema\DataTypeParser;
use Genkgo\Xsl\TransformationContext;

final class PhpCallback
Expand Down Expand Up @@ -41,9 +42,21 @@ public static function call(string $functionQname, ...$arguments)
$namespace = \substr($functionQname, 0, $dot);
$functionName = \substr($functionQname, $dot + 1);

return self::$context->getFunctions()->get($namespace)->get($functionName)->call(new Arguments($arguments), self::$context);
return self::$context->getFunctions()
->get($namespace)
->get($functionName)
->call(
new Arguments(new DataTypeParser(), $arguments),
self::$context
);
} else {
return self::$context->getFunctions()->get('')->get($functionQname)->call(new Arguments($arguments), self::$context);
return self::$context->getFunctions()
->get('')
->get($functionQname)
->call(
new Arguments(new DataTypeParser(), $arguments),
self::$context
);
}
}

Expand All @@ -57,7 +70,11 @@ public static function callStatic(string $class, string $method, ...$arguments)
{
$callable = [$class, $method];
if (\is_callable($callable)) {
return \call_user_func($callable, new Arguments($arguments), self::$context);
return \call_user_func(
$callable,
new Arguments(new DataTypeParser(), $arguments),
self::$context
);
}

throw new \RuntimeException('Calling static method that is not callable');
Expand Down
2 changes: 1 addition & 1 deletion src/Callback/StringFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function call(Arguments $arguments, TransformationContext $context)
{
$callable = [$this->className, $this->methodName];
if (\is_callable($callable)) {
return \call_user_func_array($callable, $arguments->unpackAsScalar());
return \call_user_func_array($callable, $arguments->unpackFromSchemaType());
}

throw new \InvalidArgumentException('Argument is not callable');
Expand Down
35 changes: 35 additions & 0 deletions src/Schema/DataTypeParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);

namespace Genkgo\Xsl\Schema;

final class DataTypeParser
{
/**
* @param \DOMNode $node
* @return mixed
*/
public function parse(\DOMNode $node)
{
if ($node->namespaceURI !== XmlSchema::URI) {
throw new \InvalidArgumentException(
"Expected a object with Xml Schema namespace, got {$node->namespaceURI}"
);
}

switch ($node->localName) {
case 'integer':
return XsInteger::parseNode($node);
case 'date':
return XsDate::parseNode($node);
case 'time':
return XsTime::parseNode($node);
case 'dateTime':
return XsDateTime::parseNode($node);
case 'dayTimeDuration':
return XsDayTimeDuration::parseNode($node);
default:
throw new \UnexpectedValueException('Cannot parse ' . $node->localName);
}
}
}
10 changes: 5 additions & 5 deletions src/Schema/Functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ final class Functions
*/
public static function date(Arguments $arguments)
{
return XsDate::fromString($arguments->castAsScalar(0));
return XsDate::fromString($arguments->castFromSchemaType(0));
}

/**
Expand All @@ -25,7 +25,7 @@ public static function date(Arguments $arguments)
*/
public static function time(Arguments $arguments)
{
return XsTime::fromString($arguments->castAsScalar(0));
return XsTime::fromString($arguments->castFromSchemaType(0));
}

/**
Expand All @@ -35,7 +35,7 @@ public static function time(Arguments $arguments)
*/
public static function dateTime(Arguments $arguments)
{
return XsDateTime::fromString($arguments->castAsScalar(0));
return XsDateTime::fromString($arguments->castFromSchemaType(0));
}

/**
Expand All @@ -45,7 +45,7 @@ public static function dateTime(Arguments $arguments)
*/
public static function dayTimeDuration(Arguments $arguments)
{
return XsDayTimeDuration::fromString($arguments->castAsScalar(0));
return XsDayTimeDuration::fromString($arguments->castFromSchemaType(0));
}

/**
Expand All @@ -65,7 +65,7 @@ public static function integer(Arguments $arguments)
return XsSequence::fromArray([]);
}

$value = $arguments->castAsScalar(0);
$value = $arguments->castFromSchemaType(0);

if ($value === '') {
return new XsInteger(0);
Expand Down
15 changes: 15 additions & 0 deletions src/Schema/XsDate.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@ public static function fromString($date)
throw new CastException('Cannot create date from ' . $date);
}

/**
* @param \DOMNode $node
* @return DateTimeImmutable
*/
public static function parseNode(\DOMNode $node): \DateTimeImmutable
{
$result = \DateTimeImmutable::createFromFormat(self::FORMAT, $node->textContent);

if ($result === false) {
throw new \InvalidArgumentException('Cannot parse date from ' . $node->textContent);
}

return $result;
}

/**
* @return XsDate
*/
Expand Down
20 changes: 17 additions & 3 deletions src/Schema/XsDateTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

namespace Genkgo\Xsl\Schema;

use DateTimeImmutable;
use Genkgo\Xsl\Exception\CastException;

final class XsDateTime extends AbstractXsElement
Expand Down Expand Up @@ -31,7 +30,7 @@ protected function getElementName(): string
public static function fromString($date)
{
foreach (static::$formats as $format) {
$value = DateTimeImmutable::createFromFormat($format, $date);
$value = \DateTimeImmutable::createFromFormat($format, $date);
if ($value) {
return new self($value->format(self::FORMAT));
}
Expand All @@ -40,11 +39,26 @@ public static function fromString($date)
throw new CastException('Cannot create dateTime from ' . $date);
}

/**
* @param \DOMNode $node
* @return \DateTimeImmutable
*/
public static function parseNode(\DOMNode $node): \DateTimeImmutable
{
$result = \DateTimeImmutable::createFromFormat(self::FORMAT, $node->textContent);

if ($result === false) {
throw new \InvalidArgumentException('Cannot parse dateTime from ' . $node->textContent);
}

return $result;
}

/**
* @return XsDateTime
*/
public static function now()
{
return new self((new DateTimeImmutable())->format(self::FORMAT));
return new self((new \DateTimeImmutable())->format(self::FORMAT));
}
}
12 changes: 10 additions & 2 deletions src/Schema/XsDayTimeDuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

namespace Genkgo\Xsl\Schema;

use DateInterval;
use Genkgo\Xsl\Exception\CastException;

final class XsDayTimeDuration extends AbstractXsElement
Expand All @@ -24,10 +23,19 @@ protected function getElementName(): string
public static function fromString($date)
{
try {
new DateInterval($date);
new \DateInterval($date);
return new self($date);
} catch (\Exception $e) {
throw new CastException('Cannot create dayTimeDuration from ' . $date);
}
}

/**
* @param \DOMNode $node
* @return \DateInterval
*/
public static function parseNode(\DOMNode $node): \DateInterval
{
return new \DateInterval($node->textContent);
}
}
9 changes: 9 additions & 0 deletions src/Schema/XsInteger.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,13 @@ protected function getElementName(): string
{
return 'integer';
}

/**
* @param \DOMNode $node
* @return int
*/
public static function parseNode(\DOMNode $node): int
{
return (int) $node->textContent;
}
}
20 changes: 17 additions & 3 deletions src/Schema/XsTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

namespace Genkgo\Xsl\Schema;

use DateTimeImmutable;
use Genkgo\Xsl\Exception\CastException;

final class XsTime extends AbstractXsElement
Expand Down Expand Up @@ -31,7 +30,7 @@ protected function getElementName(): string
public static function fromString($date)
{
foreach (static::$formats as $format) {
$value = DateTimeImmutable::createFromFormat($format, $date);
$value = \DateTimeImmutable::createFromFormat($format, $date);
if ($value) {
return new self($value->format(self::FORMAT));
}
Expand All @@ -40,11 +39,26 @@ public static function fromString($date)
throw new CastException('Cannot create time from ' . $date);
}

/**
* @param \DOMNode $node
* @return \DateTimeImmutable
*/
public static function parseNode(\DOMNode $node): \DateTimeImmutable
{
$result = \DateTimeImmutable::createFromFormat(self::FORMAT, $node->textContent);

if ($result === false) {
throw new \InvalidArgumentException('Cannot parse time from ' . $node->textContent);
}

return $result;
}

/**
* @return XsTime
*/
public static function now()
{
return new self((new DateTimeImmutable())->format(self::FORMAT));
return new self((new \DateTimeImmutable())->format(self::FORMAT));
}
}
9 changes: 4 additions & 5 deletions src/Xpath/ForLoopConstructor.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,12 @@ public function call(Arguments $arguments, TransformationContext $context)

/**
* @param Arguments $arguments
* @param TransformationContext $context
* @return mixed
* @return XsSequence
*/
public static function newRange(Arguments $arguments, TransformationContext $context)
public static function newRange(Arguments $arguments): XsSequence
{
$first = $arguments->castAsScalar(0);
$last = $arguments->castAsScalar(1);
$first = $arguments->castFromSchemaType(0);
$last = $arguments->castFromSchemaType(1);

return XsSequence::fromArray(\range($first, $last));
}
Expand Down
Loading

0 comments on commit 4f5e1f6

Please sign in to comment.