1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169:
<?php
namespace Coast\Model;
use Exception;
use Coast;
use Coast\Filter;
use Coast\Validator;
use Coast\Transformer;
use JsonSerializable;
class Metadata implements JsonSerializable
{
protected $_className;
protected $_properties = [];
protected $_extras = [];
public function __construct($className)
{
$this->_className = $className;
}
public function className()
{
return $this->_className;
}
public function property($name, array $value = null)
{
if (!property_exists($this->_className, $name)) {
return null;
}
if (func_num_args() > 1) {
if (!isset($this->_properties[$name])) {
$this->_properties[$name] = [
'name' => $name,
'type' => null,
'filter' => new Filter(),
'transformer' => new Transformer(),
'validator' => new Validator(),
'construct' => null,
'isTraverse' => false,
'isConstruct' => false,
'isImmutable' => false,
];
}
$current = $this->_properties[$name];
if (isset($value['filter']) && is_array($value['filter'])) {
call_user_func_array([$current['filter'], 'steps'], $value['filter']);
unset($value['filter']);
}
if (isset($value['transformer']) && is_array($value['transformer'])) {
call_user_func_array([$current['transformer'], 'steps'], $value['transformer']);
unset($value['transformer']);
}
if (isset($value['validator']) && is_array($value['validator'])) {
call_user_func_array([$current['validator'], 'steps'], $value['validator']);
unset($value['validator']);
}
$this->_properties[$name] = $value + $current;
return $this;
}
return $this->_properties[$name];
}
public function properties(array $properties = null)
{
if (func_num_args() > 0) {
if (Coast\is_array_assoc($properties)) {
foreach ($properties as $name => $value) {
$this->property($name, $value);
}
return $this;
} else {
return array_intersect_key($this->_properties, array_flip($properties));
}
}
return $this->_properties;
}
public function __clone()
{
foreach ($this->_properties as $name => $value) {
if (isset($value['filter'])) {
$value['filter'] = clone $value['filter'];
}
if (isset($value['transformer'])) {
$value['transformer'] = clone $value['transformer'];
}
if (isset($value['validator'])) {
$value['validator'] = clone $value['validator'];
}
$this->_properties[$name] = $value;
}
}
public function extra($name, $value = null)
{
if (func_num_args() > 1) {
if (isset($value)) {
$this->_extras[$name] = $value;
} else {
unset($this->_extras[$name]);
}
return $this;
}
return isset($this->_extras[$name])
? $this->_extras[$name]
: null;
}
public function extras(array $extras = null)
{
if (func_num_args() > 0) {
foreach ($extras as $name => $value) {
$this->extra($name, $value);
}
return $this;
}
return $this->_extras;
}
public function __set($name, $value)
{
return $this->extra($name, $value);
}
public function __get($name)
{
return $this->extra($name);
}
public function __isset($name)
{
return $this->extra($name) !== null;
}
public function __unset($name)
{
return $this->extra($name, null);
}
public function jsonSerialize()
{
$class = $this->_className;
$properties = $this->_properties;
foreach ($properties as $name => $property) {
if (in_array($property['type'], ['one', 'many']) && isset($property['construct'])) {
$construct = $property['construct'];
$properties[$name] += [
'metadata' => $construct::metadataStatic(),
];
}
}
$extras = $this->_extras;
return [
'className' => $class,
'properties' => $properties,
'extras' => $extras,
'defaults' => new $class(),
];
}
}