Source of file ClassProxyTrait.php

Size: 7,773 Bytes - Last Modified: 2021-01-12T22:04:13+00:00

C:/Users/MAKS/Code/_PROJECTS/amqp-agent/src/Helper/ClassProxyTrait.php

12345678910111213141516171819202122232425262728293031323334353637
Covered by 5 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCallMethodMethod
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testRespondMethodViaAliasMethodServe
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testAnExceptionIsRaisedIfPassedCallbackDoesNotReturnString
38
Covered by 5 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCallMethodMethod
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testRespondMethodViaAliasMethodServe
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testAnExceptionIsRaisedIfPassedCallbackDoesNotReturnString
394041
Covered by 5 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCallMethodMethod
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testRespondMethodViaAliasMethodServe
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testAnExceptionIsRaisedIfPassedCallbackDoesNotReturnString
4243
Covered by 5 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCallMethodMethod
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testRespondMethodViaAliasMethodServe
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testAnExceptionIsRaisedIfPassedCallbackDoesNotReturnString
44
Covered by 5 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCallMethodMethod
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testRespondMethodViaAliasMethodServe
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testAnExceptionIsRaisedIfPassedCallbackDoesNotReturnString
45464748
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCallMethodMethod
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testAnExceptionIsRaisedIfPassedCallbackDoesNotReturnString
49
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCallMethodMethod
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testAnExceptionIsRaisedIfPassedCallbackDoesNotReturnString
5051
Covered by 5 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCallMethodMethod
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testRespondMethodViaAliasMethodServe
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testAnExceptionIsRaisedIfPassedCallbackDoesNotReturnString
52
Covered by 5 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCallMethodMethod
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testRespondMethodViaAliasMethodServe
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testAnExceptionIsRaisedIfPassedCallbackDoesNotReturnString
53
Covered by 5 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCallMethodMethod
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testRequestMethodViaAliasMethodCall
  • MAKS\AmqpAgent\Tests\RPC\ClientEndpointTest::testAnExceptionIsRaisedIfCorrelationIdOfTheResponseIsNotTheSameAsTheRequest
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testRespondMethodViaAliasMethodServe
  • MAKS\AmqpAgent\Tests\RPC\ServerEndpointTest::testAnExceptionIsRaisedIfPassedCallbackDoesNotReturnString
5455565758596061626364656667
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
68
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
6970
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
7172
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
73
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
74
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
75
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
76
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
77
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
78
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
7980
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
81
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
82
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
8384858687
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
88
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
8990
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
91
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
92
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
93
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testGetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
949596979899100101102103104105106107108
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
109
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
110111
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
112113
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
114
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
115
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
116
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
117118
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
119
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
120
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
121122123124125
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
126
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
127128
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
129
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
130
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
131
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testSetPropertyMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
  • MAKS\AmqpAgent\Tests\RPC\AbstractEndpointTest::testPingMethodRaisesAnExceptionIfAnErrorOccurred
132133134135136137138139140141142143144
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testReflectOnClassMethod
145146147148149150151152153154
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testReflectOnObjectMethod
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
155156157158159160161162163164165166
Covered by 3 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodRaisesAnExceptionWhenProvidedWithAClassThatDoesNotExist
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAWrongArgument
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
167
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAWrongArgument
168
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAWrongArgument
169
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAWrongArgument
170
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAWrongArgument
171172173174175
Covered by 2 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodRaisesAnExceptionWhenProvidedWithAClassThatDoesNotExist
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
176
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodRaisesAnExceptionWhenProvidedWithAClassThatDoesNotExist
177
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodRaisesAnExceptionWhenProvidedWithAClassThatDoesNotExist
178
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodRaisesAnExceptionWhenProvidedWithAClassThatDoesNotExist
179180181182183184185
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
186187
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
188
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
189190
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
191192
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
193
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
194
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
195
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
196197
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
198
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
199
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
200
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
201202203
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
204
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
205206207208209210211
Covered by 1 test(s):
  • MAKS\AmqpAgent\Tests\Helper\ClassProxyTest::testCastObjectToClassMethodWithAClassWithPrivateProperties
212213214215216217
<?php

/**
 * @author Marwan Al-Soltany <MarwanAlsoltany@gmail.com>
 * @copyright Marwan Al-Soltany 2020
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

declare(strict_types=1);

namespace MAKS\AmqpAgent\Helper;

use Closure;
use Exception;
use ReflectionClass;
use ReflectionObject;
use ReflectionException;
use MAKS\AmqpAgent\Exception\AmqpAgentException;

/**
 * A trait containing methods for proxy methods calling, properties manipulation, and class utilities.
 * @since 2.0.0
 */
trait ClassProxyTrait
{
    /**
     * Calls a private, protected, or public method on an object.
     * @param object $object Class instance.
     * @param string $method Method name.
     * @param mixed ...$arguments
     * @return mixed The function result, or false on error.
     * @throws AmqpAgentException On failure or if the called function threw an exception.
     */
    public static function callMethod($object, string $method, ...$arguments)
    {
        return call_user_func(
            Closure::bind(
                function () use ($object, $method, $arguments) {
                    try {
                        return call_user_func_array(
                            array(
                                $object,
                                $method
                            ),
                            $arguments
                        );
                    } catch (Exception $error) {
                        AmqpAgentException::rethrow($error, sprintf('%s::%s() failed!', static::class, __FUNCTION__), false);
                    }
                },
                null,
                $object
            )
        );
    }

    /**
     * Gets a private, protected, or public property (default, static, or constant) of an object.
     * @param object $object Class instance.
     * @param string $property Property name.
     * @return mixed The property value.
     * @throws AmqpAgentException On failure.
     */
    public static function getProperty($object, string $property)
    {
        return call_user_func(
            Closure::bind(
                function () use ($object, $property) {
                    $return = null;
                    try {
                        $class = get_class($object);
                        if (defined($class . '::' . $property)) {
                            $return = constant($class . '::' . $property);
                        } elseif (isset($object::$$property)) {
                            $return = $object::$$property;
                        } elseif (isset($object->{$property})) {
                            $return = $object->{$property};
                        } else {
                            throw new Exception(
                                sprintf(
                                    'No default, static, or constant property with the name "%s" exists!',
                                    $property
                                )
                            );
                        }
                    } catch (Exception $error) {
                        AmqpAgentException::rethrow($error, sprintf('%s::%s() failed!', static::class, __FUNCTION__), false);
                    }
                    return $return;
                },
                null,
                $object
            )
        );
    }

    /**
     * Sets a private, protected, or public property (default or static) of an object.
     * @param object $object Class instance.
     * @param string $property Property name.
     * @param string $value Property value.
     * @return mixed The new property value.
     * @throws AmqpAgentException On failure.
     */
    public static function setProperty($object, string $property, $value)
    {
        return call_user_func(
            Closure::bind(
                function () use ($object, $property, $value) {
                    $return = null;
                    try {
                        if (isset($object::$$property)) {
                            $return = $object::$$property = $value;
                        } elseif (isset($object->{$property})) {
                            $return = $object->{$property} = $value;
                        } else {
                            throw new Exception(
                                sprintf(
                                    'No default or static property with the name "%s" exists!',
                                    $property
                                )
                            );
                        }
                    } catch (Exception $error) {
                        AmqpAgentException::rethrow($error, sprintf('%s::%s() failed!', static::class, __FUNCTION__), false);
                    }
                    return $return;
                },
                null,
                $object
            )
        );
    }

    /**
     * Returns a reflection class instance on a class.
     * @param object|string $class Class instance or class FQN.
     * @return ReflectionClass
     * @throws ReflectionException
     */
    public static function reflectOnClass($class)
    {
        return new ReflectionClass($class);
    }

    /**
     * Returns a reflection object instance on an object.
     * @param object $object Class instance.
     * @return ReflectionObject
     */
    public static function reflectOnObject($object)
    {
        return new ReflectionObject($object);
    }

    /**
     * Tries to cast an object into a new class. Similar classes work best.
     * @param object $fromObject Class instance.
     * @param string $toClass Class FQN.
     * @return object
     * @throws AmqpAgentException When passing a wrong argument or on failure.
     */
    public static function castObjectToClass($fromObject, string $toClass)
    {
        if (!is_object($fromObject)) {
            throw new AmqpAgentException(
                sprintf(
                    'The first parameter must be an instance of class, a wrong parameter with (data-type: %s) was passed instead.',
                    gettype($fromObject)
                )
            );
        }

        if (!class_exists($toClass)) {
            throw new AmqpAgentException(
                sprintf(
                    'Unknown class: %s.',
                    $toClass
                )
            );
        }

        try {
            $toClass = new $toClass();

            $toClassReflection = self::reflectOnObject($toClass);
            $fromObjectReflection = self::reflectOnObject($fromObject);

            $fromObjectProperties = $fromObjectReflection->getProperties();

            foreach ($fromObjectProperties as $fromObjectProperty) {
                $fromObjectProperty->setAccessible(true);
                $name = $fromObjectProperty->getName();
                $value = $fromObjectProperty->getValue($fromObject);

                if ($toClassReflection->hasProperty($name)) {
                    $property = $toClassReflection->getProperty($name);
                    $property->setAccessible(true);
                    $property->setValue($toClass, $value);
                } else {
                    try {
                        self::setProperty($toClass, $name, $value);
                    } catch (Exception $e) {
                        // This exception means target object has a __set()
                        // magic method that prevents setting the property.
                    }
                }
            }

            return $toClass;
        } catch (Exception $error) {
            AmqpAgentException::rethrow($error, sprintf('%s::%s() failed!', static::class, __FUNCTION__), false);
        }
    }
}