Skip to content

Commit 0df5d00

Browse files
authored
PHRAS-4140 sb-filter-for-expiringrights (#4594)
* add 'status' filter (for "owners" job) ```json // type 'target' => 'owners', // filters 'databox' => 'db_databox1', 'status' => '00xxxx', 'collection' => ['test', 'boo'], 'expire_field' => 'ExpireDate', 'prior_notice' => -30, // action 'set_status' => '01xxxx', 'alerts' => [ [ 'method' => 'webhook', 'recipient' => [ '[email protected]', '[email protected]', ], ], ], ``` * add 'set_collection' action (for "owners" job) acts on records using api, not sql * add negated clause on 'set_collection'
1 parent ef9d9f6 commit 0df5d00

File tree

1 file changed

+88
-43
lines changed

1 file changed

+88
-43
lines changed

lib/Alchemy/Phrasea/Command/ExpiringRights/AlertExpiringRightsCommand.php

Lines changed: 88 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ private function playJobOwners($jobname, $job)
154154
return true;
155155
}
156156

157+
// actions by api
158+
$actions = [];
159+
157160
// build sql where clause
158161
$wheres = [];
159162

@@ -173,7 +176,7 @@ private function playJobOwners($jobname, $job)
173176
$dbox = $this->databoxes[$d]['dbox'];
174177
$sbas_id = $dbox->get_sbas_id();
175178

176-
// filter on collections ?
179+
// filter on collections
177180
$collList = [];
178181
foreach (get_in($job, ['collection'], []) as $c) {
179182
/** @var collection $coll */
@@ -190,38 +193,69 @@ private function playJobOwners($jobname, $job)
190193
}
191194
}
192195

