Skip to content

Commit

Permalink
Merge pull request #5 from mahmoudmohamedramadan/development
Browse files Browse the repository at this point in the history
[1.x] Extend the "scopes" to accept paramteres
  • Loading branch information
mahmoudmohamedramadan authored Oct 31, 2024
2 parents 784a528 + 79d841f commit c338da9
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 17 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,8 @@ public function index()
->usingScopes([
// new EmailVerifiedScope, // Global Scope in object
EmailVerifiedScope::class, // Global Scope in string
'isAdmin' // Local Scope
// 'isAdmin', // Local Scope
'isAdmin' => [false], // Local Scope With Parameters
])
->execute()
->get();
Expand Down
15 changes: 7 additions & 8 deletions src/Concerns/HasModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,21 +156,20 @@ protected function resolveModel()
*/
public function usingScopes(array $scopes)
{
// TODO: Add the ability to pass additional arguments to local scopes.
$localScopes = [];

foreach ($scopes as $scope) {
if (is_a($scope, Scope::class, true)) {
$identifier = is_string($scope) ? $scope : get_class($scope);
$scope = is_string($scope) ? new $scope : $scope;
$this->getEloquentBuilder()->withGlobalScope($identifier, $scope);
foreach ($scopes as $scope => $parameters) {
if (is_a($parameters, Scope::class, true)) {
$identifier = is_string($parameters) ? $parameters : get_class($parameters);
$scope = is_string($parameters) ? new $parameters : $parameters;
$this->eloquentBuilder = $this->getEloquentBuilder()->withGlobalScope($identifier, $scope);
} else {
$localScopes[] = $scope;
$localScopes[$scope] = $parameters;
}
}

if (!empty($localScopes)) {
$this->getEloquentBuilder()->scopes($localScopes);
$this->eloquentBuilder = $this->getEloquentBuilder()->scopes($localScopes);
}

return $this;
Expand Down
27 changes: 19 additions & 8 deletions src/Concerns/Orderable.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Ramadan\EasyModel\Exceptions\InvalidArrayStructure;
use Ramadan\EasyModel\Exceptions\InvalidOrderableRelationship;

trait Orderable
{
Expand All @@ -20,6 +21,7 @@ trait Orderable
*
* @throws \Ramadan\EasyModel\Exceptions\InvalidSearchableModel
* @throws \Ramadan\EasyModel\Exceptions\InvalidArrayStructure
* @throws \Ramadan\EasyModel\Exceptions\InvalidOrderableRelationship
*/
public function addOrderBy(array $orders, Builder $query = null)
{
Expand Down Expand Up @@ -49,6 +51,7 @@ public function addOrderBy(array $orders, Builder $query = null)
* @return array
*
* @throws \Ramadan\EasyModel\Exceptions\InvalidArrayStructure
* @throws \Ramadan\EasyModel\Exceptions\InvalidOrderableRelationship
*/
protected function prepareParamtersForOrderBy(string|array $order, $queryBuilder)
{
Expand All @@ -74,8 +77,8 @@ protected function prepareParamtersForOrderBy(string|array $order, $queryBuilder
}

if (count($parts) > 1) {
// In case the order is related to the model relationships, we need to get
// the relationships and the column that needs to be ordered (e.g., "posts.created_at").
// In case the order is related to the model relationships, we need to get the last
// relationship and the column that needs to be ordered (e.g., "post.comments.created_at").
$column = $this->performJoinsForOrderByRelationships($parts, $queryBuilder);
}

Expand All @@ -95,6 +98,8 @@ protected function prepareParamtersForOrderBy(string|array $order, $queryBuilder
* @param array $relationships
* @param \Illuminate\Database\Query\Builder $queryBuilder
* @return string
*
* @throws \Ramadan\EasyModel\Exceptions\InvalidOrderableRelationship
*/
protected function performJoinsForOrderByRelationships($relationships, $queryBuilder)
{
Expand All @@ -104,20 +109,20 @@ protected function performJoinsForOrderByRelationships($relationships, $queryBui
$currentRelationship = $currentModel->{$relationships[$i]}();
$relatedModel = $currentRelationship->getModel();

// At first let's pretend that the current model is "App\Models\User" which is the parent and he has
// one or many child models (e.g., "post", "comments") in this case, the foreign key of the current
// At first let's pretend that the current model is "App\Models\User" which is the parent and it has
// one or many child models (e.g., "profile", "accounts") in this case, the foreign key of the current
// model is "user_id" and must be exists in the child table(s).
if (in_array(get_class($currentRelationship), [HasMany::class, HasOne::class])) {
if (in_array(get_class($currentRelationship), [HasOne::class, HasMany::class])) {
$currentTableName = $currentModel->getTable();
$relatedTableName = $relatedModel->getTable();

$currentForeignKey = $currentModel->getForeignKey();
$currentTablePrimaryKey = $currentModel->getKeyName();
}

// But, in case the current model is "App\Models\Post" which is the child and it belongs to
// a parent model (e.g., "user") the foreign key "user_id" must exists in the table of the
// current related model "posts".
// But, in case the current model is "App\Models\Comment" which is the child and it belongs to a
// parent model (e.g., "App\Models\Post") the foreign key "post_id" must exists in the table of the
// current related model "comments".
elseif (in_array(get_class($currentRelationship), [BelongsTo::class, BelongsToMany::class])) {
$currentTableName = $relatedModel->getTable();
$relatedTableName = $currentModel->getTable();
Expand All @@ -126,6 +131,12 @@ protected function performJoinsForOrderByRelationships($relationships, $queryBui
$currentTablePrimaryKey = $currentModel->getKeyName();
}

if (empty($currentTableName) || empty($relatedTableName)) {
throw new InvalidOrderableRelationship(
sprintf('The orderable relationship [%s] is unsupported.', get_class($currentRelationship))
);
}

// Perform the join
$queryBuilder->join(
table: $relatedModel->getTable(),
Expand Down
19 changes: 19 additions & 0 deletions src/Exceptions/InvalidOrderableRelationship.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Ramadan\EasyModel\Exceptions;

use Exception;

class InvalidOrderableRelationship extends Exception
{
/**
* Create a new exception instance.
*
* @param string $message
* @return void
*/
public function __construct($message)
{
parent::__construct($message);
}
}

0 comments on commit c338da9

Please sign in to comment.