Skip to content

Commit

Permalink
Merge pull request #13 from ecphp/feat-xml2array-contrib-lib
Browse files Browse the repository at this point in the history
Parse XML with a contrib library and get rid of custom class.
  • Loading branch information
drupol authored Aug 3, 2020
2 parents 140d32e + 8c27a72 commit 6f49f5c
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 163 deletions.
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
"license": "BSD-3-Clause",
"require": {
"php": ">= 7.1.3",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-simplexml": "*",
"league/uri-query-parser": "^1.0",
"openlss/lib-array2xml": "^1.0",
"psr/cache": "^1.0.1",
"psr/http-client": "^1.0.0",
"psr/http-factory": "^1.0.1",
Expand Down
53 changes: 25 additions & 28 deletions spec/EcPhp/CasLib/CasSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@
use EcPhp\CasLib\Configuration\Properties as CasProperties;
use EcPhp\CasLib\Introspection\Introspector;
use EcPhp\CasLib\Introspection\ServiceValidate;
use EcPhp\CasLib\Utils\SimpleXml;
use Exception;
use InvalidArgumentException;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7\Response;
use Nyholm\Psr7\ServerRequest;
Expand Down Expand Up @@ -1358,60 +1355,60 @@ public function it_can_validate_a_service_ticket()

public function it_can_validate_any_type_of_ticket()
{
$body = <<< 'EOF'
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
<cas:authenticationSuccess>
<cas:user>username</cas:user>
</cas:authenticationSuccess>
</cas:serviceResponse>
EOF;
$body = [
'serviceResponse' => [
'authenticationSuccess' => [
'user' => 'username',
],
],
];

$request = new ServerRequest('GET', 'http://from?ticket=ST-TICKET');
$response = new Response(
200,
['Content-Type' => 'application/json'],
json_encode(SimpleXml::toArray(SimpleXml::fromString($body)))
json_encode($body)
);

$this
->withServerRequest($request)
->requestTicketValidation([], $response)
->shouldBeAnInstanceOf(ResponseInterface::class);

$body = <<< 'EOF'
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
<cas:authenticationSuccess>
<cas:user>username</cas:user>
<cas:proxyGrantingTicket>pgtIou</cas:proxyGrantingTicket>
</cas:authenticationSuccess>
</cas:serviceResponse>
EOF;
$body = [
'serviceResponse' => [
'authenticationSuccess' => [
'user' => 'username',
'proxyGrantingTicket' => 'pgtIou',
],
],
];

$request = new ServerRequest('GET', 'http://from?ticket=PT-TICKET');
$response = new Response(
200,
['Content-Type' => 'application/json'],
json_encode(SimpleXml::toArray(SimpleXml::fromString($body)))
json_encode($body)
);

$this
->withServerRequest($request)
->requestTicketValidation([], $response)
->shouldBeNull();

$body = <<< 'EOF'
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
<cas:authenticationSuccess>
<cas:user>username</cas:user>
</cas:authenticationSuccess>
</cas:serviceResponse>
EOF;
$body = [
'serviceResponse' => [
'authenticationSuccess' => [
'user' => 'username',
],
],
];

$request = new ServerRequest('GET', 'http://from');
$response = new Response(
500,
['Content-Type' => 'application/json'],
json_encode(SimpleXml::toArray(SimpleXml::fromString($body)))
json_encode($body)
);

$this
Expand Down
26 changes: 16 additions & 10 deletions spec/EcPhp/CasLib/Introspection/ServiceValidateSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,7 @@ public function it_can_detect_a_proxy_service_validate_response()
$psr17Factory = new Psr17Factory();

$body = <<< 'EOF'
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
<cas:authenticationSuccess>
<cas:user>user</cas:user>
<cas:proxyGrantingTicket>proxyGrantingTicket</cas:proxyGrantingTicket>
<cas:proxies>
<cas:proxy>http://proxy1</cas:proxy>
<cas:proxy>http://proxy2</cas:proxy>
</cas:proxies>
</cas:authenticationSuccess>
</cas:serviceResponse>
Useless stuff here.
EOF;

$response = (new Response(200))
Expand All @@ -41,6 +32,17 @@ public function it_can_detect_a_proxy_service_validate_response()
'http://proxy2',
],
],
'extendedAttributes' => [
'extendedAttribute' => [
'attributeValue' => [
0 => 'rex',
1 => 'snoopy',
],
'@attributes' => [
'name' => 'http://stork.eu/motherInLawDogName',
],
],
],
];

