/** * @param PropertyMetadata $property * @return PropertyMetadata */ private function makeItemProperty(PropertyMetadata $property) { $itemProperty = new PropertyMetadata($property->getName()); $itemProperty->setExpose(true)->setSerializedName($property->getSerializedName()); if (preg_match('/array<(?<type>[a-zA-Z\\\\]+)>/', $property->getType(), $matches)) { $itemProperty->setType($matches['type']); } return $itemProperty; }
/** * @param $value * @param PropertyMetadata $property * @param $direct * @param null|mixed $object * @param bool $inner * @throws \Opensoft\SimpleSerializer\Exception\InvalidArgumentException * @return array|bool|float|int|string|null */ private function handleValue($value, $property, $direct, $object = null, $inner = false) { $type = $property->getType(); if ($value !== null) { if ($type === 'string') { $value = (string) $value; } elseif ($type === 'boolean') { $value = (bool) $value; } elseif ($type === 'integer') { $value = (int) $value; } elseif ($type === 'double') { $value = (double) $value; } elseif ($type === 'DateTime' || $type[0] === 'D' && strpos($type, 'DateTime<') === 0) { if ($direct == self::DIRECTION_SERIALIZE) { $dateTimeFormat = $this->extractDateTimeFormat($type, DateTime::ISO8601); $value = $value->format($dateTimeFormat); } elseif ($direct == self::DIRECTION_UNSERIALIZE) { $originalValue = trim($value); $dateTimeFormat = $this->extractDateTimeFormat($type); // we should not allow empty string as date time argument. //It can lead us to unexpected results //Only 'null' is possible empty value if (!$originalValue) { throw new InvalidArgumentException('DateTime argument should be well formed string'); } try { $value = new DateTime($value); } catch (\Exception $e) { throw new InvalidArgumentException(sprintf('Invalid DateTime argument "%s"', $value), $e->getCode(), $e); } // if format was specified in metadata - format and compare parsed DateTime object with original string if (isset($dateTimeFormat) && $value->format($dateTimeFormat) !== $originalValue) { throw new InvalidArgumentException(sprintf('Invalid DateTime argument "%s"', $originalValue)); } } } elseif ($type === 'array' || $type[0] === 'a' && strpos($type, 'array<') === 0) { $tmpResult = array(); $tmpType = new PropertyMetadata($property->getName()); $tmpType->setExpose(true)->setSerializedName($property->getSerializedName()); if (preg_match('/array<(?<type>[a-zA-Z\\\\]+)>/', $type, $matches)) { $tmpType->setType($matches['type']); } if ($direct == self::DIRECTION_UNSERIALIZE) { $existsData = $this->exposeValue($object, $property); } foreach ($value as $k => $v) { $tmpObject = $object; if ($direct == self::DIRECTION_UNSERIALIZE && isset($existsData[$k]) && is_object($existsData[$k])) { $tmpObject = $existsData[$k]; $inner = true; } $v = $this->handleValue($v, $tmpType, $direct, $tmpObject, $inner); $tmpResult[$k] = $v; unset($tmpObject); } $value = $tmpResult; unset($tmpResult, $tmpType); } elseif (is_object($value) && $direct == self::DIRECTION_SERIALIZE) { $value = $this->toArray($value); } elseif (is_array($value) && $direct == self::DIRECTION_UNSERIALIZE) { if ($inner) { $innerObject = $object; } else { $innerObject = $this->exposeValue($object, $property); } if (!is_object($innerObject) || !$innerObject instanceof $type) { if (PHP_VERSION_ID >= 50400) { $rc = new \ReflectionClass($type); $innerObject = $rc->newInstanceWithoutConstructor(); } else { $innerObject = unserialize(sprintf('O:%d:"%s":0:{}', strlen($type), $type)); } } $value = $this->toObject($value, $innerObject); } elseif ($type !== null) { throw new InvalidArgumentException(sprintf('Unsupported type: %s', $type)); } } return $value; }
/** * @param PropertyMetadata $metadata */ public function addPropertyMetadata(PropertyMetadata $metadata) { $this->properties[$metadata->getName()] = $metadata; }