Skip to content

Instantly share code, notes, and snippets.

@SocalNick
Created April 11, 2012 21:27
Show Gist options
  • Save SocalNick/2362761 to your computer and use it in GitHub Desktop.
Save SocalNick/2362761 to your computer and use it in GitHub Desktop.
Ign Custom View Strategy
<?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