Skip to content

Commit

Permalink
Introduce Exception Codes for ViewModelRenderer Exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
theseer committed Jul 27, 2023
1 parent 4d761e1 commit ef39913
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 19 deletions.
95 changes: 76 additions & 19 deletions src/viewmodel/ViewModelRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ public function render(DOMNode $context, object $model): void {
$document = $context->ownerDocument;

if ($document === null) {
throw new ViewModelRendererException('Given context node must be connected to a document');
throw new ViewModelRendererException(
'Given context node must be connected to a document',
ViewModelRendererException::NotInDocument
);
}

$this->pointer = $document->createComment('templado pointer node');
Expand Down Expand Up @@ -100,7 +103,10 @@ private function registerPrefix(string $prefixString): void {
$parts = explode(': ', $prefixString);

if (count($parts) !== 2) {
throw new ViewModelRendererException('Invalid prefix definition');
throw new ViewModelRendererException(
'Invalid prefix definition',
ViewModelRendererException::InvalidPrefixDefinition
);
}

[$prefix, $method] = $parts;
Expand All @@ -121,11 +127,17 @@ private function registerPrefix(string $prefixString): void {
property_exists($this->rootModel, $method) => $this->rootModel->{$method},
method_exists($this->rootModel, '__get') => $this->rootModel->{$method},

default => throw new ViewModelRendererException(sprintf('Cannot resolve prefix request for "%s"', $method))
default => throw new ViewModelRendererException(
sprintf('Cannot resolve prefix request for "%s"', $method),
ViewModelRendererException::PrefixResolvingFailed
)
};

if (!is_object($result)) {
throw new ViewModelRendererException('Prefix type must be an object');
throw new ViewModelRendererException(
'Prefix type must be an object',
ViewModelRendererException::WrongTypeForPrefix
);
}

$this->prefixModels[$prefix] = $result;
Expand All @@ -139,7 +151,10 @@ private function resolveResource(string $resource): object {
$model = $this->modelForPrefix($prefix);

if ($model === null) {
throw new ViewModelRendererException(sprintf('Cannot resolve resource request for "%s" using prefix "%s"', $resource, $prefix));
throw new ViewModelRendererException(
sprintf('Cannot resolve resource request for "%s" using prefix "%s"', $resource, $prefix),
ViewModelRendererException::ResourceResolvingWithPrefixFailed
);
}
}

Expand All @@ -153,19 +168,28 @@ private function resolveResource(string $resource): object {
property_exists($model, $resource) => $model->{$resource},
method_exists($model, '__get') => $model->{$resource},

default => throw new ViewModelRendererException(sprintf('Cannot resolve resource request for "%s"', $resource))
default => throw new ViewModelRendererException(
sprintf('Cannot resolve resource request for "%s"', $resource),
ViewModelRendererException::ResourceResolvingFailed
)
};

if (!is_object($result)) {
throw new ViewModelRendererException('Resouce type must be a object');
throw new ViewModelRendererException(
'Resouce type must be a object',
ViewModelRendererException::WrongTypeForResource
);
}

return $result;
}

private function modelForPrefix(string $prefix): ?object {
if (!array_key_exists($prefix, $this->prefixModels)) {
throw new ViewModelRendererException('No modell set for prefix');
throw new ViewModelRendererException(
'No model set for prefix',
ViewModelRendererException::NoModelForPrefix
);
}

return $this->prefixModels[$prefix];
Expand All @@ -186,7 +210,10 @@ private function modelSupportsVocab(object $model, string $requiredVocab): void
};

if (!is_string($modelVocab)) {
throw new ViewModelRendererException('Result of vocab query must be of type string');
throw new ViewModelRendererException(
'Result of vocab query must be of type string',
ViewModelRendererException::WrongTypeForVocab
);
}

$this->supported = $modelVocab === $requiredVocab;
Expand Down Expand Up @@ -230,12 +257,18 @@ private function processProperty(DOMElement $context, object $model): object {
property_exists($model, $property) => $model->{$property},
method_exists($model, '__get') => $model->{$property},

default => throw new ViewModelRendererException(sprintf('Cannot resolve property request for "%s"', $property))
default => throw new ViewModelRendererException(
sprintf('Cannot resolve property request for "%s"', $property),
ViewModelRendererException::ResolvingPropertyFailed
)
};

if ($context->hasAttribute('typeof')) {
if (!is_iterable($result) && !is_object($result)) {
throw new ViewModelRendererException('TypeOf handling requires object / list of objects');
throw new ViewModelRendererException(
'TypeOf handling requires object / list of objects',
ViewModelRendererException::WrongTypeForTypeOf
);
}

$this->conditionalApply($context, $result);
Expand Down Expand Up @@ -272,7 +305,10 @@ private function processProperty(DOMElement $context, object $model): object {
return $result;
}

throw new ViewModelRendererException('Unsupported type');
throw new ViewModelRendererException(
'Unsupported type',
ViewModelRendererException::UnsupportedTypeForProperty
);
}

private function conditionalApply(DOMElement $context, object|iterable $model): void {
Expand All @@ -287,11 +323,17 @@ private function conditionalApply(DOMElement $context, object|iterable $model):

foreach ($model as $current) {
if (!is_object($current)) {
throw new ViewModelRendererException('Model must be an object when used for type of checks');
throw new ViewModelRendererException(
'Model must be an object when used for type of checks',
ViewModelRendererException::WrongTypeForTypeOf
);
}

if (!method_exists($current, 'typeOf')) {
throw new ViewModelRendererException('Model must provide method typeOf for type of checks');
throw new ViewModelRendererException(
'Model must provide method typeOf for type of checks',
ViewModelRendererException::TypeOfMethodRequired
);
}

$matches = $this->xp->query(
Expand All @@ -304,7 +346,10 @@ private function conditionalApply(DOMElement $context, object|iterable $model):
);

if ($matches->count() === 0) {
throw new ViewModelRendererException('No matching types found');
throw new ViewModelRendererException(
'No matching types found',
ViewModelRendererException::NoMatch
);
}

$clone = $matches->item(0)->cloneNode(true);
Expand Down Expand Up @@ -344,7 +389,10 @@ private function iterableApply(DOMElement $context, iterable $list): void {
assert($ownerDocument instanceof DOMDocument);

if ($context->isSameNode($ownerDocument->documentElement)) {
throw new ViewModelRendererException('Cannot apply multiple on root element');
throw new ViewModelRendererException(
'Cannot apply multiple on root element',
ViewModelRendererException::MultipleRootElements
);
}

$parent = $context->parentNode;
Expand Down Expand Up @@ -381,7 +429,10 @@ private function iterableApply(DOMElement $context, iterable $list): void {
continue;
}

throw new ViewModelRendererException('Unsupported type of model in list');
throw new ViewModelRendererException(
'Unsupported type of model in list',
ViewModelRendererException::UnsupportedTypeForProperty
);
}

$list = StaticNodeList::fromNodeList($this->xp->query(
Expand Down Expand Up @@ -410,7 +461,10 @@ private function objectApply(DOMElement $context, object $model): void {
$textContent = $model->asString($context->textContent);

if (!is_string($textContent)) {
throw new ViewModelRendererException('Cannot use non string type for text content');
throw new ViewModelRendererException(
'Cannot use non string type for text content',
ViewModelRendererException::StringRequired
);
}

$context->textContent = $textContent;
Expand Down Expand Up @@ -460,7 +514,10 @@ private function objectApply(DOMElement $context, object $model): void {
continue;
}

throw new ViewModelRendererException(\sprintf('Unsupported type "%s" for attribute', gettype($result)));
throw new ViewModelRendererException(
\sprintf('Unsupported type "%s" for attribute', gettype($result)),
ViewModelRendererException::WrongTypeForAttribute
);
}
}

Expand Down
17 changes: 17 additions & 0 deletions src/viewmodel/ViewModelRendererException.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,21 @@
namespace Templado\Engine;

final class ViewModelRendererException extends Exception {
public const NotInDocument = 1;
public const InvalidPrefixDefinition = 2;
public const PrefixResolvingFailed = 3;
public const WrongTypeForPrefix = 4;
public const ResourceResolvingWithPrefixFailed = 5;
public const ResourceResolvingFailed = 6;
public const WrongTypeForResource = 7;
public const NoModelForPrefix = 8;
public const WrongTypeForVocab = 9;
public const ResolvingPropertyFailed = 10;
public const WrongTypeForTypeOf = 11;
public const UnsupportedTypeForProperty = 12;
public const TypeOfMethodRequired = 13;
public const NoMatch = 14;
public const MultipleRootElements = 15;
public const StringRequired = 16;
public const WrongTypeForAttribute = 17;
}

0 comments on commit ef39913

Please sign in to comment.