Skip to content

Commit

Permalink
2.1.5 release.
Browse files Browse the repository at this point in the history
[Property.php] Added new methods: hasDefaultValue(), getDefaultValue(), getProperty(), haveValue(), getVisibility();
[Property.php] Rewrote methods: getValue();
[Property.php] Refactoring: $owner is now the object that was passed by reflection;

[ReflectedObject] Refactor: method init() some changes;

[Reflector] Refactor: logic;

[test.cmd] Removed;
  • Loading branch information
ZloyNick committed Mar 5, 2022
1 parent 558a38a commit 3745ddd
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 70 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/.idea/
/vendor/
composer.lock
composer.lock
test.cmd
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
],
"minimum-stability": "dev",
"license": "GPL-3.0+",
"version": "v2.0.1",
"version": "v2.1.5",
"require": {
"phpunit/phpunit": "9.5.16"
},
Expand Down
114 changes: 74 additions & 40 deletions src/Reflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@
namespace joole\reflector;

use ErrorException;
use InvalidArgumentException;
use joole\reflector\object\ReflectedObject;
use joole\reflector\object\ReflectedObjectInterface;
use Prophecy\Exception\Doubler\ClassNotFoundException;
use ReflectionException;

use function is_string;
use function is_null;
use function is_array;
use function class_exists;
use function array_keys;
use function call_user_func_array;
use function class_exists;
use function is_subclass_of;
use function is_int;
use function is_null;
use function is_object;
use function is_string;
use function method_exists;
use function array_keys;

