diff --git a/control/ContentNegotiator.php b/control/ContentNegotiator.php index 311877ce7..c2bdf12aa 100644 --- a/control/ContentNegotiator.php +++ b/control/ContentNegotiator.php @@ -28,6 +28,8 @@ */ class ContentNegotiator { + protected static $content_type = ''; + protected static $encoding = 'utf-8'; protected static $enabled = false; @@ -122,20 +124,24 @@ class ContentNegotiator { $negotiator->$chosenFormat( $response ); } - /** - * Only sends the HTTP Content-Type as "application/xhtml+xml" - * if the template starts with the typical ", ,  ). + /** + * Check user defined content type and use it, if it's empty use the strict application/xhtml+xml. + * Replaces a few common tags and entities with their XHTML representations (
, ,   + * , checked, selected). * * @param $response SS_HTTPResponse * @return string - * @todo More flexible tag and entity parsing through regular expressions or tag definition lists + * @todo Search for more xhtml replacement */ public function xhtml(SS_HTTPResponse $response) { $content = $response->getBody(); - $response->addHeader("Content-Type", "application/xhtml+xml; charset=" . self::$encoding); + $contentType = Config::inst()->get('ContentNegotiator', 'content_type'); + if (empty($contentType)) { + $response->addHeader("Content-Type", "application/xhtml+xml; charset=" . self::$encoding); + } else { + $response->addHeader("Content-Type", $contentType . "; charset=" . self::$encoding); + } $response->addHeader("Vary" , "Accept"); // Fix base tag @@ -146,19 +152,28 @@ class ContentNegotiator { $content = str_replace('
','
', $content); $content = str_replace('
','
', $content); $content = preg_replace('#(]*[^/>])>#i', '\\1/>', $content); + $content = preg_replace('#(]*[^/>])>#i', '\\1/>', $content); + $content = preg_replace("#(\]*[\s]+selected)(?!\s*\=)#si", "$1=\"selected\"$2", $content); + $content = preg_replace("#(\]*[\s]+checked)(?!\s*\=)#si", "$1=\"checked\"$2", $content); $response->setBody($content); } /* - * Sends HTTP Content-Type as "text/html", and replaces existing doctypes with - * HTML4.01 Strict. + * Check user defined content type and use it, if it's empty use the text/html. + * If find a XML header replaces it and existing doctypes with HTML4.01 Strict. * Replaces self-closing tags like with unclosed solitary tags like . * Replaces all occurrences of "application/xhtml+xml" with "text/html" in the template. * Removes "xmlns" attributes and any Pragmas. */ public function html(SS_HTTPResponse $response) { - $response->addHeader("Content-Type", "text/html; charset=" . self::$encoding); + + $contentType = Config::inst()->get('ContentNegotiator', 'content_type'); + if (empty($contentType)) { + $response->addHeader("Content-Type", "text/html; charset=" . self::$encoding); + } else { + $response->addHeader("Content-Type", $contentType . "; charset=" . self::$encoding); + } $response->addHeader("Vary", "Accept"); $content = $response->getBody(); diff --git a/tests/view/ContentNegotiatorTest.php b/tests/view/ContentNegotiatorTest.php new file mode 100644 index 000000000..4fb841907 --- /dev/null +++ b/tests/view/ContentNegotiatorTest.php @@ -0,0 +1,67 @@ +process($data); + } + + public function testXhtmltagReplacement() { + $tmpl1 = ' + + + <% base_tag %> + +
+ + ff + gg + hh + ii + jj + +
+ + '; + + // Check that the content negotiator converts to the equally legal formats + $negotiator = new ContentNegotiator(); + + $response = new SS_HTTPResponse($this->render($tmpl1)); + $negotiator->xhtml($response); + + //////////////////////// + // XHTML select options + //////////////////////// + $this->assertRegExp('/