Created
April 11, 2012 21:27
-
-
Save SocalNick/2362761 to your computer and use it in GitHub Desktop.
Ign Custom View Strategy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Ign\View\Strategy; | |
use Zend\EventManager\EventCollection, | |
Zend\EventManager\ListenerAggregate, | |
Zend\Feed\Writer\Feed, | |
Zend\Mvc\MvcEvent, | |
Zend\View\Renderer\FeedRenderer, | |
Zend\View\Renderer\JsonRenderer, | |
Zend\View\Renderer\PhpRenderer, | |
Zend\View\ViewEvent; | |
class AcceptRoutingStrategy implements ListenerAggregate | |
{ | |
protected $feedRenderer; | |
protected $jsonRenderer; | |
protected $phpRenderer; | |
protected $listeners = array(); | |
protected $validRenderers = array('jsonRenderer', 'feedRenderer'); | |
public function __construct( | |
PhpRenderer $phpRenderer, | |
JsonRenderer $jsonRenderer, | |
FeedRenderer $feedRenderer | |
) { | |
$this->phpRenderer = $phpRenderer; | |
$this->jsonRenderer = $jsonRenderer; | |
$this->feedRenderer = $feedRenderer; | |
} | |
public function attach(EventCollection $events, $priority = null) | |
{ | |
if (null === $priority) { | |
$this->listeners[] = $events->attach(ViewEvent::EVENT_RENDERER, array($this, 'selectRenderer')); | |
$this->listeners[] = $events->attach(ViewEvent::EVENT_RESPONSE, array($this, 'injectResponse')); | |
} else { | |
$this->listeners[] = $events->attach(ViewEvent::EVENT_RENDERER, array($this, 'selectRenderer'), $priority); | |
$this->listeners[] = $events->attach(ViewEvent::EVENT_RESPONSE, array($this, 'injectResponse'), $priority); | |
} | |
} | |
public function detach(EventCollection $events) | |
{ | |
foreach ($this->listeners as $index => $listener) { | |
if ($events->detach($listener)) { | |
unset($this->listeners[$index]); | |
} | |
} | |
} | |
public function validateRenderers(MvcEvent $e) | |
{ | |
$routeMatch = $e->getRouteMatch(); | |
$validRenderers = $routeMatch->getParam('valid-renderers', array()); | |
foreach (array_diff($this->validRenderers, $validRenderers) as $invalidRenderer) { | |
if (isset($this->$invalidRenderer)) { | |
unset($this->$invalidRenderer); | |
} | |
} | |
} | |
public function selectRenderer(ViewEvent $e) | |
{ | |
$request = $e->getRequest(); | |
$headers = $request->headers(); | |
// No Accept header? return PhpRenderer | |
if (!$headers->has('accept')) { | |
return $this->phpRenderer; | |
} | |
$accept = $headers->get('accept'); | |
foreach ($accept->getPrioritized() as $mediaType) { | |
if (isset($this->jsonRenderer)) { | |
if (0 === strpos($mediaType, 'application/json')) { | |
// jquery dataType json sends: | |
// application/json, text/javascript, */*; q=0.01 | |
return $this->jsonRenderer; | |
} | |
if (0 === strpos($mediaType, 'application/javascript')) { | |
// jQuery dataType jsonp sends: | |
// text/javascript, application/javascript, | |
// application/ecmascript, application/x-ecmascript, */*; q=0.01 | |
if (false != ($callback = $request->query()->get('callback'))) { | |
$this->jsonRenderer->setJsonpCallback($callback); | |
} | |
return $this->jsonRenderer; | |
} | |
} | |
if (isset($this->feedRenderer)) { | |
if (0 === strpos($mediaType, 'application/rss+xml')) { | |
$this->feedRenderer->setFeedType('rss'); | |
return $this->feedRenderer; | |
} | |
if (0 === strpos($mediaType, 'application/atom+xml')) { | |
$this->feedRenderer->setFeedType('atom'); | |
return $this->feedRenderer; | |
} | |
} | |
} | |
// Nothing matched; return PhpRenderer. Technically, we should probably | |
// return an HTTP 415 Unsupported response. | |
return $this->phpRenderer; | |
} | |
public function injectResponse(ViewEvent $e) | |
{ | |
$renderer = $e->getRenderer(); | |
$response = $e->getResponse(); | |
$result = $e->getResult(); | |
if (isset($this->jsonRenderer) && $renderer === $this->jsonRenderer) { | |
// JSON Renderer; set content-type header | |
$headers = $response->headers(); | |
if ($this->jsonRenderer->hasJsonpCallback()) { | |
$headers->addHeaderLine('content-type', 'application/javascript'); | |
} else { | |
$headers->addHeaderLine('content-type', 'application/json'); | |
} | |
} elseif (isset($this->feedRenderer) && $renderer === $this->feedRenderer) { | |
// Feed Renderer; set content-type header, and export the feed if | |
// necessary | |
$feedType = $this->feedRenderer->getFeedType(); | |
$headers = $response->headers(); | |
$mediatype = 'application/' | |
. (('rss' == $feedType) ? 'rss' : 'atom') | |
. '+xml'; | |
$headers->addHeaderLine('content-type', $mediatype); | |
// If the $result is a feed, export it | |
if ($result instanceof Feed) { | |
$result = $result->export($feedType); | |
} | |
} elseif ($renderer !== $this->phpRenderer) { | |
// Not a renderer we support, therefor not our strategy. Return | |
return; | |
} | |
// Inject the content | |
$response->setContent($result); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment