mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 21:22:40 +00:00
Implement handling for arrays of ranges
Multiple ranges of articles or editions were not implemented, but the functionality is generic and could be extended if later needed.
This commit is contained in:
parent
f6799e2ab1
commit
2acacd2647
2 changed files with 105 additions and 67 deletions
|
@ -236,7 +236,7 @@ trait ExclusionMembers {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function modifiedRanges(array $spec) {
|
public function modifiedRanges(array $spec = null) {
|
||||||
if (isset($spec)) {
|
if (isset($spec)) {
|
||||||
$spec = $this->cleanDateRangeArray($spec);
|
$spec = $this->cleanDateRangeArray($spec);
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ trait ExclusionMembers {
|
||||||
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
return $this->act(__FUNCTION__, func_num_args(), $spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function markedRanges(array $spec) {
|
public function markedRanges(array $spec = null) {
|
||||||
if (isset($spec)) {
|
if (isset($spec)) {
|
||||||
$spec = $this->cleanDateRangeArray($spec);
|
$spec = $this->cleanDateRangeArray($spec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1593,10 +1593,8 @@ class Database {
|
||||||
"annotated" => ["annotated", "=", "bool"],
|
"annotated" => ["annotated", "=", "bool"],
|
||||||
];
|
];
|
||||||
foreach ($options as $m => [$col, $op, $type]) {
|
foreach ($options as $m => [$col, $op, $type]) {
|
||||||
if (!$context->$m()) {
|
if ($context->$m()) {
|
||||||
// context is not being used
|
if ($op === "between") {
|
||||||
continue;
|
|
||||||
} elseif ($op === "between") {
|
|
||||||
// option is a range
|
// option is a range
|
||||||
if ($context->$m[0] === null) {
|
if ($context->$m[0] === null) {
|
||||||
// range is open at the low end
|
// range is open at the low end
|
||||||
|
@ -1619,12 +1617,9 @@ class Database {
|
||||||
$q->setWhere("{$colDefs[$col]} $op ?", $type, $context->$m);
|
$q->setWhere("{$colDefs[$col]} $op ?", $type, $context->$m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// further handle exclusionary options if specified
|
// handle the exclusionary version
|
||||||
foreach ($options as $m => [$col, $op, $type]) {
|
if (method_exists($context->not, $m) && $context->not->$m()) {
|
||||||
if (!method_exists($context->not, $m) || !$context->not->$m()) {
|
if ($op === "between") {
|
||||||
// context option is not being used
|
|
||||||
continue;
|
|
||||||
} elseif ($op === "between") {
|
|
||||||
// option is a range
|
// option is a range
|
||||||
if ($context->not->$m[0] === null) {
|
if ($context->not->$m[0] === null) {
|
||||||
// range is open at the low end
|
// range is open at the low end
|
||||||
|
@ -1647,7 +1642,8 @@ class Database {
|
||||||
$q->setWhereNot("{$colDefs[$col]} $op ?", $type, $context->not->$m);
|
$q->setWhereNot("{$colDefs[$col]} $op ?", $type, $context->not->$m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// handle folders, labels, and tags
|
}
|
||||||
|
// handle folder trees, labels, and tags
|
||||||
$options = [
|
$options = [
|
||||||
// each context array consists of a common table expression to select from, the column to match in the main join, the column to match in the CTE, the column to select in the CTE, an operator, and a type for the match in the CTE
|
// each context array consists of a common table expression to select from, the column to match in the main join, the column to match in the CTE, the column to select in the CTE, an operator, and a type for the match in the CTE
|
||||||
'folder' => ["folders", "folder", "folders.id", "req", "=", "int"],
|
'folder' => ["folders", "folder", "folders.id", "req", "=", "int"],
|
||||||
|
@ -1695,28 +1691,70 @@ class Database {
|
||||||
"annotationTerms" => ["note"],
|
"annotationTerms" => ["note"],
|
||||||
];
|
];
|
||||||
foreach ($options as $m => $columns) {
|
foreach ($options as $m => $columns) {
|
||||||
if (!$context->$m()) {
|
$columns = array_map(function($c) use ($colDefs) {
|
||||||
continue;
|
assert(isset($colDefs[$c]), new Exception("constantUnknown", $c));
|
||||||
} elseif (!$context->$m) {
|
return $colDefs[$c];
|
||||||
|
}, $columns);
|
||||||
|
if ($context->$m()) {
|
||||||
|
if (!$context->$m) {
|
||||||
throw new Db\ExceptionInput("tooShort", ['field' => $m, 'action' => $this->caller(), 'min' => 1]); // must have at least one array element
|
throw new Db\ExceptionInput("tooShort", ['field' => $m, 'action' => $this->caller(), 'min' => 1]); // must have at least one array element
|
||||||
}
|
}
|
||||||
$columns = array_map(function($c) use ($colDefs) {
|
|
||||||
assert(isset($colDefs[$c]), new Exception("constantUnknown", $c));
|
|
||||||
return $colDefs[$c];
|
|
||||||
}, $columns);
|
|
||||||
$q->setWhere(...$this->generateSearch($context->$m, $columns));
|
$q->setWhere(...$this->generateSearch($context->$m, $columns));
|
||||||
}
|
}
|
||||||
// further handle exclusionary text-matching context options
|
// handle the exclusionary version
|
||||||
foreach ($options as $m => $columns) {
|
if ($context->not->$m() && $context->not->$m) {
|
||||||
if (!$context->not->$m() || !$context->not->$m) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$columns = array_map(function($c) use ($colDefs) {
|
|
||||||
assert(isset($colDefs[$c]), new Exception("constantUnknown", $c));
|
|
||||||
return $colDefs[$c];
|
|
||||||
}, $columns);
|
|
||||||
$q->setWhereNot(...$this->generateSearch($context->not->$m, $columns, true));
|
$q->setWhereNot(...$this->generateSearch($context->not->$m, $columns, true));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// handle arrays of ranges
|
||||||
|
$options = [
|
||||||
|
'modifiedRanges' => ["modified_date", "datetime"],
|
||||||
|
'markedRanges' => ["marked_date", "datetime"],
|
||||||
|
];
|
||||||
|
foreach ($options as $m => [$col, $type]) {
|
||||||
|
if ($context->$m()) {
|
||||||
|
if (!$context->$m) {
|
||||||
|
throw new Db\ExceptionInput("tooShort", ['field' => $m, 'action' => $this->caller(), 'min' => 1]); // must have at least one array element
|
||||||
|
}
|
||||||
|
$w = [];
|
||||||
|
$t = [];
|
||||||
|
$v = [];
|
||||||
|
foreach ($context->$m as $r) {
|
||||||
|
if ($r[0] === null) {
|
||||||
|
// range is open at the low end
|
||||||
|
$w[] = "{$colDefs[$col]} <= ?";
|
||||||
|
$t[] = $type;
|
||||||
|
$v[] = $r[1];
|
||||||
|
} elseif ($context->$m[1] === null) {
|
||||||
|
// range is open at the high end
|
||||||
|
$w[] = "{$colDefs[$col]} >= ?";
|
||||||
|
$t[] = $type;
|
||||||
|
$v[] = $r[0];
|
||||||
|
} else {
|
||||||
|
// range is bounded in both directions
|
||||||
|
$w[] = "{$colDefs[$col]} BETWEEN ? AND ?";
|
||||||
|
$t[] = [$type, $type];
|
||||||
|
$v[] = $r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$q->setWhere("(".implode(" OR ", $w).")", $t, $v);
|
||||||
|
}
|
||||||
|
// handle the exclusionary version
|
||||||
|
if ($context->not->$m() && $context->not->$m) {
|
||||||
|
foreach ($context->not->$m as $r) {
|
||||||
|
if ($r[0] === null) {
|
||||||
|
// range is open at the low end
|
||||||
|
$q->setWhereNot("{$colDefs[$col]} <= ?", $type, $r[1]);
|
||||||
|
} elseif ($r[1] === null) {
|
||||||
|
// range is open at the high end
|
||||||
|
$q->setWhereNot("{$colDefs[$col]} >= ?", $type, $r[0]);
|
||||||
|
} else {
|
||||||
|
// range is bounded in both directions
|
||||||
|
$q->setWhereNot("{$colDefs[$col]} BETWEEN ? AND ?", [$type, $type], $r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// return the query
|
// return the query
|
||||||
return $q;
|
return $q;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue