entityType)) { $classNames = explode('\\', get_class($this)); $this->entityType = end($classNames); } $this->entityManager = $entityManager; if (!empty($defs['fields'])) { $this->fields = $defs['fields']; } if (!empty($defs['relations'])) { $this->relations = $defs['relations']; } } public function clear($name = null) { if (is_null($name)) { $this->reset(); } unset($this->valuesContainer[$name]); } public function reset() { $this->valuesContainer = []; } protected function setValue($name, $value) { $this->valuesContainer[$name] = $value; } public function set($p1, $p2 = null) { if (is_array($p1) || is_object($p1)) { if (is_object($p1)) { $p1 = get_object_vars($p1); } if ($p2 === null) { $p2 = false; } $this->populateFromArray($p1, $p2); } else if (is_string($p1)) { $name = $p1; $value = $p2; if ($name == 'id') { $this->id = $value; } if ($this->hasAttribute($name)) { $method = '_set' . ucfirst($name); if (method_exists($this, $method)) { $this->$method($value); } else { $this->valuesContainer[$name] = $value; } } } } public function get($name, $params = []) { if ($name == 'id') { return $this->id; } $method = '_get' . ucfirst($name); if (method_exists($this, $method)) { return $this->$method(); } if ($this->hasAttribute($name) && isset($this->valuesContainer[$name])) { return $this->valuesContainer[$name]; } if ($this->hasRelation($name) && $this->id) { $value = $this->entityManager->getRepository($this->getEntityType())->findRelated($this, $name, $params); return $value; } return null; } public function has($name) { if ($name == 'id') { return !!$this->id; } $method = '_has' . ucfirst($name); if (method_exists($this, $method)) { return $this->$method(); } if (array_key_exists($name, $this->valuesContainer)) { return true; } return false; } public function populateFromArray(array $data, $onlyAccessible = true, $reset = false) { if ($reset) { $this->reset(); } foreach ($this->getAttributes() as $attribute => $defs) { if (array_key_exists($attribute, $data)) { if ($attribute == 'id') { $this->id = $data[$attribute]; continue; } if ($onlyAccessible) { if (isset($defs['notAccessible']) && $defs['notAccessible'] == true) { continue; } } $value = $data[$attribute]; if (!is_null($value)) { $valueType = $defs['type']; if ($valueType === self::FOREIGN) { $relation = $this->getAttributeParam($attribute, 'relation'); $foreign = $this->getAttributeParam($attribute, 'foreign'); if (is_string($foreign)) { $foreignEntityType = $this->getRelationParam($relation, 'entity'); if ($foreignEntityType) { $valueType = $this->entityManager->getMetadata()->get($foreignEntityType, ['fields', $foreign, 'type']); } } } switch ($valueType) { case self::VARCHAR: break; case self::BOOL: $value = ($value === 'true' || $value === '1' || $value === true); break; case self::INT: $value = intval($value); break; case self::FLOAT: $value = floatval($value); break; case self::JSON_ARRAY: $value = is_string($value) ? json_decode($value) : $value; if (!is_array($value)) { $value = null; } break; case self::JSON_OBJECT: $value = is_string($value) ? json_decode($value) : $value; if (!($value instanceof \stdClass) && !is_array($value)) { $value = null; } break; default: break; } } $method = '_set' . ucfirst($attribute); if (method_exists($this, $method)) { $this->$method($value); } else { $this->valuesContainer[$attribute] = $value; } } } } public function isNew() { return $this->isNew; } public function setIsNew($isNew) { $this->isNew = $isNew; } public function isSaved() { return $this->isSaved; } public function setIsSaved($isSaved) { $this->isSaved = $isSaved; } public function getEntityName() { return $this->getEntityType(); } public function getEntityType() { return $this->entityType; } public function hasField($fieldName) { return isset($this->fields[$fieldName]); } public function hasAttribute($name) { return isset($this->fields[$name]); } public function hasRelation($relationName) { return isset($this->relations[$relationName]); } public function getAttributeList() { return array_keys($this->getAttributes()); } public function getRelationList() { return array_keys($this->getRelations()); } public function getValues() { return $this->toArray(); } public function toArray() { $arr = []; if (isset($this->id)) { $arr['id'] = $this->id; } foreach ($this->fields as $field => $defs) { if ($field == 'id') { continue; } if ($this->has($field)) { $arr[$field] = $this->get($field); } } return $arr; } public function getValueMap() { $array = $this->toArray(); return (object) $array; } public function getFields() { return $this->fields; } public function getAttributes() { return $this->fields; } public function getRelations() { return $this->relations; } public function getAttributeType($attribute) { if (isset($this->fields[$attribute]) && isset($this->fields[$attribute]['type'])) { return $this->fields[$attribute]['type']; } return null; } public function getRelationType($relation) { if (isset($this->relations[$relation]) && isset($this->relations[$relation]['type'])) { return $this->relations[$relation]['type']; } return null; } public function getAttributeParam($attribute, $name) { if (isset($this->fields[$attribute]) && isset($this->fields[$attribute][$name])) { return $this->fields[$attribute][$name]; } return null; } public function getRelationParam($relation, $name) { if (isset($this->relations[$relation]) && isset($this->relations[$relation][$name])) { return $this->relations[$relation][$name]; } return null; } public function isFetched() { return $this->isFetched; } public function isFieldChanged($name) { return $this->has($name) && ($this->get($name) != $this->getFetched($name)); } public function isAttributeChanged($name) { if (!$this->has($name)) return false; if (!$this->hasFetched($name)) { return true; } return !self::areValuesEqual( $this->getAttributeType($name), $this->get($name), $this->getFetched($name), $this->getAttributeParam($name, 'isUnordered') ); } public static function areValuesEqual($type, $v1, $v2, $isUnordered = false) { if ($type === self::JSON_ARRAY) { if (is_array($v1) && is_array($v2)) { if ($isUnordered) { sort($v1); sort($v2); } if ($v1 != $v2) { return false; } foreach ($v1 as $i => $itemValue) { if (is_object($v1[$i]) && is_object($v2[$i])) { if (!self::areValuesEqual(self::JSON_OBJECT, $v1[$i], $v2[$i])) { return false; } continue; } if ($v1[$i] !== $v2[$i]) { return false; } } return true; } } else if ($type === self::JSON_OBJECT) { if (is_object($v1) && is_object($v2)) { if ($v1 != $v2) { return false; } $a1 = get_object_vars($v1); $a2 = get_object_vars($v2); foreach ($v1 as $key => $itemValue) { if (is_object($a1[$key]) && is_object($a2[$key])) { if (!self::areValuesEqual(self::JSON_OBJECT, $a1[$key], $a2[$key])) { return false; } continue; } if (is_array($a1[$key]) && is_array($a2[$key])) { if (!self::areValuesEqual(self::JSON_ARRAY, $a1[$key], $a2[$key])) { return false; } continue; } if ($a1[$key] !== $a2[$key]) { return false; } } return true; } } return $v1 === $v2; } public function setFetched($name, $value) { if ($value) { $type = $this->getAttributeType($name); if ($type === self::JSON_OBJECT) { $value = self::cloneObject($value); } else if ($type === self::JSON_ARRAY) { $value = self::cloneArray($value); } } $this->fetchedValuesContainer[$name] = $value; } public function getFetched($name) { if ($name === 'id') { return $this->id; } if (isset($this->fetchedValuesContainer[$name])) { return $this->fetchedValuesContainer[$name]; } return null; } public function hasFetched($name) { if ($name === 'id') { return !!$this->id; } return array_key_exists($name, $this->fetchedValuesContainer); } public function resetFetchedValues() { $this->fetchedValuesContainer = []; } public function updateFetchedValues() { $this->fetchedValuesContainer = $this->valuesContainer; foreach ($this->fetchedValuesContainer as $attribute => $value) { $this->setFetched($attribute, $value); } } public function setAsFetched() { $this->isFetched = true; $this->updateFetchedValues(); } public function setAsNotFetched() { $this->isFetched = false; $this->resetFetchedValues(); } public function isBeingSaved() { return $this->isBeingSaved; } public function setAsBeingSaved() { $this->isBeingSaved = true; } public function setAsNotBeingSaved() { $this->isBeingSaved = false; } public function populateDefaults() { foreach ($this->fields as $field => $defs) { if (array_key_exists('default', $defs)) { $this->valuesContainer[$field] = $defs['default']; } } } protected function getEntityManager() { return $this->entityManager; } protected function cloneArray($value) { if (is_array($value)) { $copy = []; foreach ($value as $v) { if (is_object($v)) { $v = clone $v; } $copy[] = $v; } return $copy; } return $value; } protected function cloneObject($value) { if (is_array($value)) { $copy = []; foreach ($value as $v) { $copy[] = self::cloneObject($v); } return $copy; } if (is_object($value)) { $copy = (object) []; foreach (get_object_vars($value) as $k => $v) { $key = $k; if (!is_string($key)) { $key = strval($key); } $copy->$key = self::cloneObject($v); } return $copy; } return $value; } }