Skip to content

Commit

Permalink
Merge pull request #159 from Askedio/fix/cleanup
Browse files Browse the repository at this point in the history
fix: cleanup
  • Loading branch information
gcphost authored Oct 28, 2024
2 parents 56d16b1 + 6b0be8b commit c0d0285
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 79 deletions.
6 changes: 3 additions & 3 deletions src/Contracts/SoftCascadeable.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ interface SoftCascadeable
/**
* Cascade over Eloquent items.
*
* @param Illuminate\Database\Eloquent\Model $models
* @param string $direction update|delete|restore
* @param array $directionData
* @param \Illuminate\Database\Eloquent\Model $models
* @param 'update'|'delete'|'restore' $direction
* @param array $directionData
*
* @return void
*/
Expand Down
26 changes: 15 additions & 11 deletions src/Exceptions/SoftCascadeRestrictedException.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,38 @@
use Illuminate\Support\Arr;
use RuntimeException;

/**
* @template TModelString of class-string<\Illuminate\Database\Eloquent\Model>
*/
class SoftCascadeRestrictedException extends RuntimeException
{
/**
* Name of the affected Eloquent model.
*
* @var string
* @var TModelString
*/
protected $model;

/**
* The affected model foreignKey.
*
* @var int|array
* @var string
*/
protected $foreignKey;

/**
* The affected model foreignKeyIds.
*
* @var int|array
* @var int[]
*/
protected $foreignKeyIds;

/**
* Set the affected Eloquent model and instance foreignKeyIds.
*
* @param string $model
* @param string $foreignKey
* @param int|array $foreignKeyIds
* @param TModelString $model
* @param string $foreignKey
* @param int | int[] $foreignKeyIds
*
* @return $this
*/
Expand All @@ -43,25 +46,26 @@ public function setModel($model, $foreignKey, $foreignKeyIds)
$this->foreignKey = $foreignKey;
$this->foreignKeyIds = Arr::wrap($foreignKeyIds);

$this->message = "Integrity constraint violation [{$model}] where $foreignKey in (".implode(', ', $foreignKeyIds).')';
$this->message =
"Integrity constraint violation [{$model}] where $foreignKey in (".implode(', ', $foreignKeyIds).')';

return $this;
}

/**
* Get the affected Eloquent model.
*
* @return string
* @return TModelString
*/
public function getModel()
{
return $this->model;
}

/**
* Get the affected Eloquent model foreignKeyIds.
* Get the affected Eloquent model foreignKey.
*
* @return int|array
* @return string
*/
public function getForeignKey()
{
Expand All @@ -71,7 +75,7 @@ public function getForeignKey()
/**
* Get the affected Eloquent model foreignKeyIds.
*
* @return int|array
* @return int[]
*/
public function getForeignKeyIds()
{
Expand Down
6 changes: 4 additions & 2 deletions src/Listeners/CascadeDeleteListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ class CascadeDeleteListener
/**
* Handel the event for eloquent delete.
*
* @param $event
* @param $model
* @param string $event
* @param \Illuminate\Database\Eloquent\Model $model
*
* @return void
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter("event"))
*
* @noinspection PhpUnusedParameterInspection
*/
public function handle($event, $model)
{
Expand Down
29 changes: 24 additions & 5 deletions src/Listeners/CascadeQueryListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,39 @@
use Askedio\SoftCascade\QueryBuilderSoftCascade;
use Askedio\SoftCascade\Traits\ChecksCascading;
use Illuminate\Database\Connection;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Support\Str;

class CascadeQueryListener
{
use ChecksCascading;
const EVENT = QueryExecuted::class;

public const EVENT = QueryExecuted::class;

/**
* Check in the backtrace, if models where updated by Builder::delete() or Builder::update().
*
* @return array{
* builder: object,
* direction: string,
* directionData: array,
* } | null
*/
private function checkForCascadeEvent(): ?array
{
/**
* @var \Illuminate\Support\Collection<array-key, array{
* function: string,
* line: int,
* file: string,
* class?: string,
* object?: object,
* type: string,
* args?: array,
* }> $traces
*/
$traces = collect(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 30));

// we limit the backtrace to the current and the previous query (=2 "QueryExecuted"-events),
Expand All @@ -29,15 +48,15 @@ private function checkForCascadeEvent(): ?array
$btFunction = $backtrace['function'] ?? null;
$btEvent = $backtrace['args'][0] ?? null;
if ($btClass === Connection::class && $btFunction === 'event' && $btEvent === static::EVENT) {
$queryExecutedEventLimit = $queryExecutedEventLimit - 1;
$queryExecutedEventLimit--;
}

return $queryExecutedEventLimit <= 0;
});

foreach ($traces as $backtrace) {
$btClass = $backtrace['class'] ?? null;
if (!is_a($btClass, \Illuminate\Database\Eloquent\Builder::class, true)) {
if (!is_a($btClass, Builder::class, true)) {
continue;
}

Expand Down Expand Up @@ -73,7 +92,7 @@ public function handle(): void
{
$event = $this->checkForCascadeEvent();

if (!is_null($event)) {
if ($event !== null) {
$builder = $event['builder'];

// add `withTrashed()`, if the model has SoftDeletes
Expand All @@ -84,7 +103,7 @@ public function handle(): void

$keyName = $builder->getModel()->getKeyName();

if (!$this->hasCascadingRelations($builder->getModel()) or $keyName === null) {
if ($keyName === null || !$this->hasCascadingRelations($builder->getModel())) {
// If model doesn't have any primary key, there will be no relations
return;
}
Expand Down
8 changes: 6 additions & 2 deletions src/Listeners/CascadeRestoreListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ class CascadeRestoreListener
/**
* Handel the event for eloquent restore.
*
* @param $event
* @param $model
* @param string $event
* @param \Illuminate\Database\Eloquent\Model $model
*
* @throws \Askedio\SoftCascade\Exceptions\SoftCascadeLogicException
*
* @return void
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter("event"))
*
* @noinspection PhpUnusedParameterInspection
*/
public function handle($event, $model)
{
Expand Down
8 changes: 4 additions & 4 deletions src/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ class EventServiceProvider extends ServiceProvider
/**
* The event listener mappings for the application.
*
* @var array
* @var array<string, array<int, class-string>>
*/
protected $listen = [
'eloquent.deleting: *' => [CascadeDeleteListener::class],
'eloquent.restoring: *' => [CascadeRestoreListener::class],
CascadeQueryListener::EVENT => [CascadeQueryListener::class],
'eloquent.deleting: *' => [CascadeDeleteListener::class],
'eloquent.restoring: *' => [CascadeRestoreListener::class],
CascadeQueryListener::EVENT => [CascadeQueryListener::class],
];
}
1 change: 0 additions & 1 deletion src/Providers/GenericServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class GenericServiceProvider extends ServiceProvider
*/
public function register()
{
//
}

/**
Expand Down
21 changes: 8 additions & 13 deletions src/Providers/LumenEventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

namespace Askedio\SoftCascade\Providers;

use Askedio\SoftCascade\Listeners\CascadeDeleteListener;
use Askedio\SoftCascade\Listeners\CascadeQueryListener;
use Askedio\SoftCascade\Listeners\CascadeRestoreListener;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;

Expand All @@ -10,21 +14,12 @@ class LumenEventServiceProvider extends ServiceProvider
/**
* The event listener mappings for the application.
*
* @var array
* @return void
*/
public function register()
{
Event::listen(
'eloquent.deleting: *',
['Askedio\SoftCascade\Listeners\CascadeDeleteListener', 'handle']
);
Event::listen(
'eloquent.restoring: *',
['Askedio\SoftCascade\Listeners\CascadeRestoreListener', 'handle']
);
Event::listen(
'Illuminate\Database\Events\QueryExecuted',
['Askedio\SoftCascade\Listeners\CascadeQueryListener', 'handle']
);
Event::listen('eloquent.deleting: *', [CascadeDeleteListener::class, 'handle']);
Event::listen('eloquent.restoring: *', [CascadeRestoreListener::class, 'handle']);
Event::listen(QueryExecuted::class, [CascadeQueryListener::class, 'handle']);
}
}
1 change: 0 additions & 1 deletion src/Providers/LumenServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class LumenServiceProvider extends ServiceProvider
*/
public function register()
{
//
}

/**
Expand Down
Loading

0 comments on commit c0d0285

Please sign in to comment.