Skip to content

Commit 42952a9

Browse files
authored
Merge pull request #4 from php-casbin/develop
feat: implements updateFilteredPolicies
2 parents 5f101c0 + 2563953 commit 42952a9

File tree

7 files changed

+401
-225
lines changed

7 files changed

+401
-225
lines changed

.github/workflows/default.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
name: Default
22

3-
on:
4-
push:
5-
branches: [ master ]
6-
pull_request:
7-
branches: [ master ]
3+
on: [push, pull_request]
84

95
jobs:
106
test:

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ composer.lock
77
*.iml
88

99
# coverage report
10-
/build
10+
/build
11+
12+
.phpunit.*

.phpunit.result.cache

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/Adapter.php

Lines changed: 102 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
use Casbin\Persist\UpdatableAdapter;
1212
use Closure;
1313
use Doctrine\DBAL\Configuration;
14+
use Doctrine\DBAL\DBALException;
1415
use Doctrine\DBAL\Driver\ResultStatement;
15-
use Doctrine\DBAL\Driver\Statement;
1616
use Doctrine\DBAL\DriverManager;
1717
use Doctrine\DBAL\Connection;
1818
use Doctrine\DBAL\Exception;
1919
use Doctrine\DBAL\Query\Expression\CompositeExpression;
20+
use Doctrine\DBAL\Result;
21+
use Doctrine\DBAL\Schema\Schema;
2022
use Throwable;
2123

2224
/**
@@ -47,6 +49,11 @@ class Adapter implements FilteredAdapter, BatchAdapter, UpdatableAdapter
4749
*/
4850
private $filtered = false;
4951

52+
/**
53+
* @var string[]
54+
*/
55+
protected $columns = ['p_type', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5'];
56+
5057
/**
5158
* Adapter constructor.
5259
*
@@ -93,7 +100,7 @@ public function initTable()
93100
{
94101
$sm = $this->connection->getSchemaManager();
95102
if (!$sm->tablesExist([$this->policyTableName])) {
96-
$schema = new \Doctrine\DBAL\Schema\Schema();
103+
$schema = new Schema();
97104
$table = $schema->createTable($this->policyTableName);
98105
$table->addColumn('id', 'integer', array('autoincrement' => true));
99106
$table->addColumn('p_type', 'string', ['notnull' => false]);
@@ -144,10 +151,7 @@ public function loadPolicy(Model $model): void
144151
$stmt = $queryBuilder->select('p_type', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5')->from($this->policyTableName)->execute();
145152

146153
while ($row = $this->fetch($stmt)) {
147-
$line = implode(', ', array_filter($row, function ($val) {
148-
return '' != $val && !is_null($val);
149-
}));
150-
$this->loadPolicyLine(trim($line), $model);
154+
$this->loadPolicyArray($this->filterRule($row), $model);
151155
}
152156
}
153157

@@ -228,8 +232,7 @@ public function addPolicy(string $sec, string $ptype, array $rule): void
228232
* @param string $ptype
229233
* @param string[][] $rules
230234
*
231-
* @throws Exception
232-
* @throws \Doctrine\DBAL\DBALException
235+
* @throws DBALException
233236
*/
234237
public function addPolicies(string $sec, string $ptype, array $rules): void
235238
{
@@ -306,6 +309,41 @@ public function removePolicies(string $sec, string $ptype, array $rules): void
306309
});
307310
}
308311

