/** * Finds properties' metadata for every property used in document or inner/nested object * * @param \ReflectionClass $documentReflection * * @return array */ public function getPropertiesMetadata(\ReflectionClass $documentReflection) { $className = $documentReflection->getName(); if (array_key_exists($className, $this->propertiesMetadata)) { return $this->propertiesMetadata[$className]; } $propertyMetadata = []; /** @var \ReflectionProperty $property */ foreach ($this->getDocumentPropertiesReflection($documentReflection) as $propertyName => $property) { $propertyAnnotation = $this->getPropertyAnnotationData($property); $propertyAnnotation = $propertyAnnotation ?: $this->reader->getPropertyAnnotation($property, Id::class); $propertyAnnotation = $propertyAnnotation ?: $this->reader->getPropertyAnnotation($property, ParentId::class); $propertyAnnotation = $propertyAnnotation ?: $this->reader->getPropertyAnnotation($property, Score::class); // Ignore class properties without any recognized annotation if ($propertyAnnotation === null) { continue; } switch (get_class($propertyAnnotation)) { case Property::class: $propertyMetadata[$propertyAnnotation->name] = ['propertyName' => $propertyName, 'type' => $propertyAnnotation->type, 'multilanguage' => $propertyAnnotation->multilanguage]; // If property is a (nested) object if (in_array($propertyAnnotation->type, ['object', 'nested'])) { if (!$propertyAnnotation->objectName) { throw new \InvalidArgumentException(sprintf('Property "%s" in %s is missing "objectName" setting', $propertyName, $className)); } $child = new \ReflectionClass($this->documentLocator->resolveClassName($propertyAnnotation->objectName)); $propertyMetadata[$propertyAnnotation->name] = array_merge($propertyMetadata[$propertyAnnotation->name], ['multiple' => $propertyAnnotation->multiple, 'propertiesMetadata' => $this->getPropertiesMetadata($child), 'className' => $child->getName()]); } break; case Id::class: $propertyAnnotation->name = '_id'; $propertyAnnotation->type = 'string'; $propertyMetadata[$propertyAnnotation->name] = ['propertyName' => $propertyName, 'type' => $propertyAnnotation->type]; break; case ParentId::class: $propertyAnnotation->name = '_parent'; $propertyAnnotation->type = 'string'; $propertyMetadata[$propertyAnnotation->name] = ['propertyName' => $propertyName, 'type' => $propertyAnnotation->type]; break; case Score::class: $propertyAnnotation->name = '_score'; $propertyAnnotation->type = 'float'; $propertyMetadata[$propertyAnnotation->name] = ['propertyName' => $propertyName, 'type' => $propertyAnnotation->type]; break; } if ($property->isPublic()) { $propertyAccess = DocumentMetadata::PROPERTY_ACCESS_PUBLIC; } else { $propertyAccess = DocumentMetadata::PROPERTY_ACCESS_PRIVATE; $camelCaseName = ucfirst(Caser::camel($propertyName)); $setterMethod = 'set' . $camelCaseName; $getterMethod = 'get' . $camelCaseName; // Allow issers as getters for boolean properties if ($propertyAnnotation->type === 'boolean' && !$documentReflection->hasMethod($getterMethod)) { $getterMethod = 'is' . $camelCaseName; } if ($documentReflection->hasMethod($getterMethod) && $documentReflection->hasMethod($setterMethod)) { $propertyMetadata[$propertyAnnotation->name]['methods'] = ['getter' => $getterMethod, 'setter' => $setterMethod]; } else { $message = sprintf('Property "%s" either needs to be public or %s() and %s() methods must be defined', $propertyName, $getterMethod, $setterMethod); throw new \LogicException($message); } } $propertyMetadata[$propertyAnnotation->name]['propertyAccess'] = $propertyAccess; } $this->propertiesMetadata[$className] = $propertyMetadata; return $this->propertiesMetadata[$className]; }
/** * @param string $input * @param string $expected * @dataProvider providerForCamel */ public function testCamel($input, $expected) { $this->assertEquals($expected, Caser::camel($input)); }