Skip to content

Instantly share code, notes, and snippets.

@juzna
Created December 27, 2011 14:54
Show Gist options
  • Select an option

  • Save juzna/1523891 to your computer and use it in GitHub Desktop.

Select an option

Save juzna/1523891 to your computer and use it in GitHub Desktop.
EntitySelectBox
<?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