/** * @param object $entity Entity * * @throws \Darvin\Utils\DefaultValue\DefaultValueException */ protected function setDefaultValues($entity) { $entityClass = ClassUtils::getClass($entity); $meta = $this->extendedMetadataFactory->getExtendedMetadata($entityClass); if (!isset($meta['defaultValues']) || empty($meta['defaultValues'])) { return; } $defaultValuesMap = $meta['defaultValues']; $this->filterDefaultValuesMap($defaultValuesMap, $entity, $entityClass); if (empty($defaultValuesMap)) { return; } $sourcePropertyValues = $this->getSourcePropertyValues(array_unique(array_values($defaultValuesMap)), $entity, $entityClass); $recomputeChangeSet = false; foreach ($defaultValuesMap as $targetProperty => $sourcePropertyPath) { if (null === $sourcePropertyValues[$sourcePropertyPath]) { continue; } if (!$this->propertyAccessor->isWritable($entity, $targetProperty)) { throw new DefaultValueException(sprintf('Property "%s::$%s" is not writable.', $entityClass, $targetProperty)); } $this->propertyAccessor->setValue($entity, $targetProperty, $sourcePropertyValues[$sourcePropertyPath]); $recomputeChangeSet = true; } if ($recomputeChangeSet) { $this->recomputeChangeSet($entity); } }
/** * {@inheritdoc} */ public function apply(Request $request, ParamConverter $configuration) : bool { $class = $configuration->getClass(); $constant = sprintf('%s::EMPTY_PROPERTIES', $class); $propertiesToBeSkipped = []; $instance = new $class(); $declaredProperties = array_filter((new \ReflectionClass($class))->getProperties(), function (ReflectionProperty $property) use($class) { return $property->getDeclaringClass()->name === $class; }); // fetch result properties that are optional and to be skipped as those must not be processed if (defined($constant)) { $propertiesToBeSkipped = constant($constant); } /** @var ReflectionProperty $property */ foreach ($declaredProperties as $property) { $propertyName = $property->getName(); if (in_array($propertyName, $propertiesToBeSkipped, true)) { continue; } // non-writable properties cause issues with the DTO creation if (!$this->propertyAccess->isWritable($instance, $propertyName)) { throw new \RuntimeException($this->getInvalidPropertyExceptionMessage($class, $propertyName)); } $this->propertyAccess->setValue($instance, $propertyName, $this->findAttributeInRequest($request, $property, $this->propertyAccess->getValue($instance, $propertyName))); } $request->attributes->set($configuration->getName(), $instance); return true; }
/** * {@inheritdoc} */ public function apply(Request $request, ParamConverter $configuration) { $instance = $this->getDTOInstance($configuration->getClass()); foreach ($this->getDTOParametersByClass($configuration->getClass()) as $property) { $propertyName = $property->getName(); if (!$this->propertyAccess->isWritable($instance, $propertyName)) { throw new \RuntimeException($this->getInvalidPropertyExceptionMessage($configuration->getClass(), $propertyName)); } $this->propertyAccess->setValue($instance, $propertyName, $this->findAttributeInRequest($request, $property)); } $request->attributes->set($configuration->getName(), $instance); return true; }
/** * @param object $entity Entity * @param string $propertyPath Property path * @param mixed $value Value * * @throws \Darvin\Utils\CustomObject\CustomObjectException */ private function setPropertyValue($entity, $propertyPath, $value) { if (!$this->propertyAccessor->isWritable($entity, $propertyPath)) { throw new CustomObjectException(sprintf('Property "%s::$%s" is not writable.', ClassUtils::getClass($entity), $propertyPath)); } $this->propertyAccessor->setValue($entity, $propertyPath, $value); }
/** * @param object $object Object to clone * * @return object * @throws \Darvin\Utils\Cloner\ClonerException */ private function cloneObject($object) { $objectHash = spl_object_hash($object); if (isset($this->clonedObjects[$objectHash])) { return $this->clonedObjects[$objectHash]; } $class = ClassUtils::getClass($object); if (false === strpos($class, '\\')) { $clone = clone $object; $this->clonedObjects[$objectHash] = $clone; return $clone; } $meta = $this->extendedMetadataFactory->getExtendedMetadata($class); if (!isset($meta['clonable'])) { $message = sprintf('Class "%s" must be annotated with "%s" annotation in order to create clone of it\'s instance.', $class, Clonable::ANNOTATION); throw new ClonerException($message); } $clone = new $class(); $this->clonedObjects[$objectHash] = $clone; foreach ($meta['clonable']['properties'] as $property) { if (!$this->propertyAccessor->isReadable($object, $property)) { throw new ClonerException(sprintf('Property "%s::$%s" is not readable.', $class, $property)); } if (!$this->propertyAccessor->isWritable($clone, $property)) { throw new ClonerException(sprintf('Property "%s::$%s" is not writable.', $class, $property)); } $value = $this->propertyAccessor->getValue($object, $property); $valueCopy = $this->copyValue($value); $this->propertyAccessor->setValue($clone, $property, $valueCopy); } $this->eventDispatcher->dispatch(Events::POST_CLONE, new CloneEvent($object, $clone)); return $clone; }
/** * {@inheritdoc} */ public function getResult(ClassMetadata $classMetadata, array $options = []) { if (!isset($options['property'])) { throw new \InvalidArgumentException('The property option was not specified.'); } $instance = $classMetadata->newInstance(); if (!$this->propertyAccessor->isWritable($instance, $options['property']) || !$this->propertyAccessor->isReadable($instance, $options['property'])) { return false; } if (isset($options['create'])) { $create = $options['create']; unset($options['create']); } else { $create = true; } if ($annotation = $this->annotationQuery->getResult($classMetadata, array_merge($options, ['annotationClass' => 'Sentient\\Data\\Metadata\\Annotation\\LockedProperty']))) { if ($create ? $annotation->onCreate : $annotation->onUpdate) { return false; } } if ($annotation = $this->annotationQuery->getResult($classMetadata, array_merge($options, ['annotationClass' => 'Sentient\\Data\\Metadata\\Annotation\\CrudProperty']))) { if ($annotation->editable === CrudProperty::EDITABLE_ALWAYS) { return true; } if ($annotation->editable === CrudProperty::EDITABLE_NEVER) { return false; } if ($annotation->editable === CrudProperty::EDITABLE_ON_CREATE) { return $create; } if ($annotation->editable === CrudProperty::EDITABLE_ON_UPDATE) { return !$create; } throw new \RuntimeException('The editable property has an invalid value.'); } foreach ($this->bannedAnnotations as $annotationClass) { if ($this->annotationQuery->getResult($classMetadata, array_merge($options, compact('annotationClass')))) { return false; } } return true; }
/** * @param object $entity Entity * * @throws \Darvin\Utils\Transliteratable\TransliteratableException */ protected function transliterate($entity) { $entityClass = ClassUtils::getClass($entity); $meta = $this->extendedMetadataFactory->getExtendedMetadata($entityClass); if (!isset($meta['transliteratable']) || empty($meta['transliteratable'])) { return; } $changeSet = $this->uow->getEntityChangeSet($entity); $recomputeChangeSet = false; foreach ($meta['transliteratable'] as $property => $params) { if (!isset($changeSet[$property])) { continue; } if (!$this->propertyAccessor->isWritable($entity, $property)) { throw new TransliteratableException(sprintf('Property "%s::$%s" is not writable.', $entityClass, $property)); } $transliterated = $this->transliterator->transliterate($changeSet[$property][1], $params['sanitize'], $params['allowedSymbols'], $params['separator']); $this->propertyAccessor->setValue($entity, $property, $transliterated); $recomputeChangeSet = true; } if ($recomputeChangeSet) { $this->recomputeChangeSet($entity); } }
/** * @inheritdoc */ public function isWritable($objectOrArray, $propertyPath) { return $objectOrArray instanceof \stdClass ? true : $this->decoratedPropertyAccessor->isWritable($objectOrArray, $propertyPath); }