/**
* Reflector is used to work with the properties of objects, their changes and merges.
Expand All @@ -41,8 +42,8 @@ final class Reflector
*/
public function buildFromObject(string|object $object, array $constructParams = []): ReflectedObjectInterface|ReflectedObject
{
if(is_string($object)){
if(!class_exists($object)){
if (is_string($object)) {
if (!class_exists($object)) {
throw new ClassNotFoundException('Class not found!', $object);
}

Expand All @@ -55,13 +56,28 @@ public function buildFromObject(string|object $object, array $constructParams =
}

/**
* Sets Reflections
*
* @param string $class
*/
public static function setReflectedObjectClass(string $class)
final public static function setReflectedObjectClass(string $class)
{
if(!is_subclass_of($class, $current = ReflectedObjectInterface::class)){
throw new InvalidArgumentException("Argument 1 must be instance of {$current}. {$class} given.");
}

self::$reflectedObjectClass = $class;
}

/**
* Returns class for generation reflected object.
*
* @return string|null
*/
final public static function getReflectedObjectClass():?string{
return self::$reflectedObjectClass;
}

/**
* Merges properties from class to class.
*
Expand Down Expand Up @@ -91,56 +107,74 @@ public static function setReflectedObjectClass(string $class)
*
* @throws ReflectionException
*/
public function merge(string|object $class, string|object|array $params, array $params2 = []): object
final public function merge(string|object $class, string|object|array $params, array $params2 = []): object
{
$object = $this->buildFromObject($class);

if (!is_array($params)) {
$object2 = $this->buildFromObject($params);
if (is_object($params)) {
return $this->mergeObjects($class, $params, $params2);
} else {
foreach ($params as $param => $v) {
$prop = $object->getProperty($param);

if (is_null($prop)) {
throw new ErrorException(
'Property $' . $param . ' of class ' . $object->getClassName() . ' doesn\'t exist!'
);
}

if(count($params2) === 0){
$params2 = array_keys($object2->getProperties());
$prop->setValue($v);
}
}

foreach ($params2 as $param => $v) {
if (is_int($param)) {
$prop = $object->getProperty($v);
$prop2 = $object2->getProperty($v);
return $object->getObject();
}

if (is_null($prop)) {
throw new ErrorException(
'Property $' . $v . ' of class ' . $object->getClassName() . ' doesn\'t exist!'
);
}
/**
* Merges properties of $objectFrom to $objectTo.
*
* @param string|object $objectTo Target.
* @param object $objectFrom Merge from.
* @param array $params Properties for merge. If count < 1 merges all properties of $objectFrom.
*
* @throws ErrorException
* @throws ReflectionException
*/
private function mergeObjects(string|object $objectTo, object $objectFrom, array $params = []): object
{
$target = $this->buildFromObject($objectTo);
$object2 = $this->buildFromObject($objectFrom);

if (is_null($prop2)) {
throw new ErrorException(
'Property $' . $v . ' of class ' . $object2->getClassName() . ' doesn\'t exist!'
);
}
if (count($params) === 0) {
$params = array_keys($object2->getProperties());
}

$prop->setValue($prop2->getValue());
foreach ($params as $param => $v) {
if (is_int($param)) {
$prop = $target->getProperty($v);
$prop2 = $object2->getProperty($v);

continue;
if (is_null($prop)) {
throw new ErrorException(
'Property $' . $v . ' of class ' . $target->getClassName() . ' doesn\'t exist!'
);
}

$object->getProperty($param)->setValue($v);
}
}else{
foreach ($params as $param => $v) {
$prop = $object->getProperty($param);

if (is_null($prop)) {
if (is_null($prop2)) {
throw new ErrorException(
'Property $' . $param . ' of class ' . $object->getClassName() . ' doesn\'t exist!'
'Property $' . $v . ' of class ' . $object2->getClassName() . ' doesn\'t exist!'
);
}

$prop->setValue($v);
$prop->setValue($prop2->getValue());

continue;
}

$target->getProperty($param)->setValue($v);
}

return $object->getObject();
return $target->getObject();
}

}
17 changes: 14 additions & 3 deletions src/object/ReflectedObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,29 @@ public function getProperty(string $name): null|Property|PropertyInterface
return $this->properties[$name] ?? null;
}

/**
* Returns reflected object's name.
*
* @return string
*/
public function getClassName(): string
{
return $this->reflectedObject->getName();
}

/**
* Initializes properties.
*
* @return void
*/
protected function init(): void
{
$object = &$this->reflectedObject;

This comment has been minimized.

Copy link
@ZloyNick

ZloyNick Mar 5, 2022

Owner

'&' - bad...

$reflectedObject = $this->reflectedObject;
$object = &$this->object;

This comment has been minimized.

Copy link
@ZloyNick

ZloyNick Mar 5, 2022

Owner

&' - bad... (x2)

$properties = &$this->properties;

foreach ($object->getProperties() as $property){
$properties[$property->getName()] = new Property($property, $this);
foreach ($reflectedObject->getProperties() as $property){
$properties[$property->getName()] = new Property($property, $object);
}
}
}
98 changes: 79 additions & 19 deletions src/property/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

namespace joole\reflector\property;

use joole\reflector\object\ReflectedObjectInterface;
use ReflectionException;
use ReflectionProperty;

use function is_null;

/**
Expand All @@ -23,56 +21,118 @@ final class Property implements PropertyInterface
*/
private ReflectionProperty $property;

private ReflectedObjectInterface $owner;
/**
* An object, that owns property.
*
* @var object
*/
private object $owner;

public function __construct(ReflectionProperty $property, ReflectedObjectInterface $owner)
public function __construct(ReflectionProperty $property, object $owner)
{
$this->property = $property;
$this->owner = $owner;
}

public function setAccessible(bool $value): void
{
$this->property->setAccessible($value);
}

/**
* @throws ReflectionException
*/
public function setValue(mixed $value): void
{
$property = $this->property;
$val = $this->getValue();
$type = $property->getType();

if(!is_null($type)){
if(is_null($value)){
if(!$type->allowsNull()){
if (!is_null($type)) {
if (is_null($value)) {
if (!$type->allowsNull()) {
throw new ReflectionException('Null not allowed for property' . $property->getName());
}
}else{
} else {
$propertyType = $type->getName();
$type = gettype($value);

if ($propertyType !== $type) {
if($propertyType !== 'float' && !in_array($type, ['float', 'real', 'double'])){
if ($propertyType !== 'float' && !in_array($type, ['float', 'real', 'double'])) {
throw new ReflectionException('Value must be instance of ' . $propertyType);
}
}
}
}

$property->setValue($this->owner->getObject(), $value);
$owner = $this->owner;

$property->setValue($owner, $value);
}

public function getValue(): mixed
/**
* Returns property's value.
*
* @return mixed If no value is set, returns $default,
* otherwise returns the default value or null (if no default value is set)
*/
public function getValue(mixed $default = null): mixed
{
if(!$this->haveValue()){
return $default ?? $this->getDefaultValue();
}

$prop = $this->property;

if($prop->isStatic()){
if ($prop->isStatic()) {
return $prop->getValue();
}

return $prop->getValue($this->owner->getObject());
return $prop->getValue($this->owner);
}

public function getVisibility(bool $asString = true): string|int
{
$property = $this->property;

if ($asString) {
return $property->isPublic() ? self::NAME_T_PUBLIC :
($property->isProtected() ? self::NAME_T_PROTECTED : self::NAME_T_PRIVATE);
}

return $property->isPublic() ? self::T_PUBLIC :
($property->isProtected() ? self::T_PROTECTED : self::T_PRIVATE);
}

/**
* Checks if the property has a value.
*
* @return bool
*/
final public function haveValue(): bool
{
return $this->property->isInitialized($this->owner);
}

/**
* Returns property as reflected by php.
*
* @return ReflectionProperty
*/
final public function getProperty(): ReflectionProperty
{
return $this->property;
}

/**
* Returns default value of property.
*
* @return mixed Returns null if it has been set or if property hasn't default value.
*/
final public function getDefaultValue():mixed{
return $this->property->getDefaultValue();
}

/**
* Checks if the property has a default value.
*
* @return bool
*/
final public function hasDefaultValue():bool{
return $this->property->hasDefaultValue();
}
}
Loading

0 comments on commit 3745ddd

Please sign in to comment.