diff --git a/src/DataSource/ProcessDataSource.php b/src/DataSource/ProcessDataSource.php index 3e567785..a98ef3e0 100644 --- a/src/DataSource/ProcessDataSource.php +++ b/src/DataSource/ProcessDataSource.php @@ -10,6 +10,8 @@ class ProcessDataSource { + public mixed $datasource = null; + public function __construct( public PowerGridComponent $component, public array $properties = [], @@ -25,20 +27,25 @@ public static function make(PowerGridComponent $powerGridComponent, array $prope */ public function get(bool $isExport = false): array { + if (is_null($this->datasource)) { + $this->datasource = $this->component->datasource($this->properties); + } + + $datasource = is_object($this->datasource) ? clone $this->datasource : $this->datasource; + $processors = [ CollectionProcessor::class, ScoutBuilderProcessor::class, ]; foreach ($processors as $processor) { - // @phpstan-ignore-next-line - if ($processor::match($this->component->datasource($this->properties))) { + if ($processor::match($datasource)) { $instance = new $processor($this->component, $isExport); - return $instance->process($this->properties); + return $instance->process($this->properties, $datasource); } } - return (new ModelProcessor($this->component, $isExport))->process($this->properties); + return (new ModelProcessor($this->component, $isExport))->process($this->properties, $datasource); } } diff --git a/src/DataSource/Processors/CollectionProcessor.php b/src/DataSource/Processors/CollectionProcessor.php index 7c3c5357..5bc93cf9 100644 --- a/src/DataSource/Processors/CollectionProcessor.php +++ b/src/DataSource/Processors/CollectionProcessor.php @@ -17,9 +17,9 @@ public static function match(mixed $key): bool || is_iterable($key); } - public function process(array $properties = []): array + public function process(array $properties = [], mixed $datasource = null): array { - $datasource = $this->component->datasource($properties); + $datasource = $datasource ?? $this->component->datasource($properties); $collection = new BaseCollection($datasource); diff --git a/src/DataSource/Processors/ModelProcessor.php b/src/DataSource/Processors/ModelProcessor.php index 2d6abc73..b3c95db1 100644 --- a/src/DataSource/Processors/ModelProcessor.php +++ b/src/DataSource/Processors/ModelProcessor.php @@ -15,9 +15,9 @@ public static function match(mixed $key): bool return true; } - public function process(array $properties = []): array + public function process(array $properties = [], mixed $datasource = null): array { - $datasource = $this->component->datasource($properties); + $datasource = $datasource ?? $this->component->datasource($properties); $this->setCurrentTable($datasource); diff --git a/src/DataSource/Processors/ScoutBuilderProcessor.php b/src/DataSource/Processors/ScoutBuilderProcessor.php index 4083f560..03fb5713 100644 --- a/src/DataSource/Processors/ScoutBuilderProcessor.php +++ b/src/DataSource/Processors/ScoutBuilderProcessor.php @@ -15,10 +15,10 @@ public static function match(mixed $key): bool return $key instanceof ScoutBuilder; } - public function process(array $properties = []): array + public function process(array $properties = [], mixed $datasource = null): array { /** @var ScoutBuilder $datasource */ - $datasource = $this->component->datasource($properties); + $datasource = $datasource ?? $this->component->datasource($properties); /** @var ScoutBuilder $query */ $query = app(Pipeline::class) diff --git a/src/PowerGridComponent.php b/src/PowerGridComponent.php index 189468db..2d162d50 100644 --- a/src/PowerGridComponent.php +++ b/src/PowerGridComponent.php @@ -141,7 +141,13 @@ private function getRecordsFromCache(): mixed $customTag = strval(data_get($this->setUp, 'cache.tag')); $ttl = intval(data_get($this->setUp, 'cache.ttl')); - $tag = $prefix.($customTag ?: 'powergrid-'.$this->datasource()->getModel()->getTable().'-'.$this->tableName); + if (filled($customTag)) { + $tag = $prefix.$customTag; + } else { + $datasource = $this->datasource(); + $table = method_exists($datasource, 'getModel') ? $datasource->getModel()->getTable() : $this->tableName; + $tag = $prefix.'powergrid-'.$table.'-'.$this->tableName; + } $cacheKey = implode('-', $this->getCacheKeys()); /** @var array $results */ diff --git a/src/Traits/ExportableJob.php b/src/Traits/ExportableJob.php index ccb96e35..8fda8b8b 100644 --- a/src/Traits/ExportableJob.php +++ b/src/Traits/ExportableJob.php @@ -61,7 +61,7 @@ private function prepareToExport(array $properties = []): Eloquent\Collection|Co : $currentTable.'.'.$property; }; - $results = $this->componentTable->datasource($this->properties ?? []) // @phpstan-ignore-line + $results = $processDataSource->datasource ->where(function ($query) { app()->makeWith(SearchHandlerContract::class, [ 'component' => $this->componentTable, diff --git a/src/Traits/WithExport.php b/src/Traits/WithExport.php index 77616882..b8a0f02f 100644 --- a/src/Traits/WithExport.php +++ b/src/Traits/WithExport.php @@ -167,7 +167,7 @@ public function prepareToExport(bool $selected = false): Eloquent\Collection|Col $filtered = $processDataSource->component->checkboxValues; } - if ($processDataSource->component->datasource() instanceof Collection) { + if ($processDataSource->datasource instanceof Collection) { if ($filtered) { $results = $processDataSource->get(isExport: true)['results'] ->whereIn($this->primaryKey, $filtered); @@ -179,7 +179,7 @@ public function prepareToExport(bool $selected = false): Eloquent\Collection|Col $dataTransformer = new DataTransformer($processDataSource->component); - return $dataTransformer->transform($processDataSource->component->datasource())->collection; + return $dataTransformer->transform($processDataSource->datasource)->collection; } /** @phpstan-ignore-next-line */ @@ -195,7 +195,7 @@ public function prepareToExport(bool $selected = false): Eloquent\Collection|Col $queryOptions = data_get($this->setUp, 'exportable.queryOptions', []); - $results = $processDataSource->component->datasource() + $results = $processDataSource->datasource ->where(function ($query) { app()->makeWith(SearchHandlerContract::class, [ 'component' => $this, diff --git a/tests/Feature/DatasourceCallCountTest.php b/tests/Feature/DatasourceCallCountTest.php new file mode 100644 index 00000000..9cbc43a5 --- /dev/null +++ b/tests/Feature/DatasourceCallCountTest.php @@ -0,0 +1,107 @@ + 1, 'name' => 'Name 1'], + ['id' => 2, 'name' => 'Name 2'], + ]); + } + + public function fields(): PowerGridFields + { + return PowerGrid::fields() + ->add('id') + ->add('name'); + } + + public function columns(): array + { + return [ + Column::make('ID', 'id'), + Column::make('Name', 'name'), + ]; + } +} + +class EloquentDatasourceCountTable extends PowerGridComponent +{ + public string $tableName = 'eloquent-datasource-count-table'; + + public static int $calls = 0; + + public function datasource(): Builder + { + self::$calls++; + + return Dish::query(); + } + + public function fields(): PowerGridFields + { + return PowerGrid::fields() + ->add('id') + ->add('name'); + } + + public function columns(): array + { + return [ + Column::make('ID', 'id'), + Column::make('Name', 'name'), + ]; + } +} + +it('calls collection datasource() only once', function () { + DatasourceCountTable::$calls = 0; + + livewire(DatasourceCountTable::class) + ->assertOk(); + + expect(DatasourceCountTable::$calls)->toBe(1); +}); + +it('calls collection datasource() only once when searching', function () { + DatasourceCountTable::$calls = 0; + + livewire(DatasourceCountTable::class) + ->set('search', 'Name 1') + ->assertOk(); + + expect(DatasourceCountTable::$calls)->toBe(2); +}); + +it('calls eloquent datasource() only once', function () { + EloquentDatasourceCountTable::$calls = 0; + + livewire(EloquentDatasourceCountTable::class) + ->assertOk(); + + expect(EloquentDatasourceCountTable::$calls)->toBe(1); +}); + +it('calls eloquent datasource() only once when searching', function () { + EloquentDatasourceCountTable::$calls = 0; + + livewire(EloquentDatasourceCountTable::class) + ->set('search', 'Dish 1') + ->assertOk(); + + expect(EloquentDatasourceCountTable::$calls)->toBe(2); +});