Skip to content

Commit

Permalink
Merge pull request #1 from conord33/conor/develop/userupdatebugfix
Browse files Browse the repository at this point in the history
Conor/develop/userupdatebugfix
  • Loading branch information
conord33 committed Jan 17, 2014
2 parents 21d9aa1 + 4aac3f7 commit 1fe4a8b
Show file tree
Hide file tree
Showing 43 changed files with 983 additions and 403 deletions.
51 changes: 32 additions & 19 deletions App.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
include_once __DIR__ . '/Slim/Slim.php';
include_once __DIR__ . '/Extension.php';
include_once __DIR__ . '/ErrorResponse.php';
include_once __DIR__ . '/DefaultAppErrors.php';

use \Slim\Slim;
use Slim\Exception\Stop;
Expand Down Expand Up @@ -47,6 +48,18 @@ public function getResponse() {
*/
protected static $singletonApp = NULL;

/**
* @var ErrorResponseDictionary
*/
protected $errorResponseDictionary = NULL;

/**
* @return \MABI\ErrorResponseDictionary
*/
public function getErrorResponseDictionary() {
return $this->errorResponseDictionary;
}

/**
* todo: docs
*/
Expand All @@ -70,42 +83,42 @@ public function __construct() {
array_push($this->middlewareDirectories, __DIR__ . '/middleware');
}
$this->slim = new Slim();
$this->errorResponseDictionary = new DefaultAppErrors();
parent::__construct($this);
}

