Skip to content
Merged
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
3 changes: 2 additions & 1 deletion src/helpers/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class Validator {
const OBJECT_CONTAINER_TYPE = 'type';
const OBJECT_CONTAINER_ID = 'id';
const OBJECT_CONTAINER_LID = 'lid';
const OBJECT_CONTAINER_ATTRIBUTES = 'attributes';
const OBJECT_CONTAINER_RELATIONSHIPS = 'relationships';

Expand Down Expand Up @@ -84,7 +85,7 @@ public function clearUsedFields($objectContainerToClear) {
*/
public function claimUsedResourceIdentifier(ResourceInterface $resource) {
if ($resource->getResource()->hasIdentification() === false) {
throw new InputException('can not validate resource without identifier, set type and id first');
throw new InputException('can not validate resource without identifier, set type and id/lid first');
}

$resourceKey = $resource->getResource()->getIdentificationKey();
Expand Down
50 changes: 46 additions & 4 deletions src/objects/ResourceIdentifierObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace alsvanzelf\jsonapi\objects;

use alsvanzelf\jsonapi\exceptions\Exception;
use alsvanzelf\jsonapi\exceptions\DuplicateException;
use alsvanzelf\jsonapi\helpers\AtMemberManager;
use alsvanzelf\jsonapi\helpers\Validator;
use alsvanzelf\jsonapi\interfaces\ObjectInterface;
Expand All @@ -16,6 +17,8 @@ class ResourceIdentifierObject implements ObjectInterface, ResourceInterface {
protected $type;
/** @var string */
protected $id;
/** @var string */
protected $lid;
/** @var MetaObject */
protected $meta;
/** @var Validator */
Expand All @@ -42,6 +45,7 @@ public function __construct($type=null, $id=null) {
// always mark as used, as these keys are reserved
$this->validator->claimUsedFields($fieldNames=['type'], Validator::OBJECT_CONTAINER_TYPE);
$this->validator->claimUsedFields($fieldNames=['id'], Validator::OBJECT_CONTAINER_ID);
$this->validator->claimUsedFields($fieldNames=['lid'], Validator::OBJECT_CONTAINER_LID);
}

/**
Expand Down Expand Up @@ -73,11 +77,34 @@ public function setType($type) {

/**
* @param string|int $id will be casted to a string
*
* @throws DuplicateException if localId is already set
*/
public function setId($id) {
if ($this->lid !== null) {
throw new DuplicateException('id is not allowed when localId is already set');
}

$this->id = (string) $id;
}

/**
* set a local id to connect resources to each other when created on the client
*
* @note this should not be used to send back from the server to the client
*
* @param string|int $localId will be casted to a string
*
* @throws DuplicateException if normal id is already set
*/
public function setLocalId($localId) {
if ($this->id !== null) {
throw new DuplicateException('localId is not allowed when id is already set');
}

$this->lid = (string) $localId;
}

/**
* @param MetaObject $metaObject
*/
Expand All @@ -96,7 +123,7 @@ public function setMetaObject(MetaObject $metaObject) {
* @return ResourceIdentifierObject
*/
public static function fromResourceObject(ResourceObject $resourceObject) {
$resourceIdentifierObject = new self($resourceObject->type, $resourceObject->id);
$resourceIdentifierObject = new self($resourceObject->type, $resourceObject->primaryId());

if ($resourceObject->meta !== null) {
$resourceIdentifierObject->setMetaObject($resourceObject->meta);
Expand Down Expand Up @@ -127,7 +154,7 @@ public function equals(ResourceInterface $resource) {
* @return boolean
*/
public function hasIdentification() {
return ($this->type !== null && $this->id !== null);
return ($this->type !== null && $this->primaryId() !== null);
}

/**
Expand All @@ -144,7 +171,7 @@ public function getIdentificationKey() {
throw new Exception('resource has no identification yet');
}

return $this->type.'|'.$this->id;
return $this->type.'|'.$this->primaryId();
}

/**
Expand All @@ -155,7 +182,7 @@ public function getIdentificationKey() {
* @inheritDoc
*/
public function isEmpty() {
if ($this->type !== null || $this->id !== null) {
if ($this->type !== null || $this->primaryId() !== null) {
return false;
}
if ($this->meta !== null && $this->meta->isEmpty() === false) {
Expand All @@ -179,6 +206,9 @@ public function toArray() {
if ($this->id !== null) {
$array['id'] = $this->id;
}
elseif ($this->lid !== null) {
$array['lid'] = $this->lid;
}

if ($this->meta !== null && $this->meta->isEmpty() === false) {
$array['meta'] = $this->meta->toArray();
Expand All @@ -197,4 +227,16 @@ public function toArray() {
public function getResource($identifierOnly=false) {
return $this;
}

/**
* @internal
*/

private function primaryId() {
if ($this->lid !== null) {
return $this->lid;
}

return $this->id;
}
}
76 changes: 76 additions & 0 deletions tests/objects/ResourceIdentifierObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,55 @@
namespace alsvanzelf\jsonapiTests\objects;

use alsvanzelf\jsonapi\exceptions\Exception;
use alsvanzelf\jsonapi\exceptions\DuplicateException;
use alsvanzelf\jsonapi\objects\ResourceIdentifierObject;
use PHPUnit\Framework\TestCase;

class ResourceIdentifierObjectTest extends TestCase {
public function testSetId_HappyPath() {
$resourceIdentifierObject = new ResourceIdentifierObject();
$resourceIdentifierObject->setType('test');
$resourceIdentifierObject->setId('1');

$array = $resourceIdentifierObject->toArray();

$this->assertArrayHasKey('id', $array);
$this->assertArrayNotHasKey('lid', $array);
$this->assertSame('1', $array['id']);
}

public function testSetId_WithLocalIdAlreadySet() {
$resourceIdentifierObject = new ResourceIdentifierObject();
$resourceIdentifierObject->setType('test');
$resourceIdentifierObject->setLocalId('uuid-1');

$this->expectException(DuplicateException::class);

$resourceIdentifierObject->setId('1');
}

public function testSetLocalId_HappyPath() {
$resourceIdentifierObject = new ResourceIdentifierObject();
$resourceIdentifierObject->setType('test');
$resourceIdentifierObject->setLocalId('uuid-1');

$array = $resourceIdentifierObject->toArray();

$this->assertArrayHasKey('lid', $array);
$this->assertArrayNotHasKey('id', $array);
$this->assertSame('uuid-1', $array['lid']);
}

public function testSetLocalId_WithIdAlreadySet() {
$resourceIdentifierObject = new ResourceIdentifierObject();
$resourceIdentifierObject->setType('test');
$resourceIdentifierObject->setId('1');

$this->expectException(DuplicateException::class);

$resourceIdentifierObject->setLocalId('uuid-1');
}

public function testEquals_HappyPath() {
$one = new ResourceIdentifierObject('test', 1);
$two = new ResourceIdentifierObject('test', 2);
Expand All @@ -25,13 +70,27 @@ public function testEquals_WithoutIdentification() {
$one->equals($two);
}

public function testEquals_WithLocalId() {
$one = new ResourceIdentifierObject('test');
$two = new ResourceIdentifierObject('test');
$new = new ResourceIdentifierObject('test');

$one->setLocalId('uuid-1');
$two->setLocalId('uuid-2');
$new->setLocalId('uuid-1');

$this->assertFalse($one->equals($two));
$this->assertTrue($one->equals($new));
}

public function testGetIdentificationKey_HappyPath() {
$resourceIdentifierObject = new ResourceIdentifierObject('user', 42);

$array = $resourceIdentifierObject->toArray();

$this->assertArrayHasKey('type', $array);
$this->assertArrayHasKey('id', $array);
$this->assertArrayNotHasKey('lid', $array);
$this->assertSame('user', $array['type']);
$this->assertSame('42', $array['id']);
$this->assertTrue($resourceIdentifierObject->hasIdentification());
Expand Down Expand Up @@ -59,6 +118,23 @@ public function testGetIdentificationKey_SetAfterwards() {
$this->assertSame('user|42', $resourceIdentifierObject->getIdentificationKey());
}

public function testGetIdentificationKey_WithLocalId() {
$resourceIdentifierObject = new ResourceIdentifierObject();

$resourceIdentifierObject->setType('user');
$resourceIdentifierObject->setLocalId('uuid-42');

$array = $resourceIdentifierObject->toArray();

$this->assertArrayHasKey('type', $array);
$this->assertArrayHasKey('lid', $array);
$this->assertArrayNotHasKey('id', $array);
$this->assertSame('user', $array['type']);
$this->assertSame('uuid-42', $array['lid']);
$this->assertTrue($resourceIdentifierObject->hasIdentification());
$this->assertSame('user|uuid-42', $resourceIdentifierObject->getIdentificationKey());
}

public function testGetIdentificationKey_NoIdentification() {
$resourceIdentifierObject = new ResourceIdentifierObject();

Expand Down