-
-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
387 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
/** | ||
* This file is part of the Nextras\Orm library. | ||
* @license MIT | ||
* @link https://github.com/nextras/orm | ||
*/ | ||
|
||
namespace Nextras\Orm\Entity\Embeddable; | ||
|
||
use Nextras\Orm\Entity\ImmutableDataTrait; | ||
use Nextras\Orm\Entity\Reflection\PropertyMetadata; | ||
use Nextras\Orm\InvalidArgumentException; | ||
use Nextras\Orm\NotSupportedException; | ||
|
||
|
||
class Embeddable implements IEmbeddable | ||
{ | ||
use ImmutableDataTrait; | ||
|
||
|
||
public function __construct(array $data) | ||
{ | ||
$this->metadata = $this->createMetadata(); | ||
if (count($data) !== count($this->metadata->getProperties())) { | ||
$n = count($data); | ||
$total = count($this->metadata->getProperties()); | ||
throw new InvalidArgumentException("Only $n of $total was set. Construct embeddable with all its properties. "); | ||
} | ||
$this->setImmutableData($data); | ||
} | ||
|
||
|
||
public function onLoad(array $data) | ||
{ | ||
$this->metadata = $this->createMetadata(); | ||
$this->data = $data; | ||
foreach ($this->metadata->getProperties() as $name => $metadataProperty) { | ||
if (!isset($data[$name])) { | ||
$this->data[$name] = null; | ||
} | ||
} | ||
} | ||
|
||
|
||
public function __get($name) | ||
{ | ||
return $this->getValue($name); | ||
} | ||
|
||
|
||
public function __isset($name) | ||
{ | ||
if (!$this->metadata->hasProperty($name)) { | ||
return false; | ||
} | ||
return $this->hasValue($name); | ||
} | ||
|
||
|
||
public function __set($name, $value) | ||
{ | ||
throw new NotSupportedException(); | ||
} | ||
|
||
|
||
public function __unset($name) | ||
{ | ||
throw new NotSupportedException(); | ||
} | ||
|
||
|
||
private function initProperty(PropertyMetadata $metadata, string $name) | ||
{ | ||
$this->validated[$name] = true; | ||
|
||
if (!isset($this->data[$name])) { | ||
$this->data[$name] = null; | ||
} | ||
|
||
if ($metadata->container) { | ||
$property = $this->createPropertyContainer($metadata); | ||
$property->loadValue($this->data); | ||
$this->data[$name] = $property; | ||
|
||
} elseif ($this->data[$name] !== null) { | ||
// data type coercion | ||
$this->validate($metadata, $name, $this->data[$name]); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
/** | ||
* This file is part of the Nextras\Orm library. | ||
* @license MIT | ||
* @link https://github.com/nextras/orm | ||
*/ | ||
|
||
namespace Nextras\Orm\Entity\Embeddable; | ||
|
||
use Nextras\Orm\Entity\IEntity; | ||
use Nextras\Orm\Entity\IProperty; | ||
use Nextras\Orm\Entity\IPropertyContainer; | ||
use Nextras\Orm\Entity\Reflection\PropertyMetadata; | ||
use Nextras\Orm\InvalidArgumentException; | ||
use Nextras\Orm\InvalidStateException; | ||
use Nextras\Orm\Model\MetadataStorage; | ||
use ReflectionClass; | ||
|
||
|
||
class EmbeddableContainer implements IPropertyContainer | ||
{ | ||
/** @var IEntity */ | ||
private $entity; | ||
|
||
/** @var PropertyMetadata */ | ||
private $metadata; | ||
|
||
/** @var PropertyMetadata[] */ | ||
private $properties = []; | ||
|
||
/** @var IEmbeddable|null */ | ||
private $value; | ||
|
||
/** @var string */ | ||
private $instanceType; | ||
|
||
|
||
public function __construct(IEntity $entity, PropertyMetadata $propertyMetadata) | ||
{ | ||
$this->entity = $entity; | ||
$this->metadata = $propertyMetadata; | ||
if (!isset($this->metadata->args[EmbeddableContainer::class])) { | ||
throw new InvalidStateException(); | ||
} | ||
|
||
$this->instanceType = $this->metadata->args[EmbeddableContainer::class]['class']; | ||
$this->properties = MetadataStorage::get($this->instanceType)->getProperties(); | ||
} | ||
|
||
|
||
public function loadValue(array $values) | ||
{ | ||
$data = []; | ||
$prefix = $this->metadata->name . '_'; | ||
foreach ($this->properties as $property) { | ||
$data[$property->name] = $values[$prefix . $property->name] ?? null; | ||
} | ||
|
||
$this->setRawValue($data); | ||
} | ||
|
||
|
||
public function saveValue(array $values): array | ||
{ | ||
return $this->getRawValue() + $values; | ||
} | ||
|
||
|
||
public function setRawValue($value) | ||
{ | ||
$filtered = array_filter($value, function ($val) { return $val !== null; }); | ||
if ($filtered) { | ||
$reflection = new ReflectionClass($this->instanceType); | ||
$embeddable = $reflection->newInstanceWithoutConstructor(); | ||
assert($embeddable instanceof IEmbeddable); | ||
$embeddable->onLoad($value); | ||
} else { | ||
$embeddable = null; | ||
} | ||
|
||
$this->setInjectedValue($embeddable); | ||
} | ||
|
||
|
||
public function getRawValue() | ||
{ | ||
$value = []; | ||
$prefix = $this->metadata->name . '_'; | ||
foreach ($this->properties as $property) { | ||
$name = $prefix . $property->name; | ||
$value[$name] = $this->value ? $this->value->getValue($property->name) : null; | ||
} | ||
return $value; | ||
} | ||
|
||
|
||
public function &getInjectedValue() | ||
{ | ||
return $this->value; | ||
} | ||
|
||
|
||
public function hasInjectedValue(): bool | ||
{ | ||
return $this->value !== null; | ||
} | ||
|
||
|
||
public function setInjectedValue($value) | ||
{ | ||
if ($value !== null && !$value instanceof $this->instanceType) { | ||
throw new InvalidArgumentException("Passed embeddable has to be instance of {$this->instanceType}."); | ||
} | ||
|
||
$this->value = $value; | ||
$this->entity->setAsModified($this->metadata->name); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
/** | ||
* This file is part of the Nextras\Orm library. | ||
* @license MIT | ||
* @link https://github.com/nextras/orm | ||
*/ | ||
|
||
namespace Nextras\Orm\Entity\Embeddable; | ||
|
||
|
||
interface IEmbeddable | ||
{ | ||
/** | ||
* Returns value. | ||
* @return mixed | ||
*/ | ||
public function &getValue(string $name); | ||
|
||
|
||
/** | ||
* Returns true if property has a value (not null). | ||
*/ | ||
public function hasValue(string $name): bool; | ||
|
||
|
||
/** | ||
* Load event. | ||
* @return void | ||
*/ | ||
public function onLoad(array $data); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.