ENHNANCEMENT: allow overriding of PJAX fragments included in the response.

This commit is contained in:
Mateusz Uzdowski 2012-06-07 10:26:27 +12:00
parent ce3d48e310
commit 377ac50773
2 changed files with 53 additions and 11 deletions

View File

@ -22,6 +22,11 @@ class PjaxResponseNegotiator {
protected $response = null; protected $response = null;
/**
* Overriden fragments (if any). Otherwise uses fragments from the request.
*/
protected $fragmentOverride = null;
/** /**
* @param RequestHandler $controller * @param RequestHandler $controller
* @param SS_HTTPResponse An existing response to reuse (optional) * @param SS_HTTPResponse An existing response to reuse (optional)
@ -49,6 +54,7 @@ class PjaxResponseNegotiator {
* @param array $extraCallbacks List of anonymous functions or callables returning either a string * @param array $extraCallbacks List of anonymous functions or callables returning either a string
* or SS_HTTPResponse, keyed by their fragment identifier. The 'default' key can * or SS_HTTPResponse, keyed by their fragment identifier. The 'default' key can
* be used as a fallback for non-ajax responses. * be used as a fallback for non-ajax responses.
* @param array $fragmentOverride Change the response fragments.
* @return SS_HTTPResponse * @return SS_HTTPResponse
*/ */
public function respond(SS_HTTPRequest $request, $extraCallbacks = array()) { public function respond(SS_HTTPRequest $request, $extraCallbacks = array()) {
@ -57,8 +63,18 @@ class PjaxResponseNegotiator {
$response = $this->getResponse(); $response = $this->getResponse();
$responseParts = array(); $responseParts = array();
if($fragmentStr = $request->getHeader('X-Pjax')) {
if (isset($this->fragmentOverride)) {
$fragments = $this->fragmentOverride;
} elseif ($fragmentStr = $request->getHeader('X-Pjax')) {
$fragments = explode(',', $fragmentStr); $fragments = explode(',', $fragmentStr);
} else {
if($request->isAjax()) throw new SS_HTTPResponse_Exception("Ajax requests to this URL require an X-Pjax header.", 400);
$response->setBody(call_user_func($callbacks['default']));
return $response;
}
// Execute the fragment callbacks and build the response.
foreach($fragments as $fragment) { foreach($fragments as $fragment) {
if(isset($callbacks[$fragment])) { if(isset($callbacks[$fragment])) {
$responseParts[$fragment] = call_user_func($callbacks[$fragment]); $responseParts[$fragment] = call_user_func($callbacks[$fragment]);
@ -68,10 +84,7 @@ class PjaxResponseNegotiator {
} }
$response->setBody(Convert::raw2json($responseParts)); $response->setBody(Convert::raw2json($responseParts));
$response->addHeader('Content-Type', 'text/json'); $response->addHeader('Content-Type', 'text/json');
} else {
if($request->isAjax()) throw new SS_HTTPResponse_Exception("Ajax requests to this URL require an X-Pjax header.", 400);
$response->setBody(call_user_func($callbacks['default']));
}
return $response; return $response;
} }
@ -82,4 +95,17 @@ class PjaxResponseNegotiator {
public function setCallback($fragment, $callback) { public function setCallback($fragment, $callback) {
$this->callbacks[$fragment] = $callback; $this->callbacks[$fragment] = $callback;
} }
/**
* Set up fragment overriding - will completely replace the incoming fragments.
*
* @param array $fragments Fragments to insert.
*/
public function overrideFragments($fragments) {
if (!is_array($fragments)) throw new InvalidArgumentException();
$this->fragmentOverride = $fragments;
return $this;
}
} }

View File

@ -38,4 +38,20 @@ class PjaxResponseNegotiatorTest extends SapphireTest {
$this->assertEquals('otherfragment response', $json->otherfragment); $this->assertEquals('otherfragment response', $json->otherfragment);
} }
function testFragmentsOverride() {
$negotiator = new PjaxResponseNegotiator(array(
'alpha' => function() {return 'alpha response';},
'beta' => function() {return 'beta response';}
));
$request = new SS_HTTPRequest('GET', '/');
$request->addHeader('X-Pjax', 'alpha');
$request->addHeader('Accept', 'text/json');
$response = $negotiator->overrideFragments(array('beta'))->respond($request);
$json = json_decode( $response->getBody());
$this->assertFalse(isset($json->alpha));
$this->assertObjectHasAttribute('beta', $json);
}
} }