Skip to content

Instantly share code, notes, and snippets.

@Hounddog
Created November 26, 2013 20:27
Show Gist options
  • Save Hounddog/7665633 to your computer and use it in GitHub Desktop.
Save Hounddog/7665633 to your computer and use it in GitHub Desktop.
Controller For Callback Controller of instagram
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace HdInstagram\Controller;
use Zend\Mvc\Controller\AbstractController;
use Zend\Http\Request as HttpRequest;
use Zend\Json\Json;
use Zend\Mvc\Exception;
use Zend\Mvc\MvcEvent;
use Zend\Stdlib\RequestInterface as Request;
use Zend\Stdlib\ResponseInterface as Response;
/**
* Index controller
*/
class IndexController extends AbstractController
{
const CONTENT_TYPE_JSON = 'json';
/**
* @var string
*/
protected $eventIdentifier = __CLASS__;
/**
* @var array
*/
protected $contentTypes = array(
self::CONTENT_TYPE_JSON => array(
'application/hal+json',
'application/json'
)
);
/**
* Name of request or query parameter containing identifier
*
* @var string
*/
protected $identifierName = 'hub_challenge';
/**
* @var int From Zend\Json\Json
*/
protected $jsonDecodeType = Json::TYPE_ARRAY;
/**
* Map of custom HTTP methods and their handlers
*
* @var array
*/
protected $customHttpMethodsMap = array();
/**
* Set the route match/query parameter name containing the identifier
*
* @param string $name
* @return self
*/
public function setIdentifierName($name)
{
$this->identifierName = (string) $name;
return $this;
}
/**
* Retrieve the route match/query parameter name containing the identifier
*
* @return string
*/
public function getIdentifierName()
{
return $this->identifierName;
}
/**
* Create a new resource
*
* @param mixed $data
* @return mixed
*/
public function create($data)
{
$this->response->setStatusCode(405);
return array(
'content' => 'Method Not Allowed'
);
}
/**
* Delete an existing resource
*
* @param mixed $id
* @return mixed
*/
public function delete($id)
{
$this->response->setStatusCode(405);
return array(
'content' => 'Method Not Allowed'
);
}
/**
* Basic functionality for when a page is not available
*
* @return array
*/
public function notFoundAction()
{
$this->response->setStatusCode(404);
return array(
'content' => 'Page not found'
);
}
/**
* Dispatch a request
*
* If the route match includes an "action" key, then this acts basically like
* a standard action controller. Otherwise, it introspects the HTTP method
* to determine how to handle the request, and which method to delegate to.
*
* @events dispatch.pre, dispatch.post
* @param Request $request
* @param null|Response $response
* @return mixed|Response
* @throws Exception\InvalidArgumentException
*/
public function dispatch(Request $request, Response $response = null)
{
if (! $request instanceof HttpRequest) {
throw new Exception\InvalidArgumentException(
'Expected an HTTP request');
}
return parent::dispatch($request, $response);
}
/**
* Handle the request
*
* @todo try-catch in "patch" for patchList should be removed in the future
* @param MvcEvent $e
* @return mixed
* @throws Exception\DomainException if no route matches in event or invalid HTTP method
*/
public function onDispatch(MvcEvent $e)
{
$routeMatch = $e->getRouteMatch();
if (! $routeMatch) {
/**
* @todo Determine requirements for when route match is missing.
* Potentially allow pulling directly from request metadata?
*/
throw new Exception\DomainException(
'Missing route matches; unsure how to retrieve action');
}
$request = $e->getRequest();
// Was an "action" requested?
$action = $routeMatch->getParam('action', false);
if ($action) {
// Handle arbitrary methods, ending in Action
$method = static::getMethodFromAction($action);
if (! method_exists($this, $method)) {
echo 'cant find action';
exit;
$method = 'notFoundAction';
}
$return = $this->$method();
$e->setResult($return);
return $return;
}
// Callback methods
$method = strtolower($request->getMethod());
switch ($method) {
// Custom HTTP methods (or custom overrides for standard methods)
case (isset($this->customHttpMethodsMap[$method])):
$callable = $this->customHttpMethodsMap[$method];
$action = $method;
$return = call_user_func($callable, $e);
break;
// GET
case 'get':
$challenge = $this->getChallenge($routeMatch, $request);
$response = $this->getResponse();
$response->setStatusCode(200);
$response->setContent($challenge);
return $response;
// POST
case 'post':
$action = 'create';
$return = $this->processPostData($request);
break;
// All others...
default:
$response = $e->getResponse();
$response->setStatusCode(405);
return $response;
}
$routeMatch->setParam('action', $action);
$e->setResult($return);
return $return;
}
/**
* Process post data and call create
*
* @param Request $request
* @return mixed
*/
public function processPostData(Request $request)
{
if ($this->requestHasContentType($request, self::CONTENT_TYPE_JSON)) {
$data = Json::decode($request->getContent(), $this->jsonDecodeType);
} else {
$data = $request->getPost()->toArray();
}
return $this->create($data);
}
/**
* Check if request has certain content type
*
* @param Request $request
* @param string|null $contentType
* @return bool
*/
public function requestHasContentType(Request $request, $contentType = '')
{
/** @var $headerContentType \Zend\Http\Header\ContentType */
$headerContentType = $request->getHeaders()->get('content-type');
if (!$headerContentType) {
return false;
}
$requestedContentType = $headerContentType->getFieldValue();
if (strstr($requestedContentType, ';')) {
$headerData = explode(';', $requestedContentType);
$requestedContentType = array_shift($headerData);
}
$requestedContentType = trim($requestedContentType);
if (array_key_exists($contentType, $this->contentTypes)) {
foreach ($this->contentTypes[$contentType] as $contentTypeValue) {
if (stripos($contentTypeValue, $requestedContentType) === 0) {
return true;
}
}
}
return false;
}
/**
* Register a handler for a custom HTTP method
*
* This method allows you to handle arbitrary HTTP method types, mapping
* them to callables. Typically, these will be methods of the controller
* instance: e.g., array($this, 'foobar'). The typical place to register
* these is in your constructor.
*
* Additionally, as this map is checked prior to testing the standard HTTP
* methods, this is a way to override what methods will handle the standard
* HTTP methods. However, if you do this, you will have to retrieve the
* identifier and any request content manually.
*
* Callbacks will be passed the current MvcEvent instance.
*
* To retrieve the identifier, you can use "$id =
* $this->getIdentifier($routeMatch, $request)",
* passing the appropriate objects.
*
* To retrieve the body content data, use "$data = $this->processBodyContent($request)";
* that method will return a string, array, or, in the case of JSON, an object.
*
* @param string $method
* @param Callable $handler
* @return AbstractRestfulController
*/
public function addHttpMethodHandler($method, /* Callable */ $handler)
{
if (!is_callable($handler)) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid HTTP method handler: must be a callable; received "%s"',
(is_object($handler) ? get_class($handler) : gettype($handler))
));
}
$method = strtolower($method);
$this->customHttpMethodsMap[$method] = $handler;
return $this;
}
/**
* Retrieve the identifier, if any
*
* Attempts to see if an identifier was passed in either the URI or the
* query string, returning it if found. Otherwise, returns a boolean false.
*
* @param \Zend\Mvc\Router\RouteMatch $routeMatch
* @param Request $request
* @return false|mixed
*/
protected function getChallenge($routeMatch, $request)
{
$identifier = $this->getIdentifierName();
$challenge = $request->getQuery()->get($identifier, false);
if ($challenge !== false) {
return $challenge;
}
return false;
}
/**
* Process the raw body content
*
* If the content-type indicates a JSON payload, the payload is immediately
* decoded and the data returned. Otherwise, the data is passed to
* parse_str(). If that function returns a single-member array with a key
* of "0", the method assumes that we have non-urlencoded content and
* returns the raw content; otherwise, the array created is returned.
*
* @param mixed $request
* @return object|string|array
*/
protected function processBodyContent($request)
{
$content = $request->getContent();
// JSON content? decode and return it.
if ($this->requestHasContentType($request, self::CONTENT_TYPE_JSON)) {
return Json::decode($content, $this->jsonDecodeType);
}
parse_str($content, $parsedParams);
// If parse_str fails to decode, or we have a single element with key
// 0, return the raw content.
if (!is_array($parsedParams)
|| (1 == count($parsedParams) && isset($parsedParams[0]))
) {
return $content;
}
return $parsedParams;
}
}
/*
namespace HdInstagram\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class IndexController extends AbstractActionController
{
public function indexAction()
{
if(isset($_GET['hub_challenge'])) {
$challenge = $_GET['hub_challenge'];
$viewModel = new ViewModel(array(
'challenge' => $challenge,
));
$viewModel->setTerminal(true);
return $viewModel;
} else {
//recieving update notification
}
}
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment