We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.
1 | <?php |
||||||
2 | |||||||
3 | namespace Backpack\CRUD\Tests\Unit\CrudPanel; |
||||||
4 | |||||||
5 | use Backpack\CRUD\Tests\config\Models\User; |
||||||
6 | use Backpack\CRUD\Tests\config\Models\UserWithTranslations; |
||||||
7 | use PHPUnit\Framework\Attributes\DataProvider; |
||||||
8 | |||||||
9 | /** |
||||||
10 | * @covers Backpack\CRUD\app\Library\CrudPanel\Traits\Search |
||||||
11 | */ |
||||||
12 | class CrudPanelSearchTest extends \Backpack\CRUD\Tests\config\CrudPanel\BaseCrudPanel |
||||||
13 | { |
||||||
14 | private string $expectedDefaultColumnValue = '<span>'.PHP_EOL.' user'.PHP_EOL.' </span>'; |
||||||
15 | |||||||
16 | public function setUp(): void |
||||||
17 | { |
||||||
18 | parent::setUp(); |
||||||
19 | $this->crudPanel->setModel(User::class); |
||||||
20 | } |
||||||
21 | |||||||
22 | #[DataProvider('columnsDefaultSearchLogic')] |
||||||
23 | public function testItCanApplyCustomSearchLogicOnColumns($searchTerm, $columnType, $resultSql) |
||||||
24 | { |
||||||
25 | $this->crudPanel->addColumn([ |
||||||
26 | 'name' => 'test', |
||||||
27 | 'type' => $columnType, |
||||||
28 | 'searchLogic' => $columnType, |
||||||
29 | 'tableColumn' => true, |
||||||
30 | 'entity' => $columnType === 'select' ? 'accountDetails' : ($columnType === 'select_multiple' ? 'articles' : false), |
||||||
31 | 'relation_type' => $columnType === 'select' ? 'HasOne' : ($columnType === 'select_multiple' ? 'HasMany' : false), |
||||||
32 | ]); |
||||||
33 | |||||||
34 | $this->crudPanel->applySearchTerm($searchTerm); |
||||||
35 | |||||||
36 | $this->assertEquals($resultSql, $this->crudPanel->query->toRawSql()); |
||||||
37 | } |
||||||
38 | |||||||
39 | public function testItDoesNotAttemptToSearchTheColumnIfSearchLogicIsDisabled() |
||||||
40 | { |
||||||
41 | $this->crudPanel->addColumn([ |
||||||
42 | 'name' => 'test', |
||||||
43 | 'type' => 'text', |
||||||
44 | 'searchLogic' => false, |
||||||
45 | 'tableColumn' => true, |
||||||
46 | ]); |
||||||
47 | |||||||
48 | $this->crudPanel->applySearchTerm('test'); |
||||||
49 | |||||||
50 | $this->assertEquals('select * from "users"', $this->crudPanel->query->toRawSql()); |
||||||
51 | } |
||||||
52 | |||||||
53 | public function testItDoesNotAttemptToApplyDefaultLogicIfColumnIsNotATableColumn() |
||||||
54 | { |
||||||
55 | $this->crudPanel->addColumn([ |
||||||
56 | 'name' => 'test', |
||||||
57 | 'type' => 'text', |
||||||
58 | 'searchLogic' => 'text', |
||||||
59 | 'tableColumn' => false, |
||||||
60 | ]); |
||||||
61 | |||||||
62 | $this->crudPanel->applySearchTerm('test'); |
||||||
63 | |||||||
64 | $this->assertEquals('select * from "users"', $this->crudPanel->query->toRawSql()); |
||||||
65 | } |
||||||
66 | |||||||
67 | public function testItValidateDateAndDatetimeSearchTermsAndDoesNotApplySearchIfValidationFails() |
||||||
68 | { |
||||||
69 | $this->crudPanel->addColumn([ |
||||||
70 | 'name' => 'test', |
||||||
71 | 'type' => 'date', |
||||||
72 | 'searchLogic' => 'date', |
||||||
73 | 'tableColumn' => true, |
||||||
74 | ]); |
||||||
75 | |||||||
76 | $this->crudPanel->addColumn([ |
||||||
77 | 'name' => 'test', |
||||||
78 | 'type' => 'datetime', |
||||||
79 | 'searchLogic' => 'datetime', |
||||||
80 | 'tableColumn' => true, |
||||||
81 | ]); |
||||||
82 | |||||||
83 | $this->crudPanel->applySearchTerm('invalid-date'); |
||||||
84 | |||||||
85 | $this->assertEquals('select * from "users"', $this->crudPanel->query->toRawSql()); |
||||||
86 | } |
||||||
87 | |||||||
88 | public function testItCanApplySearchLogicFromClosure() |
||||||
89 | { |
||||||
90 | $this->crudPanel->addColumn([ |
||||||
91 | 'name' => 'test', |
||||||
92 | 'type' => 'my_custom_type', |
||||||
93 | 'searchLogic' => function ($query, $column, $searchTerm) { |
||||||
94 | $query->where($column['name'], 'like', "%{$searchTerm}%"); |
||||||
95 | }, |
||||||
96 | 'tableColumn' => true, |
||||||
97 | ]); |
||||||
98 | |||||||
99 | $this->crudPanel->applySearchTerm('test'); |
||||||
100 | |||||||
101 | $this->assertEquals('select * from "users" where ("test" like \'%test%\')', $this->crudPanel->query->toRawSql()); |
||||||
102 | } |
||||||
103 | |||||||
104 | public function testItCanGetAndSetPersistentTable() |
||||||
105 | { |
||||||
106 | $this->crudPanel->enablePersistentTable(true); |
||||||
0 ignored issues
–
show
|
|||||||
107 | |||||||
108 | $this->assertTrue($this->crudPanel->getPersistentTable()); |
||||||
109 | |||||||
110 | $this->crudPanel->disablePersistentTable(); |
||||||
111 | |||||||
112 | $this->assertFalse($this->crudPanel->getPersistentTable()); |
||||||
113 | } |
||||||
114 | |||||||
115 | public function testItCanGetPersistentTableFromConfig() |
||||||
116 | { |
||||||
117 | $this->assertNull($this->crudPanel->getPersistentTable()); |
||||||
118 | } |
||||||
119 | |||||||
120 | public function testItCanGetAndSetTheResponsiveTable() |
||||||
121 | { |
||||||
122 | $this->crudPanel->enableResponsiveTable(true); |
||||||
0 ignored issues
–
show
The call to
Backpack\CRUD\app\Librar...enableResponsiveTable() has too many arguments starting with true .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||||
123 | |||||||
124 | $this->assertTrue($this->crudPanel->getResponsiveTable()); |
||||||
125 | |||||||
126 | $this->crudPanel->disableResponsiveTable(); |
||||||
127 | |||||||
128 | $this->assertFalse($this->crudPanel->getResponsiveTable()); |
||||||
129 | } |
||||||
130 | |||||||
131 | public function testItCanGetPersistentTableDurationFromOperationSetting() |
||||||
132 | { |
||||||
133 | $this->crudPanel->setOperationSetting('persistentTableDuration', 10); |
||||||
134 | |||||||
135 | $this->assertEquals(10, $this->crudPanel->getPersistentTableDuration()); |
||||||
136 | } |
||||||
137 | |||||||
138 | public function testItCanGetPersistentTableDurantionFromConfig() |
||||||
139 | { |
||||||
140 | $this->assertEquals(false, $this->crudPanel->getPersistentTableDuration()); |
||||||
141 | |||||||
142 | config(['backpack.crud.operations.list.persistentTableDuration' => 10]); |
||||||
143 | |||||||
144 | $this->assertEquals(10, $this->crudPanel->getPersistentTableDuration()); |
||||||
145 | } |
||||||
146 | |||||||
147 | public function testItCanGetResponsiveTableFromConfig() |
||||||
148 | { |
||||||
149 | $this->assertEquals(false, $this->crudPanel->getResponsiveTable()); |
||||||
150 | |||||||
151 | config(['backpack.crud.operations.list.responsiveTable' => true]); |
||||||
152 | |||||||
153 | $this->assertTrue($this->crudPanel->getResponsiveTable()); |
||||||
154 | } |
||||||
155 | |||||||
156 | public function testItCanGetTheRenderedViewsForTheColumns() |
||||||
157 | { |
||||||
158 | $this->crudPanel->addColumn([ |
||||||
159 | 'name' => 'name', |
||||||
160 | 'type' => 'test', |
||||||
161 | ]); |
||||||
162 | |||||||
163 | $entries = [$this->makeAUserModel()]; |
||||||
164 | |||||||
165 | $rowColumnsHtml = trim($this->crudPanel->getEntriesAsJsonForDatatables($entries, 1, 0)['data'][0][0]); |
||||||
166 | |||||||
167 | $this->assertEquals($this->expectedDefaultColumnValue, $rowColumnsHtml); |
||||||
168 | } |
||||||
169 | |||||||
170 | public function testItRendersTheDetailsRow() |
||||||
171 | { |
||||||
172 | $this->crudPanel->addColumn([ |
||||||
173 | 'name' => 'name', |
||||||
174 | 'type' => 'test', |
||||||
175 | ]); |
||||||
176 | |||||||
177 | $this->crudPanel->setOperationSetting('detailsRow', true); |
||||||
178 | $entries = [$this->makeAUserModel()]; |
||||||
179 | |||||||
180 | $rowColumnsHtml = $this->crudPanel->getEntriesAsJsonForDatatables($entries, 1, 0)['data'][0][0]; |
||||||
181 | |||||||
182 | $this->assertStringContainsString('details-row-button', $rowColumnsHtml); |
||||||
183 | } |
||||||
184 | |||||||
185 | public function testItRendersTheBulkActions() |
||||||
186 | { |
||||||
187 | $this->crudPanel->addColumn([ |
||||||
188 | 'name' => 'name', |
||||||
189 | 'type' => 'test', |
||||||
190 | ]); |
||||||
191 | |||||||
192 | $this->crudPanel->setOperationSetting('bulkActions', true); |
||||||
193 | $entries = [$this->makeAUserModel()]; |
||||||
194 | |||||||
195 | $rowColumnsHtml = $this->crudPanel->getEntriesAsJsonForDatatables($entries, 1, 0)['data'][0][0]; |
||||||
196 | |||||||
197 | $this->assertStringContainsString('crud_bulk_actions_line_checkbox', $rowColumnsHtml); |
||||||
198 | } |
||||||
199 | |||||||
200 | public function testItRendersTheLineStackButtons() |
||||||
201 | { |
||||||
202 | $this->crudPanel->addColumn([ |
||||||
203 | 'name' => 'name', |
||||||
204 | 'type' => 'test', |
||||||
205 | ]); |
||||||
206 | |||||||
207 | $this->crudPanel->button('test')->stack('line')->type('view')->content('backpack.theme-coreuiv2::buttons.test'); |
||||||
208 | $entries = [$this->makeAUserModel()]; |
||||||
209 | |||||||
210 | $rowColumnsHtml = $this->crudPanel->getEntriesAsJsonForDatatables($entries, 1, 0)['data'][0][1]; |
||||||
211 | |||||||
212 | $this->assertStringContainsString('btn-secondary', $rowColumnsHtml); |
||||||
213 | } |
||||||
214 | |||||||
215 | public function testItAppliesCustomOrderByPrimaryKeyForDatatables() |
||||||
216 | { |
||||||
217 | $this->crudPanel->applyDatatableOrder(); |
||||||
218 | |||||||
219 | $this->assertEquals('select * from "users" order by "id" desc', $this->crudPanel->query->toRawSql()); |
||||||
220 | } |
||||||
221 | |||||||
222 | public function testItCanApplyACustomSearchLogic() |
||||||
223 | { |
||||||
224 | $this->crudPanel->addColumn([ |
||||||
225 | 'name' => 'name', |
||||||
226 | 'type' => 'text', |
||||||
227 | 'tableColumn' => true, |
||||||
228 | 'orderLogic' => function ($query, $column, $searchTerm) { |
||||||
0 ignored issues
–
show
The parameter
$column is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$searchTerm is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
229 | $query->orderBy('name', 'asc'); |
||||||
230 | }, |
||||||
231 | ]); |
||||||
232 | |||||||
233 | $this->setupUserCreateRequest(); |
||||||
234 | $this->crudPanel->getRequest()->merge(['order' => [['column' => 0, 'dir' => 'asc']]]); |
||||||
235 | |||||||
236 | $this->crudPanel->applyDatatableOrder(); |
||||||
237 | |||||||
238 | $this->assertEquals('select * from "users" order by "name" asc, "id" desc', $this->crudPanel->query->toRawSql()); |
||||||
239 | } |
||||||
240 | |||||||
241 | public function testItDoesNotReplacePrimaryKeyIfItAlreadyExists() |
||||||
242 | { |
||||||
243 | $this->crudPanel->addColumn([ |
||||||
244 | 'name' => 'name', |
||||||
245 | 'type' => 'text', |
||||||
246 | 'tableColumn' => true, |
||||||
247 | 'orderLogic' => function ($query, $column, $searchTerm) { |
||||||
0 ignored issues
–
show
The parameter
$column is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$searchTerm is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
248 | $query->orderBy('id', 'asc'); |
||||||
249 | }, |
||||||
250 | ]); |
||||||
251 | |||||||
252 | $this->setupUserCreateRequest(); |
||||||
253 | $this->crudPanel->getRequest()->merge(['order' => [['column' => 0, 'dir' => 'asc']]]); |
||||||
254 | |||||||
255 | $this->crudPanel->applyDatatableOrder(); |
||||||
256 | |||||||
257 | $this->assertEquals('select * from "users" order by "id" asc', $this->crudPanel->query->toRawSql()); |
||||||
258 | } |
||||||
259 | |||||||
260 | public function testItCanApplyDatatableOrderFromRequest() |
||||||
261 | { |
||||||
262 | $this->crudPanel->addColumn([ |
||||||
263 | 'name' => 'name', |
||||||
264 | 'type' => 'test', |
||||||
265 | 'tableColumn' => true, |
||||||
266 | ]); |
||||||
267 | $this->setupUserCreateRequest(); |
||||||
268 | $this->crudPanel->getRequest()->merge(['order' => [['column' => 0, 'dir' => 'asc']]]); |
||||||
269 | |||||||
270 | $this->crudPanel->applyDatatableOrder(); |
||||||
271 | |||||||
272 | $this->assertEquals('select * from "users" order by "name" asc, "id" desc', $this->crudPanel->query->toRawSql()); |
||||||
273 | } |
||||||
274 | |||||||
275 | public function testItCanApplySearchLogicForTranslatableJsonColumns() |
||||||
276 | { |
||||||
277 | $this->crudPanel->setModel(UserWithTranslations::class); |
||||||
278 | |||||||
279 | $this->crudPanel->addColumn([ |
||||||
280 | 'name' => 'json', |
||||||
281 | 'type' => 'json', |
||||||
282 | 'tableColumn' => true, |
||||||
283 | ]); |
||||||
284 | $this->setupUserCreateRequest(); |
||||||
285 | $this->crudPanel->getRequest()->merge(['order' => [['column' => 0, 'dir' => 'asc']]]); |
||||||
286 | |||||||
287 | $this->crudPanel->applyDatatableOrder(); |
||||||
288 | |||||||
289 | $this->assertEquals('select * from "users" order by json_extract("json", \'$."en"\') asc, "id" desc', $this->crudPanel->query->toRawSql()); |
||||||
290 | } |
||||||
291 | |||||||
292 | public function testItCanApplySearchLogicForTranslatableColumns() |
||||||
293 | { |
||||||
294 | $this->crudPanel->setModel(UserWithTranslations::class); |
||||||
295 | |||||||
296 | $this->crudPanel->addColumn([ |
||||||
297 | 'name' => 'name', |
||||||
298 | 'type' => 'text', |
||||||
299 | 'tableColumn' => true, |
||||||
300 | ]); |
||||||
301 | $this->setupUserCreateRequest(); |
||||||
302 | $this->crudPanel->getRequest()->merge(['order' => [['column' => 0, 'dir' => 'asc']]]); |
||||||
303 | |||||||
304 | $this->crudPanel->applyDatatableOrder(); |
||||||
305 | |||||||
306 | $this->assertEquals('select * from "users" order by "name" asc, "id" desc', $this->crudPanel->query->toRawSql()); |
||||||
307 | } |
||||||
308 | |||||||
309 | public static function columnsDefaultSearchLogic() |
||||||
310 | { |
||||||
311 | return [ |
||||||
312 | ['test', 'text', 'select * from "users" where ("users"."test" like \'%test%\')'], |
||||||
313 | ['test', 'email', 'select * from "users" where ("users"."test" like \'%test%\')'], |
||||||
314 | ['test', 'textarea', 'select * from "users" where ("users"."test" like \'%test%\')'], |
||||||
315 | ['2023-12-24', 'date', 'select * from "users" where (strftime(\'%Y-%m-%d\', "users"."test") = cast(\'2023-12-24\' as text))'], |
||||||
316 | ['2023-12-24', 'datetime', 'select * from "users" where (strftime(\'%Y-%m-%d\', "users"."test") = cast(\'2023-12-24\' as text))'], |
||||||
317 | ['test', 'select', 'select * from "users" where (exists (select * from "account_details" where "users"."id" = "account_details"."user_id" and "account_details"."nickname" like \'%test%\'))'], |
||||||
318 | ['test', 'select_multiple', 'select * from "users" where (exists (select * from "articles" where "users"."id" = "articles"."user_id" and "articles"."content" like \'%test%\'))'], |
||||||
319 | ]; |
||||||
320 | } |
||||||
321 | } |
||||||
322 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.