This commit is contained in:
2020-03-27 10:13:51 +07:00
commit da1024a5b3
16614 changed files with 3274282 additions and 0 deletions

View File

@@ -0,0 +1,156 @@
<?php
namespace Codeception\Specify;
/**
* Global Specify configuration. Should be set in bootstrap.
*
* ```php
* <?php
* // disable deep cloning of properties inside specify block
* \Codeception\Specify\Config::setDeepClone(false);
* ?>
* ```
*/
class Config
{
protected static $ignoredClasses = [
'Codeception\Actor',
'Symfony\Component\EventDispatcher\EventDispatcher',
'Codeception\Scenario',
'Codeception\Lib\Parser'
];
protected static $ignoredProperties = [
// PHPUnit
'backupGlobals',
'backupGlobalsBlacklist',
'backupStaticAttributes',
'backupStaticAttributesBlacklist',
'runTestInSeparateProcess',
'preserveGlobalState',
// Codeception
'dependencies',
'dependencyInput',
'tester',
'guy',
'name'
];
protected static $deepClone = true;
public $is_deep = true;
public $ignore = array();
public $ignore_classes = array();
public $shallow = array();
public $deep = array();
public $only = null;
public function propertyIgnored($property)
{
if ($this->only) {
return !in_array($property, $this->only);
}
return in_array($property, $this->ignore);
}
public function classIgnored($value)
{
if (!is_object($value)) return false;
return in_array(get_class($value), $this->ignore_classes);
}
public function propertyIsShallowCloned($property)
{
if ($this->only and !$this->is_deep) {
return in_array($property, $this->only);
}
if (!$this->is_deep and !in_array($property, $this->deep)) {
return true;
}
return in_array($property, $this->shallow);
}
public function propertyIsDeeplyCloned($property)
{
if ($this->only and $this->is_deep) {
return in_array($property, $this->only);
}
if ($this->is_deep and !in_array($property, $this->shallow)) {
return true;
}
return in_array($property, $this->deep);
}
/**
* Enable or disable using of deep cloning for objects by default.
* Deep cloning is the default.
*
* @param boolean $deepClone
*/
public static function setDeepClone($deepClone)
{
self::$deepClone = $deepClone;
}
/***
* Set classes which are going to be ignored for cloning in specify blocks.
*
* @param array $ignoredClasses
*/
public static function setIgnoredClasses($ignoredClasses)
{
self::$ignoredClasses = $ignoredClasses;
}
/**
* Globally set class properties are going to be ignored for cloning in specify blocks.
*
* ```php
* <?php
* \Codeception\Specify\Config::setIgnoredProperties(['users', 'repository']);
* ```
*
* @param array $ignoredProperties
*/
public static function setIgnoredProperties($ignoredProperties)
{
self::$ignoredProperties = $ignoredProperties;
}
/**
* Add specific classes to cloning ignore list. Instances of those classes won't be cloned for specify blocks.
*
* ```php
* <?php
* \Codeception\Specify\Config::addIgnoredClasses(['\Acme\Domain\UserRepo', '\Acme\Domain\PostRepo']);
* ?>
* ```
*
* @param $ignoredClasses
*/
public static function addIgnoredClasses($ignoredClasses)
{
self::$ignoredClasses = array_merge(self::$ignoredClasses, $ignoredClasses);
}
private function __construct()
{
}
/**
* @return Config
*/
static function create()
{
$config = new Config();
$config->is_deep = self::$deepClone;
$config->ignore = self::$ignoredProperties;
$config->ignore_classes = self::$ignoredClasses;
$config->shallow = array();
$config->deep = array();
$config->only = null;
return $config;
}
}

View File

@@ -0,0 +1,172 @@
<?php
namespace Codeception\Specify;
/**
* Configure Specify usage.
*
* Specify copies properties of object and restores them for each specify block.
* Objects can be cloned deeply or using standard `clone` operator.
* Specify can be configured to prevent specific properties in specify blocks, to choose default cloning method,
* or cloning method for specific properties.
*
* ```php
* <?php
* $this->specifyConfig()
* ->ignore('user') // do not clone
* ?>
* ```
*/
class ConfigBuilder
{
/**
* @var Config
*/
protected $config;
public function __construct(Config $config = null)
{
$this->config = $config;
if (!$config) {
$this->config = Config::create();
}
}
/**
* Ignore cloning specific object properties in specify blocks.
*
* ```php
* <?php
* $this->user = new User;
* $this->specifyConfig()->ignore('user');
* $this->specify('change user name', function() {
* $this->user->name = 'davert';
* });
* $this->user->name == 'davert'; // name changed
* ?>
* ```
*
* @param array $properties
* @return $this
*/
public function ignore($properties = array())
{
if (!is_array($properties)) {
$properties = func_get_args();
}
$this->config->ignore = array_merge($this->config->ignore, $properties);
return $this;
}
/**
* Adds specific class to ignore list, if property is an instance of class it will not be cloned for specify block.
*
* @param array $classes
* @return $this
*/
public function ignoreClasses($classes = array())
{
$this->config->ignore_classes = array_merge($this->config->ignore_classes, $classes);
return $this;
}
/**
* Turn on/off deep cloning mode.
* Deep cloning mode can also be specified for specific properties.
*
* ```php
* <?php
* $this->user = new User;
* $this->post = new Post;
* $this->tag = new Tag;
*
* // turn on deep cloning by default
* $this->specifyConfig()->deepClone();
*
* // turn off deep cloning by default
* $this->specifyConfig()->deepClone(false);
*
* // deep clone only user and tag property
* $this->specifyConfig()->deepClone('user', 'tag');
*
* // alternatively
* $this->specifyConfig()->deepClone(['user', 'tag']);
* ?>
* ```
*
* @param bool $properties
* @return $this
*/
public function deepClone($properties = true)
{
if (is_bool($properties)) {
$this->config->is_deep = $properties;
return $this;
}
if (!is_array($properties)) {
$properties = func_get_args();
}
$this->config->deep = $properties;
return $this;
}
/**
* Disable deep cloning mode, use shallow cloning by default, which is faster.
* Deep cloning mode can also be disabled for specific properties.
*
* ```php
* <?php
* $this->user = new User;
* $this->post = new Post;
* $this->tag = new Tag;
*
* // turn off deep cloning by default
* $this->specifyConfig()->shallowClone();
*
* // turn on deep cloning by default
* $this->specifyConfig()->shallowClone(false);
*
* // shallow clone only user and tag property
* $this->specifyConfig()->shallowClone('user', 'tag');
*
* // alternatively
* $this->specifyConfig()->shallowClone(['user', 'tag']);
* ?>
* ```
*
* @param bool $properties
* @return $this
*/
public function shallowClone($properties = true)
{
if (is_bool($properties)) {
$this->config->is_deep = !$properties;
return $this;
}
if (!is_array($properties)) {
$properties = func_get_args();
}
$this->config->shallow = array_merge($this->config->shallow, $properties);
return $this;
}
/**
* Clone only specific properties
*
* ```php
* <?php
* $this->specifyConfig()->cloneOnly('user', 'post');
* ?>
* ```
*
* @param $properties
* @return $this
*/
public function cloneOnly($properties)
{
if (!is_array($properties)) {
$properties = func_get_args();
}
$this->config->only = $properties;
return $this;
}
}

View File

@@ -0,0 +1,78 @@
<?php
namespace Codeception\Specify;
/**
* Helper for manipulating by an object property.
*
* @author Roman Ishchenko <roman@ishchenko.ck.ua>
*/
class ObjectProperty
{
/**
* @var mixed
*/
private $_owner;
/**
* @var \ReflectionProperty|string
*/
private $_property;
/**
* @var mixed
*/
private $_initValue;
/**
* ObjectProperty constructor.
*
* @param $owner
* @param $property
* @param $value
*/
public function __construct($owner, $property, $value = null)
{
$this->_owner = $owner;
$this->_property = $property;
if (!($this->_property instanceof \ReflectionProperty)) {
$this->_property = new \ReflectionProperty($owner, $this->_property);
}
$this->_property->setAccessible(true);
$this->_initValue = ($value === null ? $this->getValue() : $value);
}
/**
* @return string
*/
public function getName()
{
return $this->_property->getName();
}
/**
* Restores initial value
*/
public function restoreValue()
{
$this->setValue($this->_initValue);
}
/**
* @return mixed
*/
public function getValue()
{
return $this->_property->getValue($this->_owner);
}
/**
* @param mixed $value
*/
public function setValue($value)
{
$this->_property->setValue($this->_owner, $value);
}
}