/** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Expression) { throw new UnexpectedTypeException($constraint, __NAMESPACE__ . '\\Expression'); } $variables = array(); // Symfony 2.5+ if ($this->context instanceof ExecutionContextInterface) { $variables['value'] = $value; $variables['this'] = $this->context->getObject(); } elseif (null === $this->context->getPropertyName()) { $variables['value'] = $value; $variables['this'] = $value; } else { $root = $this->context->getRoot(); $variables['value'] = $value; if (is_object($root)) { // Extract the object that the property belongs to from the object // graph $path = new PropertyPath($this->context->getPropertyPath()); $parentPath = $path->getParent(); $variables['this'] = $parentPath ? $this->getPropertyAccessor()->getValue($root, $parentPath) : $root; } else { $variables['this'] = null; } } if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) { if ($this->context instanceof ExecutionContextInterface) { $this->context->buildViolation($constraint->message)->setParameter('{{ value }}', $this->formatValue($value))->addViolation(); } else { $this->buildViolation($constraint->message)->setParameter('{{ value }}', $this->formatValue($value))->addViolation(); } } }
protected function getConstraintViolation(ConstraintViolation $constraintViolation, array &$messages) { $path = new PropertyPath($constraintViolation->getPropertyPath()); $elements = $path->getElements(); $elements[] = $constraintViolation->getConstraint()->validatedBy(); $this->propertyAccessor->setValue($messages, $this->buildPath($elements), $constraintViolation->getMessage()); }
/** * @param string $propertyPath * @return null|\Symfony\Component\PropertyAccess\PropertyPath */ private function validatePropertyPath($propertyPath) { $propertyPath = new PropertyPath($propertyPath); if ($propertyPath->isProperty($propertyPath->getLength() - 1)) { return $propertyPath; } else { return null; } }
/** * Enables object validation. * * @param Mapping $mapping The mapping object * * @return Mapping */ public function enableObjectValidation(Mapping $mapping) { $emitter = $mapping->getEmitter(); $emitter->on(Events::APPLIED, function (Data $data) { $vios = $this->validator->validate($data->getResult()); foreach ($vios as $vio) { $propertyPath = new PropertyPath($vio->getPropertyPath()); $data->addError(new Error($vio->getMessage(), $propertyPath->getElements())); } }); return $mapping; }
/** * @param string|PropertyPathInterface $propertyPath The property path to modify * * @throws NoSuchIndexException */ public function removeField($propertyPath) { $propertyPathAccessor = PropertyAccess::createPropertyAccessor(); if (!$propertyPath instanceof PropertyPathInterface) { $propertyPath = new PropertyPath($propertyPath); } if (1 === $propertyPath->getLength()) { $buffer =& $this->fields; unset($buffer[$propertyPath->getElement(0)]); } else { $parentPropertyPath = $propertyPath->getParent(); $buffer = $propertyPathAccessor->getValue($this->fields, $parentPropertyPath); unset($buffer[$propertyPath->getElement($propertyPath->getLength() - 1)]); $propertyPathAccessor->setValue($this->fields, $parentPropertyPath, $buffer); } }
/** * Returns html and attributes value of rdfa property. * * @param string $property Could be a property sequence like (block[1].title[0]) * * @return bool */ public function getPropertyValue($property) { $nodes = $this->crawler; $before = ''; $path = new PropertyPath($property); if (1 < $path->getLength()) { foreach ($path as $item) { // is not integer if (!ctype_digit(strval($item))) { $before = $item; $nodes = $nodes->filter('*[property="' . $item . '"]'); } else { $nodes = $nodes->filter('*[rel="' . $before . '"]')->eq($item); } } } else { // FIXME it is a bit complex but there is no :not operator in crawler // should be *[property="block"]:not(*[property] *) $nodes = $nodes->filter('*[property="' . $property . '"]')->reduce(function (Crawler $node) { // get parents $parents = $node->parents(); $count = 0; // check if one parent is property exclude it $parents->each(function ($node) use(&$count) { if (null !== $node->attr('property') && $node->attr('typeof') === 'collection') { ++$count; } }); return $count === 0; }); } // if rdfa property not found return false if ($nodes->count() > 0) { // create an array of changes return $nodes->each(function (Crawler $crawlerNode) { $node = $crawlerNode->getNode(0); $attributes = []; foreach ($node->attributes as $name => $value) { $attributes[$name] = $value->nodeValue; } $attributes['html'] = $crawlerNode->html(); return $attributes; }); } return false; }
function it_does_nothing_if_forms_property_is_not_translatable_in_first_translatable_parent(ManagerRegistry $managerRegistry, ObjectManager $manager, TranslatableListener $translatableListener, ClassMetadata $translatableMetadata, PropertyPath $propertyPath, FormView $view, FormInterface $form, FormConfigInterface $formConfig, FormInterface $parentForm, FormConfigInterface $parentFormConfig, FormInterface $grandParentForm, FormConfigInterface $grandParentFormConfig) { $propertyPath->__toString()->willReturn('translatable_property'); $form->getPropertyPath()->willReturn($propertyPath); $form->getConfig()->willReturn($formConfig); $form->getParent()->willReturn($parentForm); $parentForm->getConfig()->willReturn($parentFormConfig); $parentFormConfig->getInheritData()->willReturn(true); $parentForm->getParent()->willReturn($grandParentForm); $grandParentForm->getConfig()->willReturn($grandParentFormConfig); $grandParentFormConfig->getInheritData()->willReturn(false); $grandParentFormConfig->getDataClass()->willReturn('translatable_class'); $managerRegistry->getManagerForClass('translatable_class')->willReturn($manager); $translatableListener->getExtendedMetadata($manager, 'translatable_class')->willReturn($translatableMetadata); $translatableMetadata->hasTranslatableProperties()->willReturn(true); $translatableMetadata->getTranslatableProperties()->willReturn(array()); $this->finishView($view, $form, array()); expect($view->vars['translatable'])->toBe(false); expect($view->vars['not_translated'])->toBe(false); }
/** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } $variables = array(); if (null === $this->context->getPropertyName()) { $variables['this'] = $value; } else { // Extract the object that the property belongs to from the object // graph $path = new PropertyPath($this->context->getPropertyPath()); $parentPath = $path->getParent(); $root = $this->context->getRoot(); $variables['value'] = $value; $variables['this'] = $parentPath ? $this->propertyAccessor->getValue($root, $parentPath) : $root; } if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) { $this->context->addViolation($constraint->message); } }
function let(ManagerRegistry $managerRegistry, TranslatableListener $translatableListener, PropertyAccessor $propertyAccessor, ObjectManager $manager, ClassMetadata $translatableMetadata, PropertyPath $propertyPath, FormView $view, FormInterface $form, FormConfigInterface $formConfig, FormInterface $parentForm, FormConfigInterface $parentFormConfig, FormInterface $grandParentForm, FormConfigInterface $grandParentFormConfig) { $this->beConstructedWith($managerRegistry, $translatableListener, $propertyAccessor); $propertyPath->__toString()->willReturn('translatable_property'); $form->getPropertyPath()->willReturn($propertyPath); $form->getConfig()->willReturn($formConfig); $form->getParent()->willReturn($parentForm); $parentForm->getConfig()->willReturn($parentFormConfig); $parentFormConfig->getInheritData()->willReturn(true); $parentForm->getParent()->willReturn($grandParentForm); $data = new \stdClass(); $grandParentForm->getNormData()->willReturn($data); $propertyAccessor->getValue($data, 'locale')->willReturn('en'); $grandParentForm->getConfig()->willReturn($grandParentFormConfig); $grandParentFormConfig->getInheritData()->willReturn(false); $grandParentFormConfig->getDataClass()->willReturn('translatable_class'); $managerRegistry->getManagerForClass('translatable_class')->willReturn($manager); $translatableListener->getExtendedMetadata($manager, 'translatable_class')->willReturn($translatableMetadata); $translatableListener->getLocale()->willReturn('de'); $translatableMetadata->localeProperty = 'locale'; $translatableMetadata->hasTranslatableProperties()->willReturn(true); }
/** * Creates a new violation path from a string. * * @param string $violationPath The property path of a {@link ConstraintViolation} * object. */ public function __construct($violationPath) { $path = new PropertyPath($violationPath); $elements = $path->getElements(); $data = false; for ($i = 0, $l = count($elements); $i < $l; ++$i) { if (!$data) { // The element "data" has not yet been passed if ('children' === $elements[$i] && $path->isProperty($i)) { // Skip element "children" ++$i; // Next element must exist and must be an index // Otherwise consider this the end of the path if ($i >= $l || !$path->isIndex($i)) { break; } // All the following index items (regardless if .children is // explicitly used) are children and grand-children for (; $i < $l && $path->isIndex($i); ++$i) { $this->elements[] = $elements[$i]; $this->isIndex[] = true; $this->mapsForm[] = true; } // Rewind the pointer as the last element above didn't match // (even if the pointer was moved forward) --$i; } elseif ('data' === $elements[$i] && $path->isProperty($i)) { // Skip element "data" ++$i; // End of path if ($i >= $l) { break; } $this->elements[] = $elements[$i]; $this->isIndex[] = $path->isIndex($i); $this->mapsForm[] = false; $data = true; } else { // Neither "children" nor "data" property found // Consider this the end of the path break; } } else { // Already after the "data" element // Pick everything as is $this->elements[] = $elements[$i]; $this->isIndex[] = $path->isIndex($i); $this->mapsForm[] = false; } } $this->length = count($this->elements); $this->buildString(); }
/** * @param string $rootClass * @param string|PropertyPathInterface $propertyPath * @return array|null */ public function guessMetadataAndField($rootClass, $propertyPath) { if (!$propertyPath instanceof PropertyPathInterface) { $propertyPath = new PropertyPath($propertyPath); } $pathElements = array_values($propertyPath->getElements()); $elementsCount = count($pathElements); if ($elementsCount < 2) { return null; } $metadata = $this->getMetadataForClass($rootClass); $field = null; for ($i = 1; $i < $elementsCount; $i++) { $field = $pathElements[$i]; $hasAssociation = $metadata->hasAssociation($field) || $this->entityConfigProvider->hasConfig($rootClass, $field); if ($hasAssociation && $i < $elementsCount - 1) { $className = $metadata->hasAssociation($field) ? $metadata->getAssociationTargetClass($field) : $this->entityConfigProvider->getConfig($rootClass, $field)->getId()->getClassName(); $metadata = $this->getMetadataForClass($className); } elseif (!$hasAssociation && !$metadata->hasField($field)) { return null; } } return array('metadata' => $metadata, 'field' => $field); }
/** * Creates a new violation path from a string. * * @param string $violationPath The property path of a {@link ConstraintViolation} * object. */ public function __construct($violationPath) { $path = new PropertyPath($violationPath); $elements = $path->getElements(); $data = false; for ($i = 0, $l = count($elements); $i < $l; ++$i) { if (!$data) { // The element "data" has not yet been passed if ('children' === $elements[$i] && $path->isProperty($i)) { // Skip element "children" ++$i; // Next element must exist and must be an index // Otherwise consider this the end of the path if ($i >= $l || !$path->isIndex($i)) { break; } $this->elements[] = $elements[$i]; $this->isIndex[] = true; $this->mapsForm[] = true; } elseif ('data' === $elements[$i] && $path->isProperty($i)) { // Skip element "data" ++$i; // End of path if ($i >= $l) { break; } $this->elements[] = $elements[$i]; $this->isIndex[] = $path->isIndex($i); $this->mapsForm[] = false; $data = true; } else { // Neither "children" nor "data" property found // Consider this the end of the path break; } } else { // Already after the "data" element // Pick everything as is $this->elements[] = $elements[$i]; $this->isIndex[] = $path->isIndex($i); $this->mapsForm[] = false; } } $this->length = count($this->elements); $this->buildString(); }
private function extractLabels($choices, array &$labels) { foreach ($choices as $i => $choice) { if ((is_array($choice) || $choice instanceof \Traversable) && !$choice instanceof ItemInterface) { $labels[$i] = array(); $this->extractLabels($choice, $labels[$i]); } elseif ($this->labelPath) { //$labels[$i] = $this->labelPath->getValue($choice); if (version_compare(Kernel::VERSION, '2.1') <= 0) { $labelValue = $this->labelPath->getValue($choice); } else { $propertyAccessor = PropertyAccess::getPropertyAccessor(); $labelValue = $propertyAccessor->getValue($choice, $this->labelPath); } $labels[$i] = str_repeat('-', $choice->getLevel()) . ' ' . $labelValue; } elseif (method_exists($choice, '__toString')) { $labels[$i] = (string) $choice; } else { throw new StringCastException('A "__toString()" method was not found on the objects of type "' . get_class($choice) . '" passed to the choice field. To read a custom getter instead, set the argument $labelPath to the desired property path.'); } } }
/** * @param $path * @return string */ private function transformPropertyPath($path) { $path = new PropertyPath($path); return '/' . implode('/', $path->getElements()); }
/** * @param Request $request * * @return Response */ public function setObjectFieldValueAction(Request $request) { $field = $request->get('field'); $code = $request->get('code'); $objectId = $request->get('objectId'); $value = $request->get('value'); $context = $request->get('context'); $admin = $this->pool->getInstance($code); $admin->setRequest($request); // alter should be done by using a post method if (!$request->isXmlHttpRequest()) { return new JsonResponse(array('status' => 'KO', 'message' => 'Expected a XmlHttpRequest request header')); } if ($request->getMethod() != 'POST') { return new JsonResponse(array('status' => 'KO', 'message' => 'Expected a POST Request')); } $rootObject = $object = $admin->getObject($objectId); if (!$object) { return new JsonResponse(array('status' => 'KO', 'message' => 'Object does not exist')); } // check user permission if (false === $admin->isGranted('EDIT', $object)) { return new JsonResponse(array('status' => 'KO', 'message' => 'Invalid permissions')); } if ($context == 'list') { $fieldDescription = $admin->getListFieldDescription($field); } else { return new JsonResponse(array('status' => 'KO', 'message' => 'Invalid context')); } if (!$fieldDescription) { return new JsonResponse(array('status' => 'KO', 'message' => 'The field does not exist')); } if (!$fieldDescription->getOption('editable')) { return new JsonResponse(array('status' => 'KO', 'message' => 'The field cannot be edit, editable option must be set to true')); } $propertyPath = new PropertyPath($field); // If property path has more than 1 element, take the last object in order to validate it if ($propertyPath->getLength() > 1) { $object = $this->pool->getPropertyAccessor()->getValue($object, $propertyPath->getParent()); $elements = $propertyPath->getElements(); $field = end($elements); $propertyPath = new PropertyPath($field); } // Handle date type has setter expect a DateTime object if ('' !== $value && $fieldDescription->getType() == 'date') { $value = new \DateTime($value); } $this->pool->getPropertyAccessor()->setValue($object, $propertyPath, '' !== $value ? $value : null); $violations = $this->validator->validate($object); if (count($violations)) { $messages = array(); foreach ($violations as $violation) { $messages[] = $violation->getMessage(); } return new JsonResponse(array('status' => 'KO', 'message' => implode("\n", $messages))); } $admin->update($object); // render the widget // todo : fix this, the twig environment variable is not set inside the extension ... $extension = $this->twig->getExtension('sonata_admin'); $extension->initRuntime($this->twig); $content = $extension->renderListElement($rootObject, $fieldDescription); return new JsonResponse(array('status' => 'OK', 'content' => $content)); }
/** * @param $path * @param $haystack * @return bool */ private function valueExist($path, array $haystack) { $propertyPath = new PropertyPath($path); $length = $propertyPath->getLength(); $valueExist = true; for ($i = 0; $i < $length; ++$i) { $property = $propertyPath->getElement($i); $isIndex = $propertyPath->isIndex($i); $propertyExist = $this->arrayPropertyExists($property, $haystack); if ($isIndex && !$propertyExist) { $valueExist = false; break; } } unset($propertyPath); return $valueExist; }
/** * @expectedException \OutOfBoundsException */ public function testIsIndexDoesNotAcceptNegativeIndices() { $propertyPath = new PropertyPath('grandpa.parent[child]'); $propertyPath->isIndex(-1); }
/** * @param FormInterface $root * @param string $propertyPath */ public function __construct(FormInterface $root, $propertyPath) { parent::__construct($propertyPath); $this->root = $root; }
/** * @param string $path * @return string */ private function mapPropertyPath($path) { $propertyPath = new PropertyPath($path); $pathElements = $propertyPath->getElements(); return '/' . implode('/', $pathElements); }
/** * {@inheritdoc} */ public function __construct($propertyPath) { parent::__construct($propertyPath); trigger_error('\\Symfony\\Component\\Form\\Util\\PropertyPath is deprecated since version 2.2 and will be removed in 2.3. Use \\Symfony\\Component\\PropertyAccess\\PropertyPath instead.', E_USER_DEPRECATED); }
/** * @dataProvider provideCustomDataErrorTests */ public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); $parent = $this->getForm('parent', null, null, array($mapFrom => $mapTo)); $child = $this->getForm($childName, $childPath); $grandChild = $this->getForm($grandChildName, $grandChildPath); $parent->add($child); $child->add($grandChild); // Add a field mapped to the first element of $mapFrom // to try to distract the algorithm // Only add it if we expect the error to come up on a different // level than LEVEL_0, because in this case the error would // (correctly) be mapped to the distraction field if ($target !== self::LEVEL_0) { $mapFromPath = new PropertyPath($mapFrom); $mapFromPrefix = $mapFromPath->isIndex(0) ? '[' . $mapFromPath->getElement(0) . ']' : $mapFromPath->getElement(0); $distraction = $this->getForm('distraction', $mapFromPrefix); $parent->add($distraction); } $this->mapper->mapViolation($violation, $parent); if ($target !== self::LEVEL_0) { $this->assertCount(0, $distraction->getErrors(), 'distraction should not have an error, but has one'); } if (self::LEVEL_0 === $target) { $this->assertEquals(array($this->getFormError($violation)), $parent->getErrors(), $parent->getName() . ' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName . ' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName . ' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); $this->assertEquals(array($this->getFormError($violation)), $child->getErrors(), $childName . ' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName . ' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName . ' should not have an error, but has one'); $this->assertEquals(array($this->getFormError($violation)), $grandChild->getErrors(), $grandChildName . ' should have an error, but has none'); } }
/** * Replaces a sub-path by a different (sub-) path. * * @param integer $offset The offset at which to replace. * @param integer $length The length of the piece to replace. * @param PropertyPathInterface|string $path The path to insert. * @param integer $pathOffset The offset where the inserted piece * starts in $path. * @param integer $pathLength The length of the inserted piece. * If 0, the full path is inserted. * * @throws OutOfBoundsException If the offset is invalid */ public function replace($offset, $length, $path, $pathOffset = 0, $pathLength = 0) { if (is_string($path)) { $path = new PropertyPath($path); } if ($offset < 0 && abs($offset) <= $this->getLength()) { $offset = $this->getLength() + $offset; } elseif (!isset($this->elements[$offset])) { throw new OutOfBoundsException('The offset ' . $offset . ' is not within the property path'); } if (0 === $pathLength) { $pathLength = $path->getLength() - $pathOffset; } $this->resize($offset, $length, $pathLength); for ($i = 0; $i < $pathLength; ++$i) { $this->elements[$offset + $i] = $path->getElement($pathOffset + $i); $this->isIndex[$offset + $i] = $path->isIndex($pathOffset + $i); } }