Skip to content

Commit

Permalink
Implement fields
Browse files Browse the repository at this point in the history
Add handleFields to Model class
Update getIncluded data and getRelationshipData to use calls with fields

Update getIncluded to use getById with multiple ids
  • Loading branch information
nohponex committed Jan 31, 2016
1 parent 5f1eaba commit f8c4e06
Show file tree
Hide file tree
Showing 5 changed files with 393 additions and 80 deletions.
102 changes: 102 additions & 0 deletions src/Fields.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
*/
namespace Phramework\JSONAPI;

use Phramework\Exceptions\IncorrectParametersException;
use Phramework\Exceptions\RequestException;

/**
* Fields helper methods
* @since 1.0.0
Expand All @@ -24,5 +27,104 @@
*/
class Fields
{
/**
* @var object
*/
public $fields;

public function __construct($fields = null)
{
if ($fields !== null) {
$this->fields = new \stdClass();
} else {
$this->fields = $fields;
}
}

/**
* @param string $resourceType
* @return string[]
*/
public function get($resourceType)
{
if (!isset($this->fields->{$resourceType})) {
return [];
}

return $this->fields->{$resourceType};
}

/**
* @param string $resourceType
* @param string|string[] $field
* @return $this
*/
public function add($resourceType, $field)
{
//Initialize if not set
if (!isset($this->fields->{$resourceType})) {
$this->fields->{$resourceType} = [];
}

if (!is_array($field)) {
$field = [$field];
}

$this->fields->{$resourceType} = array_unique(array_merge(
$this->fields->{$resourceType},
$field
));

return $this;
}

/**
* @param object $parameters
* @param string $modelClass
* @return Fields|null
* @throws RequestException
* @throws IncorrectParametersException
*/
public static function parseFromParameters($parameters, $modelClass)
{
if (!isset($parameters->fields)) {
return null;
}

$fields = new Fields();

foreach ($parameters->fields as $resourceType => $fieldsValue) {
//check if $resourceType allowed,
//TODO incomplete since we will support 2nd level relationship data inclusion
if ($modelClass::getType() == $resourceType
|| $modelClass::relationshipExists($resourceType)
) {
} else {
throw new RequestException(sprintf(
'Not allowed resource type "%s" for fields',
$resourceType
));
}

if (!is_string($fieldsValue)) {
throw new IncorrectParametersException(sprintf(
'Expecting string value for fields of resource type "%s"',
$resourceType
));
}

$parsedFields = array_map(
'trim',
explode(',', trim($fieldsValue))
);

//Validate parsedFields
//TODO

//Push parsed fields
$fields->add($parsedFields);
}

return $fields;
}
}
113 changes: 90 additions & 23 deletions src/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
*/
abstract class Model extends \Phramework\JSONAPI\Model\Relationship
{

/**
* Enable caching of resources
* @var bool
Expand All @@ -48,7 +47,7 @@ public static function getValidationModel()
(object) [],
[],
false //No additional properties
)
) //Attributes validator
);
}

Expand Down Expand Up @@ -330,6 +329,17 @@ public static function getSortable()
return [];
}

/**
* Get attribute keys that allowed to be used for sort
* **MAY** be overwritten
* @return string[]
* @since 1.0.0
*/
public static function getFields()
{
return [];
}

/**
* Get sort attributes and default
* **MAY** be overwritten
Expand Down Expand Up @@ -414,20 +424,16 @@ protected static function handlePagination($query, $page = null)
* This method will update `{{filter}}` string inside query parameter with
* the provided filter directives
* @param string $query Query
* @param Filter|null $filter This object has 3 attributes:
* primary, relationships and attributes
* - integer[] $primary
* - integer[] $relationships
* - array $attributes (each array item [$attribute, $operator, $operant])
* - array $attributesJSON (each array item [$attribute, $key, $operator, $operant])
* @param boolean $hasWhere If query already has an WHERE, default is true
* @param Filter|null $filter
* @param boolean $hasWhere *[Optional]* If query already has an WHERE, default is true
* @return string Query
* @throws \Phramework\Exceptions\NotImplementedException
* @throws \Exception
* @todo check if query work both in MySQL and postgre
*/
protected static function handleFilter(
$query,
$filter = null,
$filter,
$hasWhere = true
) {
$additionalFilter = [];
Expand Down Expand Up @@ -566,17 +572,74 @@ protected static function handleFilter(
return $query;
}

/**
* This method will update `{{fields}}` string inside query parameter with
* the provided fields directives
* @param string $query
* @param Fields $fields
* @return string
* @since 1.0.0
*/
protected static function handleFields(
$query,
Fields $fields
) {
$type = static::getType();

//Get field attributes for this type and force id attribute
$attributes = array_unique(array_merge(
$fields->get($type),
[static::$idAttribute]
));

$escape = function ($input){
if ($input === '*') {
return $input;
}
return sprintf('"%s"', $input);
};

/**
* This method will prepare the attributes by prefixing then with "
* - * ->
* - id -> "id"
* - table.id -> "table"."id"
* and glue them with comma separator
*/
$queryPart = implode(',',
array_map(
function ($attribute) use ($escape) {
return implode(
'.',
array_map($escape, explode('.', $attribute))
);
},
$attributes
)
);

$query = str_replace(
'{{fields}}',
$queryPart,
$query
);

return $query;
}

/**
* Apply handle pagination, sort and filter to query,
* will replace `{{sort}}`, `{{pagination}}` and `{{filter}}` strings in
* will replace `{{sort}}`, `{{pagination}}`, `{{filter}}` and `{{fields}}` strings in
* query.
* @uses Model::handlePagination
* @uses Model::handleSort
* @uses Model::handleFilter
* @uses static::handlePagination
* @uses static::handleSort
* @uses static::handleFilter
* @uses static::handleFields
* @param string $query Query
* @param Page|null $page See handlePagination $page parameter
* @param Filter|null $filter See handleFilter $filter parameter
* @param Sort|null $sort See handleSort $sort parameter
* @param Sort|null $sort See handleSort $sort parameter
* @param Fields|null $fields See handleFields $fields parameter
* @param boolean $hasWhere If query already has an WHERE, default is true
* @return string Query
*/
Expand All @@ -585,18 +648,22 @@ protected static function handleGet(
Page $page,
Filter $filter,
Sort $sort,
Fields $fields,
$hasWhere = true
) {
return trim(static::handlePagination(
static::handleSort(
static::handleFilter(
$query,
$filter,
$hasWhere
return trim(static::handleFields(
static::handlePagination(
static::handleSort(
static::handleFilter(
$query,
$filter,
$hasWhere
),
$sort
),
$sort
$page
),
$page
$fields
));
}
}
Loading

0 comments on commit f8c4e06

Please sign in to comment.