Created
December 27, 2011 14:54
-
-
Save juzna/1523891 to your computer and use it in GitHub Desktop.
EntitySelectBox
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| use Nette\Forms\Controls\BaseControl, | |
| Nella\Models\IEntity; | |
| /** | |
| * Select box control that display entities | |
| * | |
| * @author Jan Dolecek <[email protected]> | |
| */ | |
| class EntitySelectBox extends BaseControl | |
| { | |
| /** @var string|bool */ | |
| protected $prompt = FALSE; | |
| /** @var IEntity */ | |
| protected $value; | |
| /** @var \Nella\Doctrine\Repository */ | |
| protected $repository; | |
| /** @var string|callback|\CMS\Renderers\ISelectBoxOptionRenderer */ | |
| protected $valueGenerator; | |
| /** @var string|callback|\CMS\Renderers\ISelectBoxOptionRenderer */ | |
| protected $keyGenerator; | |
| public function __construct($label = NULL, $repository = NULL, $valueGenerator = NULL, $keyGenerator = 'id') | |
| { | |
| parent::__construct($label); | |
| $this->control->setName('select'); | |
| $this->repository = $repository; | |
| $this->valueGenerator = $valueGenerator; | |
| $this->keyGenerator = $keyGenerator; | |
| } | |
| public function setValue($value) { | |
| if($value === null) { | |
| $entity = null; | |
| } elseif(is_scalar($value)) { | |
| $entity = $this->repository->find($value); // TODO: should be modular! | |
| } elseif($value instanceof IEntity) { | |
| $entity = $value; | |
| } else throw new \Nette\InvalidArgumentException("Expected entity or id"); | |
| $this->value = $entity; | |
| return $this; | |
| } | |
| /** | |
| * Returns selected item | |
| * @return \Nella\Models\IEntity | |
| */ | |
| public function getValue() | |
| { | |
| return $this->value; | |
| } | |
| /** | |
| * Returns selected item key | |
| * @return mixed | |
| */ | |
| public function getRawValue() | |
| { | |
| $value = $this->getValue(); | |
| return $value ? $value->getId() : NULL; | |
| } | |
| /** | |
| * Has been any item selected? | |
| * @return bool | |
| */ | |
| public function isFilled() | |
| { | |
| return $this->value !== NULL; | |
| } | |
| /** | |
| * Ignores the first item in select box. | |
| * @param string | |
| * @return SelectBox provides a fluent interface | |
| */ | |
| public function setPrompt($prompt) | |
| { | |
| $this->prompt = $prompt; | |
| return $this; | |
| } | |
| /** | |
| * Is first item in select box ignored? | |
| * @return string | |
| */ | |
| final public function getPrompt() | |
| { | |
| return $this->prompt; | |
| } | |
| /** | |
| * Fetches entities to be displayed, may be overridden | |
| * @return IEntity[] | |
| */ | |
| protected function getItems() | |
| { | |
| return $this->repository->findAll(); | |
| } | |
| /** | |
| * Generates control's HTML element. | |
| * @return \Nette\Utils\Html | |
| */ | |
| public function getControl() | |
| { | |
| $control = parent::getControl(); | |
| // Prepare a map of selected entities (entity -> TRUE) for fast access | |
| $selectedEntitiesMap = new \SplObjectStorage(); | |
| $selected = $this->getValue(); | |
| if(is_array($selected)) { | |
| foreach($selected as $entity) $selectedEntitiesMap[$entity] = TRUE; | |
| } elseif($selected !== NULL) $selectedEntitiesMap[$selected] = TRUE; | |
| $option = \Nette\Utils\Html::el('option'); | |
| // Prepare generators | |
| $keyGenerator = $this->createGeneratorCallback($this->keyGenerator, true); | |
| $valueGenerator = $this->createGeneratorCallback($this->valueGenerator, false); | |
| if ($this->prompt !== false) { | |
| $control->data('nette-empty-value', ''); | |
| $control->add((string) $option->value(null)->setText($this->prompt)); | |
| } | |
| foreach ($this->getItems() as $entity) { | |
| $key = $keyGenerator ? $keyGenerator($entity) : NULL; | |
| $value = $valueGenerator ? $valueGenerator($entity) : NULL; | |
| $value = $this->translate((string) $value); | |
| $control->add((string) $option->value($key === $value ? NULL : $key) | |
| ->selected(isset($selectedEntitiesMap[$entity])) | |
| ->setText($value)); | |
| } | |
| return $control; | |
| } | |
| /** | |
| * Prepare callback which will generate keys and/or values | |
| * @param string|callback|\CMS\Renderers\ISelectBoxOptionRenderer $generatorDefinition | |
| * @param bool $keyGenerator Are we generating callback for keys? | |
| * @return closure|null | |
| */ | |
| protected function createGeneratorCallback($generatorDefinition, $keyGenerator) { | |
| if($generatorDefinition === NULL) { // nothing | |
| return NULL; | |
| } elseif(is_string($generatorDefinition)) { // property name given -> create getter | |
| return function($entity) use($generatorDefinition) { | |
| return $entity->$generatorDefinition; | |
| }; | |
| } elseif(is_callable($generatorDefinition)) { // callback -> trivial | |
| return $generatorDefinition; | |
| } elseif($generatorDefinition instanceof \CMS\Renderers\ISelectBoxOptionRenderer) { // renderer | |
| $method = $keyGenerator ? 'renderKey' : 'renderValue'; | |
| return function($entity) use($generatorDefinition, $method) { | |
| return $entity->$method($entity); | |
| }; | |
| } else throw new \InvalidArgumentException; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment