From fd485100dd59aae4527ff8335eb1d829536686cf Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 16 Feb 2018 16:27:24 +0100 Subject: [PATCH] Removed Nette\Object & ObjectMixin (BC break) --- src/Utils/Object.php | 162 -------- src/Utils/ObjectMixin.php | 387 +----------------- tests/Utils/Object.arrayProperty.phpt | 35 -- tests/Utils/Object.closureProperty.phpt | 66 --- tests/Utils/Object.events.phpt | 82 ---- tests/Utils/Object.extensionMethod.phpt | 44 -- .../Object.extensionMethodViaInterface.phpt | 64 --- tests/Utils/Object.magicMethod.errors.phpt | 68 --- .../Utils/Object.magicMethod.inheritance.phpt | 49 --- tests/Utils/Object.magicMethod.phpt | 56 --- tests/Utils/Object.magicMethod.types.phpt | 66 --- tests/Utils/Object.methodGetter.phpt | 73 ---- tests/Utils/Object.property.phpt | 112 ----- tests/Utils/Object.referenceProperty.phpt | 37 -- tests/Utils/Object.reflection.phpt | 22 - tests/Utils/Object.undeclaredMethod.phpt | 58 --- tests/Utils/Object.unsetProperty.phpt | 46 --- tests/Utils/ObjectMixin.checkType().phpt | 170 -------- 18 files changed, 5 insertions(+), 1592 deletions(-) delete mode 100644 src/Utils/Object.php delete mode 100644 tests/Utils/Object.arrayProperty.phpt delete mode 100644 tests/Utils/Object.closureProperty.phpt delete mode 100644 tests/Utils/Object.events.phpt delete mode 100644 tests/Utils/Object.extensionMethod.phpt delete mode 100644 tests/Utils/Object.extensionMethodViaInterface.phpt delete mode 100644 tests/Utils/Object.magicMethod.errors.phpt delete mode 100644 tests/Utils/Object.magicMethod.inheritance.phpt delete mode 100644 tests/Utils/Object.magicMethod.phpt delete mode 100644 tests/Utils/Object.magicMethod.types.phpt delete mode 100644 tests/Utils/Object.methodGetter.phpt delete mode 100644 tests/Utils/Object.property.phpt delete mode 100644 tests/Utils/Object.referenceProperty.phpt delete mode 100644 tests/Utils/Object.reflection.phpt delete mode 100644 tests/Utils/Object.undeclaredMethod.phpt delete mode 100644 tests/Utils/Object.unsetProperty.phpt delete mode 100644 tests/Utils/ObjectMixin.checkType().phpt diff --git a/src/Utils/Object.php b/src/Utils/Object.php deleted file mode 100644 index b1a17d832..000000000 --- a/src/Utils/Object.php +++ /dev/null @@ -1,162 +0,0 @@ - - * $val = $obj->label; // equivalent to $val = $obj->getLabel(); - * $obj->label = 'Nette'; // equivalent to $obj->setLabel('Nette'); - * - * Property names are case-sensitive, and they are written in the camelCaps - * or PascalCaps. - * - * Event functionality is provided by declaration of property named 'on{Something}' - * Multiple handlers are allowed. - * - * public $onClick; // declaration in class - * $this->onClick[] = 'callback'; // attaching event handler - * if (!empty($this->onClick)) ... // are there any handlers? - * $this->onClick($sender, $arg); // raises the event with arguments - * - * - * Adding method to class (i.e. to all instances) works similar to JavaScript - * prototype property. The syntax for adding a new method is: - * - * MyClass::extensionMethod('newMethod', function (MyClass $obj, $arg, ...) { ... }); - * $obj = new MyClass; - * $obj->newMethod($x); - * - * - * @property-read Nette\Reflection\ClassType|\ReflectionClass $reflection - * @deprecated use trait Nette\SmartObject - */ -abstract class Object -{ - - /** - * Access to reflection. - * @return Nette\Reflection\ClassType|\ReflectionClass - */ - public static function getReflection() - { - $class = class_exists(Nette\Reflection\ClassType::class) ? Nette\Reflection\ClassType::class : 'ReflectionClass'; - return new $class(get_called_class()); - } - - - /** - * Call to undefined method. - * @param string method name - * @param array arguments - * @return mixed - * @throws MemberAccessException - */ - public function __call($name, $args) - { - return Nette\Utils\ObjectMixin::call($this, $name, $args); - } - - - /** - * Call to undefined static method. - * @param string method name (in lower case!) - * @param array arguments - * @return mixed - * @throws MemberAccessException - */ - public static function __callStatic($name, $args) - { - return Nette\Utils\ObjectMixin::callStatic(get_called_class(), $name, $args); - } - - - /** - * Adding method to class. - * @param string method name - * @param callable - * @return mixed - */ - public static function extensionMethod($name, $callback = null) - { - if (strpos($name, '::') === false) { - $class = get_called_class(); - } else { - [$class, $name] = explode('::', $name); - $class = (new \ReflectionClass($class))->getName(); - } - if ($callback === null) { - return Nette\Utils\ObjectMixin::getExtensionMethod($class, $name); - } else { - Nette\Utils\ObjectMixin::setExtensionMethod($class, $name, $callback); - } - } - - - /** - * Returns property value. Do not call directly. - * @param string property name - * @return mixed property value - * @throws MemberAccessException if the property is not defined. - */ - public function &__get($name) - { - return Nette\Utils\ObjectMixin::get($this, $name); - } - - - /** - * Sets value of a property. Do not call directly. - * @param string property name - * @param mixed property value - * @return void - * @throws MemberAccessException if the property is not defined or is read-only - */ - public function __set($name, $value) - { - Nette\Utils\ObjectMixin::set($this, $name, $value); - } - - - /** - * Is property defined? - * @param string property name - * @return bool - */ - public function __isset($name) - { - return Nette\Utils\ObjectMixin::has($this, $name); - } - - - /** - * Access to undeclared property. - * @param string property name - * @return void - * @throws MemberAccessException - */ - public function __unset($name) - { - Nette\Utils\ObjectMixin::remove($this, $name); - } -} diff --git a/src/Utils/ObjectMixin.php b/src/Utils/ObjectMixin.php index e6067c7e6..21bb0fee6 100644 --- a/src/Utils/ObjectMixin.php +++ b/src/Utils/ObjectMixin.php @@ -10,7 +10,6 @@ namespace Nette\Utils; use Nette; -use Nette\MemberAccessException; /** @@ -21,399 +20,23 @@ final class ObjectMixin { use Nette\StaticClass; - /** @var array [name => [type => callback]] used by extension methods */ - private static $extMethods = []; - - - /** - * __call() implementation. - * @param object - * @return mixed - * @throws MemberAccessException - */ - public static function call($_this, string $name, array $args) - { - $class = get_class($_this); - $isProp = ObjectHelpers::hasProperty($class, $name); - - if ($name === '') { - throw new MemberAccessException("Call to class '$class' method without name."); - - } elseif ($isProp === 'event') { // calling event handlers - if (is_iterable($_this->$name)) { - foreach ($_this->$name as $handler) { - $handler(...$args); - } - } elseif ($_this->$name !== null) { - throw new Nette\UnexpectedValueException("Property $class::$$name must be iterable or null, " . gettype($_this->$name) . ' given.'); - } - - } elseif ($isProp && $_this->$name instanceof \Closure) { // closure in property - return ($_this->$name)(...$args); - - } elseif (($methods = &self::getMethods($class)) && isset($methods[$name]) && is_array($methods[$name])) { // magic @methods - [$op, $rp, $type] = $methods[$name]; - if (count($args) !== ($op === 'get' ? 0 : 1)) { - throw new Nette\InvalidArgumentException("$class::$name() expects " . ($op === 'get' ? 'no' : '1') . ' argument, ' . count($args) . ' given.'); - - } elseif ($type && $args && !self::checkType($args[0], $type)) { - throw new Nette\InvalidArgumentException("Argument passed to $class::$name() must be $type, " . gettype($args[0]) . ' given.'); - } - - if ($op === 'get') { - return $rp->getValue($_this); - } elseif ($op === 'set') { - $rp->setValue($_this, $args[0]); - } elseif ($op === 'add') { - $val = $rp->getValue($_this); - $val[] = $args[0]; - $rp->setValue($_this, $val); - } - return $_this; - - } elseif ($cb = self::getExtensionMethod($class, $name)) { // extension methods - return $cb($_this, ...$args); - - } else { - ObjectHelpers::strictCall($class, $name, array_keys(self::getExtensionMethods($class))); - } - } - - - /** - * __callStatic() implementation. - * @throws MemberAccessException - */ - public static function callStatic(string $class, string $method, array $args) - { - ObjectHelpers::strictStaticCall($class, $method); - } - - - /** - * __get() implementation. - * @param object - * @return mixed - * @throws MemberAccessException if the property is not defined. - */ - public static function &get($_this, string $name) - { - $class = get_class($_this); - $uname = ucfirst($name); - $methods = &self::getMethods($class); - - if ($name === '') { - throw new MemberAccessException("Cannot read a class '$class' property without name."); - - } elseif (isset($methods[$m = 'get' . $uname]) || isset($methods[$m = 'is' . $uname])) { // property getter - if ($methods[$m] === 0) { - $methods[$m] = (new \ReflectionMethod($class, $m))->returnsReference(); - } - if ($methods[$m] === true) { - return $_this->$m(); - } else { - $val = $_this->$m(); - return $val; - } - - } elseif (isset($methods[$name])) { // public method as closure getter - if (preg_match('#^(is|get|has)([A-Z]|$)#', $name) && !(new \ReflectionMethod($class, $name))->getNumberOfRequiredParameters()) { - trigger_error("Did you forget parentheses after $name" . self::getSource() . '?', E_USER_WARNING); - } - $val = Callback::closure($_this, $name); - return $val; - - } elseif (isset($methods['set' . $uname])) { // property getter - throw new MemberAccessException("Cannot read a write-only property $class::\$$name."); - - } else { - ObjectHelpers::strictGet($class, $name); - } - } - - - /** - * __set() implementation. - * @param object - * @throws MemberAccessException if the property is not defined or is read-only - */ - public static function set($_this, string $name, $value): void - { - $class = get_class($_this); - $uname = ucfirst($name); - $methods = &self::getMethods($class); - - if ($name === '') { - throw new MemberAccessException("Cannot write to a class '$class' property without name."); - - } elseif (ObjectHelpers::hasProperty($class, $name)) { // unsetted property - $_this->$name = $value; - - } elseif (isset($methods[$m = 'set' . $uname])) { // property setter - $_this->$m($value); - - } elseif (isset($methods['get' . $uname]) || isset($methods['is' . $uname])) { // property setter - throw new MemberAccessException("Cannot write to a read-only property $class::\$$name."); - - } else { - ObjectHelpers::strictSet($class, $name); - } - } - - - /** - * __unset() implementation. - * @param object - * @throws MemberAccessException - */ - public static function remove($_this, string $name): void - { - $class = get_class($_this); - if (!ObjectHelpers::hasProperty($class, $name)) { - throw new MemberAccessException("Cannot unset the property $class::\$$name."); - } - } - - - /** - * __isset() implementation. - * @param object - */ - public static function has($_this, string $name): bool - { - $name = ucfirst($name); - $methods = &self::getMethods(get_class($_this)); - return $name !== '' && (isset($methods['get' . $name]) || isset($methods['is' . $name])); - } - - - /********************* magic @methods ****************d*g**/ - - - /** - * Returns array of magic methods defined by annotation @method. - */ - public static function getMagicMethods(string $class): array - { - $rc = new \ReflectionClass($class); - preg_match_all('~^ - [ \t*]* @method [ \t]+ - (?: [^\s(]+ [ \t]+ )? - (set|get|is|add) ([A-Z]\w*) - (?: ([ \t]* \() [ \t]* ([^)$\s]*) )? - ()~mx', (string) $rc->getDocComment(), $matches, PREG_SET_ORDER); - - $methods = []; - foreach ($matches as [, $op, $prop, $bracket, $type]) { - if ($bracket !== '(') { - trigger_error("Bracket must be immediately after @method $op$prop() in class $class.", E_USER_WARNING); - } - $name = $op . $prop; - $prop = strtolower($prop[0]) . substr($prop, 1) . ($op === 'add' ? 's' : ''); - if ($rc->hasProperty($prop) && ($rp = $rc->getProperty($prop)) && !$rp->isStatic()) { - $rp->setAccessible(true); - if ($op === 'get' || $op === 'is') { - $type = null; - $op = 'get'; - } elseif (!$type && preg_match('#@var[ \t]+(\S+)' . ($op === 'add' ? '\[\]#' : '#'), (string) $rp->getDocComment(), $m)) { - $type = $m[1]; - } - if ($rc->inNamespace() && preg_match('#^[A-Z]\w+(\[|\||\z)#', (string) $type)) { - $type = $rc->getNamespaceName() . '\\' . $type; - } - $methods[$name] = [$op, $rp, $type]; - } - } - return $methods; - } - - - /** - * Finds whether a variable is of expected type and do non-data-loss conversion. - * @internal - */ - public static function checkType(&$val, string $type): bool - { - if (strpos($type, '|') !== false) { - $found = null; - foreach (explode('|', $type) as $type) { - $tmp = $val; - if (self::checkType($tmp, $type)) { - if ($val === $tmp) { - return true; - } - $found[] = $tmp; - } - } - if ($found) { - $val = $found[0]; - return true; - } - return false; - - } elseif (substr($type, -2) === '[]') { - if (!is_array($val)) { - return false; - } - $type = substr($type, 0, -2); - $res = []; - foreach ($val as $k => $v) { - if (!self::checkType($v, $type)) { - return false; - } - $res[$k] = $v; - } - $val = $res; - return true; - } - - switch (strtolower($type)) { - case null: - case 'mixed': - return true; - case 'bool': - case 'boolean': - return ($val === null || is_scalar($val)) && settype($val, 'bool'); - case 'string': - return ($val === null || is_scalar($val) || (is_object($val) && method_exists($val, '__toString'))) && settype($val, 'string'); - case 'int': - case 'integer': - return ($val === null || is_bool($val) || is_numeric($val)) && ((float) (int) $val === (float) $val) && settype($val, 'int'); - case 'float': - return ($val === null || is_bool($val) || is_numeric($val)) && settype($val, 'float'); - case 'scalar': - case 'array': - case 'object': - case 'callable': - case 'resource': - case 'null': - return ("is_$type")($val); - default: - return $val instanceof $type; - } - } - - - /********************* extension methods ****************d*g**/ - - /** - * Adds a method to class. + * @deprecated use ObjectHelpers::getSuggestion() */ - public static function setExtensionMethod(string $class, string $name, /*callable*/ $callback): void - { - $name = strtolower($name); - self::$extMethods[$name][$class] = Callback::check($callback); - self::$extMethods[$name][''] = null; - } - - - /** - * Returns extension method. - * @return mixed - */ - public static function getExtensionMethod(string $class, string $name) - { - $list = &self::$extMethods[strtolower($name)]; - $cache = &$list[''][$class]; - if (isset($cache)) { - return $cache; - } - - foreach ([$class] + class_parents($class) + class_implements($class) as $cl) { - if (isset($list[$cl])) { - return $cache = $list[$cl]; - } - } - return $cache = false; - } - - - /** - * Returns extension methods. - */ - public static function getExtensionMethods(string $class): array - { - $res = []; - foreach (array_keys(self::$extMethods) as $name) { - if ($cb = self::getExtensionMethod($class, $name)) { - $res[$name] = $cb; - } - } - return $res; - } - - - /********************* utilities ****************d*g**/ - - - /** - * Returns array of public (static, non-static and magic) methods. - */ - private static function &getMethods(string $class): array - { - static $cache; - if (!isset($cache[$class])) { - $cache[$class] = array_fill_keys(get_class_methods($class), 0) + self::getMagicMethods($class); - if ($parent = get_parent_class($class)) { - $cache[$class] += self::getMethods($parent); - } - } - return $cache[$class]; - } - - - private static function getSource() - { - foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $item) { - if (isset($item['file']) && dirname($item['file']) !== __DIR__) { - return " in $item[file]:$item[line]"; - } - } - } - - - /********************* moved to ObjectHelpers ****************d*g**/ - - public static function getSuggestion(array $possibilities, string $value): ?string { return ObjectHelpers::getSuggestion($possibilities, $value); } - /** - * @deprecated use ObjectHelpers::strictGet() - */ - public static function strictGet(string $class, string $name): void - { - ObjectHelpers::strictGet($class, $name); - } - - - /** - * @deprecated use ObjectHelpers::strictSet() - */ - public static function strictSet(string $class, string $name): void + public static function setExtensionMethod($class, $name, $callback) { - ObjectHelpers::strictSet($class, $name); + trigger_error('Class Nette\Utils\ObjectMixin is deprecated', E_USER_DEPRECATED); } - /** - * @deprecated use ObjectHelpers::strictCall() - */ - public static function strictCall(string $class, string $method, array $additionalMethods = []): void - { - ObjectHelpers::strictCall($class, $method, $additionalMethods); - } - - - /** - * @deprecated use ObjectHelpers::strictStaticCall() - */ - public static function strictStaticCall(string $class, string $method): void + public static function getExtensionMethod($class, $name) { - ObjectHelpers::strictStaticCall($class, $method); + trigger_error('Class Nette\Utils\ObjectMixin is deprecated', E_USER_DEPRECATED); } } diff --git a/tests/Utils/Object.arrayProperty.phpt b/tests/Utils/Object.arrayProperty.phpt deleted file mode 100644 index 5b2ca7eb9..000000000 --- a/tests/Utils/Object.arrayProperty.phpt +++ /dev/null @@ -1,35 +0,0 @@ -items; - } - - - public function setItems(array $value) - { - $this->items = $value; - } -} - - -$obj = new TestClass; -$obj->items[] = 'test'; -Assert::same(['test'], $obj->items); diff --git a/tests/Utils/Object.closureProperty.phpt b/tests/Utils/Object.closureProperty.phpt deleted file mode 100644 index cab53246a..000000000 --- a/tests/Utils/Object.closureProperty.phpt +++ /dev/null @@ -1,66 +0,0 @@ -public = $this->onPublic = $this->protected = $this->private = $func; - } -} - - -test(function () { - $obj = new TestClass(function ($a, $b) { - return "$a $b"; - }); - - Assert::same('1 2', $obj->public(1, 2)); -}); - - -test(function () { - Assert::exception(function () { - $obj = new TestClass(123); - $obj->onPublic = function () {}; // accidentally forgotten [] - $obj->onPublic(1, 2); - }, Nette\UnexpectedValueException::class, 'Property TestClass::$onPublic must be iterable or null, object given.'); - - - Assert::exception(function () { - $obj = new TestClass(123); - $obj->public(); - }, Nette\MemberAccessException::class, 'Call to undefined method TestClass::public().'); - - - Assert::exception(function () { - $obj = new TestClass(function () {}); - $obj->protected(); - }, Nette\MemberAccessException::class, 'Call to undefined method TestClass::protected().'); - - - Assert::exception(function () { - $obj = new TestClass(function () {}); - $obj->private(); - }, Nette\MemberAccessException::class, 'Call to undefined method TestClass::private().'); -}); diff --git a/tests/Utils/Object.events.phpt b/tests/Utils/Object.events.phpt deleted file mode 100644 index 169e7fa24..000000000 --- a/tests/Utils/Object.events.phpt +++ /dev/null @@ -1,82 +0,0 @@ -counter++; -} - - -class Handler -{ - public function __invoke($obj) - { - $obj->counter++; - } -} - - -$obj = new TestClass; -$obj->onPublic(); - -$var = new stdClass; -$var->counter = 0; - -$obj->onPublic[] = 'handler'; - -$obj->onPublic($var); -Assert::same(1, $var->counter); - - -$obj->onPublic[] = new Handler; - -$obj->onPublic($var); -Assert::same(3, $var->counter); - - -Assert::exception(function () use ($obj) { - $obj->onPublicStatic(123); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::onPublicStatic().'); - - -Assert::exception(function () use ($obj) { - $obj->onProtected(123); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::onProtected().'); - - -Assert::exception(function () use ($obj) { - $obj->onPrivate(123); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::onPrivate().'); - - -Assert::exception(function () use ($obj) { - $obj->onUndefined(123); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::onUndefined().'); - -Assert::exception(function () use ($obj) { - $obj->onPublic = 'string'; - $obj->onPublic(); -}, Nette\UnexpectedValueException::class, 'Property TestClass::$onPublic must be iterable or null, string given.'); diff --git a/tests/Utils/Object.extensionMethod.phpt b/tests/Utils/Object.extensionMethod.phpt deleted file mode 100644 index 641564f6c..000000000 --- a/tests/Utils/Object.extensionMethod.phpt +++ /dev/null @@ -1,44 +0,0 @@ -foo . $separator . $that->bar; -}); - -$obj = new TestClass; -Assert::same('Hello*World', $obj->join('*')); - - -Assert::same( - ['join' => $func], - Nette\Utils\ObjectMixin::getExtensionMethods(TestClass::class) -); - -Assert::same( - [], - Nette\Utils\ObjectMixin::getExtensionMethods(Nette\Object::class) -); - -Assert::exception(function () { - $obj = new TestClass; - $obj->joi(); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::joi(), did you mean join()?'); diff --git a/tests/Utils/Object.extensionMethodViaInterface.phpt b/tests/Utils/Object.extensionMethodViaInterface.phpt deleted file mode 100644 index a91d9d014..000000000 --- a/tests/Utils/Object.extensionMethodViaInterface.phpt +++ /dev/null @@ -1,64 +0,0 @@ -foo . $separator . $that->bar; -} - - -function ISecond_join(ISecond $that, $separator) -{ - return __METHOD__ . ' says ' . $that->foo . $separator . $that->bar; -} - - -Object::extensionMethod('ISecond::join', 'ISecond_join'); -Object::extensionMethod('IFirst::join', 'IFirst_join'); - -$obj = new TestClass; -Assert::same('ISecond_join says Hello*World', $obj->join('*')); - -Assert::same( - ['join' => 'ISecond_join'], - Nette\Utils\ObjectMixin::getExtensionMethods(TestClass::class) -); - -Assert::same( - ['join' => 'IFirst_join'], - Nette\Utils\ObjectMixin::getExtensionMethods(IFirst::class) -); - -Assert::exception(function () { - $obj = new TestClass; - $obj->joi(); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::joi(), did you mean join()?'); diff --git a/tests/Utils/Object.magicMethod.errors.phpt b/tests/Utils/Object.magicMethod.errors.phpt deleted file mode 100644 index 5fe62d277..000000000 --- a/tests/Utils/Object.magicMethod.errors.phpt +++ /dev/null @@ -1,68 +0,0 @@ -setAbc(); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::setAbc(), did you mean getAbc()?'); - -Assert::exception(function () { - $obj = new TestClass; - $obj->abc(); -}, Nette\MemberAccessException::class, 'Call to undefined method parent::abc().'); - -Assert::exception(function () { - $obj = new TestClass; - $obj->adItem(); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::adItem(), did you mean addItem()?'); - - -// Wrong parameters count -Assert::exception(function () { - $obj = new TestClass; - $obj->setItems(); -}, Nette\InvalidArgumentException::class, 'TestClass::setItems() expects 1 argument, 0 given.'); - -Assert::exception(function () { - $obj = new TestClass; - $obj->setItems(1, 2); -}, Nette\InvalidArgumentException::class, 'TestClass::setItems() expects 1 argument, 2 given.'); - -Assert::exception(function () { - $obj = new TestClass; - $obj->getItems(1); -}, Nette\InvalidArgumentException::class, 'TestClass::getItems() expects no argument, 1 given.'); - -Assert::exception(function () { - $obj = new TestClass; - $obj->addItem(); -}, Nette\InvalidArgumentException::class, 'TestClass::addItem() expects 1 argument, 0 given.'); diff --git a/tests/Utils/Object.magicMethod.inheritance.phpt b/tests/Utils/Object.magicMethod.inheritance.phpt deleted file mode 100644 index af48c99b8..000000000 --- a/tests/Utils/Object.magicMethod.inheritance.phpt +++ /dev/null @@ -1,49 +0,0 @@ -setA('hello'); -Assert::same('hello', $obj->getA()); - -Assert::exception(function () use ($obj) { - $obj->setC(123); -}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::setC(), did you mean setB()?'); - - -Assert::exception(function () use ($obj) { - $obj->setB(123); -}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::setB(), did you mean getB()?'); diff --git a/tests/Utils/Object.magicMethod.phpt b/tests/Utils/Object.magicMethod.phpt deleted file mode 100644 index 7ec4dc57b..000000000 --- a/tests/Utils/Object.magicMethod.phpt +++ /dev/null @@ -1,56 +0,0 @@ -setName('hello')); -Assert::same('hello', $obj->name); -Assert::same('hello', $obj->getName()); - -// protected -Assert::same($obj, $obj->setEnabled(11)); -Assert::same(11, $obj->isEnabled()); - -// magic accessors for magic methods -$obj->enabled = 22; -Assert::same(22, $obj->enabled); - -// adder -Assert::same($obj, $obj->addItem('world')); -Assert::same(['world'], $obj->items); -Assert::same(['world'], $obj->getItems()); - -Assert::same($obj, $obj->setItems([])); -Assert::same([], $obj->items); -Assert::same([], $obj->getItems()); diff --git a/tests/Utils/Object.magicMethod.types.phpt b/tests/Utils/Object.magicMethod.types.phpt deleted file mode 100644 index a28503cad..000000000 --- a/tests/Utils/Object.magicMethod.types.phpt +++ /dev/null @@ -1,66 +0,0 @@ -setName(123); -Assert::same('123', $obj->name); - - -$obj->setEnabled(1); -Assert::same(true, $obj->enabled); - -Assert::exception(function () use ($obj) { - $obj->setEnabled(new stdClass); -}, Nette\InvalidArgumentException::class, 'Argument passed to Test\TestClass::setEnabled() must be bool, object given.'); - - -$obj->setItems([new TestClass]); -Assert::equal([new TestClass], $obj->items); - -Assert::exception(function () use ($obj) { - $obj->setItems([1]); -}, Nette\InvalidArgumentException::class, 'Argument passed to Test\TestClass::setItems() must be Test\TestClass[], array given.'); - - -$obj->addItem(new TestClass); -Assert::equal([new TestClass, new TestClass], $obj->items); - -Assert::exception(function () use ($obj) { - $obj->addItem(1); -}, Nette\InvalidArgumentException::class, 'Argument passed to Test\TestClass::addItem() must be Test\TestClass, integer given.'); diff --git a/tests/Utils/Object.methodGetter.phpt b/tests/Utils/Object.methodGetter.phpt deleted file mode 100644 index c0cbeb32b..000000000 --- a/tests/Utils/Object.methodGetter.phpt +++ /dev/null @@ -1,73 +0,0 @@ -id = $id; - } - - - public function publicMethod($a, $b) - { - return "$this->id $a $b"; - } - - - protected function protectedMethod() - { - } - - - private function privateMethod() - { - } - - - public function getWithoutParameters() - { - } -} - - -$obj1 = new TestClass(1); -$method = $obj1->publicMethod; -Assert::same('1 2 3', $method(2, 3)); - -$rm = new ReflectionFunction($method); -Assert::same($obj1, $rm->getClosureThis()); -Assert::same('publicMethod', $rm->getName()); -Assert::same(2, $rm->getNumberOfParameters()); - - -Assert::exception(function () { - $obj = new TestClass; - $method = $obj->protectedMethod; -}, Nette\MemberAccessException::class, 'Cannot read an undeclared property TestClass::$protectedMethod.'); - - -Assert::exception(function () { - $obj = new TestClass; - $method = $obj->privateMethod; -}, Nette\MemberAccessException::class, 'Cannot read an undeclared property TestClass::$privateMethod.'); - - -Assert::error(function () { - $obj = new TestClass; - $method = $obj->getWithoutParameters; -}, E_USER_WARNING, 'Did you forget parentheses after getWithoutParameters in ' . __FILE__ . ':' . (__LINE__ - 1) . '?'); diff --git a/tests/Utils/Object.property.phpt b/tests/Utils/Object.property.phpt deleted file mode 100644 index 5b85eaa98..000000000 --- a/tests/Utils/Object.property.phpt +++ /dev/null @@ -1,112 +0,0 @@ -foo = $foo; - $this->bar = $bar; - } - - - public function foo() - { // method getter has lower priority than getter - } - - - public function getFoo() - { - return $this->foo; - } - - - public function setFoo($foo) - { - $this->foo = $foo; - } - - - public function getBar() - { - return $this->bar; - } - - - public function setBazz($value) - { - $this->bar = $value; - } - - - public function gets() // or setupXyz, settle... - { - echo __METHOD__; - return 'ERROR'; - } -} - - -$obj = new TestClass; -$obj->foo = 'hello'; -Assert::same('hello', $obj->foo); -Assert::same('hello', $obj->Foo); - - -$obj->foo .= ' world'; -Assert::same('hello world', $obj->foo); - - -// Undeclared property writing -Assert::exception(function () use ($obj) { - $obj->undeclared = 'value'; -}, Nette\MemberAccessException::class, 'Cannot write to an undeclared property TestClass::$undeclared, did you mean $declared?'); - - -// Undeclared property reading -Assert::false(isset($obj->S)); -Assert::false(isset($obj->s)); -Assert::false(isset($obj->undeclared)); - -Assert::exception(function () use ($obj) { - $val = $obj->undeclared; -}, Nette\MemberAccessException::class, 'Cannot read an undeclared property TestClass::$undeclared, did you mean $declared?'); - - -// Read-only property -$obj = new TestClass('Hello', 'World'); -Assert::true(isset($obj->bar)); -Assert::same('World', $obj->bar); - -Assert::exception(function () use ($obj) { - $obj->bar = 'value'; -}, Nette\MemberAccessException::class, 'Cannot write to a read-only property TestClass::$bar.'); - - -// write-only property -$obj = new TestClass; -Assert::false(isset($obj->bazz)); -$obj->bazz = 'World'; -Assert::same('World', $obj->bar); - -Assert::exception(function () use ($obj) { - $val = $obj->bazz; -}, Nette\MemberAccessException::class, 'Cannot read a write-only property TestClass::$bazz.'); diff --git a/tests/Utils/Object.referenceProperty.phpt b/tests/Utils/Object.referenceProperty.phpt deleted file mode 100644 index 4bccbb7e9..000000000 --- a/tests/Utils/Object.referenceProperty.phpt +++ /dev/null @@ -1,37 +0,0 @@ -foo; - } - - - public function setFoo($foo) - { - $this->foo = $foo; - } -} - - -$obj = new TestClass; -$obj->foo = 'hello'; -@$x = &$obj->foo; -$x = 'changed by reference'; -Assert::same('hello', $obj->foo); diff --git a/tests/Utils/Object.reflection.phpt b/tests/Utils/Object.reflection.phpt deleted file mode 100644 index d13329a0a..000000000 --- a/tests/Utils/Object.reflection.phpt +++ /dev/null @@ -1,22 +0,0 @@ -getReflection()->getName()); -Assert::same('TestClass', $obj->Reflection->getName()); diff --git a/tests/Utils/Object.undeclaredMethod.phpt b/tests/Utils/Object.undeclaredMethod.phpt deleted file mode 100644 index efcf953c3..000000000 --- a/tests/Utils/Object.undeclaredMethod.phpt +++ /dev/null @@ -1,58 +0,0 @@ -abc(); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::abc().'); - -Assert::exception(function () { - $obj = new TestClass; - $obj->method(); -}, Nette\MemberAccessException::class, 'Call to undefined method TestClass::method(), did you mean methodO2()?'); - -Assert::exception(function () { - TestClass::abc(); -}, Nette\MemberAccessException::class, 'Call to undefined static method TestClass::abc().'); - -Assert::exception(function () { - TestClass::method(); -}, Nette\MemberAccessException::class, 'Call to undefined static method TestClass::method(), did you mean methodS2()?'); - -Assert::exception(function () { - Nette\Utils\Image::fromBlank(1, 1)->filledElippse(); -}, Nette\MemberAccessException::class, 'Call to undefined method Nette\Utils\Image::filledElippse(), did you mean filledEllipse()?'); diff --git a/tests/Utils/Object.unsetProperty.phpt b/tests/Utils/Object.unsetProperty.phpt deleted file mode 100644 index 289bdbf0b..000000000 --- a/tests/Utils/Object.unsetProperty.phpt +++ /dev/null @@ -1,46 +0,0 @@ -foo); - Assert::false(isset($obj->foo)); - - // re-set - $obj->foo = 'hello'; - Assert::same('hello', $obj->foo); -}); - - -test(function () { - // double unset - $obj = new TestClass; - unset($obj->foo, $obj->foo); -}); - - -test(function () { - // reading of unset property - Assert::exception(function () { - $obj = new TestClass; - unset($obj->foo); - $val = $obj->foo; - }, Nette\MemberAccessException::class, 'Cannot read an undeclared property TestClass::$foo.'); -}); diff --git a/tests/Utils/ObjectMixin.checkType().phpt b/tests/Utils/ObjectMixin.checkType().phpt deleted file mode 100644 index a18b2eedd..000000000 --- a/tests/Utils/ObjectMixin.checkType().phpt +++ /dev/null @@ -1,170 +0,0 @@ - $val) { - Assert::true(ObjectMixin::checkType($val, $type)); - Assert::same($vals[$key], $val); - } -} - - -function assertRejects($type, $vals) -{ - foreach ($vals as $key => $val) { - Assert::false(ObjectMixin::checkType($val, $type)); - Assert::same($vals[$key], $val); - } -} - - -function assertConverts($type, $vals) -{ - foreach ($vals as $val) { - Assert::true(ObjectMixin::checkType($val[0], $type)); - Assert::same($val[1], $val[0]); - } -} - - -$resource = fopen(__FILE__, 'r'); - -assertAccepts('', [null, true, false, 0, 0.0, 0.1, 1, 12, '', 'true', 'false', '-123', '123x', '+1.2', '1.0', [], [1, 2], ['a', 'b'], new stdClass, new StrClass, $resource]); -assertAccepts('mixed', [null, true, false, 0, 0.0, 0.1, 1, 12, '', 'true', 'false', '-123', '123x', '+1.2', '1.0', [], [1, 2], ['a', 'b'], new stdClass, new StrClass, $resource]); - -assertAccepts('scalar', [true, false, 0, 0.0, 0.1, 1, 12, '', 'true', 'false', '-123', '123x', '+1.2', '1.0']); -assertRejects('scalar', [null, [], [1, 2], ['a', 'b'], new stdClass, new StrClass, $resource]); - -assertAccepts('boolean', [true, false]); -assertAccepts('bool', [true, false]); -assertRejects('bool', [[], [1, 2], ['a', 'b'], new stdClass, new StrClass, $resource]); -assertConverts('bool', [ - [null, false], - [0, false], - [0.0, false], - [0.1, true], - [1, true], - [12, true], - ['', false], - ['0', false], - ['false', true], - ['-123', true], - ['123x', true], -]); - -assertAccepts('string', ['', 'true', 'false', '-123', '123x', '+1.2', '1.0']); -assertRejects('string', [[], [1, 2], ['a', 'b'], new stdClass, $resource]); -assertConverts('string', [ - [null, ''], - [true, '1'], - [false, ''], - [0, '0'], - [0.0, '0'], - [0.1, '0.1'], - [1, '1'], - [12, '12'], - [new StrClass, '1'], -]); - -assertAccepts('integer', [0, 1, 12]); -assertAccepts('int', [0, 1, 12]); -assertRejects('int', [0.1, '', 'true', 'false', '123x', '+1.2', [], [1, 2], ['a', 'b'], new stdClass, new StrClass, $resource]); -assertConverts('int', [ - [null, 0], - [true, 1], - [false, 0], - [0.0, 0], - ['-123', -123], - ['1.0', 1], -]); - -assertAccepts('float', [0.0, 0.1]); -assertRejects('float', ['', 'true', 'false', '123x', [], [1, 2], ['a', 'b'], new stdClass, new StrClass, $resource]); -assertConverts('float', [ - [null, 0.0], - [true, 1.0], - [false, 0.0], - [0, 0.0], - [1, 1.0], - [12, 12.0], - ['-123', -123.0], - ['+1.2', 1.2], - ['1.0', 1.0], -]); - -assertAccepts('array', [[], [1, 2], ['a', 'b']]); -assertRejects('array', [null, true, false, 0, 0.1, 12, '', '123x', new stdClass, new StrClass, $resource]); - -assertAccepts('object', [new stdClass, new StrClass]); -assertRejects('object', [null, true, false, 0, 0.1, 12, '', '123x', [], [1, 2], ['a', 'b'], $resource]); - -assertAccepts('callable', [[new StrClass, '__toString']]); -assertRejects('callable', [null, true, false, 0, 0.1, 12, '', '123x', [], [1, 2], ['a', 'b'], new stdClass, new StrClass, $resource]); - -assertAccepts('resource', [$resource]); -assertRejects('resource', [null, true, false, 0, 0.1, 12, '', '123x', [], [1, 2], ['a', 'b'], new stdClass, new StrClass]); - -assertAccepts('stdClass', [new stdClass]); -assertRejects('stdClass', [null, true, false, 0, 0.1, 12, '', '123x', [], [1, 2], ['a', 'b'], new StrClass, $resource]); - -assertAccepts('null', [null]); -assertAccepts('NULL', [null]); -assertRejects('NULL', [true, false, 0, 0.1, 12, '', '123x', [], [1, 2], ['a', 'b'], new stdClass, new StrClass, $resource]); - -assertAccepts('int[]', [[], [1, 2]]); -assertRejects('int[]', [null, true, false, 0, 0.1, 12, '', '123x', ['a', 'b'], new stdClass, new StrClass, $resource]); -assertConverts('int[]', [ - [['1'], [1]], -]); - -$val = ['1', new stdClass]; -ObjectMixin::checkType($val, 'int[]'); -Assert::equal(['1', new stdClass], $val); // do not modify - -assertAccepts('array|string', ['', '123x', [], [1, 2], ['a', 'b']]); -assertRejects('array|string', [new stdClass, $resource]); -assertConverts('array|string', [ - [null, ''], - [true, '1'], - [false, ''], - [0, '0'], - [0.0, '0'], - [0.1, '0.1'], - [1, '1'], - [12, '12'], - [new StrClass, '1'], -]); - - -assertAccepts('string|bool|null', [null, true, false, '', '123x']); -assertRejects('string|bool|null', [[], [1, 2], ['a', 'b'], new stdClass, $resource]); -assertConverts('string|bool|null', [ - [0, '0'], - [0.0, '0'], - [0.1, '0.1'], - [1, '1'], - [12, '12'], - [new StrClass, '1'], -]);