Browse Source

Fix addContextProvider()

Update addContextProvider() so it prepends new items into the list of
providers. This makes it easier for userland additions that customize
EntityContext or ArrayContext. Tests were added for the replace and
augment scenarios.

Refs #4967
Mark Story 11 years ago
parent
commit
6b4d755653
2 changed files with 54 additions and 11 deletions
  1. 15 9
      src/View/Helper/FormHelper.php
  2. 39 2
      tests/TestCase/View/Helper/FormHelperTest.php

+ 15 - 9
src/View/Helper/FormHelper.php

@@ -161,7 +161,7 @@ class FormHelper extends Helper {
  * @var array
  * @see addContextProvider
  */
-	protected $_contextProviders;
+	protected $_contextProviders = [];
 
 /**
  * The action attribute value of the last created form.
@@ -211,12 +211,6 @@ class FormHelper extends Helper {
  * @return void
  */
 	protected function _addDefaultContextProviders() {
-		$this->addContextProvider('array', function ($request, $data) {
-			if (is_array($data['entity']) && isset($data['entity']['schema'])) {
-				return new ArrayContext($request, $data['entity']);
-			}
-		});
-
 		$this->addContextProvider('orm', function ($request, $data) {
 			if (is_array($data['entity']) || $data['entity'] instanceof Traversable) {
 				$pass = (new Collection($data['entity']))->first() !== null;
@@ -231,6 +225,12 @@ class FormHelper extends Helper {
 				return new EntityContext($request, $data);
 			}
 		});
+
+		$this->addContextProvider('array', function ($request, $data) {
+			if (is_array($data['entity']) && isset($data['entity']['schema'])) {
+				return new ArrayContext($request, $data['entity']);
+			}
+		});
 	}
 
 /**
@@ -2256,7 +2256,12 @@ class FormHelper extends Helper {
  * @return void
  */
 	public function addContextProvider($type, callable $check) {
-		$this->_contextProviders[$type] = $check;
+		foreach ($this->_contextProviders as $i => $provider) {
+			if ($provider['type'] === $type) {
+				unset($this->_contextProviders[$i]);
+			}
+		}
+		array_unshift($this->_contextProviders, ['type' => $type, 'callable' => $check]);
 	}
 
 /**
@@ -2290,7 +2295,8 @@ class FormHelper extends Helper {
 		}
 		$data += ['entity' => null];
 
-		foreach ($this->_contextProviders as $key => $check) {
+		foreach ($this->_contextProviders as $provider) {
+			$check = $provider['callable'];
 			$context = $check($this->request, $data);
 			if ($context) {
 				break;

+ 39 - 2
tests/TestCase/View/Helper/FormHelperTest.php

@@ -241,12 +241,49 @@ class FormHelperTest extends TestCase {
  */
 	public function testAddContextProvider() {
 		$context = 'My data';
-		$this->Form->addContextProvider('test', function ($request, $data) use ($context) {
+		$stub = $this->getMock('Cake\View\Form\ContextInterface');
+		$this->Form->addContextProvider('test', function ($request, $data) use ($context, $stub) {
 			$this->assertInstanceOf('Cake\Network\Request', $request);
 			$this->assertEquals($context, $data['entity']);
-			return $this->getMock('Cake\View\Form\ContextInterface');
+			return $stub;
 		});
 		$this->Form->create($context);
+		$result = $this->Form->context();
+		$this->assertSame($stub, $result);
+	}
+
+/**
+ * Test replacing a context class.
+ *
+ * @return void
+ */
+	public function testAddContextProviderReplace() {
+		$entity = new Article();
+		$stub = $this->getMock('Cake\View\Form\ContextInterface');
+		$this->Form->addContextProvider('orm', function ($request, $data) use ($stub) {
+			return $stub;
+		});
+		$this->Form->create($entity);
+		$result = $this->Form->context();
+		$this->assertSame($stub, $result);
+	}
+
+/**
+ * Test overriding a context class.
+ *
+ * @return void
+ */
+	public function testAddContextProviderAdd() {
+		$entity = new Article();
+		$stub = $this->getMock('Cake\View\Form\ContextInterface');
+		$this->Form->addContextProvider('newshiny', function ($request, $data) use ($stub) {
+			if ($data['entity'] instanceof Entity) {
+				return $stub;
+			}
+		});
+		$this->Form->create($entity);
+		$result = $this->Form->context();
+		$this->assertSame($stub, $result);
 	}
 
 /**