Skip to content

Commit 700a6d5

Browse files
committed
prevent double constructor call
1 parent 1aa95a7 commit 700a6d5

File tree

4 files changed

+79
-0
lines changed

4 files changed

+79
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
v1.0.2 (2017-04)
2+
* prevent double constructor call
3+
14
v1.0.1 (2017-01-12)
25
* renamed "aux" directory
36
* more examples

src/Value/AbstractValue.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ final public function value () {
5050
}
5151

5252

53+
/**
54+
* This variable is used to prevent double constructor calls,
55+
* which could otherwise be used to change the wrapped value.
56+
*
57+
* @var bool
58+
*/
59+
private $is_set = false;
60+
61+
5362
/**
5463
* The constructor uses the subclass' IsValid method to test its input
5564
* argument. Valid values are stored in the new instance, invalid values
@@ -66,6 +75,11 @@ final public function value () {
6675
*/
6776
public function __construct ($raw_value) {
6877

78+
if ($this->is_set) {
79+
throw new DoubleConstructorCallException ("double constructor call is not allowed");
80+
}
81+
$this->is_set = true;
82+
6983
if ($raw_value instanceof static) {
7084
/* Re-wrapping an existing instance works,
7185
* the contained value has already passed the IsValid check once. */
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
namespace mle86\Value;
3+
4+
class DoubleConstructorCallException
5+
extends \BadMethodCallException
6+
{
7+
}
8+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
namespace mle86\Value\Tests;
3+
4+
use mle86\Value\AbstractValue;
5+
use mle86\Value\Value;
6+
require_once 'helpers/TestWrapper4.php';
7+
8+
9+
/**
10+
* Ensures that the class constructor
11+
* cannot be used to change the stored value.
12+
*/
13+
class DoubleConstructorCallTest
14+
extends \PHPUnit_Framework_TestCase
15+
{
16+
17+
const VALID_VALUE1 = "41111";
18+
const VALID_VALUE2 = "42222";
19+
20+
/**
21+
* @return Value
22+
*/
23+
public function testInstance () {
24+
$tw = new TestWrapper4 (self::VALID_VALUE1);
25+
26+
$this->assertTrue(($tw && $tw instanceof TestWrapper4 && $tw instanceof AbstractValue && $tw instanceof Value),
27+
"new TestWrapper4() did not result in a valid object");
28+
29+
$this->assertSame(self::VALID_VALUE1, $tw->value());
30+
31+
return $tw;
32+
}
33+
34+
/**
35+
* @depends testInstance
36+
*/
37+
public function testDoubleConstructorCall (Value $o) {
38+
try {
39+
$o->__construct(self::VALID_VALUE2);
40+
} catch (\Throwable $e) {
41+
// Okay, this produced an exception.
42+
// But we still need to check the value...
43+
}
44+
45+
$this->assertNotEquals(self::VALID_VALUE2, $o->value(),
46+
"Stored value can be CHANGED with a double constructor call!");
47+
$this->assertNotNull($o->value(),
48+
"Stored value was RESET by a double constructor call!");
49+
$this->assertEquals(self::VALID_VALUE1, $o->value(),
50+
"Stored value was UNEXPECTEDLY ALTERED by a double constructor call!");
51+
}
52+
53+
}
54+

0 commit comments

Comments
 (0)