Skip to content

Commit

Permalink
Merge pull request #77 from naxvog/refactor-reflection-parts
Browse files Browse the repository at this point in the history
Refactor reflection parts
  • Loading branch information
WendellAdriel committed Nov 13, 2023
2 parents e13cf15 + 75c7461 commit 87221db
Showing 1 changed file with 98 additions and 60 deletions.
158 changes: 98 additions & 60 deletions src/Lift.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@
use WendellAdriel\Lift\Concerns\ManageRelations;
use WendellAdriel\Lift\Concerns\RulesValidation;
use WendellAdriel\Lift\Concerns\WatchProperties;
use WendellAdriel\Lift\Exceptions\EventDoesNotExistException;
use WendellAdriel\Lift\Exceptions\ImmutablePropertyException;
use WendellAdriel\Lift\Support\MethodInfo;
use WendellAdriel\Lift\Support\PropertyInfo;

/** @mixin Model */
trait Lift
{
use AttributesGuard,
Expand All @@ -42,7 +44,7 @@ trait Lift
WatchProperties;

/**
* @throws ImmutablePropertyException|ValidationException
* @throws ImmutablePropertyException|ValidationException|ReflectionException
*/
public static function bootLift(): void
{
Expand Down Expand Up @@ -126,6 +128,9 @@ public static function bootLift(): void
}
}

/**
* @throws EventDoesNotExistException|ReflectionException
*/
public function syncOriginal(): void
{
parent::syncOriginal();
Expand All @@ -152,7 +157,7 @@ public function toArray(): array
return $result;
}

public function setCreatedAt($value)
public function setCreatedAt($value): static
{
$createdAtColumn = $this->getCreatedAtColumn();

Expand All @@ -162,7 +167,7 @@ public function setCreatedAt($value)
return $this;
}

public function setUpdatedAt($value)
public function setUpdatedAt($value): static
{
$updatedAtColumn = $this->getUpdatedAtColumn();

Expand All @@ -172,7 +177,7 @@ public function setUpdatedAt($value)
return $this;
}

