public function getDatabaseIdentifierValue($id) { $idType = $this->fieldMappings[$this->identifier]['type']; return Types\Type::getType($idType)->convertToDatabaseValue($id); }
/** {@inheritdoc} */ public function exchangeArray(array $data, IBaseObjectItem $instance = null) { if (empty($data)) { return $this; } $properties = (new \ReflectionClass($this))->getProperties(); foreach ($properties as $property) { // do some checks if ($property->isStatic() || false !== stripos($docComment = $property->getDocComment(), CHAOS_ANNOTATION_IGNORE)) { unset($data[$property->name]); continue; } if (!$property->isPublic()) { $property->setAccessible(true); } // check if given name not exist in data if (!array_key_exists($property->name, $data)) { $data[$property->name] = $property->getValue($this); // continue; } // do we have any defined TYPE(s)? $types = $this->getTypes($property); $isCollection = isset($types[1]); $value = $data[$property->name]; // switch... if ($types['is_scalar']) { // type juggling if (false === stripos($docComment, CHAOS_ANNOTATION_IGNORE_TYPE_JUGGLING)) { $value = Types\Type::getType(strtolower($types[0]))->convertToPHPValue($value); } // do we have any defined filters & validators? if (false === stripos($docComment, CHAOS_ANNOTATION_IGNORE_RULES)) { $this->addRules($property); } } elseif (isset($instance) && $types[0] === @get_class($instance)) { // check for circular object references if ($isCollection) { $value = $this->addToCollection($instance, $types[1]); } else { $value =& $instance; } } elseif (class_exists($types[0]) && is_array($value)) { if (is_subclass_of($types[0], __NAMESPACE__ . '\\IBaseObjectItem')) { $obj = $isCollection ? $types[1] : null; if (!empty($value) && false === stripos($docComment, CHAOS_ANNOTATION_IGNORE_DATA)) { if ($isCollection) { /** @var IBaseObjectItem $cls */ $method = method_exists($obj, 'add') ? 'add' : 'append'; // guess supported method $firstKey = key($value); $isMulti = is_array($value[$firstKey]) || is_object($value[$firstKey]); if (!$isMulti) { $value = [$value]; } if (0 === iterator_count($obj)) { foreach ($value as $v) { $cls = new $types[0](); is_object($v) ? $v instanceof $cls ? $cls = $v : $cls->exchangeObject($v) : $cls->exchangeArray($v, $this); $this->addToCollection($cls, $obj, $method); } } else { $identifier = array_flip($this->getIdentifier()); $tmp = []; foreach ($obj as $k => $v) { if (is_object($v)) { $v = get_object_vars($v); } if ($v = array_intersect_key($v, $identifier)) { $tmp[$k] = $v; } } foreach ($value as $v) { if (is_object($v)) { $v = get_object_vars($v); } if (($v = array_intersect_key($v, $identifier)) && false !== ($k = array_search($v, $tmp))) { if ($obj[$k] instanceof IBaseObjectItem) { $obj[$k]->exchangeArray($v, $this); } else { foreach ($obj[$k] as $key => $val) { if (array_key_exists($key, $v)) { $obj[$k]->{$key} = $v[$key]; } } } } else { $cls = new $types[0](); $cls->exchangeArray($v, $this); $this->addToCollection($cls, $obj, $method); } } } } else { /** @var IBaseObjectItem $obj */ $obj = new $types[0](); $obj->exchangeArray($value, $this); } } $value = $obj; } else { try { // unknown object, we use a kind of default instance $obj = new $types[0]($value); if ($isCollection) { $obj = $this->addToCollection($obj, $types[1]); } $value = $obj; } catch (\Exception $ex) { } } } // set our new value (if any) $property->setValue($this, $value); unset($data[$property->name]); // for next loop } return $this; }
/** * Get property type(s) * * @param \ReflectionProperty $property * @return array */ private function getTypes(\ReflectionProperty $property) { $getter = 'get' . $property->name . 'DataType'; // check if getXyzDataType() method exists if (method_exists($this, $getter)) { $types = @call_user_func([$this, $getter]); if (!is_array($types)) { $types = [$types]; } } else { $docComment = $property->getDocComment(); if (false !== stripos($docComment, '@var')) { // e.g. @var int // return ['int'] // e.g. @var \Doctrine\Common\Collections\ArrayCollection(Channel) // return ['Doctrine\Common\Collections\ArrayCollection', 'Channel']; preg_match(CHAOS_MATCH_VAR, $docComment, $types); } elseif (false !== stripos($docComment, 'orm\\') || false !== stripos($docComment, 'customcolumn')) { // e.g. @Doctrine\ORM\Mapping\Column(type="integer") // return ['integer'] if (0 === preg_match(CHAOS_MATCH_COLUMN_TYPE, $docComment, $types)) { // e.g. @Doctrine\ORM\Mapping\Column(columnDefinition="tinyint(4) DEFAULT NULL") // return ['tinyint'] if (0 === preg_match(CHAOS_MATCH_COLUMN_DEFINITION, $docComment, $types)) { // e.g. @Doctrine\ORM\Mapping\OneToMany(targetEntity="Channel") // return ['Doctrine\Common\Collections\ArrayCollection', 'Channel']; preg_match(CHAOS_MATCH_ONE_MANY, $docComment, $types); if (isset($types[1]) && isset($types[2])) { if ('OneToMany' === $types[1] || 'ManyToMany' === $types[1]) { $types[1] = DOCTRINE_ARRAY_COLLECTION; } } } } } if (!empty($types)) { array_shift($types); } } if (empty($types)) { return [gettype($property->getValue($this)), 'is_scalar' => true]; } // parse the found "types[1]" if any $scalars = Types\Type::getTypesMap(); if (isset($types[1])) { // e.g. ['Channel', 'Doctrine\Common\Collections\ArrayCollection']; $types = array_reverse($types); $value = $property->getValue($this); // check if this property has been instanced if (isset($value)) { $types[1] = $value; } elseif (!isset($scalars[strtolower($types[1])])) { if (false === strpos($types[1], '\\')) { $types[1] = $property->getDeclaringClass()->getNamespaceName() . '\\' . $types[1]; } if (is_subclass_of($types[1], __NAMESPACE__ . '\\IBaseObjectCollection')) { $types[1] = new $types[1](); } elseif (class_exists($types[1], false)) { // unknown object, we use a kind of default instance $types[1] = (new \ReflectionClass($types[1]))->newInstanceWithoutConstructor(); } } // currently we only support type \Traversable if (!$types[1] instanceof \Traversable) { unset($types[1]); } } // define default namespace for the primary type if any $types['is_scalar'] = isset($scalars[strtolower($types[0])]); if (!$types['is_scalar'] && false === strpos($types[0], '\\')) { $types[0] = $property->getDeclaringClass()->getNamespaceName() . '\\' . $types[0]; } // bye! return $types; }