Skip to content

Instantly share code, notes, and snippets.

@ClaudioVarandas
Last active September 8, 2015 13:51
Show Gist options
  • Save ClaudioVarandas/f1898433dbf383975239 to your computer and use it in GitHub Desktop.
Save ClaudioVarandas/f1898433dbf383975239 to your computer and use it in GitHub Desktop.
ApiController - Base api controller
<?php
namespace Api\v1;
use Apilog;
use Config;
use Input;
use League\Fractal;
use League\Fractal\Pagination\Cursor;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Serializer\DataArraySerializer;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Request;
use User;
/**
* Class ApiController
*
* @package Api\v1
*/
class ApiController extends \BaseController
{
/**
* @var \Illuminate\Database\Eloquent\Model|null|static
*/
protected $apikey;
/**
* The Fractal Manager
*
* @var Fractal\Manager
*/
protected $fractal;
/**
* @var array
*/
protected $requiredHeaders;
/**
* @var array
*/
protected $requiredMobileHeaders;
/**
* The restapi.php endpoint
*
* @var string
*/
protected $apiEndpoint = '1.0';
/**
* Map of fields for the resources
* Key = external field in camelCase
* Value = internal field in snake_case
*
* @var array
*/
protected $fieldsMap = [];
/**
* Create a new resource instance
*
* @param FractalManager|Fractal\Manager $fractal
*/
public function __construct(Fractal\Manager $fractal)
{
/** @var ApiRequestService $apiRequestService */
$apiRequestService = \App::make('***\Services\Api\ApiRequestService');
$this->requiredHeaders = $apiRequestService->getRequiredHeaders();
$this->requiredMobileHeaders = $apiRequestService->getRequiredMobileHeaders();
// disable session for API methods
Config::set('session.driver', 'array');
$this->beforeFilter('@filterHeaders');
$this->beforeFilter('@filterHandleLanguageHeader');
if (Config::get('restapi.logging')) {
$this->afterFilter('@filterLog');
}
$this->fractal = $fractal;
$this->fractal->setSerializer(new DataArraySerializer());
if (Input::has('include')) {
$this->fractal->parseIncludes(Input::get('include'));
#$this->fractal->setRequestedScopes(explode(',', Input::get('include')));
}
}
/**
* Process a item
*
* @param mixed $item
* @param mixed $callback
* @param mixed $meta
*
* @return array
*/
public function processItem($item, $callback, $meta = [])
{
$resource = new Item($item, $callback);
foreach ($meta as $metaKey => $metaValue) {
$resource->setMetaValue($metaKey, $metaValue);
}
$rootScope = $this->fractal->createData($resource);
return $rootScope->toArray();
}
/**
* Process a collection of items through Fractal
*
* @param mixed $collection
* @param mixed $callback
* @param \League\Fractal\Pagination\Cursor $cursor
* @param mixed $meta
*
* @return array
*/
public function processCollection($collection, $callback, Cursor $cursor = null, $meta = [])
{
$resource = new Collection($collection, $callback);
foreach ($meta as $metaKey => $metaValue) {
$resource->setMetaValue($metaKey, $metaValue);
}
if (!is_null($cursor)) {
$resource->setCursor($cursor);
}
$rootScope = $this->fractal->createData($resource);
return $rootScope->toArray();
}
/**
* Process a collection with simple transformer
*
* @access public
*
* @param \Illuminate\Support\Collection $collection Collection of items to be transformed
* @param Transformer $transformer Transformer to be applied
*
* @return \Illuminate\Support\Collection A collection of transformed items
* @since 1.2.0
*/
public function processCollectionSimple($collection, Transformer $transformer, $listing = false)
{
$returnData = new \Illuminate\Support\Collection();
foreach ($collection as $collectionItem) {
if (!$listing) {
$returnData->push($transformer->transformSimple($collectionItem));
} else {
$returnData->push($transformer->transformListing($collectionItem));
}
}
return $returnData;
}
/**
* Process an item with simple transformer
*
* @access public
*
* @param Entity $item Item to be transformed
* @param Transformer $transformer Transformer to be applied
*
* @return array The transformed item
* @since 1.2.0
*/
public function processItemSimple(Entity $item, Transformer $transformer)
{
return $transformer->transformSimple($item);
}
################
### FILTERS ####
################
/**
* Filter the request headers
*
* @return \Illuminate\Http\JsonResponse
*/
public function filterHeaders()
{
/** @var ApiRequestService $apiRequestService */
$apiRequestService = \App::make('***\Services\Api\ApiRequestService');
// Validate required headers
if (!$apiRequestService->isValidRequiredHeaders()) {
return ApiResponseService::respondHeadersRequired($apiRequestService->getMissingRequiredHeaders());
}
// Validate platform type
if (!$apiRequestService->isValidPlatform()) {
$platformTypeHeaderName = $apiRequestService::HEADER_X_PLATFORM_TYPE;
return ApiResponseService::respondHeadersInvalid([$platformTypeHeaderName => 'Unsupported platform']);
}
// Validate app code
if (!$apiRequestService->isValidApp()) {
$appCodeHeaderName = $apiRequestService::HEADER_X_APP_CODE;
return ApiResponseService::respondHeadersInvalid([$appCodeHeaderName => 'Invalid application code']);
}
// Validate device headers (family and os)
if ($apiRequestService->isMobile()) {
if (!$apiRequestService->isValidDeviceFamily()) {
$deviceFamilyHeaderName = $apiRequestService::HEADER_X_DEVICE_FAMILY;
return ApiResponseService::respondHeadersInvalid([$deviceFamilyHeaderName => 'Invalid device family']);
}
if (!$apiRequestService->isValidDeviceOs()) {
$deviceOsHeaderName = $apiRequestService::HEADER_X_DEVICE_FAMILY;
return ApiResponseService::respondHeadersInvalid([$deviceOsHeaderName => 'Invalid device os']);
}
}
}
/**
* Do the log of the request
*
* @param mixed $route The requested route
* @param mixed $request The request
*/
public function filterLog($route, $request)
{
$routeAction = $route->getAction();
$input = $request->all(); #\Input::all();
// disable saving of password in plain text on DB
if (isset($input['password']) && $input['password'] != '') {
$input['password'] = 'password';
}
if (isset($input['password_confirmation']) && $input['password_confirmation'] != '') {
$input['password_confirmation'] = 'password';
}
/** @var \***\Services\Api\ApiRequestService $apiRequestService */
$apiRequestService = \App::make('***\Services\Api\ApiRequestService');
/** @var \***\Services\UserService $userService */
$userService = \App::make('***\Services\UserService');
$user = $userService->getCurrentUser();
if ($user) {
$logUserId = $user->id;
}
$uri = explode('?', Request::getRequestUri());
### Log this API request ###
// create a log channel
$log = new Logger('api_requests');
$log->pushHandler(new StreamHandler(storage_path('logs') . '/' . 'api_requests' . date('Y-m-d') . '.log',
Logger::INFO));
$logUserId = isset($logUserId) ? $logUserId : 'GUEST';
$logAppName = $apiRequestService->getAppName();
$logAction = $routeAction['controller'];
$logMethod = $request->method();
$logEndpoint = $uri[0];
$logParams = http_build_query($input);
$logIp = $request->ip();
// add records to the log
$log->addInfo($logIp . '-' . $logUserId . '-' . $logAppName . '-' . $logEndpoint . '-' . $logAction . '-' . $logMethod . '-' . urldecode($logParams));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment