Skip to content

Commit 92b76bd

Browse files
committed
added cloning configuration.
1 parent 813b6a3 commit 92b76bd

File tree

7 files changed

+410
-15
lines changed

7 files changed

+410
-15
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
#### 0.4.0
4+
5+
* added global and local specify configs, for disabling cloning properties and changing cloning methods *2014-10-15*
6+
7+
38
#### 0.3.6 03/22/2014
49

510
* Cloning unclonnable items

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.3.6
1+
0.4.0

src/Codeception/Specify.php

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,55 @@
11
<?php
22
namespace Codeception;
33

4+
use Codeception\Specify\Config;
5+
use Codeception\Specify\ConfigBuilder;
6+
47
trait Specify {
58

9+
private $beforeSpecify;
10+
private $afterSpecify;
611

7-
protected $__beforeSpecify;
8-
protected $__afterSpecify;
12+
/**
13+
* @var Specify\Config
14+
*/
15+
private $specifyConfig;
16+
17+
/**
18+
* @var \DeepCopy\DeepCopy()
19+
*/
20+
private $copier;
21+
22+
private function specifyInit()
23+
{
24+
if ($this->copier) return;
25+
$this->copier = new \DeepCopy\DeepCopy();
26+
$this->copier->skipUncloneable();
27+
if (!$this->specifyConfig) $this->specifyConfig = Config::create();
28+
}
929

1030
function specify($specification, \Closure $callable = null, $params = [])
1131
{
1232
if (!$callable) return;
13-
// config
33+
$this->specifyInit();
34+
1435
$test = $callable->bindTo($this);
1536
$name = $this->getName();
1637
$this->setName($this->getName().' | '.$specification);
1738

18-
$copier = new \DeepCopy\DeepCopy();
19-
$copier->skipUncloneable();
2039
// copy current object properties
2140
$properties = get_object_vars($this);
2241
foreach ($properties as $property => $val) {
23-
if ($property == '__beforeSpecify') continue;
24-
if ($property == '__afterSpecify') continue;
25-
if ($property == '__savedProperties') continue;
26-
$this->$property = $copier->copy($val);
42+
if ($this->specifyConfig->propertyIgnored($property)) continue;
43+
if ($this->specifyConfig->classIgnored($val)) continue;
44+
45+
if ($this->specifyConfig->propertyIsShallowCloned($property)) {
46+
if (is_object($val)) {
47+
$this->$property = clone $val;
48+
}
49+
}
50+
if ($this->specifyConfig->propertyIsDeeplyCloned($property)) {
51+
$this->$property = $this->copier->copy($val);
52+
}
2753
}
2854

2955

@@ -32,14 +58,15 @@ function specify($specification, \Closure $callable = null, $params = [])
3258
$examples = $this->getSpecifyExamples($params);
3359

3460
foreach ($examples as $example) {
35-
if ($this->__beforeSpecify instanceof \Closure) $this->__beforeSpecify->__invoke();
61+
if ($this->beforeSpecify instanceof \Closure) $this->beforeSpecify->__invoke();
3662
$this->specifyExecute($test, $throws, $example);
3763

3864
// restore class properties
3965
foreach ($properties as $property => $val) {
66+
if (in_array($property, $this->specifyConfig->ignore)) continue;
4067
$this->$property = $val;
4168
}
42-
if ($this->__afterSpecify instanceof \Closure) $this->__afterSpecify->__invoke();
69+
if ($this->afterSpecify instanceof \Closure) $this->afterSpecify->__invoke();
4370
}
4471

4572
$this->setName($name);
@@ -102,19 +129,24 @@ private function specifyExecute($test, $throws = false, $examples = array())
102129
}
103130
}
104131

132+
public function specifyConfig()
133+
{
134+
return new ConfigBuilder($this->specifyConfig);
135+
}
136+
105137
function beforeSpecify(\Closure $callable = null)
106138
{
107-
$this->__beforeSpecify = $callable->bindTo($this);
139+
$this->beforeSpecify = $callable->bindTo($this);
108140
}
109141

110142
function afterSpecify(\Closure $callable = null)
111143
{
112-
$this->__afterSpecify = $callable->bindTo($this);
144+
$this->afterSpecify = $callable->bindTo($this);
113145
}
114146

115147
function cleanSpecify()
116148
{
117-
$this->__beforeSpecify = $this->__afterSpecify = null;
149+
$this->beforeSpecify = $this->afterSpecify = null;
118150
}
119151

