Skip to content

Commit 482c8d8

Browse files
authored
Enforce sort direction in dql. Do not allowing ordering when disabled. (#389)
* Enforce sort direction in dql. Do not allowing ordering when disabled. * mb_strtolower
1 parent 1555e12 commit 482c8d8

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

src/DataTable.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,10 @@ public function addOrderBy($column, string $direction = self::SORT_ASCENDING)
174174
if (!$column instanceof AbstractColumn) {
175175
$column = is_int($column) ? $this->getColumn($column) : $this->getColumnByName((string) $column);
176176
}
177-
$this->options['order'][] = [$column->getIndex(), $direction];
177+
if (false !== $this->getOption('ordering')) {
178+
$direction = self::SORT_ASCENDING === mb_strtolower($direction) ? self::SORT_ASCENDING : self::SORT_DESCENDING;
179+
$this->options['order'][] = [$column->getIndex(), $direction];
180+
}
178181

179182
return $this;
180183
}

src/DataTableState.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,10 @@ public function setGlobalSearch(string $globalSearch): static
181181

182182
public function addOrderBy(AbstractColumn $column, string $direction = DataTable::SORT_ASCENDING): static
183183
{
184-
$this->orderBy[] = [$column, $direction];
184+
if (false !== $this->dataTable->getOption('ordering')) {
185+
$direction = DataTable::SORT_ASCENDING === mb_strtolower($direction) ? DataTable::SORT_ASCENDING : DataTable::SORT_DESCENDING;
186+
$this->orderBy[] = [$column, $direction];
187+
}
185188

186189
return $this;
187190
}
@@ -199,7 +202,10 @@ public function getOrderBy(): array
199202
*/
200203
public function setOrderBy(array $orderBy = []): static
201204
{
202-
$this->orderBy = $orderBy;
205+
$this->orderBy = [];
206+
foreach ($orderBy as [$column, $direction]) {
207+
$this->addOrderBy($column, $direction);
208+
}
203209

204210
return $this;
205211
}

tests/Unit/DataTableTest.php

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ public function testFactoryRemembersInstances(): void
7777
public function testDataTableState(): void
7878
{
7979
$datatable = $this->createMockDataTable();
80-
$datatable->add('foo', TextColumn::class)->setMethod(Request::METHOD_GET);
80+
$datatable
81+
->add('foo', TextColumn::class)
82+
->add('bar', TextColumn::class)
83+
->setMethod(Request::METHOD_GET);
8184
$datatable->handleRequest(Request::create('/?_dt=' . $datatable->getName()));
8285
$state = $datatable->getState();
8386

@@ -91,13 +94,20 @@ public function testDataTableState(): void
9194
$state->setStart(5);
9295
$state->setLength(10);
9396
$state->setGlobalSearch('foo');
94-
$state->setOrderBy([[0, 'asc'], [1, 'desc']]);
97+
$state->setOrderBy([
98+
[$datatable->getColumn(0), 'asc'],
99+
[$datatable->getColumn(1), 'desc0"XOR(if(now()=sysdate(),sleep(15),0))XOR"Z'], // intentional sql-injection test
100+
]);
95101
$state->setColumnSearch($datatable->getColumn(0), 'bar');
96102

97103
$this->assertSame(5, $state->getStart());
98104
$this->assertSame(10, $state->getLength());
99105
$this->assertSame('foo', $state->getGlobalSearch());
100106
$this->assertCount(2, $state->getOrderBy());
107+
foreach ($state->getOrderBy() as $order) {
108+
// ensure sql-injection failed
109+
$this->assertContains($order[1], [DataTable::SORT_ASCENDING, DataTable::SORT_DESCENDING]);
110+
}
101111
$this->assertSame('bar', $state->getSearchColumns(onlySearchable: false)['foo']['search']);
102112

103113
// Test boundaries
@@ -133,6 +143,24 @@ public function testDataTableStateSearchColumns(): void
133143
$this->assertSame('foo', $searchColumns['foo']['search']);
134144
}
135145

146+
/**
147+
* If ordering is false, ensure columns are not ordered.
148+
*/
149+
public function testDataTablesStateOrdering(): void
150+
{
151+
$datatable = $this
152+
->createMockDataTable(['ordering' => false])
153+
->add('foo', TextColumn::class, ['searchable' => true])
154+
->add('bar', TextColumn::class, ['searchable' => false])
155+
->setMethod(Request::METHOD_GET)
156+
;
157+
$datatable->handleRequest(Request::create('/?_dt=' . $datatable->getName()));
158+
159+
$state = $datatable->getState();
160+
$state->addOrderBy($datatable->getColumn(0), DataTable::SORT_DESCENDING);
161+
$this->assertEmpty($state->getOrderBy());
162+
}
163+
136164
public function testPostMethod(): void
137165
{
138166
$datatable = $this->createMockDataTable();

0 commit comments

Comments
 (0)