Skip to content

Commit

Permalink
Write phpunit tests for handlePost
Browse files Browse the repository at this point in the history
  • Loading branch information
nohponex committed Oct 8, 2016
1 parent 748aff3 commit bfc3862
Show file tree
Hide file tree
Showing 10 changed files with 1,142 additions and 73 deletions.
7 changes: 6 additions & 1 deletion src/Controller/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,6 @@ function ($d) {
$model
);


if ($parsed !== null) {
//overwrite
if ($overwrite
Expand All @@ -238,6 +237,12 @@ function ($d) {
return $directives;
}

/**
* @param $object
* @param ISource|null $source
* @param string[] ...$properties
* @throws MissingParametersException
*/
public static function requireProperties(
$object,
ISource $source = null,
Expand Down
79 changes: 44 additions & 35 deletions src/Controller/Helper/RequestBodyQueue.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@
use Phramework\Validate\ArrayValidator;
use Phramework\Validate\EnumValidator;
use Phramework\Validate\ObjectValidator;
use Phramework\Validate\StringValidator;

/**
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache-2.0
* @author Xenofon Spafaridis <nohponex@gmail.com>
* @since 3.0.0
*/
trait RequestBodyQueue
final class RequestBodyQueue
{
/**
* What is resource ?
* @todo
* @param \stdClass $resource Primary data resource
*/
Expand All @@ -59,10 +59,10 @@ public static function handleResource(
$parsedAttributes = $validationModel->getAttributes()
->setSource(new Pointer($source->getPath() . '/attributes'))
->parse(
$requestAttributes
);
$requestAttributes
);

$parsedRelationships = new \stdClass();
//$parsedRelationships = new \stdClass();

/**
* Format, object with
Expand Down Expand Up @@ -103,17 +103,19 @@ public static function handleResource(

$relationshipData = $rValue->data;

$itemValidator = (new ObjectValidator(
(object) [
'id' => new StringValidator(), // $r->getResourceModel()->getIdAttributeValidator(),
'type' => new EnumValidator([$resourceType], true)
],
['id', 'type']
))->setSource(new Pointer(
$rSource->getPath() . '/data'
));

switch ($r->getType()) {
case Relationship::TYPE_TO_ONE:
(new ObjectValidator(
(object)[
'id' => $r->getResourceModel()->getIdAttributeValidator(),
'type' => new EnumValidator($resourceType, true)
],
['id', 'type']
))->setSource(new Pointer(
$rSource->getPath() . '/data'
))->parse($relationshipData);
$itemValidator->parse($relationshipData);

//Push relationship for this relationship key
$relationships->{$rKey} = $relationshipData->id;
Expand All @@ -122,15 +124,9 @@ public static function handleResource(
$parsed = (new ArrayValidator(
0,
null,
(new ObjectValidator(
(object)[
'id' => $r->getResourceModel()->getIdAttributeValidator(),
'type' => new EnumValidator($resourceType, true)
],
['id', 'type']
))->setSource(new Pointer(
$rSource->getPath() . '/data'
))
$itemValidator
))->setSource(new Pointer(
$rSource->getPath() . '/data'
))->parse($relationshipData);

//Push relationship for this relationship key
Expand All @@ -145,26 +141,40 @@ function (\stdClass $p) {
}

/*
* Validate relationships against relationships validator
* Validate relationships against relationships validator if is set
*/
if (count((array)$relationships)) {
$parsedRelationships = $validationModel->getRelationships()->parse(
$relationships
);
if ($validationModel->getRelationships() !== null) {
$validator = $validationModel->getRelationships();

foreach ($validator->properties as $k => &$p) {
//force source to be ../data/id
$p->setSource(new Pointer(
$source->getPath() . '/relationships/' . $k . '/data/id'
));
}

$validator
//set source that will be used for missing parameters exception
->setSource(new Pointer(
$source->getPath() . '/relationships'
))
->parse(
$relationships
);
}

/*
* Foreach request relationship
* Check if requested relationship resources exist
* Copy TYPE_TO_ONE attributes to primary data's attributes
*/
foreach ($parsedRelationships as $rKey => $rValue) {
foreach ($relationships as $rKey => $rValue) {
$r = $model->getRelationship($rKey);
$rResourceModel = $r->getResourceModel();

//Convert to array
$tempIds = (
is_array($rValue)
is_array($rValue)
? $rValue
: [$rValue]
);
Expand Down Expand Up @@ -192,26 +202,25 @@ function (\stdClass $p) {
* //todo what if a TO_MANY has getRecordDataAttribute ?
*/
if ($r->getType() === Relationship::TYPE_TO_ONE) {
$parsedAttributes->{$r->getRecordDataAttribute()} = $relationshipData;
$parsedAttributes->{$r->getRecordDataAttribute()} = $relationshipData->id;
}
}


/*
* Call Validation callbacks
*/
foreach ($validationCallbacks as $callback) {
$callback(
$resource,
$parsedAttributes, //parsed
$parsedRelationships //parsed
$relationships, //parsed
$source
);
}

return new ResourceQueueItem(
$parsedAttributes,
$parsedRelationships
$relationships
);
}
}

85 changes: 52 additions & 33 deletions src/Controller/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

use Phramework\Exceptions\ForbiddenException;
use Phramework\Exceptions\IncorrectParameterException;
use Phramework\Exceptions\MissingParametersException;
use Phramework\Exceptions\RequestException;
use Phramework\Exceptions\ServerException;
use Phramework\Exceptions\Source\Pointer;
Expand All @@ -41,21 +42,29 @@
*/
trait Post
{
use RequestBodyQueue;

//prototype
/**
* Handle HTTP POST request method to create new resources
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @param ResourceModel $model
* @param array $validationCallbacks
* @param callable|null $viewCallback
* @param array $validationCallbacks function of
* - \stdClass $resource
* - \stdClass $parsedAttributes
* - \stdClass $parsedRelationships
* - ISource $source
* returning void
* @param callable|null $viewCallback function of
* - ServerRequestInterface $request,
* - ResponseInterface $response,
* - string[] $ids
* - returning ResponseInterface
* @param int|null $bulkLimit
* @param array $directives
* @return ResponseInterface
* @throws ForbiddenException
* @throws RequestException
* @throws MissingParametersException
* @throws ServerException
*/
public static function handlePost(
ServerRequestInterface $request,
Expand All @@ -67,10 +76,12 @@ public static function handlePost(
array $directives = []
) : ResponseInterface {
//todo figure out a permanent solution to have body as object instead of array, for every framework
$body = json_decode(json_encode($request->getParsedBody()));
$body = json_decode(json_encode($request->getParsedBody())) ?? new \stdClass();

Controller::requireProperties($body, new Pointer('/'), 'data');

//Access request body primary data
$data = $body->data ?? [new \stdClass()];
$data = $body->data;

/**
* @var bool
Expand All @@ -88,7 +99,7 @@ public static function handlePost(
//check bulk limit
if ($bulkLimit !== null && count($data) > $bulkLimit) {
throw new RequestException(sprintf(
'Number of batch requests is exceeding the maximum of %s',
'Number of bulk requests is exceeding the maximum of %s',
$bulkLimit
));
}
Expand Down Expand Up @@ -128,9 +139,10 @@ public static function handlePost(

//Throw exception if resource id is forced
if (property_exists($resource, 'id')) {
//todo include source
throw new ForbiddenException(
'Unsupported request to create a resource with a client-generated ID'
throw new IncorrectParameterException(
'additionalProperties',
'Unsupported request to create a resource with a client-generated id',
new Pointer($source->getPath())
);
}

Expand All @@ -140,18 +152,13 @@ public static function handlePost(
* Will call $validationModel relationship validator on relationships
* Will copy TO_ONE relationship data to parsed attributes
*/
$item = static::handleResource(
$item = RequestBodyQueue::handleResource(
$resource,
$source,
$model,
$validationModel,
$validationCallbacks
);

/*//todo use helper class
$queueItem = (object) [
'attributes' => $requestAttributes,
'relationships' => $requestRelationships
];*/

$requestQueue->push($item);

Expand Down Expand Up @@ -203,17 +210,17 @@ public static function handlePost(
$rKey
));
}
}

/*
* Call post relationship callback to post each of relationships pairs
*/
foreach ($rValue as $v) {
call_user_func(
$r->getCallbacks()->{'PATCH'},
$id, //Inserted resource id
$v
);
/*
* Call post relationship callback to post each of relationships pairs
*/
foreach ($rValue as $v) {
call_user_func(
$r->getCallbacks()->{'PATCH'},
$id, //Inserted resource id
$v
);
}
}
}

Expand All @@ -233,13 +240,25 @@ public static function handlePost(
);
}

/*if (count($ids) === 1) {
//Prepare response with 201 Created status code
return Response::created(
return Post::defaultPostViewCallback(
$request,
$response,
$ids
);
}

public static function defaultPostViewCallback(
ServerRequestInterface $request,
ResponseInterface $response,
array $ids
) : ResponseInterface {
if (count($ids) === 1) {
//Prepare Location header
$response = Response::created(
$response,
'link' . $ids[0] // location
'link/' . $ids[0] // location //todo
);
}*/ //see https://stackoverflow.com/questions/11309444/can-the-location-header-be-used-for-multiple-resource-locations-in-a-201-created
} //see https://stackoverflow.com/questions/11309444/can-the-location-header-be-used-for-multiple-resource-locations-in-a-201-created

//Return 204 No Content
return Response::noContent($response);
Expand Down
2 changes: 1 addition & 1 deletion src/Directive/FilterAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public static function parse($filterKey, $filterValue)
}

//@todo is this required?
$singleFilterValue = urldecode($singleFilterValue);
$singleFilterValue = urldecode((string) $singleFilterValue);

list($operator, $operand) = Operator::parse($singleFilterValue);

Expand Down
2 changes: 1 addition & 1 deletion tests/APP/DataSource/MemoryDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public function post(

if (!property_exists($attributes, $idAttribute)) {
//generate an id
$attributes->{$idAttribute} = md5(mt_rand());
$attributes->{$idAttribute} = md5((string) mt_rand());
}

$table = $this->resourceModel->getVariable('table');
Expand Down
Loading

0 comments on commit bfc3862

Please sign in to comment.