120152

src/Codeception/Specify/Config.php

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<?php
2+
namespace Codeception\Specify;
3+
4+
/**
5+
* Global Specify configuration. Should be set in bootstrap.
6+
*
7+
* ```php
8+
* <?php
9+
* // disable deep cloning of properties inside specify block
10+
* \Codeception\Specify\Config::setDeepClone(false);
11+
* ?>
12+
* ```
13+
*/
14+
class Config
15+
{
16+
protected static $ignoredClasses = [
17+
'Codeception\Actor',
18+
'Symfony\Component\EventDispatcher\EventDispatcher',
19+
'Codeception\Scenario',
20+
'Codeception\Lib\Parser'
21+
];
22+
23+
protected static $ignoredProperties = [
24+
25+
// PHPUnit
26+
'backupGlobals',
27+
'backupGlobalsBlacklist',
28+
'backupStaticAttributes',
29+
'backupStaticAttributesBlacklist',
30+
'runTestInSeparateProcess',
31+
'preserveGlobalState',
32+
33+
// Codeception
34+
'dependencies',
35+
'dependencyInput',
36+
];
37+
38+
protected static $deepClone = true;
39+
40+
public $is_deep = true;
41+
public $ignore = array();
42+
public $ignore_classes = array();
43+
public $shallow = array();
44+
public $deep = array();
45+
46+
public function propertyIgnored($property)
47+
{
48+
return in_array($property, $this->ignore);
49+
}
50+
51+
public function classIgnored($value)
52+
{
53+
if (!is_object($value)) return false;
54+
return in_array(get_class($value), $this->ignore_classes);
55+
}
56+
57+
public function propertyIsShallowCloned($property)
58+
{
59+
if (!$this->is_deep and !in_array($property, $this->deep)) {
60+
return true;
61+
}
62+
return in_array($property, $this->shallow);
63+
}
64+
65+
public function propertyIsDeeplyCloned($property)
66+
{
67+
if ($this->is_deep and !in_array($property, $this->shallow)) {
68+
return true;
69+
}
70+
return in_array($property, $this->deep);
71+
}
72+
73+
/**
74+
* Enable or disable using of deep cloning for objects by default.
75+
* Deep cloning is the default.
76+
*
77+
* @param boolean $deepClone
78+
*/
79+
public static function setDeepClone($deepClone)
80+
{
81+
self::$deepClone = $deepClone;
82+
}
83+
84+
/***
85+
* Set classes which are going to be ignored for cloning in specify blocks.
86+
*
87+
* @param array $ignoredClasses
88+
*/
89+
public static function setIgnoredClasses($ignoredClasses)
90+
{
91+
self::$ignoredClasses = $ignoredClasses;
92+
}
93+
94+
/**
95+
* Globally set class properties are going to be ignored for cloning in specify blocks.
96+
*
97+
* ```php
98+
* <?php
99+
* \Codeception\Specify\Config::setIgnoredProperties(['users', 'repository']);
100+
* ```
101+
*
102+
* @param array $ignoredProperties
103+
*/
104+
public static function setIgnoredProperties($ignoredProperties)
105+
{
106+
self::$ignoredProperties = $ignoredProperties;
107+
}
108+
109+
/**
110+
* Add specific classes to cloning ignore list. Instances of those classes won't be cloned for specify blocks.
111+
*
112+
* ```php
113+
* <?php
114+
* \Codeception\Specify\Config::addIgnoredClasses(['\Acme\Domain\UserRepo', '\Acme\Domain\PostRepo']);
115+
* ?>
116+
* ```
117+
*
118+
* @param $ignoredClasses
119+
*/
120+
public static function addIgnoredClasses($ignoredClasses)
121+
{
122+
self::$ignoredClasses = array_merge(self::$ignoredClasses, $ignoredClasses);
123+
}
124+
125+
private function __construct()
126+
{
127+
}
128+
129+
/**
130+
* @return Config
131+
*/
132+
static function create()
133+
{
134+
$config = new Config();
135+
$config->is_deep = self::$deepClone;
136+
$config->ignore = self::$ignoredProperties;
137+
$config->ignore_classes = self::$ignoredClasses;
138+
$config->shallow = array();
139+
$config->deep = array();
140+
return $config;
141+
}
142+
}

0 commit comments

Comments
 (0)