Skip to content

Commit 83de036

Browse files
committed
wip
1 parent 858eb1c commit 83de036

File tree

8 files changed

+237
-17
lines changed

8 files changed

+237
-17
lines changed

composer.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
],
1818
"require": {
1919
"php": "^8.1",
20-
"spatie/laravel-package-tools": "^1.14.0",
21-
"illuminate/contracts": "^10.0"
20+
"doctrine/dbal": "^3.6",
21+
"illuminate/contracts": "^10.0",
22+
"spatie/laravel-package-tools": "^1.14.0"
2223
},
2324
"require-dev": {
2425
"laravel/pint": "^1.0",
@@ -37,7 +38,10 @@
3738
"psr-4": {
3839
"Designbycode\\Datatables\\": "src/",
3940
"Designbycode\\Datatables\\Database\\Factories\\": "database/factories/"
40-
}
41+
},
42+
"files": [
43+
"src/FunctionsHelpers/transform.php"
44+
]
4145
},
4246
"autoload-dev": {
4347
"psr-4": {

src/FunctionsHelpers/transform.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
function singleArrayToMultiArray($array, $value = ''): array
4+
{
5+
$newArray = [];
6+
foreach ($array as $key) {
7+
$newArray[$key] = $value;
8+
}
9+
10+
return $newArray;
11+
}

src/Http/Controllers/DatatablesController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ abstract class DatatablesController extends Controller
1212

1313
public function index(Request $request): array
1414
{
15-
return $this->getData($request);
15+
return $this->getResponse($request);
1616
}
1717

1818
public function show(string $id)

src/Http/Traits/DatatableTrait.php

Lines changed: 199 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,30 @@
33
namespace Designbycode\Datatables\Http\Traits;
44

55
use Exception;
6-
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
76
use Illuminate\Database\Eloquent\Builder;
87
use Illuminate\Http\Request;
8+
use Illuminate\Pagination\LengthAwarePaginator;
9+
use Illuminate\Support\Arr;
10+
use Illuminate\Support\Facades\Schema;
11+
use Illuminate\Support\Str;
912

1013
trait DatatableTrait
1114
{
12-
private Builder $builder;
15+
protected bool $allowDeletion = true;
1316

17+
protected bool $allowCreation = true;
18+
19+
protected bool $createUsingDialog = false;
20+
21+
protected bool $allowSearching = true;
22+
23+
protected int $default_limit = 25;
24+
25+
public Builder $builder;
26+
27+
/**
28+
* @throws Exception
29+
*/
1430
public function __construct()
1531
{
1632
$builder = $this->builder();
@@ -22,19 +38,197 @@ public function __construct()
2238
$this->builder = $builder;
2339
}
2440

25-
abstract protected function builder(): Builder;
41+
/**
42+
* Use Model::query() image model controller
43+
*/
44+
abstract public function builder(): Builder;
2645

27-
protected function getData(Request $request): array
46+
/**
47+
* Get all response data to be added to index
48+
*
49+
* @return array[]
50+
*/
51+
public function getResponse(Request $request): array
2852
{
2953
return [
3054
'data' => [
55+
'name' => $this->getDataTableName(),
56+
'name_singular' => Str::singular($this->getDataTableName()),
57+
'settings' => [
58+
'allow' => [
59+
'deletions' => $this->allowDeletion,
60+
'creation' => $this->allowCreation,
61+
'searching' => $this->allowSearching,
62+
],
63+
'create_with_dialog' => $this->createUsingDialog,
64+
'pagination_limit' => $this->getLimit($request),
65+
],
66+
'database' => [
67+
'typings' => $this->getModelDatabaseTypings(),
68+
'input_types' => $this->getFormInputTypes(),
69+
],
70+
'columns' => [
71+
'updatable' => $this->getUpdatableColumns(),
72+
'creatable' => $this->getCreatableColumns(),
73+
'displayable' => $this->getDisplayableColumns(),
74+
],
3175
'records' => $this->getRecords($request),
3276
],
3377
];
3478
}
3579

80+
/**
81+
* Get the name of the database table
82+
*/
83+
protected function getDataTableName(): string
84+
{
85+
return $this->builder->getModel()->getTable();
86+
}
87+
88+
/**
89+
* Get the paginated limit
90+
*/
91+
private function getLimit(Request $request): int
92+
{
93+
return $request->limit ?? $this->default_limit;
94+
}
95+
96+
/**
97+
* They will give the typing of the database field
98+
*/
99+
private function getModelDatabaseTypings(): array
100+
{
101+
return array_intersect_key($this->getTableColumns(), array_flip(array_values($this->getCreatableColumns())));
102+
}
103+
104+
/**
105+
* Get array of database columns
106+
*/
107+
protected function getTableColumns(): array
108+
{
109+
$table = $this->builder->getModel()->getTable();
110+
$builder = $this->builder->getModel()->getConnection()->getSchemaBuilder();
111+
$columns = $builder->getColumnListing($table);
112+
$columnsWithType = collect($columns)->mapWithKeys(function ($item, $key) use ($builder, $table) {
113+
$key = $builder->getColumnType($table, $item);
114+
115+
return [$item => $key];
116+
});
117+
118+
return $columnsWithType->toArray();
119+
}
120+
121+
/**
122+
* Give array of fields that is fillable
123+
*/
124+
protected function getCreatableColumns(): array
125+
{
126+
return $this->builder->getModel()->getFillable();
127+
}
128+
129+
/**
130+
* Create form input types
131+
*/
132+
abstract public function getFormInputTypes(): array;
133+
134+
/**
135+
* Only column field that can be updated
136+
*/
137+
protected function getUpdatableColumns(): array
138+
{
139+
return $this->getDisplayableColumns();
140+
}
141+
142+
/**
143+
* Give array of database columns
144+
*/
145+
private function getDisplayableColumns(): array
146+
{
147+
return array_diff($this->getDisplayableColumnNames(), $this->builder->getModel()->getHidden(), $this->builder->getModel()->getDates());
148+
}
149+
150+
/**
151+
* Gives the names of database column
152+
*/
153+
protected function getDisplayableColumnNames(): array
154+
{
155+
return Schema::getColumnListing($this->builder->getModel()->getTable());
156+
}
157+
158+
/**
159+
* Build query and return collection of data
160+
*/
36161
private function getRecords(Request $request): LengthAwarePaginator
37162
{
38-
return $this->builder->orderBy('id', 'asc')->paginate();
163+
$builder = $this->builder;
164+
165+
if ($this->hasSearchQuery($request)) {
166+
$builder = $this->buildSearch($builder, $request);
167+
}
168+
169+
return $this->builder->orderBy('id', 'asc')->paginate($this->getLimit($request))
170+
->through(function ($model) {
171+
return Arr::only($model->toArray(), $this->getDisplayableColumns());
172+
});
173+
}
174+
175+
/**
176+
* Check if search query is present
177+
*/
178+
protected function hasSearchQuery(Request $request): bool
179+
{
180+
return count(array_filter($request->only('column', 'operator', 'value'))) === 3;
181+
}
182+
183+
private function buildSearch(Builder $builder, Request $request): Builder
184+
{
185+
$queryParts = $this->resolveQueryParts($request->operator, $request->value);
186+
187+
if (! $this->hasSearchQuery($request)) {
188+
dd('no');
189+
}
190+
191+
return $builder->where($request->column, $queryParts['operator'], $queryParts['value']);
192+
}
193+
194+
/**
195+
* Query part for search builder.
196+
*/
197+
private function resolveQueryParts($operator, $value): mixed
198+
{
199+
return Arr::get([
200+
'equals' => [
201+
'operator' => '=',
202+
'value' => $value,
203+
],
204+
'contains' => [
205+
'operator' => 'LIKE',
206+
'value' => "%{$value}%",
207+
],
208+
'starts_with' => [
209+
'operator' => 'LIKE',
210+
'value' => "{$value}%",
211+
],
212+
'ends_with' => [
213+
'operator' => 'LIKE',
214+
'value' => "%{$value}",
215+
],
216+
'greater_than' => [
217+
'operator' => '>',
218+
'value' => $value,
219+
],
220+
'greater_or_equal_than' => [
221+
'operator' => '>=',
222+
'value' => $value,
223+
],
224+
'less_than' => [
225+
'operator' => '<',
226+
'value' => $value,
227+
],
228+
'less_or_equal_than' => [
229+
'operator' => '<=',
230+
'value' => $value,
231+
],
232+
], $operator);
39233
}
40234
}

tests/Feature/DatatableTest.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,16 @@
33
use Designbycode\Datatables\Tests\Stubs\Post;
44

55
it('can visit posts route', function () {
6-
$posts = $this->get('/posts')
6+
$posts = $this->get(route('posts.index'))
77
->assertStatus(200);
88
});
99

10-
1110
it('cant see title of post', function () {
1211
$post = Post::factory()->create(['title' => 'Fake Title']);
1312
expect($post->title)->toEqual('Fake Title');
1413
});
1514

16-
1715
it('can have multiple posts', function () {
1816
$posts = Post::factory()->count(10)->create();
19-
expect($posts->count())->toEqual(10);
17+
expect($posts)->toHaveCount(10);
2018
});

tests/Stubs/Post.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,12 @@
22

33
namespace Designbycode\Datatables\Tests\Stubs;
44

5-
use Designbycode\Datatables\Tests\Stubs\Factories\PostFactory;
65
use Illuminate\Database\Eloquent\Factories\HasFactory;
76
use Illuminate\Database\Eloquent\Model;
87

98
class Post extends Model
109
{
11-
1210
use HasFactory;
1311

1412
protected $fillable = ['title', 'content'];
15-
1613
}

tests/Stubs/PostController.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@
77

88
class PostController extends DatatablesController
99
{
10-
protected function builder(): Builder
10+
public function builder(): Builder
1111
{
1212
return Post::query();
1313
}
14+
15+
public function getFormInputTypes(): array
16+
{
17+
return [];
18+
}
1419
}

tests/Unit/UnitDatatableTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
it('cant transform array into array with key and empty value', function () {
4+
$array = singleArrayToMultiArray(['name', 'surname', 'email']);
5+
6+
expect($array)->toMatchArray([
7+
'name' => '',
8+
'surname' => '',
9+
'email' => '',
10+
]);
11+
});

0 commit comments

Comments
 (0)