From d03c37cef17a4748d8572a11d767b96a96d39caa Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Wed, 7 Aug 2024 07:12:04 -0400 Subject: [PATCH] allow for creating an Auditable model even if application is not spun up --- src/Auditable.php | 129 +++++++++++++++---------- tests/Unit/OutsideOfAppContextTest.php | 15 +++ 2 files changed, 93 insertions(+), 51 deletions(-) create mode 100644 tests/Unit/OutsideOfAppContextTest.php diff --git a/src/Auditable.php b/src/Auditable.php index 3696afb2..5b63f9e4 100644 --- a/src/Auditable.php +++ b/src/Auditable.php @@ -71,7 +71,22 @@ trait Auditable */ public static function bootAuditable() { - if (static::isAuditingEnabled()) { + try { + $isAuditingEnabled = static::isAuditingEnabled(); + } catch (\RuntimeException $e) { + if ($e->getMessage() !== 'A facade root has not been set.') { + throw $e; + } + + /** + * Facade root has not been set. The user may be attempting to use + * their Auditable outside of the application context. We will + * just skip booting for now. + */ + return; + } + + if ($isAuditingEnabled) { static::observe(new AuditableObserver()); } } @@ -273,8 +288,8 @@ public function readyForAuditing(): bool /** * Modify attribute value. * - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return mixed * @throws AuditingException @@ -341,14 +356,14 @@ public function toAudit(): array $user = $this->resolveUser(); return $this->transformAudit(array_merge([ - 'old_values' => $old, - 'new_values' => $new, - 'event' => $this->auditEvent, - 'auditable_id' => $this->getKey(), - 'auditable_type' => $this->getMorphClass(), - $morphPrefix . '_id' => $user ? $user->getAuthIdentifier() : null, - $morphPrefix . '_type' => $user ? $user->getMorphClass() : null, - 'tags' => empty($tags) ? null : $tags, + 'old_values' => $old, + 'new_values' => $new, + 'event' => $this->auditEvent, + 'auditable_id' => $this->getKey(), + 'auditable_type' => $this->getMorphClass(), + $morphPrefix.'_id' => $user ? $user->getAuthIdentifier() : null, + $morphPrefix.'_type' => $user ? $user->getMorphClass() : null, + 'tags' => empty($tags) ? null : $tags, ], $this->runResolvers())); } @@ -408,7 +423,7 @@ protected function runResolvers(): array } if (!is_subclass_of($implementation, Resolver::class)) { - throw new AuditingException('Invalid Resolver implementation for: ' . $name); + throw new AuditingException('Invalid Resolver implementation for: '.$name); } $resolved[$name] = call_user_func([$implementation, 'resolve'], $this); } @@ -430,7 +445,7 @@ public function preloadResolverData() /** * Determine if an attribute is eligible for auditing. * - * @param string $attribute + * @param string $attribute * * @return bool */ @@ -451,7 +466,7 @@ protected function isAttributeAuditable(string $attribute): bool /** * Determine whether an event is auditable. * - * @param string $event + * @param string $event * * @return bool */ @@ -463,7 +478,7 @@ protected function isEventAuditable($event): bool /** * Attribute getter method resolver. * - * @param string $event + * @param string $event * * @return string|null */ @@ -552,8 +567,8 @@ public static function enableAuditing() /** * Execute a callback while auditing is disabled. * - * @param callable $callback - * @param bool $globally + * @param callable $callback + * @param bool $globally * * @return mixed */ @@ -700,17 +715,23 @@ public function transitionTo(Contracts\Audit $audit, bool $old = false): Contrac */ /** - * @param string $relationName - * @param mixed $id - * @param array $attributes - * @param bool $touch - * @param array $columns - * @param \Closure|null $callback + * @param string $relationName + * @param mixed $id + * @param array $attributes + * @param bool $touch + * @param array $columns + * @param \Closure|null $callback * @return void * @throws AuditingException */ - public function auditAttach(string $relationName, $id, array $attributes = [], $touch = true, $columns = ['*'], $callback = null) - { + public function auditAttach( + string $relationName, + $id, + array $attributes = [], + $touch = true, + $columns = ['*'], + $callback = null + ) { $this->validateRelationshipMethodExistence($relationName, 'attach'); $relationCall = $this->{$relationName}(); @@ -727,11 +748,11 @@ public function auditAttach(string $relationName, $id, array $attributes = [], $ } /** - * @param string $relationName - * @param mixed $ids - * @param bool $touch - * @param array $columns - * @param \Closure|null $callback + * @param string $relationName + * @param mixed $ids + * @param bool $touch + * @param array $columns + * @param \Closure|null $callback * @return int * @throws AuditingException */ @@ -755,11 +776,11 @@ public function auditDetach(string $relationName, $ids = null, $touch = true, $c } /** - * @param string $relationName - * @param Collection|Model|array $ids - * @param bool $detaching - * @param array $columns - * @param \Closure|null $callback + * @param string $relationName + * @param Collection|Model|array $ids + * @param bool $detaching + * @param array $columns + * @param \Closure|null $callback * @return array * @throws AuditingException */ @@ -788,10 +809,10 @@ public function auditSync(string $relationName, $ids, $detaching = true, $column } /** - * @param string $relationName - * @param Collection|Model|array $ids - * @param array $columns - * @param \Closure|null $callback + * @param string $relationName + * @param Collection|Model|array $ids + * @param array $columns + * @param \Closure|null $callback * @return array * @throws AuditingException */ @@ -803,16 +824,22 @@ public function auditSyncWithoutDetaching(string $relationName, $ids, $columns = } /** - * @param string $relationName - * @param Collection|Model|array $ids - * @param array $values - * @param bool $detaching - * @param array $columns - * @param \Closure|null $callback + * @param string $relationName + * @param Collection|Model|array $ids + * @param array $values + * @param bool $detaching + * @param array $columns + * @param \Closure|null $callback * @return array */ - public function auditSyncWithPivotValues(string $relationName, $ids, array $values, bool $detaching = true, $columns = ['*'], $callback = null) - { + public function auditSyncWithPivotValues( + string $relationName, + $ids, + array $values, + bool $detaching = true, + $columns = ['*'], + $callback = null + ) { $this->validateRelationshipMethodExistence($relationName, 'syncWithPivotValues'); if ($ids instanceof Model) { @@ -829,10 +856,10 @@ public function auditSyncWithPivotValues(string $relationName, $ids, array $valu } /** - * @param string $relationName - * @param string $event - * @param Collection $old - * @param Collection $new + * @param string $relationName + * @param string $event + * @param Collection $old + * @param Collection $new * @return void */ private function dispatchRelationAuditEvent($relationName, $event, $old, $new) diff --git a/tests/Unit/OutsideOfAppContextTest.php b/tests/Unit/OutsideOfAppContextTest.php new file mode 100644 index 00000000..48afec09 --- /dev/null +++ b/tests/Unit/OutsideOfAppContextTest.php @@ -0,0 +1,15 @@ +assertInstanceOf(Article::class, $article); + } +} \ No newline at end of file