From c25adb07dd92d9a51154ca74c3caab31ffb15cd7 Mon Sep 17 00:00:00 2001 From: LT Date: Sat, 1 Feb 2025 10:48:03 +0300 Subject: [PATCH 1/3] fix: BelongsToMany and add onRequestValue --- .../src/DependencyInjection/MoonShine.php | 8 ++++ .../Relationships/ModelRelationField.php | 40 ++++++++++++++----- .../Fields/BelongsToOrManyCreatable.php | 5 +++ src/UI/src/Fields/FormElement.php | 26 +++++++++++- 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/Laravel/src/DependencyInjection/MoonShine.php b/src/Laravel/src/DependencyInjection/MoonShine.php index 3cc9ee0f5..d0eb1f7b6 100644 --- a/src/Laravel/src/DependencyInjection/MoonShine.php +++ b/src/Laravel/src/DependencyInjection/MoonShine.php @@ -7,6 +7,7 @@ use MoonShine\Contracts\Core\DependencyInjection\StorageContract; use MoonShine\Core\Core; use MoonShine\Core\Storage\FileStorage; +use MoonShine\Laravel\Fields\Relationships\ModelRelationField; /** * @extends Core @@ -58,4 +59,11 @@ public function getStorage(...$parameters): StorageContract { return app()->make(StorageContract::class, $parameters) ?? new FileStorage(); } + + public function flushState(): void + { + parent::flushState(); + + ModelRelationField::$excludeInstancing = []; + } } diff --git a/src/Laravel/src/Fields/Relationships/ModelRelationField.php b/src/Laravel/src/Fields/Relationships/ModelRelationField.php index 969326f62..8202937d6 100644 --- a/src/Laravel/src/Fields/Relationships/ModelRelationField.php +++ b/src/Laravel/src/Fields/Relationships/ModelRelationField.php @@ -43,6 +43,8 @@ abstract class ModelRelationField extends Field implements HasResourceContract protected bool $isMorph = false; + public static array $excludeInstancing = []; + /** * @throws Throwable */ @@ -76,7 +78,7 @@ public function __construct( ->singular() ->snake() ->append('_id') - ->value() + ->value(), ); } @@ -89,11 +91,27 @@ public function __construct( } // required to create field entities and load assets - if ($this instanceof HasFieldsContract && ! $this->isMorph()) { + if ($this instanceof HasFieldsContract && !$this->isExcludeInstancing() && ! $this->isMorph()) { + $this->excludeInstancing(); $this->getResource()?->getFormFields(); } } + public function excludeInstancing(): void + { + self::$excludeInstancing[$this->getExcludeInstanceName()] = true; + } + + private function getExcludeInstanceName(): string + { + return class_basename($this) . $this->getRelationName(); + } + + private function isExcludeInstancing(): bool + { + return isset(self::$excludeInstancing[$this->getExcludeInstanceName()]); + } + /** * @param ?class-string $classString * @throws Throwable @@ -112,13 +130,13 @@ protected function findResource(?string $classString = null): ModelResource ->singular() ->append('Resource') ->kebab() - ->value() + ->value(), ); if (\is_null($resource) && $this->isMorph()) { /** @var ModelResource $resource */ $resource = moonshine()->getResources()->findByUri( - moonshineRequest()->getResourceUri() + moonshineRequest()->getResourceUri(), ); } @@ -127,9 +145,9 @@ protected function findResource(?string $classString = null): ModelResource function (?ModelResource $resource): void { throw_if( \is_null($resource), - FieldException::resourceRequired(static::class, $this->getRelationName()) + FieldException::resourceRequired(static::class, $this->getRelationName()), ); - } + }, ); } @@ -156,15 +174,15 @@ protected function resolveFill(array $raw = [], ?DataWrapperContract $casted = n if ($this->isToOne()) { $this->setColumn( - $this->getRelation()?->getForeignKeyName() ?? '' + $this->getRelation()?->getForeignKeyName() ?? '', ); $this->setRawValue( - $raw[$this->getColumn()] ?? null + $raw[$this->getColumn()] ?? null, ); $this->setFormattedValue( - data_get($data, $this->getResourceColumn()) + data_get($data, $this->getResourceColumn()), ); } @@ -185,8 +203,8 @@ public function toFormattedValue(): mixed $this->getFormattedValueCallback(), $value ?? $this->getRelation()?->getModel(), $this->getRowIndex(), - $this - ) + $this, + ), ); } diff --git a/src/Laravel/src/Traits/Fields/BelongsToOrManyCreatable.php b/src/Laravel/src/Traits/Fields/BelongsToOrManyCreatable.php index 20ee439da..7cd9c48c4 100644 --- a/src/Laravel/src/Traits/Fields/BelongsToOrManyCreatable.php +++ b/src/Laravel/src/Traits/Fields/BelongsToOrManyCreatable.php @@ -7,6 +7,7 @@ use Closure; use MoonShine\Contracts\UI\ActionButtonContract; use MoonShine\Laravel\Buttons\BelongsToOrManyButton; +use MoonShine\Laravel\Fields\Relationships\BelongsToMany; use Throwable; trait BelongsToOrManyCreatable @@ -43,6 +44,10 @@ public function getCreateButton(): ?ActionButtonContract return null; } + if ($this->getParent() instanceof BelongsToMany) { + return null; + } + $button = BelongsToOrManyButton::for($this, button: $this->creatableButton); return $button->isSee() diff --git a/src/UI/src/Fields/FormElement.php b/src/UI/src/Fields/FormElement.php index 71296f84b..6fe3a5249 100644 --- a/src/UI/src/Fields/FormElement.php +++ b/src/UI/src/Fields/FormElement.php @@ -73,6 +73,8 @@ abstract class FormElement extends MoonShineComponent implements FormElementCont protected static ?Closure $requestValueResolver = null; + protected ?Closure $onRequestValue = null; + protected ?string $requestKeyPrefix = null; protected bool $hasOld = true; @@ -520,18 +522,40 @@ public static function requestValueResolver(Closure $resolver): void static::$requestValueResolver = $resolver; } + /** + * @param Closure(mixed $value, string $name, mixed $default, static $ctx): mixed $callback + */ + public function onRequestValue(Closure $callback): static + { + $this->onRequestValue = $callback; + + return $this; + } + public function getRequestValue(string|int|null $index = null): mixed { if (! \is_null(static::$requestValueResolver)) { return \call_user_func(static::$requestValueResolver, $index, $this->getDefaultIfExists(), $this); } - return $this->prepareRequestValue( + $value = $this->prepareRequestValue( $this->getCore()->getRequest()->get( $this->getRequestNameDot($index), $this->getDefaultIfExists() ) ?? false ); + + if($this->onRequestValue !== null) { + return \call_user_func( + $this->onRequestValue, + $value, + $this->getRequestNameDot($index), + $this->getDefaultIfExists(), + $this + ); + } + + return $value; } public function getRequestNameDot(string|int|null $index = null): string From c6aff28d3e6a8b6e6116e1139a7952e76624970a Mon Sep 17 00:00:00 2001 From: lee-to Date: Sat, 1 Feb 2025 07:48:59 +0000 Subject: [PATCH 2/3] [rector] Rector fixes --- src/UI/src/Fields/FormElement.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UI/src/Fields/FormElement.php b/src/UI/src/Fields/FormElement.php index 6fe3a5249..6aa677b58 100644 --- a/src/UI/src/Fields/FormElement.php +++ b/src/UI/src/Fields/FormElement.php @@ -545,7 +545,7 @@ public function getRequestValue(string|int|null $index = null): mixed ) ?? false ); - if($this->onRequestValue !== null) { + if($this->onRequestValue instanceof Closure) { return \call_user_func( $this->onRequestValue, $value, From 6fb7fdb5c6bd9ae3d97e27aaeb36c8afae8d855e Mon Sep 17 00:00:00 2001 From: lee-to Date: Sat, 1 Feb 2025 07:50:02 +0000 Subject: [PATCH 3/3] Fix styling --- src/Laravel/src/Fields/Relationships/ModelRelationField.php | 2 +- src/UI/src/Fields/FormElement.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Laravel/src/Fields/Relationships/ModelRelationField.php b/src/Laravel/src/Fields/Relationships/ModelRelationField.php index 8202937d6..25c12ced1 100644 --- a/src/Laravel/src/Fields/Relationships/ModelRelationField.php +++ b/src/Laravel/src/Fields/Relationships/ModelRelationField.php @@ -91,7 +91,7 @@ public function __construct( } // required to create field entities and load assets - if ($this instanceof HasFieldsContract && !$this->isExcludeInstancing() && ! $this->isMorph()) { + if ($this instanceof HasFieldsContract && ! $this->isExcludeInstancing() && ! $this->isMorph()) { $this->excludeInstancing(); $this->getResource()?->getFormFields(); } diff --git a/src/UI/src/Fields/FormElement.php b/src/UI/src/Fields/FormElement.php index 6aa677b58..223aaed53 100644 --- a/src/UI/src/Fields/FormElement.php +++ b/src/UI/src/Fields/FormElement.php @@ -545,7 +545,7 @@ public function getRequestValue(string|int|null $index = null): mixed ) ?? false ); - if($this->onRequestValue instanceof Closure) { + if ($this->onRequestValue instanceof Closure) { return \call_user_func( $this->onRequestValue, $value,