312+
/**
313+
* @param string $sec
314+
* @param string $ptype
315+
* @param int $fieldIndex
316+
* @param string|null ...$fieldValues
317+
* @return array
318+
* @throws Throwable
319+
*/
320+
public function _removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, ?string ...$fieldValues): array
321+
{
322+
$removedRules = [];
323+
$this->connection->transactional(function (Connection $conn) use ($ptype, $fieldIndex, $fieldValues, &$removedRules) {
324+
$queryBuilder = $conn->createQueryBuilder();
325+
$queryBuilder->where('p_type = :ptype')->setParameter('ptype', $ptype);
326+
327+
foreach ($fieldValues as $value) {
328+
if (!is_null($value) && $value !== '') {
329+
$key = 'v' . strval($fieldIndex);
330+
$queryBuilder->andWhere($key . ' = :' . $key)->setParameter($key, $value);
331+
}
332+
$fieldIndex++;
333+
}
334+
335+
$stmt = $queryBuilder->select(...$this->columns)->from($this->policyTableName)->execute();
336+
337+
while ($row = $this->fetch($stmt)) {
338+
$removedRules[] = $this->filterRule($row);
339+
}
340+
341+
$queryBuilder->delete($this->policyTableName)->execute();
342+
});
343+
344+
return $removedRules;
345+
}
346+
309347
/**
310348
* RemoveFilteredPolicy removes policy rules that match the filter from the storage.
311349
* This is part of the Auto-Save feature.
@@ -314,23 +352,11 @@ public function removePolicies(string $sec, string $ptype, array $rules): void
314352
* @param string $ptype
315353
* @param int $fieldIndex
316354
* @param string ...$fieldValues
317-
* @throws Exception
355+
* @throws Exception|Throwable
318356
*/
319357
public function removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, string ...$fieldValues): void
320358
{
321-
$queryBuilder = $this->connection->createQueryBuilder();
322-
$queryBuilder->where('p_type = :ptype')->setParameter('ptype', $ptype);
323-
324-
foreach (range(0, 5) as $value) {
325-
if ($fieldIndex <= $value && $value < $fieldIndex + count($fieldValues)) {
326-
if ('' != $val = $fieldValues[$value - $fieldIndex]) {
327-
$key = 'v' . strval($value);
328-
$queryBuilder->andWhere($key . ' = :' . $key)->setParameter($key, $val);
329-
}
330-
}
331-
}
332-
333-
$queryBuilder->delete($this->policyTableName)->execute();
359+
$this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
334360
}
335361

336362
/**
@@ -369,6 +395,7 @@ public function updatePolicy(string $sec, string $ptype, array $oldRule, array $
369395
* @param string[][] $oldRules
370396
* @param string[][] $newRules
371397
* @return void
398+
* @throws Throwable
372399
*/
373400
public function updatePolicies(string $sec, string $ptype, array $oldRules, array $newRules): void
374401
{
@@ -379,6 +406,46 @@ public function updatePolicies(string $sec, string $ptype, array $oldRules, arra
379406
});
380407
}
381408

409+
/**
410+
* @param string $sec
411+
* @param string $ptype
412+
* @param array $newRules
413+
* @param int $fieldIndex
414+
* @param string ...$fieldValues
415+
* @return array
416+
* @throws Throwable
417+
*/
418+
public function updateFilteredPolicies(string $sec, string $ptype, array $newRules, int $fieldIndex, ?string ...$fieldValues): array
419+
{
420+
$oldRules = [];
421+
$this->getConnection()->transactional(function ($conn) use ($sec, $ptype, $newRules, $fieldIndex, $fieldValues, &$oldRules) {
422+
$oldRules = $this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
423+
$this->addPolicies($sec, $ptype, $newRules);
424+
});
425+
426+
return $oldRules;
427+
}
428+
429+
/**
430+
* Filter the rule.
431+
*
432+
* @param array $rule
433+
* @return array
434+
*/
435+
public function filterRule(array $rule): array
436+
{
437+
$rule = array_values($rule);
438+
439+
$i = count($rule) - 1;
440+
for (; $i >= 0; $i--) {
441+
if ($rule[$i] != "" && !is_null($rule[$i])) {
442+
break;
443+
}
444+
}
445+
446+
return array_slice($rule, 0, $i + 1);
447+
}
448+
382449
/**
383450
* Returns true if the loaded policy has been filtered.
384451
*
@@ -409,17 +476,29 @@ public function getConnection(): Connection
409476
return $this->connection;
410477
}
411478

479+
/**
480+
* Gets columns.
481+
*
482+
* @return string[]
483+
*/
484+
public function getColumns(): array
485+
{
486+
return $this->columns;
487+
}
488+
412489
/**
413490
* @param mixed $stmt
414491
*
415492
* @return mixed
493+
* @throws Exception
416494
*/
417-
private function fetch($stmt)
495+
private function fetch(Result $stmt)
418496
{
419497
if (method_exists($stmt, 'fetchAssociative')) {
420498
return $stmt->fetchAssociative();
421499
}
422500

423501
return $stmt->fetch();
424502
}
503+
425504
}

0 commit comments

Comments
 (0)