Skip to content
Browse files

API Make SSViewer#process return HTMLText not string

This means that you dont have to worry about casting it
as HTMLText again when using the result in a template or other context

However in some situations code might be assuming it can
check with is_string, in which case you now need to use instanceof HTMLText
  • Loading branch information...
1 parent 9bd6dd9 commit 743a186c3248d62ce001e6c40fed2123da10b54c @hafriedlander hafriedlander committed with sminnee Mar 12, 2013
View
4 control/Controller.php
@@ -157,9 +157,9 @@ public function handleRequest(SS_HTTPRequest $request, DataModel $model) {
. "returning it without modification.");
}
$this->response = $body;
-
+
} else {
- if(is_object($body)) {
+ if($body instanceof Object && $body->hasMethod('getViewer')) {
if(isset($_REQUEST['debug_request'])) {
Debug::message("Request handler $body->class object to $this->class controller;"
. "rendering with template returned by $body->class::getViewer()");
View
2 control/HTTPResponse.php
@@ -159,7 +159,7 @@ public function isError() {
* @return SS_HTTPRequest $this
*/
public function setBody($body) {
- $this->body = $body;
+ $this->body = $body ? (string)$body : $body; // Don't type-cast false-ish values, eg null is null not ''
}
/**
View
3 control/PjaxResponseNegotiator.php
@@ -79,7 +79,8 @@ public function respond(SS_HTTPRequest $request, $extraCallbacks = array()) {
// Execute the fragment callbacks and build the response.
foreach($fragments as $fragment) {
if(isset($callbacks[$fragment])) {
- $responseParts[$fragment] = call_user_func($callbacks[$fragment]);
+ $res = call_user_func($callbacks[$fragment]);
+ $responseParts[$fragment] = $res ? (string)$res : $res;
} else {
throw new SS_HTTPResponse_Exception("X-Pjax = '$fragment' not supported for this URL.", 400);
}
View
11 dev/SapphireTest.php
@@ -510,6 +510,17 @@ public function tearDown() {
$controller->response->removeHeader('Location');
}
}
+
+ public static function assertContains($needle, $haystack, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE) {
+ if ($haystack instanceof DBField) $haystack = (string)$haystack;
+ parent::assertContains($needle, $haystack, $message, $ignoreCase, $checkForObjectIdentity);
+ }
+
+ public static function assertNotContains($needle, $haystack, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE) {
+ if ($haystack instanceof DBField) $haystack = (string)$haystack;
+ parent::assertNotContains($needle, $haystack, $message, $ignoreCase, $checkForObjectIdentity);
+ }
+
/**
* Clear the log of emails sent
*/
View
5 model/fieldtypes/DBField.php
@@ -295,5 +295,8 @@ public function debug() {
</ul>
DBG;
}
-
+
+ public function __toString() {
+ return $this->forTemplate();
+ }
}
View
11 view/SSViewer.php
@@ -866,7 +866,7 @@ protected function includeGeneratedTemplate($cacheFile, $item, $overlay, $underl
* @param ViewableData $item
* @param SS_Cache $cache Optional cache backend.
*
- * @return String Parsed template output.
+ * @return HTMLText Parsed template output.
*/
public function process($item, $arguments = null) {
SSViewer::$topLevel[] = $item;
@@ -909,12 +909,7 @@ public function process($item, $arguments = null) {
$subtemplateViewer->includeRequirements(false);
$subtemplateViewer->setPartialCacheStore($this->getPartialCacheStore());
- $underlay[$subtemplate] = DBField::create_field(
- 'HTMLText',
- $subtemplateViewer->process($item, $arguments),
- $subtemplate,
- array('shortcodes' => false)
- );
+ $underlay[$subtemplate] = $subtemplateViewer->process($item, $arguments);
}
}
@@ -939,7 +934,7 @@ public function process($item, $arguments = null) {
}
}
- return $output;
+ return DBField::create_field('HTMLText', $output, null, array('shortcodes' => false));
}
/**
View
2 view/ViewableData.php
@@ -318,7 +318,7 @@ public function buildCastingCache(&$cache) {
*
* @param string|array|SSViewer $template the template to render into
* @param array $customFields fields to customise() the object with before rendering
- * @return string
+ * @return HTMLText
*/
public function renderWith($template, $customFields = null) {
if(!is_object($template)) {

3 comments on commit 743a186

@dhensby
SilverStripe Ltd. member

@sminnee This appears to have caused a slight issue with doing something like:

$jsonEncode = array();
foreach (Page::get() as $page) {
    $jsonEncode[$page->ID] = $page->forTemplate();
}
return Convert::raw2json($jsonEncode);

Previously, that would have returned a JSON object of

"ID" : "<html template>"

But now it returns

"ID" : { "class" : "HTMLText" }

My reading of the docs is, that the json_encode function turns the object into a json object based on it's public variables (class being the only one in this instance).

I'm not sure of a way to make json_encode use some other function to determine how it should be represented (in 5.3, you can in 5.4 - see http://www.php.net/manual/en/class.jsonserializable.php).

Not sure how best to patch this? Either the docs need to make it very clear that you need to be casting as string in these circumstances (I think it's very big deal for updgrades) or the Convert::array2json() needs to walk the entire array making sure that all items are strings and casting them as such - but equally, that could break other code that relies on encoding an object and not a string...

@hafriedlander
SilverStripe Ltd. member

Yeah, you now need to cast as strings, like $jsonEncode[$page->ID] = (string)$page->forTemplate(); - it's a difficult change to catch, as it's only needed where the behaviour for objects is different than the behavior for strings. It is briefly mentioned in the 3.1 upgrade docs but that should probably be expanded.

@dhensby
SilverStripe Ltd. member

I'm happy with that position, if it is the way it's being put now, then sure. But i do think it's a big deal and needs to be made very clear in the docs.

Please sign in to comment.
Something went wrong with that request. Please try again.