Skip to content

Commit

Permalink
Add emulation for public properties.
Browse files Browse the repository at this point in the history
In order to get to PSR7 compliance & immutability the various public
properties will all need to be deprecated. These public properties don't
have accessors and are currently being offered as attributes in the
middleware layers. Being consistent will allow us to remove the
RequestTransformer in the long run.
  • Loading branch information
markstory committed Aug 31, 2016
1 parent 20e8d3c commit bd46657
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 3 deletions.
29 changes: 27 additions & 2 deletions src/Network/Request.php
Expand Up @@ -19,6 +19,7 @@
use Cake\Core\Configure;
use Cake\Network\Exception\MethodNotAllowedException;
use Cake\Utility\Hash;
use InvalidArgumentException;

/**
* A class that helps wrap Request information and particulars about a single request.
Expand Down Expand Up @@ -1437,7 +1438,12 @@ public function withParam($name, $value)
public function withAttribute($name, $value)
{
$new = clone $this;
$new->attributes[$name] = $value;
$emulated = ['webroot', 'base', 'params'];
if (in_array($name, $emulated, true)) {
$new->{$name} = $value;
} else {
$new->attributes[$name] = $value;
}
return $new;
}

Expand All @@ -1447,10 +1453,17 @@ public function withAttribute($name, $value)
* @param string $name The attribute name.
* @param mixed $value The value of the attribute.
* @return static
* @throws InvalidArgumentException
*/
public function withoutAttribute($name)
{
$new = clone $this;
$emulated = ['webroot', 'base', 'params'];
if (in_array($name, $emulated, true)) {
throw new InvalidArgumentException(
"You cannot unset '$name'. It is a required CakePHP attribute."
);
}
unset($new->attributes[$name]);
return $new;
}
Expand All @@ -1464,6 +1477,10 @@ public function withoutAttribute($name)
*/
public function getAttribute($name, $default = null)
{
$emulated = ['webroot', 'base', 'params'];
if (in_array($name, $emulated, true)) {
return $this->{$name};
}
if (array_key_exists($name, $this->attributes)) {
return $this->attributes[$name];
}
Expand All @@ -1473,11 +1490,19 @@ public function getAttribute($name, $default = null)
/**
* Get all the attributes in the request.
*
* This will include the params, webroot, and base attributes that CakePHP
* provides.
*
* @return array
*/
public function getAttributes()
{
return $this->attributes;
$emulated = [
'params' => $this->params,
'webroot' => $this->webroot,
'base' => $this->base
];
return $this->attributes + $emulated;
}

/**
Expand Down
95 changes: 94 additions & 1 deletion tests/TestCase/Network/RequestTest.php
Expand Up @@ -2659,6 +2659,63 @@ public function testWithAttribute()
$this->assertSame(['complex'], $update->getAttribute('key'));
}

/**
* Test that withAttribute() can modify the deprecated public properties.
*
* @return void
*/
public function testWithAttributesCompatibility()
{
$request = new Request([
'params' => [
'controller' => 'Articles',
'action' => 'index'
],
'base' => '/cakeapp',
'webroot' => '/cakeapp/'
]);

$new = $request->withAttribute('base', '/replace')
->withAttribute('webroot', '/replace/')
->withAttribute('params', ['controller' => 'Tags']);

// Original request should not change.
$this->assertSame('/cakeapp', $request->getAttribute('base'));
$this->assertSame('/cakeapp/', $request->getAttribute('webroot'));
$this->assertSame(
['controller' => 'Articles', 'action' => 'index'],
$request->getAttribute('params')
);

$this->assertSame('/replace', $new->getAttribute('base'));
$this->assertSame('/replace', $new->base);
$this->assertSame('/replace/', $new->getAttribute('webroot'));
$this->assertSame('/replace/', $new->webroot);

$this->assertSame(['controller' => 'Tags'], $new->getAttribute('params'));
$this->assertSame(['controller' => 'Tags'], $new->params);
}

/**
* Test that getAttribute() can read deprecated public properties.
*
* @dataProvider emulatedPropertyProvider
* @return void
*/
public function testGetAttributesCompatibility($prop)
{
$request = new Request([
'params' => [
'controller' => 'Articles',
'action' => 'index'
],
'base' => '/cakeapp',
'webroot' => '/cakeapp/'
]);

$this->assertSame($request->{$prop}, $request->getAttribute($prop));
}

/**
* Test getting all attributes.
*
Expand All @@ -2676,7 +2733,16 @@ public function testGetAttributes()
$expected = [
'key' => 'value',
'nully' => null,
'falsey' => false
'falsey' => false,
'params' => [
'plugin' => null,
'controller' => null,
'action' => null,
'_ext' => null,
'pass' => [],
],
'webroot' => '',
'base' => ''
];
$this->assertEquals($expected, $new->getAttributes());
}
Expand All @@ -2696,6 +2762,33 @@ public function testWithoutAttribute()
$this->assertNull($update->getAttribute('key'));
}

/**
* Test that withoutAttribute() cannot remove deprecated public properties.
*
* @dataProvider emulatedPropertyProvider
* @expectedException InvalidArgumentException
* @return void
*/
public function testWithoutAttributesDenyEmulatedProperties($prop)
{
$request = new Request([]);
$request->withoutAttribute($prop);
}

/**
* Data provider for emulated property tests.
*
* @return array
*/
public function emulatedPropertyProvider()
{
return [
['params'],
['base'],
['webroot']
];
}

/**
* loadEnvironment method
*
Expand Down

0 comments on commit bd46657

Please sign in to comment.