Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
composer.phar
composer.lock
vendor
.idea
40 changes: 25 additions & 15 deletions src/Architect.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,28 @@

namespace Optimus\Architect;

use InvalidArgumentException;
use Illuminate\Support\Collection;
use InvalidArgumentException;

class Architect
{
private $modeResolvers = [];

/**
* Parse a collection using given modes.
* @param mixed $data The collection to be parsed
*
* @param mixed $data The collection to be parsed
* @param array $modes The modes to be used, format is ['relation' => 'mode']
* @param string $key A key to hoist the collection into the root array
* @param string $key A key to hoist the collection into the root array
*
* @return array
*/
public function parseData($data, array $modes, $key = null)
{
$return = [];

uksort($modes, function ($a, $b) {
return substr_count($b, '.')-substr_count($a, '.');
return substr_count($b, '.') - substr_count($a, '.');
});

if (Utility::isCollection($data)) {
Expand All @@ -35,7 +37,7 @@ public function parseData($data, array $modes, $key = null)
} else {
if (in_array('sideload', $modes)) {
throw new InvalidArgumentException('$key cannot be null when ' .
'resources are transformed using sideload.');
'resources are transformed using sideload.');
}

$return = $parsed;
Expand All @@ -46,10 +48,12 @@ public function parseData($data, array $modes, $key = null)

/**
* Parse a collection using given modes
*
* @param array $modes
* @param mixed $collection
* @param array $root
* @param mixed $collection
* @param array $root
* @param string $fullPropertyPath
*
* @return mixed
*/
private function parseCollection(array $modes, $collection, &$root, $fullPropertyPath = '')
Expand All @@ -58,7 +62,7 @@ private function parseCollection(array $modes, $collection, &$root, $fullPropert
foreach ($collection as $i => $resource) {
$collection[$i] = $this->parseResource($modes, $resource, $root, $fullPropertyPath);
}
} elseif ($collection instanceof Collection) {
} else if ($collection instanceof Collection) {
$collection = $collection->map(function ($resource) use ($modes, &$root, $fullPropertyPath) {
return $this->parseResource($modes, $resource, $root, $fullPropertyPath);
});
Expand All @@ -69,16 +73,18 @@ private function parseCollection(array $modes, $collection, &$root, $fullPropert

/**
* Parse a single resource using given modes
*
* @param array $modes
* @param mixed $resource
* @param array $root
* @param mixed $resource
* @param array $root
* @param string $fullPropertyPath
*
* @return mixed
*/
private function parseResource(array $modes, &$resource, &$root, $fullPropertyPath = '')
{
foreach ($modes as $relation => $mode) {
$modeResolver = $this->resolveMode($mode);
$this->resolveMode($mode);

$steps = explode('.', $relation);

Expand All @@ -102,12 +108,12 @@ private function parseResource(array $modes, &$resource, &$root, $fullPropertyPa
if (empty($steps)) {
// This is the deepest level. Resolve it.
$fullPropertyPath .= $relation;
$object = $this->modeResolvers[$mode]->resolve($relation, $object, $root, $fullPropertyPath);
$object = $this->modeResolvers[$mode]->resolve($relation, $object, $root, $fullPropertyPath);
} else {
// More levels exist in this relation.
// We want a drill down and resolve the deepest level first.

$path = implode('.', $steps);
$path = implode('.', $steps);
$modes = [
$path => $mode
];
Expand All @@ -133,8 +139,10 @@ private function parseResource(array $modes, &$resource, &$root, $fullPropertyPa

/**
* Resolve a mode resolver class if it has not been resolved before
*
* @param string $mode The mode to be resolved
* @return Optimus\Architect\ModeResolver\ModeResolverInterface
*
* @return \Optimus\Architect\ModeResolver\ModeResolverInterface
*/
private function resolveMode($mode)
{
Expand All @@ -147,8 +155,10 @@ private function resolveMode($mode)

/**
* Instantiate a mode resolver class
*
* @param string $mode [description]
* @return Optimus\Architect\ModeResolver\ModeResolverInterface
*
* @return \Optimus\Architect\ModeResolver\ModeResolverInterface
*/
private function createModeResolver($mode)
{
Expand Down
8 changes: 4 additions & 4 deletions src/ModeResolver/EmbedModeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

namespace Optimus\Architect\ModeResolver;

use Optimus\Architect\ModeResolver\ModeResolverInterface;

class EmbedModeResolver implements ModeResolverInterface
{
/**
* Simply returns the object since embedded is the default
* transformation
*
* @param string $property
* @param object $object
* @param array $root
* @param array $root
* @param string $fullPropertyPath
* @return object
*
* @return object
*/
public function resolve($property, &$object, &$root, $fullPropertyPath)
{
Expand Down
21 changes: 11 additions & 10 deletions src/ModeResolver/IdsModeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,46 @@

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Optimus\Architect\ModeResolver\ModeResolverInterface;
use Optimus\Architect\Utility;

class IdsModeResolver implements ModeResolverInterface
{
/**
* Map through the collection and convert it to a collection
* of ids
*
* @param string $property
* @param object $object
* @param array $root
* @param array $root
* @param string $fullPropertyPath
*
* @return mixed
*/
public function resolve($property, &$object, &$root, $fullPropertyPath)
{
if (is_array($object)) {
// We need to determine if this is a singular relationship or
// a collection of models
$arrayCopy = $object;
$arrayCopy = $object;
$firstElement = array_shift($arrayCopy);

// The object was not a collection, and was rather a single
// model, because the first item returned was a property
// We therefore just return the single ID
if (Utility::isPrimitive($firstElement)) {
return (int) Utility::getProperty($object, 'id');
return (int)Utility::getProperty($object, 'id');
}

return array_map(function ($entry) {
return (int) Utility::getProperty($entry, 'id');
return (int)Utility::getProperty($entry, 'id');
}, $object);
} elseif ($object instanceof Collection) {
} else if ($object instanceof Collection) {
return $object->map(function ($entry) {
return (int) Utility::getProperty($entry, 'id');
return (int)Utility::getProperty($entry, 'id');
});
// The relation is not a collection, but rather
// a singular relation
} elseif ($object instanceof Model) {
// The relation is not a collection, but rather
// a singular relation
} else if ($object instanceof Model) {
return $object->id;
}
}
Expand Down
39 changes: 22 additions & 17 deletions src/ModeResolver/SideloadModeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Support\Collection;
use Optimus\Architect\ModeResolver\IdsModeResolver;
use Optimus\Architect\ModeResolver\ModeResolverInterface;
use Optimus\Architect\Utility;

class SideloadModeResolver implements ModeResolverInterface
Expand All @@ -20,10 +18,12 @@ public function __construct()
/**
* Move all relational resources to the root element and
* use idsResolver to replace them with a collection of identifiers
* @param string $property The property to resolve
* @param object $object The object which has the property
* @param array $root The root array which will contain the object
*
* @param string $property The property to resolve
* @param object $object The object which has the property
* @param array $root The root array which will contain the object
* @param string $fullPropertyPath The full dotnotation path to this property
*
* @return mixed
*/
public function resolve($property, &$object, &$root, $fullPropertyPath)
Expand All @@ -35,9 +35,11 @@ public function resolve($property, &$object, &$root, $fullPropertyPath)

/**
* Add the collection to the root array
* @param array $root
*
* @param array $root
* @param object $object
* @param string $fullPropertyPath
*
* @return void
*/
private function addCollectionToRoot(&$root, &$object, $fullPropertyPath)
Expand All @@ -46,26 +48,26 @@ private function addCollectionToRoot(&$root, &$object, $fullPropertyPath)
// collection of resources
$isResource = false;
if (is_array($object)) {
$copy = $object;
$values = array_values($copy);
$copy = $object;
$values = array_values($copy);
$firstPropertyOrResource = array_shift($values);

if (Utility::isPrimitive($firstPropertyOrResource)) {
$isResource = true;
}
} elseif ($object instanceof EloquentModel) {
} else if ($object instanceof EloquentModel) {
$isResource = true;
}

$newCollection = $isResource ? [$object] : $object;

// Does existing collections use arrays or Collections
$copy = $root;
$values = array_values($copy);
$copy = $root;
$values = array_values($copy);
$existingRootCollection = array_shift($values);

$newCollection = $existingRootCollection instanceof Collection ?
new Collection($newCollection) : $newCollection;
new Collection($newCollection) : $newCollection;

if (!array_key_exists($fullPropertyPath, $root)) {
$root[$fullPropertyPath] = $newCollection;
Expand All @@ -77,8 +79,10 @@ private function addCollectionToRoot(&$root, &$object, $fullPropertyPath)
/**
* If a collection for this resource has already begun (i.e. multiple
* resources share this type of resource), then merge with the existing collection
* @param mixed $collection
*
* @param mixed $collection
* @param object $object
*
* @return void
*/
private function mergeRootCollection(&$collection, $object)
Expand All @@ -87,7 +91,7 @@ private function mergeRootCollection(&$collection, $object)
foreach ($object as $resource) {
$this->addResourceToRootCollectionIfNonExistant($collection, $resource);
}
} elseif ($object instanceof Collection) {
} else if ($object instanceof Collection) {
$object->each(function ($resource) use (&$collection) {
$this->addResourceToRootCollectionIfNonExistant($collection, $resource);
});
Expand All @@ -97,18 +101,19 @@ private function mergeRootCollection(&$collection, $object)
/**
* Check if the resource already exists in the root collection by id
* TODO: https://github.com/esbenp/laravel-controller/issues/2
*
* @param mixed $collection
* @param mixed $resource
*/
private function addResourceToRootCollectionIfNonExistant(&$collection, $resource)
{
$identifier = Utility::getProperty($resource, 'id');
$exists = false;
$exists = false;

$copy = $collection instanceof Collection ? $collection->toArray() : $collection;

foreach ($copy as $rootResource) {
if ((int) Utility::getProperty($rootResource, 'id') === (int) $identifier) {
if ((int)Utility::getProperty($rootResource, 'id') === (int)$identifier) {
$exists = true;
break;
}
Expand All @@ -117,7 +122,7 @@ private function addResourceToRootCollectionIfNonExistant(&$collection, $resourc
if ($exists === false) {
if (is_array($collection)) {
$collection[] = $resource;
} elseif ($collection instanceof Collection) {
} else if ($collection instanceof Collection) {
$collection->push($resource);
}
}
Expand Down
23 changes: 15 additions & 8 deletions src/Utility.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ class Utility
{
/**
* Get a property of an array or object
* @param mixed $objectOrArray object or array
*
* @param mixed $objectOrArray object or array
* @param string $property
*
* @return mixed
*/
public static function getProperty($objectOrArray, $property)
Expand All @@ -24,7 +26,8 @@ public static function getProperty($objectOrArray, $property)

/**
* Set a property of an Eloquent model, normal object or array
* @param mixed $objectOrArray model, object or array
*
* @param mixed $objectOrArray model, object or array
* @param string $property
* @param void
*/
Expand All @@ -41,15 +44,15 @@ public static function setProperty(&$objectOrArray, $property, $value)
if ($objectOrArray->relationLoaded($property) && !Utility::isPrimitive($value)) {
$objectOrArray->setRelation($property, $value);

// If attribute is not a relation we just set it on
// the model directly. If it is a primitive relation (a relation
// converted to IDs) we unset the relation and set it as an attribute
// If attribute is not a relation we just set it on
// the model directly. If it is a primitive relation (a relation
// converted to IDs) we unset the relation and set it as an attribute
} else {
unset($objectOrArray[$property]);
$objectOrArray->setAttribute($property, $value);
}
}
} elseif (is_array($objectOrArray)) {
} else if (is_array($objectOrArray)) {
$objectOrArray[$property] = $value;
} else {
$objectOrArray->{$property} = $value;
Expand All @@ -58,7 +61,9 @@ public static function setProperty(&$objectOrArray, $property, $value)

/**
* Is the variable a primitive type
* @param mixed $input
*
* @param mixed $input
*
* @return boolean
*/
public static function isPrimitive($input)
Expand All @@ -68,7 +73,9 @@ public static function isPrimitive($input)

/**
* Is the input a collection of resources?
* @param mixed $input
*
* @param mixed $input
*
* @return boolean
*/
public static function isCollection($input)
Expand Down