Created
February 14, 2013 11:50
-
-
Save VaclavSir/4952313 to your computer and use it in GitHub Desktop.
EntityFormBuilder
This file contains 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 | |
namespace VS\UI; | |
/** | |
* Simple form generator for plain old data objects. | |
* | |
* Creates a field for each scalar setter. Nothing more. | |
* | |
* @author Václav Šír | |
*/ | |
class EntityFormBuilder extends \Nette\Object | |
{ | |
/** | |
* @param \Nette\Forms\Form $form | |
* @param object $entity | |
*/ | |
public function build(\Nette\Forms\Form $form, $entity) | |
{ | |
$classType = \Nette\Reflection\ClassType::from($entity); | |
$methods = $classType->getMethods(\ReflectionMethod::IS_PUBLIC); | |
$fieldNames = array(); | |
foreach ($methods as $method) { | |
if ($this->isSuitableSetter($method)) { | |
// Field creation | |
$fieldName = substr($method->name, 3); | |
$type = $this->getFirstParameterType($method); | |
$caption = "$fieldName: "; | |
switch ($type) { | |
case 'bool': | |
case 'boolean': | |
$form->addCheckbox($fieldName, $caption); | |
break; | |
default: | |
$form->addTextArea($fieldName, $caption, 40, 3); | |
break; | |
} | |
$fieldNames[] = $fieldName; | |
// Assign default value | |
$getterName = 'get' . $fieldName; | |
$defaultValue = $classType->hasMethod($getterName) | |
? $classType->getMethod($getterName)->invoke($entity) | |
: null; | |
$form[$fieldName]->setDefaultValue($defaultValue); | |
} | |
} | |
$form->onSuccess[] = new EntityFormBuilder_OnSuccessCallback($entity, $fieldNames); | |
} | |
private function isSuitableSetter(\Nette\Reflection\Method $method) | |
{ | |
$parameters = $method->getParameters(); | |
$typeOfTheParameter = $this->getFirstParameterType($method); | |
return substr($method->name, 0, 3) === 'set' | |
&& count($parameters) === 1 | |
&& $parameters[0]->getClass() === null | |
&& $typeOfTheParameter !== 'array' | |
&& $typeOfTheParameter !== 'object' | |
&& !\Nette\Utils\Strings::endsWith($typeOfTheParameter, '[]') | |
&& !class_exists($typeOfTheParameter); | |
} | |
private function getFirstParameterType(\Nette\Reflection\Method $method) | |
{ | |
$parameters = $method->getParameters(); | |
if (empty($parameters)) { return null; } | |
if ($typehintedClass = $parameters[0]->getClassName()) { return $typehintedClass; } | |
if ($parameters[0]->isArray()) { return 'array'; } | |
if ($annotation = $method->getAnnotation('param')) { | |
$splits = preg_split('~[|\s]+~', $annotation, 2); | |
return array_shift($splits); | |
} | |
return 'mixed'; | |
} | |
} | |
This file contains 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 | |
namespace VS\UI; | |
/** | |
* @author Václav Šír | |
*/ | |
class EntityFormBuilder_OnSuccessCallback extends \Nette\Object | |
{ | |
private $entity; | |
private $fieldNames; | |
public function __construct($entity, $fieldNames) | |
{ | |
$this->entity = $entity; | |
$this->fieldNames = $fieldNames; | |
} | |
public function __invoke(\Nette\Forms\Form $form) | |
{ | |
$values = $form->getValues(); | |
foreach ($this->fieldNames as $fieldName) { | |
$setterName = "set$fieldName"; | |
try { | |
$this->entity->$setterName($values[$fieldName]); | |
} catch (\Exception $e) { | |
$form[$fieldName]->addError(get_class($e) . ': ' . $e->getMessage()); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment