* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\ChoiceList\Factory; use Symfony\Component\Form\ChoiceList\ChoiceListInterface; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; use Symfony\Component\Form\ChoiceList\View\ChoiceListView; use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\PropertyAccess\PropertyPath; /** * Adds property path support to a choice list factory. * * Pass the decorated factory to the constructor: * * ```php * $decorator = new PropertyAccessDecorator($factory); * ``` * * You can now pass property paths for generating choice values, labels, view * indices, HTML attributes and for determining the preferred choices and the * choice groups: * * ```php * // extract values from the $value property * $list = $createListFromChoices($objects, 'value'); * ``` * * @author Bernhard Schussek */ class PropertyAccessDecorator implements ChoiceListFactoryInterface { private $decoratedFactory; private $propertyAccessor; public function __construct(ChoiceListFactoryInterface $decoratedFactory, PropertyAccessorInterface $propertyAccessor = null) { $this->decoratedFactory = $decoratedFactory; $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } /** * Returns the decorated factory. * * @return ChoiceListFactoryInterface The decorated factory */ public function getDecoratedFactory() { return $this->decoratedFactory; } /** * {@inheritdoc} * * @param iterable $choices The choices * @param null|callable|string|PropertyPath $value The callable or path for * generating the choice values * * @return ChoiceListInterface The choice list */ public function createListFromChoices($choices, $value = null) { if (is_string($value) && !is_callable($value)) { $value = new PropertyPath($value); } elseif (is_string($value) && is_callable($value)) { @trigger_error('Passing callable strings is deprecated since Symfony 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($value instanceof PropertyPath) { $accessor = $this->propertyAccessor; $value = function ($choice) use ($accessor, $value) { // The callable may be invoked with a non-object/array value // when such values are passed to // ChoiceListInterface::getValuesForChoices(). Handle this case // so that the call to getValue() doesn't break. if (is_object($choice) || is_array($choice)) { return $accessor->getValue($choice, $value); } }; } return $this->decoratedFactory->createListFromChoices($choices, $value); } /** * {@inheritdoc} * * @param ChoiceLoaderInterface $loader The choice loader * @param null|callable|string|PropertyPath $value The callable or path for * generating the choice values * * @return ChoiceListInterface The choice list */ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = null) { if (is_string($value) && !is_callable($value)) { $value = new PropertyPath($value); } elseif (is_string($value) && is_callable($value)) { @trigger_error('Passing callable strings is deprecated since Symfony 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($value instanceof PropertyPath) { $accessor = $this->propertyAccessor; $value = function ($choice) use ($accessor, $value) { // The callable may be invoked with a non-object/array value // when such values are passed to // ChoiceListInterface::getValuesForChoices(). Handle this case // so that the call to getValue() doesn't break. if (is_object($choice) || is_array($choice)) { return $accessor->getValue($choice, $value); } }; } return $this->decoratedFactory->createListFromLoader($loader, $value); } /** * {@inheritdoc} * * @param ChoiceListInterface $list The choice list * @param null|array|callable|string|PropertyPath $preferredChoices The preferred choices * @param null|callable|string|PropertyPath $label The callable or path generating the choice labels * @param null|callable|string|PropertyPath $index The callable or path generating the view indices * @param null|callable|string|PropertyPath $groupBy The callable or path generating the group names * @param null|array|callable|string|PropertyPath $attr The callable or path generating the HTML attributes * * @return ChoiceListView The choice list view */ public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null) { $accessor = $this->propertyAccessor; if (is_string($label) && !is_callable($label)) { $label = new PropertyPath($label); } elseif (is_string($label) && is_callable($label)) { @trigger_error('Passing callable strings is deprecated since Symfony 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($label instanceof PropertyPath) { $label = function ($choice) use ($accessor, $label) { return $accessor->getValue($choice, $label); }; } if (is_string($preferredChoices) && !is_callable($preferredChoices)) { $preferredChoices = new PropertyPath($preferredChoices); } elseif (is_string($preferredChoices) && is_callable($preferredChoices)) { @trigger_error('Passing callable strings is deprecated since Symfony 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($preferredChoices instanceof PropertyPath) { $preferredChoices = function ($choice) use ($accessor, $preferredChoices) { try { return $accessor->getValue($choice, $preferredChoices); } catch (UnexpectedTypeException $e) { // Assume not preferred if not readable return false; } }; } if (is_string($index) && !is_callable($index)) { $index = new PropertyPath($index); } elseif (is_string($index) && is_callable($index)) { @trigger_error('Passing callable strings is deprecated since Symfony 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($index instanceof PropertyPath) { $index = function ($choice) use ($accessor, $index) { return $accessor->getValue($choice, $index); }; } if (is_string($groupBy) && !is_callable($groupBy)) { $groupBy = new PropertyPath($groupBy); } elseif (is_string($groupBy) && is_callable($groupBy)) { @trigger_error('Passing callable strings is deprecated since Symfony 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($groupBy instanceof PropertyPath) { $groupBy = function ($choice) use ($accessor, $groupBy) { try { return $accessor->getValue($choice, $groupBy); } catch (UnexpectedTypeException $e) { // Don't group if path is not readable } }; } if (is_string($attr) && !is_callable($attr)) { $attr = new PropertyPath($attr); } elseif (is_string($attr) && is_callable($attr)) { @trigger_error('Passing callable strings is deprecated since Symfony 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($attr instanceof PropertyPath) { $attr = function ($choice) use ($accessor, $attr) { return $accessor->getValue($choice, $attr); }; } return $this->decoratedFactory->createView($list, $preferredChoices, $label, $index, $groupBy, $attr); } } __halt_compiler();----SIGNATURE:----PlnoazVK3zHGREugWQTdWBTdoCfF1BfKduVQAKzuya4nCpraROMFEld3wN6uOjHyp6cowtLPlpFlrvJZxLtUDdw2awYgln2zPEMw0o+5PDxVLNoiCDQ6tx712Y3qF0jyETERTFPsMOFr1TOjpaOl1jeKN8zaU/kfacZU5PmuSOp1KPBaPc3Ji6GO6AMziOVKZC1Lcxs24+uVlTeGSOaFglMEMV/HsLXvNfRsHZvEs8KWljx6MBeBd+6OTuE+mzbKb3ag32D30aZbt06hAFF4SKWMIHQnKBqOzGaM87yWC3l2P3uoRDUjgUqr7OqWGVBXjP+F8nLz6FaT3Apa+PWRh3HNyG9ezn0hjE4CTOzjk/UYsOneAYKrI42GDUlZ6QrLuDI6WTTtwXcYxipxlmtAr0B1Q2fmnoxZtpMLhcA6LMwAYu0pFcNIxz0cCs2LqXVMZAMASpcT9FTL+WnqoueNW1hY6OXFQhgX7zE2TzO5GR1urw7Ngpz5UcFCRYe4aE0/WMfxhwMfK4FrMwutJfNzkLhcEBNtD8XjnrIJreYkpFL3BMVxHaQsbN32PCP4hIzkNXVmUsIkHNJeX1xHLTsTa0el9tgLasdrEW/b5cy02o6veXGbnch6ku6cLedXLWGIADTso2yjo+6coaD4BGEvb/qk2yl/O3M6rhjw7Q21Mpg=----ATTACHMENT:----MzQ2NjAxODMxNTYwNTI1MyAyOTI0NjMyNDI5NDAyNTg3IDM2MzkwMzc5OTMwMzk1OTk=