/**
* Returns a JSON array displaying the error to the client and stops execution
*
* Example Error Message Definition:
* define('ERRORDEF_NO_ACCESS', array('message' => 'No Access', 'code' => 1007, 'httpcode' => 402));
* array('ERRORDEF_NO_ACCESS' => array('message' => 'No Access', 'code' => 1007, 'httpcode' => 402));
*
* @param $message string|array|ErrorResponse
* @param $httpStatusCodeOrReplacementArray int|null|array
* @param $applicationErrorCode int|null
* @param $errorKeyOrDefinition string|array
* @param $replacementArray array
*
* @throws \Slim\Exception\Stop
* @throws \Exception
*/
public function returnError($message, $httpStatusCodeOrReplacementArray = NULL, $applicationErrorCode = NULL) {
$replacementArray = $httpStatusCodeOrReplacementArray;
if (is_array($message)) {
$message = ErrorResponse::FromArray($message);
public function returnError($errorKeyOrDefinition, $replacementArray = array()) {
if (is_string($errorKeyOrDefinition)) {
$errorKey = $errorKeyOrDefinition;
}
elseif(is_string($message)) {
$message = new ErrorResponse($message, $httpStatusCodeOrReplacementArray, $applicationErrorCode);
$replacementArray = null;
else {
$errorKeys = array_keys($errorKeyOrDefinition);
$errorKey = $errorKeys[0];
}
elseif (!is_subclass_of($message, 'MABI\\ErrorResponse')) {
throw new \Exception('Invalid type ' . get_class($message) . ' instead of a MABI\ErrorResponse');

$errorResponse = $this->errorResponseDictionary->getErrorResponse($errorKey);
if (empty($errorResponse)) {
$errorResponse = ErrorResponse::FromArray($errorKeyOrDefinition[$errorKey]);
}

$appCode = $message->getCode();
$appCode = $errorResponse->getCode();
echo json_encode(array(
'error' => empty($appCode) ? array('message' => $message->getFormattedMessage($replacementArray)) :
array('code' => $appCode, 'message' => $message->getFormattedMessage($replacementArray))
'error' => empty($appCode) ? array('message' => $errorResponse->getFormattedMessage($replacementArray)) :
array('code' => $appCode, 'message' => $errorResponse->getFormattedMessage($replacementArray))
));
$this->getResponse()->status($message->getHttpcode());
throw new Stop($message->getFormattedMessage($replacementArray));
$this->getResponse()->status($errorResponse->getHttpcode());
throw new Stop($errorResponse->getFormattedMessage($replacementArray));
}

public function errorHandler($e) {
Expand Down
27 changes: 23 additions & 4 deletions Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ public function loadRoutes($slim) {

$rClass = new \ReflectionClass($this);
$rMethods = $rClass->getMethods(\ReflectionMethod::IS_PUBLIC);
$baseMethods = array();
foreach ($rMethods as $rMethod) {
// If there is a '@endpoint ignore' property, the function is not served as an endpoint
if (in_array('ignore', ReflectionHelper::getDocDirective($rMethod->getDocComment(), 'endpoint'))) {
Expand All @@ -183,20 +184,34 @@ public function loadRoutes($slim) {
$action = strtolower(substr($methodName, 6));
$httpMethod = \Slim\Http\Request::METHOD_DELETE;
}

if (!empty($action)) {
$slim->map("/{$this->base}/{$action}",
$slim->map("/{$this->base}/{$action}(/?)",
array($this, 'preMiddleware'),
array($this, '_runControllerMiddlewares'),
array($this, 'preCallable'),
array($this, $methodName))->via($httpMethod);
$slim->map("/{$this->base}/{$action}(/:param+)",
$slim->map("/{$this->base}/{$action}(/:param+)(/?)",
array($this, 'preMiddleware'),
array($this, '_runControllerMiddlewares'),
array($this, 'preCallable'),
array($this, $methodName))->via($httpMethod);
}
elseif(!empty($httpMethod)) {
array_push($baseMethods, array(
'name' => $methodName,
'method' => $httpMethod
));
}
}

foreach ($baseMethods as $httpMethod) {
$slim->map("/{$this->base}(/?)",
array($this, 'preMiddleware'),
array($this, '_runControllerMiddlewares'),
array($this, 'preCallable'),
array($this, $httpMethod['name']))->via($httpMethod['method']);
}
}

/**
Expand Down Expand Up @@ -272,10 +287,14 @@ public function getDocJSON(Parser $parser) {
continue;
}
$action = strtolower($methodDoc['MethodName']);
$methodDoc['URI'] = "/{$this->base}/{$action}";
$methodDoc['URI'] = "/{$this->base}" . (empty($action) ? '' : "/{$action}");
$methodDoc['Synopsis'] = $parser->parse(ReflectionHelper::getDocText($rMethod->getDocComment()));
$methodDoc['parameters'] = $this->getDocParameters($rMethod);

if (empty($methodDoc['MethodName'])) {
$methodDoc['MethodName'] = ucwords($this->base);
}

// Allow controller middlewares to modify the documentation for this method
if (!empty($this->middlewares)) {
$middleware = reset($this->middlewares);
Expand Down
31 changes: 31 additions & 0 deletions DefaultAppErrors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace MABI;

include_once __DIR__ . '/ErrorResponseDictionary.php';

class DefaultAppErrors extends ErrorResponseDictionary {
public static $NOT_AUTHORIZED = array(
'NOT_AUTHORIZED' => array(
'message' => 'Not properly authenticated for this route',
'httpcode' => 401,
'code' => 1007
)
);

public static $ENTRY_EXISTS = array(
'ENTRY_EXISTS' => array(
'message' => 'An entry with the id !modelid already exists.',
'httpcode' => 409,
'code' => 1008
)
);

public static $INVALID_JSON = array(
'INVALID_JSON' => array(
'message' => 'Could not load model from json: !message',
'httpcode' => 400,
'code' => 1009
)
);
}
36 changes: 6 additions & 30 deletions ErrorResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ class ErrorResponse

/**
* @param string $message
* @param int|null $httpcode
* @param int $httpcode
* @param int|null $code
*/
function __construct($message, $httpcode = null, $code = null)
function __construct($message, $httpcode, $code = null)
{
$this->message = $message;
$this->httpcode = $httpcode;
Expand All @@ -46,18 +46,10 @@ public static function FromArray($array)
{
if (!isset($array['message'])) throw new \Exception('Invalid ErrorResponse Array. Must contain a message');
return $newErrorResponse = new ErrorResponse($array['message'],
isset($array['httpcode']) ? $array['httpcode'] : null,
$array['httpcode'],
isset($array['code']) ? $array['code'] : null);
}

/**
* @param int $code
*/
public function setCode($code)
{
$this->code = $code;
}

/**
* @return int
*/
Expand All @@ -66,14 +58,6 @@ public function getCode()
return $this->code;
}

/**
* @param int $httpcode
*/
public function setHttpcode($httpcode)
{
$this->httpcode = $httpcode;
}

/**
* @return int
*/
Expand All @@ -82,14 +66,6 @@ public function getHttpcode()
return $this->httpcode;
}

/**
* @param string $message
*/
public function setMessage($message)
{
$this->message = $message;
}

/**
* @return string
*/
Expand All @@ -98,11 +74,11 @@ public function getMessage()
return $this->message;
}

public function getFormattedMessage($replacementArray = null)
public function getFormattedMessage($replacementArray = array())
{
if (!empty($replacementArray)) {
return str_replace(array_keys($replacementArray), array_values($replacementArray), $this->message);
return str_replace(array_keys($replacementArray), array_values($replacementArray), $this->getMessage());
}
return str_replace($this->replacementTokens, $this->replacementValues, $this->message);
return str_replace($this->replacementTokens, $this->replacementValues, $this->getMessage());
}
}
70 changes: 70 additions & 0 deletions ErrorResponseDictionary.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace MABI;

class ErrorResponseDictionary {
/**
* @var ErrorResponse[]
*/
protected $errorResponses = array();

/**
* Should be in the format (all required):
* static $SAMPLE_ERROR_KEY = array(
* 'message' => 'sample error message',
* 'httpcode' => '401',
* 'code' => 1); // optional
*/
function __construct() {
$rClass = new \ReflectionClass(get_called_class());
$rProperties = $rClass->getProperties(\ReflectionProperty::IS_STATIC);
$defaultProps = $rClass->getDefaultProperties();
foreach ($rProperties as $rProperty) {
$ignoreAnnotation = ReflectionHelper::getDocDirective($rProperty->getDocComment(), 'ignore');
if (!empty($ignoreAnnotation) || !is_array($defaultProps[$rProperty->getName()]) ||
empty($defaultProps[$rProperty->getName()])
) {
continue;
}

$propertyKeys = array_keys($defaultProps[$rProperty->getName()]);
$key = $propertyKeys[0];
$errorResponseArray = $defaultProps[$rProperty->getName()][$key];
if (empty($errorResponseArray['message']) || empty($errorResponseArray['httpcode'])) {
continue;
}

$this->errorResponses[$key] = ErrorResponse::FromArray($errorResponseArray);
}
}

/**
* Creates or overrides error responses with an initialization array in mass
*
* @param $initArray
*/
public function overrideErrorResponses(ErrorResponseDictionary $overridingDictionary) {
foreach ($overridingDictionary->errorResponses as $key => $errorResponse) {
$this->errorResponses[$key] = $errorResponse;
}
}

public function overrideErrorResponse($key, ErrorResponse $errorResponse) {
$this->errorResponses[$key] = $errorResponse;
}

/**
* todo: docs
*
* @param $key
*
* @return ErrorResponse|null
*/
public function getErrorResponse($key) {
if (empty($this->errorResponses[$key])) {
return NULL;
}

return $this->errorResponses[$key];
}
}
2 changes: 1 addition & 1 deletion Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ public function loadFromExternalSource($source) {
try {
$this->load($source, TRUE);
} catch (InvalidJSONException $ex) {
$this->app->returnError($ex->getMessage(), 400, 1009);
$this->app->returnError(DefaultAppErrors::$INVALID_JSON, array('!message' => $ex->getMessage()));
}
}

Expand Down
Loading

0 comments on commit 1fe4a8b

Please sign in to comment.