Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions src/app/Library/CrudPanel/CrudPanel.php
Original file line number Diff line number Diff line change
Expand Up @@ -489,22 +489,4 @@ private function getRelatedEntries($model, $relationString)

return $results;
}

/**
* Check if the method in the given model has any parameters.
*
* @param object $model
* @param string $method
* @return bool
*/
private function modelMethodHasParameters($model, $method)
{
$reflectClassMethod = new \ReflectionMethod(get_class($model), $method);

if ($reflectClassMethod->getNumberOfParameters() > 0) {
return true;
}

return false;
}
}
48 changes: 24 additions & 24 deletions src/app/Library/CrudPanel/Traits/ColumnsProtectedMethods.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,32 +190,33 @@ protected function makeSureColumnHasEntity($column)
if (strpos($column['name'], '.') !== false) {
$possibleMethodName = Str::before($column['name'], '.');

// if the first part of the string exists as method,
// it is a relationship
// if the first part of the string exists as method in the model
if (method_exists($this->model, $possibleMethodName)) {

// if it has parameters it's not a relation method.
$column['entity'] = $this->modelMethodHasParameters($this->model, $possibleMethodName) ? false : $column['name'];
// check model method for possibility of being a relationship
$column['entity'] = $this->modelMethodIsRelationship($this->model, $possibleMethodName) ? $column['name'] : false;

$parts = explode('.', $column['entity']);
if ($column['entity']) {
$parts = explode('.', $column['entity']);

$attribute_in_relation = false;
$attribute_in_relation = false;

$model = $this->model;
$model = $this->model;

// here we are going to iterate through all relation parts to check
// if the attribute is present in the relation string.
foreach ($parts as $i => $part) {
try {
$model = $model->$part()->getRelated();
} catch (\Exception $e) {
$attribute_in_relation = true;
// here we are going to iterate through all relation parts to check
// if the attribute is present in the relation string.
foreach ($parts as $i => $part) {
try {
$model = $model->$part()->getRelated();
} catch (\Exception $e) {
$attribute_in_relation = true;
}
}
// if the user setup the attribute in relation string, we are not going to infer that attribute from model
// instead we get the defined attribute by the user.
if ($attribute_in_relation) {
$column['attribute'] = $column['attribute'] ?? end($parts);
}
}
// if the user setup the attribute in relation string, we are not going to infer that attribute from model
// instead we get the defined attribute by the user.
if ($attribute_in_relation) {
$column['attribute'] = $column['attribute'] ?? end($parts);
}

return $column;
Expand All @@ -225,8 +226,8 @@ protected function makeSureColumnHasEntity($column)
// if there's a method on the model with this name
if (method_exists($this->model, $column['name'])) {

// if it has parameters it's not a relation method.
$column['entity'] = $this->modelMethodHasParameters($this->model, $column['name']) ? false : $column['name'];
// check model method for possibility of being a relationship
$column['entity'] = $this->modelMethodIsRelationship($this->model, $column['name']);

return $column;
}
Expand All @@ -237,9 +238,8 @@ protected function makeSureColumnHasEntity($column)
$possibleMethodName = Str::replaceLast('_id', '', $column['name']);

if (method_exists($this->model, $possibleMethodName)) {

// if it has parameters it's not a relation method.
$column['entity'] = $this->modelMethodHasParameters($this->model, $possibleMethodName) ? false : $possibleMethodName;
// check model method for possibility of being a relationship
$column['entity'] = $this->modelMethodIsRelationship($this->model, $possibleMethodName);

return $column;
}
Expand Down
12 changes: 6 additions & 6 deletions src/app/Library/CrudPanel/Traits/FieldsProtectedMethods.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,16 @@ protected function makeSureFieldHasEntity($field)
//if the name is dot notation we are sure it's a relationship
if (strpos($field['name'], '.') !== false) {
$possibleMethodName = Str::of($field['name'])->before('.');
// if it has parameters it's not a relation method.
$field['entity'] = $this->modelMethodHasParameters($model, $possibleMethodName) ? false : $field['name'];
// check model method for possibility of being a relationship
$field['entity'] = $this->modelMethodIsRelationship($model, $possibleMethodName) ? $field['name'] : false;

return $field;
}

// if there's a method on the model with this name
if (method_exists($model, $field['name'])) {
// if it has parameters it's not a relation method.
$field['entity'] = $this->modelMethodHasParameters($model, $field['name']) ? false : $field['name'];
// check model method for possibility of being a relationship
$field['entity'] = $this->modelMethodIsRelationship($model, $field['name']);

return $field;
}
Expand All @@ -162,8 +162,8 @@ protected function makeSureFieldHasEntity($field)
$possibleMethodName = Str::replaceLast('_id', '', $field['name']);

if (method_exists($model, $possibleMethodName)) {
// if it has parameters it's not a relation method.
$field['entity'] = $this->modelMethodHasParameters($model, $possibleMethodName) ? false : $possibleMethodName;
// check model method for possibility of being a relationship
$field['entity'] = $this->modelMethodIsRelationship($model, $possibleMethodName);

return $field;
}
Expand Down
44 changes: 44 additions & 0 deletions src/app/Library/CrudPanel/Traits/Relationships.php
Original file line number Diff line number Diff line change
Expand Up @@ -309,4 +309,48 @@ private static function getPivotFieldStructure($field)

return $pivotSelectorField;
}

/**
* Checks the properties of the provided method to better verify if it could be a relation.
* Case the method is not public, is not a relation.
* Case the return type is Attribute, or extends Attribute is not a relation method.
* If the return type extends the Relation class is for sure a relation
* Otherwise we just assume it's a relation.
*
* DEV NOTE: In future versions we will return `false` when no return type is set and make the return type mandatory for relationships.
* This function should be refactored to only check if $returnType is a subclass of Illuminate\Database\Eloquent\Relations\Relation.
*
* @param $model
* @param $method
* @return bool|string
*/
private function modelMethodIsRelationship($model, $method)
{
$methodReflection = new \ReflectionMethod($model, $method);

// relationship methods function does not have parameters
if ($methodReflection->getNumberOfParameters() > 0) {
return false;
}

// relationships are always public methods.
if (! $methodReflection->isPublic()) {
return false;
}

$returnType = $methodReflection->getReturnType();

if ($returnType) {
$returnType = $returnType->getName();
if (is_a((new $returnType), 'Illuminate\Database\Eloquent\Casts\Attribute')) {
return false;
}

if (is_a((new $returnType), 'Illuminate\Database\Eloquent\Relations\Relation')) {
return $method;
}
}

return $method;
}
}