diff --git a/classes/Utils.php b/classes/Utils.php index 01fc9b90cc2ae25590c29d2bf87a02bb5b7ab33b..80eda140140c11c176ae099bcb1bd1be16a76096 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -124,39 +124,50 @@ class Utils return $obj; } - public static function getExtension($accept_string) + public static function getExtension($accept_string, array $configuration): string { - global $conf; - $extension = "html"; - foreach ($conf['http_accept'] as $ext => $accept_arr) { - if (in_array($accept_string, $accept_arr)) { - $extension = $ext; + foreach ($configuration as $extension => $extensions) { + if (in_array($accept_string, $extensions, true)) { + return $extension; } } - return $extension; + + return 'html'; } - public static function getBestContentType($accept_string) + /** + * header from the current request, if there is one. + * + * @param $accept_string + * Contents of the Accept: header from the current request. + * @param array $configuration + * @return int|string + */ + public static function getBestContentType($accept_string, array $configuration) { - global $conf; $a = explode(",", $accept_string); - $b = array(); + if ($a[0] === 'text/html' || $a[0] === 'text/css' || $a[0] === '*/*') { + return 'text/html'; + } + + $b = []; foreach ($a as $v) { - foreach ($conf['http_accept'] as $formatTypeArray) { - if (strstr($v, ";")) { - $aux = explode(";", $v); + foreach ($configuration as $formatTypeArray) { + if (strpos($v, ";") !== false) { + $aux = explode(';', $v); $aux[0] = trim($aux[0]); - if (in_array($aux[0], $formatTypeArray)) { - $b[$aux[0]] = floatval(trim(str_replace("q=", "", $aux[1]))); + if (in_array($aux[0], $formatTypeArray, true)) { + $b[$aux[0]] = (float)trim(str_replace("q=", "", $aux[1])); } } else { $value = trim($v); - if (in_array($value, $formatTypeArray)) { + if (in_array($value, $formatTypeArray, true)) { $b[$value] = 1.0; } } } } + $a = $b; arsort($a); $ct = 'text/html'; @@ -164,9 +175,11 @@ class Utils $ct = $k; break; } - if ($ct == null || $ct == "" || $ct == "*/*") { - $ct = 'text/html'; + + if ($ct === null || $ct === "" || $ct === "*/*") { + return 'text/html'; } + return $ct; } @@ -250,7 +263,7 @@ class Utils global $conf; global $lodspk; $contentType = $lodspk['contentType']; - $extension = Utils::getExtension($contentType); + $extension = Utils::getExtension($contentType, $conf['http_accept']); header('Content-Type: ' . $contentType); if (isset($lodspk['resultRdf']) && $lodspk['resultRdf'] == true) { diff --git a/classes/modules/serviceModule.php b/classes/modules/serviceModule.php index 0d5001b4c4df6bd56d3041701e89ae86907c4524..a75dae07f7df03e10fc1d187d4f835995b82c8c3 100644 --- a/classes/modules/serviceModule.php +++ b/classes/modules/serviceModule.php @@ -25,7 +25,7 @@ class ServiceModule extends abstractModule } - $extension = Utils::getExtension($acceptContentType); + $extension = Utils::getExtension($acceptContentType, $conf['http_accept']); $viewFile = null; $tokens = $qArr; $arguments = array(); @@ -140,7 +140,7 @@ class ServiceModule extends abstractModule $params = $this->getParams($localUri); //$params[] = $context; //$acceptContentType = Utils::getBestContentType($_SERVER['HTTP_ACCEPT']); - $extension = Utils::getExtension($acceptContentType); + $extension = Utils::getExtension($acceptContentType, $conf['http_accept']); $args = array(); list($modelFile, $viewFile) = $service; try { diff --git a/classes/modules/sparqlFilterModule.php b/classes/modules/sparqlFilterModule.php index 1a51b91740f9322344d711c74676fa42492a3ad4..d269776ce495a43642a630bbb0a61f28f473c500 100644 --- a/classes/modules/sparqlFilterModule.php +++ b/classes/modules/sparqlFilterModule.php @@ -86,7 +86,7 @@ class sparqlFilterModule extends abstractModule $localUri = preg_replace("|^" . $conf['ns']['local'] . "|", $conf['basedir'], $res); } - $extension = Utils::getExtension($format); + $extension = Utils::getExtension($format, $conf['http_accept']); /*Redefine Content type based on the * dcterms:format for this page diff --git a/classes/modules/typeModule.php b/classes/modules/typeModule.php index 10126d6005afd85cc52d84f0a110bee1dff5cd01..76d6cdac24351eec262089e19b1d80e03c0d9282 100644 --- a/classes/modules/typeModule.php +++ b/classes/modules/typeModule.php @@ -64,7 +64,7 @@ class TypeModule extends abstractModule $localUri = preg_replace("|^" . $conf['ns']['local'] . "|", $conf['basedir'], $res); } - $extension = Utils::getExtension($format); + $extension = Utils::getExtension($format, $conf['http_accept']); /*Redefine Content type based on the * dcterms:format for this page diff --git a/classes/modules/uriModule.php b/classes/modules/uriModule.php index b816028775b4c209d4bd2eadf56d4ee0c3a8312b..59c39a65a37a692b50f7441eaf39c7fd4f6b8678 100644 --- a/classes/modules/uriModule.php +++ b/classes/modules/uriModule.php @@ -43,7 +43,7 @@ class UriModule extends abstractModule return false; } } - $extension = Utils::getExtension($pair[2]); + $extension = Utils::getExtension($pair[2], $conf['http_accept']); $curie = Utils::uri2curie($pair[0]); list($modelFile, $viewFile) = $this->getModelandView($curie, $extension); if ($modelFile == null) { @@ -88,7 +88,7 @@ class UriModule extends abstractModule $localUri = preg_replace("|^" . $conf['ns']['local'] . "|", $conf['basedir'], $res); } - $extension = Utils::getExtension($format); + $extension = Utils::getExtension($format, $conf['http_accept']); /*Redefine Content type based on the * dcterms:format for this page diff --git a/index.php b/index.php index 971b798ca9b2a5ccc336490f8bd09a9d6b902d79..b90dcaba92e2bd037188b76b6f0c523209c384fc 100644 --- a/index.php +++ b/index.php @@ -50,8 +50,8 @@ $firstResults = array(); $endpoints = array(); $endpoints['local'] = new Endpoint($conf['endpoint']['local'], $conf['endpointParams']['config']); -$acceptContentType = Utils::getBestContentType($_SERVER['HTTP_ACCEPT']); -$extension = Utils::getExtension($acceptContentType); +$acceptContentType = Utils::getBestContentType($_SERVER['HTTP_ACCEPT'], $conf['http_accept']); +$extension = Utils::getExtension($acceptContentType, $conf['http_accept']); //Check content type is supported by LODSPeaKr diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000000000000000000000000000000000000..bb0d4f69beac65a183691e472c5a676a7345df4f --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd" + bootstrap="vendor/autoload.php" + cacheResultFile=".phpunit.cache/test-results" + executionOrder="depends,defects" + forceCoversAnnotation="true" + beStrictAboutCoversAnnotation="true" + beStrictAboutOutputDuringTests="true" + beStrictAboutTodoAnnotatedTests="true" + failOnRisky="true" + failOnWarning="true" + verbose="true"> + <testsuites> + <testsuite name="default"> + <directory>tests</directory> + </testsuite> + </testsuites> + + <coverage cacheDirectory=".phpunit.cache/code-coverage" + processUncoveredFiles="true"> + <include> + <directory suffix=".php">classes</directory> + </include> + </coverage> +</phpunit> diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4e336debb43a70fcba4a5a4b5af732728184cc8d --- /dev/null +++ b/tests/UtilsTest.php @@ -0,0 +1,140 @@ +<?php declare(strict_types=1); + +use PHPUnit\Framework\TestCase; +use uib\ub\loadspeakr\Utils; + +final class UtilsTest extends TestCase +{ + private array $http_accept; + + public function setUp(): void + { + parent::setUp(); + $this->http_accept = [ + 'html' => ['text/html'], + 'rdf' => ['application/rdf+xml'], + 'ttl' => [ + 'text/n3', + 'application/x-turtle', + 'application/turtle', + 'text/turtle', + 'application/rdf+turtle', + ], + 'json' => [ + 'application/json', + 'application/x-javascript', + 'text/javascript', + 'text/x-javascript', + 'text/x-json', + ], + 'nt' => ['text/plain'], + ]; + } + + /** + * Test Loadspeakr content negotiation. + * + * @dataProvider requestProvider + * @covers \uib\ub\loadspeakr\Utils::getBestContentType + */ + public function testGetBestContentType($expected, $requestHeader): void + { + self::assertSame($expected, Utils::getBestContentType($requestHeader, $this->http_accept)); + } + + /** + * Test Loadspeakr extension negotiation. + * + * @dataProvider requestGetExtensionProvider + * @covers \uib\ub\loadspeakr\Utils::getExtension + */ + public function testGetExtension($expected, $mediaType): void + { + self::assertEquals($expected, Utils::getExtension($mediaType, $this->http_accept)); + } + + + /** + * @see testGetBestContentType + */ + public function requestProvider(): array + { + + return [ + 'null header' => [ + 'expected' => 'text/html', + 'media-type' => 'text/html', + ], + 'Empty header' => [ + 'expected' => 'text/html', + 'media-type' => 'text/html', + ], + 'Empty string' => [ + 'expected' => 'text/html', + 'media-type' => 'text/html', + ], + 'Illegal string' => [ + 'expected' => 'text/html', + 'media-type' => 'foo, bar', + ], + 'html request' => [ + 'expected' => 'text/html', + 'media-type' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + ], + 'CSS request' => [ + 'expected' => 'text/html', + 'media-type' => 'text/css,*/*;q=0.1', + ], + 'JSON request' => [ + 'expected' => 'application/json', + 'media-type' => 'json/txt,application/json,*/*;q=0.1', + ], + 'Illegal JSON' => [ + 'expected' => 'text/html', + 'media-type' => 'json/born, application/jsons, */* ;q=0.1', + ], + ]; + } + + /** + * @see testGetExtension + */ + public function requestGetExtensionProvider(): array + { + return [ + 'Text html' => [ + 'expected' => 'html', + 'media-type' => 'text/html', + ], + 'Unknown media type' => [ + 'expected' => 'html', + 'media-type' => 'foo/bar', + ], + 'Empty string' => [ + 'expected' => 'html', + 'media-type' => '', + ], + 'Plain text' => [ + 'expected' => 'html', + 'media-type' => 'text/plain', + ], + 'CSS request' => [ + 'expected' => 'json', + 'media-type' => 'application/json', + ], + 'JSON request' => [ + 'expected' => 'json', + 'media-type' => 'application/json', + ], + 'Illegal JSON' => [ + 'expected' => 'json', + 'media-type' => 'application/jsons', + ], + 'Image jpeg' => [ + 'expected' => 'json', + 'media-type' => 'image/jpeg', + ], + ]; + } + +}