$parsed = [
Expand Down Expand Up @@ -74,6 +76,10 @@ public function it_can_detect_a_proxy_service_validate_response()
$this
->getResponse()
->shouldReturn($response);

$this
->getParsedResponse()
->shouldReturn($parsed);
}

public function it_can_detect_a_service_validate_response()
Expand Down
60 changes: 0 additions & 60 deletions spec/EcPhp/CasLib/Utils/SimpleXmlSpec.php

This file was deleted.

47 changes: 41 additions & 6 deletions src/Introspection/Introspector.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@

namespace EcPhp\CasLib\Introspection;

use DOMDocument;
use DOMXPath;
use EcPhp\CasLib\Introspection\Contract\IntrospectionInterface;
use EcPhp\CasLib\Introspection\Contract\IntrospectorInterface;
use EcPhp\CasLib\Utils\SimpleXml;
use Exception;
use InvalidArgumentException;
use LSS\XML2Array;
use Psr\Http\Message\ResponseInterface;

use const JSON_ERROR_NONE;
use const LIBXML_NOBLANKS;
use const LIBXML_NOCDATA;
use const LIBXML_NONET;
use const LIBXML_NSCLEAN;

final class Introspector implements IntrospectorInterface
{
Expand Down Expand Up @@ -73,18 +80,37 @@ public function detect(ResponseInterface $response): IntrospectionInterface
*/
public function parse(ResponseInterface $response, string $format = 'XML'): array
{
$body = (string) $response->getBody();

if ('' === $body) {
throw new InvalidArgumentException('Empty response body');
}

if ('XML' === $format) {
$xml = SimpleXml::fromString((string) $response->getBody());
libxml_disable_entity_loader(true);
libxml_use_internal_errors(true);

try {
$dom = new DOMDocument();

$dom
->loadXML(
$body,
LIBXML_NSCLEAN | LIBXML_NOCDATA | LIBXML_NOBLANKS | LIBXML_NONET
);

$this->removeDomNamespace($dom, 'cas');

if (null === $xml) {
throw new InvalidArgumentException('Unable to parse the response using XML format.');
$data = XML2Array::createArray($dom);
} catch (Exception $e) {
throw new InvalidArgumentException('Unable to parse the response using XML format.', 0, $e);
}

return SimpleXml::toArray($xml);
return $data;
}

if ('JSON' === $format) {
$json = json_decode((string) $response->getBody(), true);
$json = json_decode($body, true);

if (null === $json || JSON_ERROR_NONE !== json_last_error()) {
throw new InvalidArgumentException('Unable to parse the response using JSON format.');
Expand All @@ -95,4 +121,13 @@ public function parse(ResponseInterface $response, string $format = 'XML'): arra

throw new InvalidArgumentException('Unsupported format.');
}

private function removeDomNamespace(DOMDocument $doc, string $namespace): void
{
$query = sprintf('//*[namespace::%s and not(../namespace::%s)]', $namespace, $namespace);

foreach ((new DOMXPath($doc))->query($query) as $node) {
$node->removeAttributeNS($node->lookupNamespaceURI($namespace), $namespace);
}
}
}
59 changes: 0 additions & 59 deletions src/Utils/SimpleXml.php

This file was deleted.

0 comments on commit 6f49f5c

Please sign in to comment.