Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Start to implement isRequired for the EntityContext.

Do some refactoring around entity location and validator handling.
  • Loading branch information...
commit ccd4b8cf8d201c71f163bd3cea1ee59d811e051b 1 parent 20b9b01
@markstory markstory authored
View
104 src/View/Form/EntityContext.php
@@ -54,9 +54,22 @@ 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.
*
* @param Cake\Network\Request
@@ -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) {
View
44 tests/TestCase/View/Form/EntityContextTest.php
@@ -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();
+ }
+
}
Please sign in to comment.
Something went wrong with that request. Please try again.