/** * 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; }