Skip to content
Permalink
Browse files

Start to implement isRequired for the EntityContext.

Do some refactoring around entity location and validator handling.
  • Loading branch information...
markstory committed Feb 1, 2014
1 parent 20b9b01 commit ccd4b8cf8d201c71f163bd3cea1ee59d811e051b
Showing with 137 additions and 11 deletions.
  1. +93 −11 src/View/Form/EntityContext.php
  2. +44 −0 tests/TestCase/View/Form/EntityContextTest.php
@@ -54,8 +54,21 @@ class EntityContext {
*/
protected $_context;
/**
* The plural name of the top level entity/table object.
*
* @var string
*/
protected $_pluralName;
/**
* A dictionary of validators and their
* related tables.
*
* @var array
*/
protected $_validators = [];
/**
* Constructor.
*
@@ -80,11 +93,16 @@ public function __construct(Request $request, array $context) {
* @return void
*/
protected function _prepare() {
$table = null;
// TODO handle the other cases (string, array, instance)
if (is_string($this->_context['table'])) {
$plural = $this->_context['table'];
}
$this->_pluralName = $plural;
if (is_object($this->_context['validator'])) {
$this->_validators['_default'] = $this->_context['validator'];
}
}
/**
@@ -100,24 +118,46 @@ public function val($field) {
return null;
}
$parts = explode('.', $field);
$entity = $this->_getEntity($parts);
if (!$entity) {
return null;
}
return $entity->get(array_pop($parts));
}
/**
* Fetch the leaf entity for the given path.
*
* This method will traverse the given path and find the leaf
* entity. If the path does not contain a leaf entity false
* will be returned.
*
* @param array $path The path to traverse to find the leaf entity.
* @return boolean|Entity Either the leaf entity or false.
*/
protected function _getEntity($path) {
$entity = $this->_context['entity'];
if (count($path) === 1) {
return $entity;
}
// Remove the model name if present.
if (count($parts) > 1 && $parts[0] === $this->_pluralName) {
array_shift($parts);
// Remove the Table name if present.
if (count($path) > 1 && $path[0] === $this->_pluralName) {
array_shift($path);
}
$val = $this->_context['entity'];
foreach ($parts as $prop) {
$val = $this->_getProp($val, $prop);
foreach ($path as $prop) {
$next = $this->_getProp($entity, $prop);
if (
!is_array($val) &&
!($val instanceof Traversable) &&
!($val instanceof Entity)
!is_array($next) &&
!($next instanceof Traversable) &&
!($next instanceof Entity)
) {
return $val;
return $entity;
}
$entity = $next;
}
return $val;
return false;
}
/**
@@ -138,7 +178,49 @@ protected function _getProp($target, $field) {
return $target->get($field);
}
/**
* Check if a field should be marked as required.
*
* @param string $field The dot separated path to the field you want to check.
* @return boolean
*/
public function isRequired($field) {
if (empty($this->_context['validator'])) {
return false;
}
$parts = explode('.', $field);
$entity = $this->_getEntity($parts);
if (!$entity) {
return false;
}
$field = array_pop($parts);
$validator = $this->_getValidator($entity);
if (!$validator->hasField($field)) {
return false;
}
$allowed = $validator->isEmptyAllowed($field, $entity->isNew());
return $allowed === false;
}
/**
* Get the validator associated to an entity based on naming
* conventions.
*
* If no match is found the `_root` validator will be used.
*
* @param Cake\ORM\Entity $entity
* @return Validator
*/
protected function _getValidator($entity) {
list($ns, $entityClass) = namespaceSplit(get_class($entity));
if (isset($this->_validators[$entityClass])) {
return $this->_validators[$entityClass];
}
if (isset($this->_validators['_default'])) {
return $this->_validators['_default'];
}
}
public function type($field) {
@@ -16,6 +16,7 @@
use Cake\ORM\Entity;
use Cake\ORM\Table;
use Cake\ORM\TableRegistry;
use Cake\Network\Request;
use Cake\TestSuite\TestCase;
use Cake\View\Form\EntityContext;
@@ -122,4 +123,47 @@ public function testValAssociated() {
$this->assertNull($result);
}
/**
* Test isRequired in basic scenarios.
*
* @return void
*/
public function testIsRequired() {
$articles = TableRegistry::get('Articles');
$validator = $articles->validator();
$validator->add('title', 'minlength', [
'rule' => ['minlength', 10]
])
->add('body', 'maxlength', [
'rule' => ['maxlength', 1000]
])->allowEmpty('body');
$context = new EntityContext($this->request, [
'entity' => new Entity(),
'table' => 'Articles',
'validator' => $validator
]);
$this->assertTrue($context->isRequired('Articles.title'));
$this->assertTrue($context->isRequired('title'));
$this->assertFalse($context->isRequired('Articles.body'));
$this->assertFalse($context->isRequired('body'));
$this->assertFalse($context->isRequired('Herp.derp.derp'));
$this->assertFalse($context->isRequired('nope'));
}
public function testIsRequiredCustomValidationMethod() {
$this->markTestIncomplete();
}
public function testIsRequiredAssociated() {
$this->markTestIncomplete();
}
public function testIsRequiredAssociatedValidator() {
$this->markTestIncomplete();
}
}

0 comments on commit ccd4b8c

Please sign in to comment.
You can’t perform that action at this time.