193-
// clause on sb (negated)
194-
$mask = get_in($job, ['set_status']);
195-
if ($mask === null) {
196-
$this->output->writeln(sprintf("<error>missing 'set_status' clause</error>"));
197-
return false;
198-
}
199-
$m = preg_replace('/[^0-1]/', 'x', trim($mask));
200-
if (strlen($m) > 32) {
201-
$this->output->writeln(sprintf("<error>status mask (%s) too long</error>", $mask));
202-
return false;
203-
}
204-
$mask_xor = str_replace(' ', '0', ltrim(str_replace(array('0', 'x'), array(' ', ' '), $m)));
205-
$mask_and = str_replace(' ', '0', ltrim(str_replace(array('x', '0'), array(' ', '1'), $m)));
206-
if ($mask_xor && $mask_and) {
207-
$wheres[] = '((r.`status` ^ 0b' . $mask_xor . ') & 0b' . $mask_and . ') != 0';
208-
} elseif ($mask_xor) {
209-
$wheres[] = '(r.`status` ^ 0b' . $mask_xor . ') != 0';
210-
} elseif ($mask_and) {
211-
$wheres[] = '(r.`status` & 0b' . $mask_and . ') != 0';
212-
} else {
213-
$this->output->writeln(sprintf("<error>empty status mask</error>"));
214-
return false;
196+
// filter on status
197+
if (($status = get_in($job, ['status'])) !== null) {
198+
$m = preg_replace('/[^0-1]/', 'x', trim($status));
199+
if (strlen($m) == 0 || strlen($m) > 32) {
200+
$this->output->writeln(sprintf("<error>invalid status (%s)</error>", $status));
201+
return false;
202+
}
203+
$mask_xor = str_replace(' ', '0', ltrim(str_replace(['0', 'x'], [' ', ' '], $m)));
204+
$mask_and = str_replace(' ', '0', ltrim(str_replace(['x', '0'], [' ', '1'], $m)));
205+
if ($mask_xor && $mask_and) {
206+
$wheres[] = '((r.`status` ^ 0b' . $mask_xor . ') & 0b' . $mask_and . ') = 0';
207+
}
208+
elseif ($mask_xor) {
209+
$wheres[] = '(r.`status` ^ 0b' . $mask_xor . ') = 0';
210+
}
211+
elseif ($mask_and) {
212+
$wheres[] = '(r.`status` & 0b' . $mask_and . ') = 0';
213+
}
215214
}
216-
// set status
217-
$set_status = "`status`";
218-
$set_or = str_replace(' ', '0', ltrim(str_replace(array('0', 'x'), array(' ', ' '), $m)));
219-
$set_nand = str_replace(' ', '0', ltrim(str_replace(array('x', '1', '0'), array(' ', ' ', '1'), $m)));
220-
if($set_or) {
221-
$set_status = "(" . $set_status . " | 0b" . $set_or . ")";
215+
216+
// filter on negated set_status
217+
if(($set_status = get_in($job, ['set_status'])) !== null) {
218+
$m = preg_replace('/[^0-1]/', 'x', trim($set_status));
219+
if (strlen($m) == 0 || strlen($m) > 32) {
220+
$this->output->writeln(sprintf("<error>invalid set_status (%s)</error>", $set_status));
221+
return false;
222+
}
223+
$mask_xor = str_replace(' ', '0', ltrim(str_replace(['0', 'x'], [' ', ' '], $m)));
224+
$mask_and = str_replace(' ', '0', ltrim(str_replace(['x', '0'], [' ', '1'], $m)));
225+
if ($mask_xor && $mask_and) {
226+
$wheres[] = '((r.`status` ^ 0b' . $mask_xor . ') & 0b' . $mask_and . ') != 0';
227+
}
228+
elseif ($mask_xor) {
229+
$wheres[] = '(r.`status` ^ 0b' . $mask_xor . ') != 0';
230+
}
231+
elseif ($mask_and) {
232+
$wheres[] = '(r.`status` & 0b' . $mask_and . ') != 0';
233+
}
234+
235+
// set status by actions api
236+
foreach (str_split(strrev($m)) as $bit => $val) {
237+
if ($val == '0' || $val == '1') {
238+
if(!array_key_exists('status', $actions)) {
239+
$actions['status'] = [];
240+
}
241+
$actions['status'][] = ['bit' => $bit, 'state' => $val=='1'];
242+
}
243+
}
222244
}
223-
if($set_nand) {
224-
$set_status = "(" . $set_status . " & ~0b" . $set_nand . ")";
245+
246+
// filter on negated set_collection
247+
if($set_collection = get_in($job, ['set_collection'])) {
248+
/** @var collection $coll */
249+
if (($coll = get_in($this->databoxes[$sbas_id], ['collections', $set_collection])) !== null) {
250+
$wheres[] = "r.`coll_id`!=" . $dbox->get_connection()->quote($coll->get_coll_id());
251+
252+
// change collection by actions api
253+
$actions['base_id'] = $coll->get_coll_id();
254+
}
255+
else {
256+
$this->output->writeln(sprintf("<error>unknown collection (%s)</error>", $c));
257+
return false;
258+
}
225259
}
226260

227261
// clause on expiration date
@@ -270,18 +304,30 @@ private function playJobOwners($jobname, $job)
270304
$this->output->writeln(sprintf("<info>dry mode: updates on %d records NOT executed</info>", $stmt->rowCount()));
271305
}
272306

307+
if(empty($actions)) {
308+
$this->output->writeln(sprintf("<error>no actions defined</error>"));
309+
return false;
310+
}
311+
273312
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
274313
$record = $dbox->get_record($row['record_id']);
275314
$row['collection'] = $record->getCollection()->get_name();
276315
$row['title'] = $record->get_title();
277316
$records[] = $row;
278317

279-
$sql = "UPDATE `record` SET `status`=" . $set_status . " WHERE record_id=" . $dbox->get_connection()->quote($row['record_id']);
280-
if ($this->input->getOption('show-sql')) {
281-
$this->output->writeln(sprintf("sql: %s", $sql));
282-
}
283-
if (!$this->input->getOption('dry')) {
284-
$dbox->get_connection()->exec($sql);
318+
// update by api
319+
if(!empty($actions)) {
320+
$js = json_encode($actions);
321+
$this->output->writeln(sprintf("on databox(%s), record(%s) :%s js=%s \n",
322+
$sbas_id,
323+
$row['record_id'],
324+
$this->input->getOption('dry') ? " [DRY]" : '',
325+
$js
326+
));
327+
328+
if(!$this->input->getOption('dry')) {
329+
$record->setMetadatasByActions(json_decode($js, false)); // false: setMetadatasByActions expects object, not array !
330+
}
285331
}
286332
}
287333
$stmt->closeCursor();
@@ -575,12 +621,11 @@ private function sanitizeJob($job)
575621

576622
private function sanitizeJobOwners($job)
577623
{
578-
return $this->sanitize(
579-
$job,
580-
[
581-
'set_status' => "is_string",
582-
]
583-
);
624+
if(get_in($job, ['set_status']) === null && get_in($job, ['set_collection']) === null) {
625+
$this->output->writeln(sprintf("<error>missing 'set_status' or 'set_collection' setting</error>"));
626+
return false;
627+
}
628+
return true;
584629
}
585630

586631
private function sanitizeJobDownloaders($job)

0 commit comments

Comments
 (0)