Skip to content

Commit

Permalink
add transformation exception (#23)
Browse files Browse the repository at this point in the history
* add transformation exception, with previous errors based on libxml errors

* reset error level to previous state, instead of leaving it to true

* style
  • Loading branch information
frederikbosch authored May 5, 2019
1 parent 70d40a6 commit 3ffa879
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 17 deletions.
28 changes: 28 additions & 0 deletions src/Exception/TransformationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);

namespace Genkgo\Xsl\Exception;

final class TransformationException extends \Exception
{
public static function fromLibxmlErrorList(array $errors): self
{
if ($errors === []) {
throw new \InvalidArgumentException('Cannot create exception while there are no libxml errors');
}

$exceptions = [];
while ($errors !== []) {
/** @var \LibXMLError $error */
$error = \array_shift($errors);
$previous = isset($exceptions[0]) ? $exceptions[0] : null;
$exception = new self($error->message, 0, $previous);
$exception->file = $error->file;
$exception->code = $error->code;
$exception->line = $error->line;
$exceptions[] = $exception;
}

return new self('Transformation failed: ' . $exceptions[0]->message, 0, $exceptions[0]);
}
}
67 changes: 50 additions & 17 deletions src/XsltProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use DOMDocument;
use Genkgo\Xsl\Callback\FunctionCollection;
use Genkgo\Xsl\Callback\PhpCallback;
use Genkgo\Xsl\Exception\TransformationException;
use Genkgo\Xsl\Util\TransformerCollection;
use Psr\SimpleCache\CacheInterface;
use SimpleXMLElement;
Expand Down Expand Up @@ -65,12 +66,19 @@ public function transformToXML($doc)
$styleSheet = $this->styleSheetToDomDocument();

$transpiler = $this->createTranspiler($styleSheet);
\libxml_use_internal_errors();
parent::importStylesheet($this->getTranspiledStyleSheet($transpiler, $styleSheet));

return $transpiler->transform(function () use ($doc) {
return parent::transformToXml($doc);
});
$useInternalErrors = \libxml_use_internal_errors(true);

try {
parent::importStylesheet($this->getTranspiledStyleSheet($transpiler, $styleSheet));
$this->throwOnLibxmlError();

return $transpiler->transform(function () use ($doc) {
return parent::transformToXml($doc);
});
} finally {
\libxml_clear_errors();
\libxml_use_internal_errors($useInternalErrors);
}
}

/**
Expand All @@ -82,11 +90,19 @@ public function transformToDoc($doc)
$styleSheet = $this->styleSheetToDomDocument();

$transpiler = $this->createTranspiler($styleSheet);
parent::importStylesheet($this->getTranspiledStyleSheet($transpiler, $styleSheet));

return $transpiler->transform(function () use ($doc) {
return parent::transformToDoc($doc);
});
$useInternalErrors = \libxml_use_internal_errors(true);

try {
parent::importStylesheet($this->getTranspiledStyleSheet($transpiler, $styleSheet));
$this->throwOnLibxmlError();

return $transpiler->transform(function () use ($doc) {
return parent::transformToDoc($doc);
});
} finally {
\libxml_clear_errors();
\libxml_use_internal_errors($useInternalErrors);
}
}

/**
Expand All @@ -97,13 +113,20 @@ public function transformToDoc($doc)
public function transformToUri($doc, $uri)
{
$styleSheet = $this->styleSheetToDomDocument();

$transpiler = $this->createTranspiler($styleSheet);
parent::importStylesheet($this->getTranspiledStyleSheet($transpiler, $styleSheet));

return $transpiler->transform(function () use ($doc, $uri) {
return parent::transformToUri($doc, $uri);
});
$useInternalErrors = \libxml_use_internal_errors(true);

try {
parent::importStylesheet($this->getTranspiledStyleSheet($transpiler, $styleSheet));
$this->throwOnLibxmlError();

return $transpiler->transform(function () use ($doc, $uri) {
return parent::transformToUri($doc, $uri);
});
} finally {
\libxml_clear_errors();
\libxml_use_internal_errors($useInternalErrors);
}
}

/**
Expand Down Expand Up @@ -241,4 +264,14 @@ private function createStreamOptions(Transpiler $transpiler)

return $contextOptions;
}

private function throwOnLibxmlError()
{
$errors = \libxml_get_errors();
if ($errors === []) {
return;
}

throw TransformationException::fromLibxmlErrorList($errors);
}
}
28 changes: 28 additions & 0 deletions test/Integration/ExceptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);

namespace Genkgo\Xsl\Integration;

use DOMDocument;
use Genkgo\Xsl\AbstractTestCase;
use Genkgo\Xsl\Cache\NullCache;
use Genkgo\Xsl\Exception\TransformationException;
use Genkgo\Xsl\XsltProcessor;

final class ExceptionTest extends AbstractTestCase
{
public function testException()
{
$this->expectException(TransformationException::class);

$xslDoc = new DOMDocument();
$xslDoc->loadXML((string)\file_get_contents('Stubs/invalid-stylesheet.xsl'));

$xmlDoc = new DOMDocument();
$xmlDoc->load('Stubs/collection.xml');

$transpiler = new XsltProcessor(new NullCache());
$transpiler->importStylesheet($xslDoc);
$transpiler->transformToXML($xmlDoc);
}
}
3 changes: 3 additions & 0 deletions test/Stubs/invalid-stylesheet.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1">
<xsl:variable match="/">test</xsl:variable>
</xsl:stylesheet>

0 comments on commit 3ffa879

Please sign in to comment.