diff --git a/src/AdminModel/IsAdminModel.php b/src/AdminModel/IsAdminModel.php index 6ca1337..a3d9790 100644 --- a/src/AdminModel/IsAdminModel.php +++ b/src/AdminModel/IsAdminModel.php @@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Arr; +use Illuminate\Support\Str; trait IsAdminModel { @@ -122,9 +123,34 @@ public function getDateAttributes(): array { $casts = $this->getCasts(); - //dd($casts); + $date_fields = []; - return $casts; + foreach ($casts as $attribute => $cast) { + if (is_string($cast) && Str::startsWith($cast, 'date')) { + $date_fields[] = $attribute; + } + } + + return array_merge($date_fields, $this->getDates()); + } + + /** + * Query records between dates + */ + public function scopeDateBetween($query, ?string $date_field, $from, $to): mixed + { + if ($date_field && static::isAllowedDateField($date_field)) { + if ($from = parse_date($from)) { + $query->where($this->getTable() . '.' . $date_field, '>=', $from); + } + + if ($to = parse_date($to)) { + $query->where($this->getTable() . '.' . $date_field, '<=', $to); + } + + } + + return $query; } /** @@ -132,7 +158,7 @@ public function getDateAttributes(): array */ public static function getDateFieldsList(): array { - $date_fields = static::$dateFields ?? []; + $date_fields = (new static)->getDateAttributes(); $labels = []; foreach ($date_fields as $field) { @@ -141,4 +167,14 @@ public static function getDateFieldsList(): array return $labels; } + + /** + * Check if allowed date field + */ + public static function isAllowedDateField(string $field): bool + { + $date_fields = (new static)->getDateAttributes(); + + return in_array($field, $date_fields); + } } diff --git a/tests/Feature/AdminModelTest.php b/tests/Feature/AdminModelTest.php index 69eb778..df39fdd 100644 --- a/tests/Feature/AdminModelTest.php +++ b/tests/Feature/AdminModelTest.php @@ -8,17 +8,50 @@ use Javaabu\Helpers\Tests\TestCase; use Javaabu\Helpers\Tests\InteractsWithDatabase; -class CategoryWithSearchable extends Model implements AdminModel +class CategoryWithDateCast extends Model implements AdminModel { use IsAdminModel; protected $table = 'categories'; - protected static array $dateFields = [ - 'created_at', - 'updated_at' + protected $casts = [ + 'published_at' => 'date' + ]; + + protected $guarded = [ ]; + public function getAdminUrlAttribute(): string + { + return ''; + } +} + +class CategoryWithDateTimeCast extends Model implements AdminModel +{ + use IsAdminModel; + + protected $table = 'categories'; + + protected $casts = [ + 'published_at' => 'datetime' + ]; + + protected $guarded = [ + ]; + + public function getAdminUrlAttribute(): string + { + return ''; + } +} + +class CategoryWithSearchable extends Model implements AdminModel +{ + use IsAdminModel; + + protected $table = 'categories'; + protected array $searchable = [ 'name' ]; @@ -95,6 +128,56 @@ protected function setUp(): void $this->runMigrations(); } + /** @test */ + public function it_can_get_list_of_date_fields(): void + { + $this->assertEquals([ + 'published_at' => 'Published At', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At' + ], CategoryWithDateCast::getDateFieldsList()); + } + + /** @test */ + public function it_can_determine_if_an_attribute_is_an_allowed_date_field(): void + { + $this->assertTrue(CategoryWithDateCast::isAllowedDateField('published_at')); + $this->assertTrue(CategoryWithDateCast::isAllowedDateField('created_at')); + $this->assertTrue(CategoryWithDateCast::isAllowedDateField('updated_at')); + $this->assertFalse(CategoryWithDateCast::isAllowedDateField('name')); + } + + /** @test */ + public function it_can_determine_date_fields_from_date_casts(): void + { + $category = new CategoryWithDateCast(); + + $this->assertEquals(['published_at', 'created_at', 'updated_at'], $category->getDateAttributes()); + } + + /** @test */ + public function it_can_determine_date_fields_from_datetime_casts(): void + { + $category = new CategoryWithDateTimeCast(); + + $this->assertEquals(['published_at', 'created_at', 'updated_at'], $category->getDateAttributes()); + } + + /** @test */ + public function it_can_filter_models_by_date_range(): void + { + $category = new CategoryWithDateCast([ + 'name' => 'Apple', + 'slug' => 'some-slug', + 'published_at' => '2024-02-11' + ]); + $category->save(); + + $found = CategoryWithDateCast::dateBetween('published_at', '2024-02-10', '2024-02-12')->first(); + + $this->assertEquals($category->id, $found->id); + } + /** @test */ public function it_can_search_models_using_a_partial_match(): void { diff --git a/tests/database/create_categories_table.php b/tests/database/create_categories_table.php index 9885ede..ba2261e 100644 --- a/tests/database/create_categories_table.php +++ b/tests/database/create_categories_table.php @@ -17,6 +17,7 @@ public function up() $table->id(); $table->string('name'); $table->string('slug'); + $table->dateTime('published_at')->nullable(); $table->timestamps(); }); }