public function setUniqueIds()
public function setUniqueIds(): void
{
foreach ($this->uniqueIds() as $column) {
if (empty($this->{$column})) {
Expand All @@ -183,6 +188,11 @@ public function setUniqueIds()
}
}

/**
* @return array<string>
*
* @throws ReflectionException
*/
public function setRawAttributes(array $attributes, $sync = false)
{
parent::setRawAttributes($attributes, $sync);
Expand All @@ -196,8 +206,7 @@ public function setRawAttributes(array $attributes, $sync = false)

protected static function ignoredProperties(): array
{
$reflectionClass = new ReflectionClass(self::class);
$ignoredProperties = collect($reflectionClass->getAttributes(IgnoreProperties::class))
$ignoredProperties = collect(static::getReflectionClass(static::class)->getAttributes(IgnoreProperties::class))
->flatMap(fn (ReflectionAttribute $attribute) => $attribute->getArguments());

return [
Expand All @@ -214,90 +223,112 @@ protected static function ignoredProperties(): array
];
}

/**
* @return Collection<PropertyInfo>
*
* @throws ReflectionException
*/
private static function getPropertiesWithAttributes(Model $model): Collection
{
$publicProperties = self::getModelPublicProperties($model);
$customColumns = self::customColumns();
$result = [];

foreach ($publicProperties as $prop) {
try {
$modelProp = $customColumns[$prop] ?? $prop;

$reflectionProperty = new ReflectionProperty($model, $prop);
return collect(static::getModelPublicReflectionProperties($model))
->map(function (ReflectionProperty $reflectionProperty) use ($model, $customColumns): ?PropertyInfo {
$propName = $reflectionProperty->getName();
$modelProp = $customColumns[$propName] ?? $propName;

if (! blank($model->getKey()) && ! $model->isDirty($prop) && $reflectionProperty->isInitialized($model)) {
$model->setAttribute($modelProp, $model->{$prop});
if (! blank($model->getKey()) && ! $model->isDirty($propName) && $reflectionProperty->isInitialized($model)) {
$model->setAttribute($modelProp, $model->{$propName});
}

$attributes = $reflectionProperty->getAttributes();

if (count($attributes) > 0) {
$result[] = new PropertyInfo(
name: $prop,
if ($attributes = $reflectionProperty->getAttributes()) {
return new PropertyInfo(
name: $propName,
value: $model->getAttribute($modelProp) ?? null,
attributes: collect($attributes),
);
}
} catch (ReflectionException) {
continue;
}
}

return collect($result);
return null;
})
->filter();
}

/**
* @return Collection<MethodInfo>
*
* @throws ReflectionException
*/
private static function getMethodsWithAttributes(Model $model): Collection
{
$publicMethods = self::getModelPublicMethods($model);
$result = [];

foreach ($publicMethods as $method) {
try {

$reflectionMethod = new ReflectionMethod($model, $method);
$attributes = $reflectionMethod->getAttributes();
return collect(static::getModelPublicReflectionMethods($model))
->filter(fn (ReflectionMethod $reflectionMethod): bool => (bool) $reflectionMethod->getAttributes())
->map(fn (ReflectionMethod $reflectionMethod): MethodInfo => new MethodInfo(
name: $reflectionMethod->getName(),
method: $reflectionMethod,
attributes: collect($reflectionMethod->getAttributes()),
));
}

if (count($attributes) > 0) {
$result[] = new MethodInfo(
name: $method,
method: $reflectionMethod,
attributes: collect($attributes),
);
}
} catch (ReflectionException) {
continue;
}
/**
* @throws ReflectionException
*/
private static function getReflectionClass(object|string $objectOrClass): ReflectionClass
{
static $cache = [];
$key = is_string($objectOrClass) ? $objectOrClass : get_class($objectOrClass);
if (! isset($cache[$key])) {
$cache[$key] = new ReflectionClass($objectOrClass);
}

return collect($result);
return $cache[$key];
}

/**
* @return array<string>
*
* @throws ReflectionException
*/
private static function getModelPublicProperties(Model $model): array
{
$reflectionClass = new ReflectionClass($model);
$properties = [];
return array_column(static::getModelPublicReflectionProperties($model), 'name');
}

foreach ($reflectionClass->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
if (in_array($property->getName(), self::ignoredProperties())) {
continue;
}
$properties[] = $property->getName();
}
/**
* @return array<ReflectionProperty>
*
* @throws ReflectionException
*/
private static function getModelPublicReflectionProperties(Model $model): array
{
$properties = static::getReflectionClass($model)->getProperties(ReflectionProperty::IS_PUBLIC);
$propertyNameMap = array_combine(array_column($properties, 'name'), $properties);
$relevantProperties = array_diff_key(
$propertyNameMap,
array_flip(static::ignoredProperties())
);

return $properties;
return array_values($relevantProperties);
}

/**
* @return array<string>
*
* @throws ReflectionException
*/
private static function getModelPublicMethods(Model $model): array
{
$reflectionClass = new ReflectionClass($model);
$methods = [];

foreach ($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
$methods[] = $method->getName();
}
return array_column(static::getModelPublicReflectionMethods($model), 'name');
}

return $methods;
/**
* @return array<ReflectionMethod>
*
* @throws ReflectionException
*/
private static function getModelPublicReflectionMethods(Model $model): array
{
return static::getReflectionClass($model)->getMethods(ReflectionMethod::IS_PUBLIC);
}

/**
Expand Down Expand Up @@ -328,6 +359,9 @@ private static function getMethodsForAttributes(Collection $methods, array $attr
);
}

/**
* @param Collection<MethodInfo> $methods
*/
private static function getMethodForAttribute(Collection $methods, string $attributeClass): ?MethodInfo
{
return $methods->first(
Expand All @@ -337,6 +371,10 @@ private static function getMethodForAttribute(Collection $methods, string $attri
);
}

/**
* @param Collection<MethodInfo> $methods
* @return Collection<MethodInfo>
*/
private static function getMethodsForAttribute(Collection $methods, string $attributeClass): Collection
{
return $methods->filter(
Expand Down

0 comments on commit 87221db

Please sign in to comment.