From f846b1f4036e49c4ed8f53078afd627be842680f Mon Sep 17 00:00:00 2001 From: Luan Freitas Date: Sat, 28 May 2022 19:18:41 -0300 Subject: [PATCH 1/3] add searchableRaw --- src/Column.php | 16 +++++++++++++++- src/Helpers/Model.php | 10 ++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Column.php b/src/Column.php index 5413aa4d..cc422fdb 100644 --- a/src/Column.php +++ b/src/Column.php @@ -32,6 +32,8 @@ final class Column public bool $searchable = false; + public string $searchableRaw = ''; + public bool $sortable = false; public array $sum = [ @@ -118,7 +120,6 @@ public function placeholder(string $placeholder): Column /** * Makes the column searchable * - * @return Column */ public function searchable(): Column { @@ -127,6 +128,19 @@ public function searchable(): Column return $this; } + /** + * Makes the column searchable with SQL Raw + * + */ + public function searchableRaw(string $sql): Column + { + $this->searchable(); + + $this->searchableRaw = $sql; + + return $this; + } + /** * Adds sort to the column header * diff --git a/src/Helpers/Model.php b/src/Helpers/Model.php index d075916a..63f1f467 100644 --- a/src/Helpers/Model.php +++ b/src/Helpers/Model.php @@ -263,10 +263,8 @@ public function filterContains(): Model /** @var Column $column */ foreach ($this->columns as $column) { - /** @var string $searchable */ - $searchable = data_get($column, 'searchable'); - /** @var string $field */ - $field = data_get($column, 'dataField') ?: data_get($column, 'field'); + $searchable = strval(data_get($column, 'searchable')); + $field = strval(data_get($column, 'dataField')) ?: strval(data_get($column, 'field')); if ($searchable && $field) { if (str_contains($field, '.')) { @@ -282,6 +280,10 @@ public function filterContains(): Model if ($hasColumn) { $query->orWhere($table . '.' . $field, SqlSupport::like(), '%' . $this->search . '%'); } + + if ($sqlRaw = strval(data_get($column, 'searchableRaw'))) { + $query->orWhereRaw($sqlRaw . ' ' . SqlSupport::like() . ' "%' . $this->search . '%"'); + } } } From 85702be87034978c6ce2367813c0b8af06a5655b Mon Sep 17 00:00:00 2001 From: Luan Freitas Date: Sun, 29 May 2022 11:18:49 -0300 Subject: [PATCH 2/3] add tests --- src/Helpers/Model.php | 2 +- tests/DishesSearchableRawTable.php | 97 +++++++++++++++++++++++++++++ tests/Feature/SearchableRawTest.php | 30 +++++++++ tests/Pest.php | 42 +++++++++++-- 4 files changed, 164 insertions(+), 7 deletions(-) create mode 100644 tests/DishesSearchableRawTable.php create mode 100644 tests/Feature/SearchableRawTest.php diff --git a/src/Helpers/Model.php b/src/Helpers/Model.php index 63f1f467..2033a42a 100644 --- a/src/Helpers/Model.php +++ b/src/Helpers/Model.php @@ -282,7 +282,7 @@ public function filterContains(): Model } if ($sqlRaw = strval(data_get($column, 'searchableRaw'))) { - $query->orWhereRaw($sqlRaw . ' ' . SqlSupport::like() . ' "%' . $this->search . '%"'); + $query->orWhereRaw($sqlRaw . ' ' . SqlSupport::like() . ' \'%' . $this->search . '%\''); } } } diff --git a/tests/DishesSearchableRawTable.php b/tests/DishesSearchableRawTable.php new file mode 100644 index 00000000..2b53099a --- /dev/null +++ b/tests/DishesSearchableRawTable.php @@ -0,0 +1,97 @@ +showCheckBox(); + + return [ + Header::make() + ->showSearchInput(), + + Footer::make() + ->showPerPage() + ->showRecordCount(), + ]; + } + + public function datasource(): Builder + { + $searchableRaw = match ($this->database) { + 'sqlite' => 'STRFTIME("%d/%m/%Y", dishes.produced_at) as produced_at_formatted', + 'mysql' => 'DATE_FORMAT(dishes.produced_at, "%d/%m/%Y") as produced_at_formatted', + 'pgsql' => 'to_char(dishes.produced_at, \'DD/MM/YYYY\')::text as produced_at_formatted', + default => '' + }; + + return Dish::query() + ->join('categories', function ($categories) { + $categories->on('dishes.category_id', '=', 'categories.id'); + }) + ->select('dishes.*', 'categories.name as category_name', DB::raw($searchableRaw)); + } + + public function addColumns(): PowerGridEloquent + { + return PowerGrid::eloquent() + ->addColumn('id') + ->addColumn('name') + ->addColumn('produced_at_formatted'); + } + + public function columns(): array + { + $searchableRaw = match ($this->database) { + 'sqlite' => 'STRFTIME("%d/%m/%Y", dishes.produced_at)', + 'mysql' => 'DATE_FORMAT(dishes.produced_at, "%d/%m/%Y")', + 'pgsql' => 'to_char(dishes.produced_at, \'DD/MM/YYYY\')::text', + default => '' + }; + + return [ + Column::make('ID', 'id') + ->searchable() + ->sortable(), + + Column::make('Prato', 'name') + ->searchable() + ->editOnClick() + ->clickToCopy(true) + ->makeInputText('name') + ->placeholder('Prato placeholder') + ->sortable(), + + Column::make('Produced At Formatted', 'produced_at_formatted') + ->searchableRaw($searchableRaw) + ->sortable(), + ]; + } + + public function bootstrap() + { + config(['livewire-powergrid.theme' => 'bootstrap']); + } + + public function tailwind() + { + config(['livewire-powergrid.theme' => 'tailwind']); + } +} diff --git a/tests/Feature/SearchableRawTest.php b/tests/Feature/SearchableRawTest.php new file mode 100644 index 00000000..21a19c00 --- /dev/null +++ b/tests/Feature/SearchableRawTest.php @@ -0,0 +1,30 @@ + 'sqlite']) + ->call($params->theme) + ->set('search', '09/09/2021') + ->assertSee('Polpetone Filé Mignon') + ->assertDontSee('Barco-Sushi Simples') + ->assertDontSee('No records found'); +})->with('searchable-raw')->requiresSQLite(); + +it('searches data using whereRaw on mysql', function (string $component, object $params) { + livewire($component, ['database' => 'mysql']) + ->call($params->theme) + ->set('search', '09/09/2021') + ->assertSee('Polpetone Filé Mignon') + ->assertDontSee('Barco-Sushi Simples') + ->assertDontSee('No records found'); +})->with('searchable-raw')->requiresMySQL(); + +it('searches data using whereRaw on pgsql', function (string $component, object $params) { + livewire($component, ['database' => 'pgsql']) + ->call($params->theme) + ->set('search', '09/09/2021') + ->assertSee('Polpetone Filé Mignon') + ->assertDontSee('Barco-Sushi Simples') + ->assertDontSee('No records found'); +})->with('searchable-raw')->requiresPostgreSQL(); diff --git a/tests/Pest.php b/tests/Pest.php index 027595f1..15ee187a 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,22 +1,21 @@ in(__DIR__); @@ -47,7 +46,6 @@ function powergrid(): PowerGridComponent $component = new PowerGridComponent(1); $component->datasource = Dish::query(); $component->columns = $columns; - $component->perPage = 10; return $component; } @@ -163,6 +161,11 @@ function expectInputText(object $params, mixed $component, string $value, string [DishesCollectionTable::class, 'bootstrap'], ]); +dataset('searchable-raw', [ + 'tailwind' => [DishesSearchableRawTable::class, (object) ['theme' => 'tailwind']], + 'bootstrap' => [DishesSearchableRawTable::class, (object) ['theme' => 'bootstrap']], +]); + /** * Skip tests based on minimum PHP Version * @@ -178,6 +181,33 @@ function onlyFromPhp(string $version): mixed return test(); } +function requiresMySQL() +{ + if (DB::getDriverName() !== 'mysql') { + test()->markTestSkipped('This test requires MySQL database'); + } + + return test(); +} + +function requiresSQLite() +{ + if (DB::getDriverName() !== 'sqlite') { + test()->markTestSkipped('This test requires SQLite database'); + } + + return test(); +} + +function requiresPostgreSQL() +{ + if (DB::getDriverName() !== 'pgsql') { + test()->markTestSkipped('This test requires PostgreSQL database'); + } + + return test(); +} + expect()->extend('notToBeFileDownloaded', function ($component) { $downloadEffect = data_get($component->lastResponse, 'original.effects.download'); From b8954f249f223173a4fba1e0b8faa185b8e3edd9 Mon Sep 17 00:00:00 2001 From: Luan Freitas Date: Mon, 30 May 2022 11:30:24 -0300 Subject: [PATCH 3/3] add more asserts --- tests/Feature/SearchableRawTest.php | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/tests/Feature/SearchableRawTest.php b/tests/Feature/SearchableRawTest.php index 21a19c00..164bb209 100644 --- a/tests/Feature/SearchableRawTest.php +++ b/tests/Feature/SearchableRawTest.php @@ -8,16 +8,31 @@ ->set('search', '09/09/2021') ->assertSee('Polpetone Filé Mignon') ->assertDontSee('Barco-Sushi Simples') - ->assertDontSee('No records found'); + ->assertDontSee('No records found') + # 09/09/2022 + ->set('search', '09/09/2022') + ->assertSee('No records found') + # 06/2026 + ->set('search', '06/2026') + ->assertSee('Francesinha') + ->assertDontSee('Polpetone Filé Mignon'); })->with('searchable-raw')->requiresSQLite(); it('searches data using whereRaw on mysql', function (string $component, object $params) { livewire($component, ['database' => 'mysql']) + ->call($params->theme) ->call($params->theme) ->set('search', '09/09/2021') ->assertSee('Polpetone Filé Mignon') ->assertDontSee('Barco-Sushi Simples') - ->assertDontSee('No records found'); + ->assertDontSee('No records found') + # 09/09/2022 + ->set('search', '09/09/2022') + ->assertSee('No records found') + # 06/2026 + ->set('search', '06/2026') + ->assertSee('Francesinha') + ->assertDontSee('Polpetone Filé Mignon'); })->with('searchable-raw')->requiresMySQL(); it('searches data using whereRaw on pgsql', function (string $component, object $params) { @@ -26,5 +41,12 @@ ->set('search', '09/09/2021') ->assertSee('Polpetone Filé Mignon') ->assertDontSee('Barco-Sushi Simples') - ->assertDontSee('No records found'); + ->assertDontSee('No records found') + # 09/09/2022 + ->set('search', '09/09/2022') + ->assertSee('No records found') + # 06/2026 + ->set('search', '06/2026') + ->assertSee('Francesinha') + ->assertDontSee('Polpetone Filé Mignon'); })->with('searchable-raw')->requiresPostgreSQL();