diff --git a/lib/Alchemy/Phrasea/Command/ExpiringRights/AlertExpiringRightsCommand.php b/lib/Alchemy/Phrasea/Command/ExpiringRights/AlertExpiringRightsCommand.php index f354aee59d..d3b2fc9804 100644 --- a/lib/Alchemy/Phrasea/Command/ExpiringRights/AlertExpiringRightsCommand.php +++ b/lib/Alchemy/Phrasea/Command/ExpiringRights/AlertExpiringRightsCommand.php @@ -154,6 +154,9 @@ private function playJobOwners($jobname, $job) return true; } + // actions by api + $actions = []; + // build sql where clause $wheres = []; @@ -173,7 +176,7 @@ private function playJobOwners($jobname, $job) $dbox = $this->databoxes[$d]['dbox']; $sbas_id = $dbox->get_sbas_id(); - // filter on collections ? + // filter on collections $collList = []; foreach (get_in($job, ['collection'], []) as $c) { /** @var collection $coll */ @@ -190,38 +193,69 @@ private function playJobOwners($jobname, $job) } } - // clause on sb (negated) - $mask = get_in($job, ['set_status']); - if ($mask === null) { - $this->output->writeln(sprintf("missing 'set_status' clause")); - return false; - } - $m = preg_replace('/[^0-1]/', 'x', trim($mask)); - if (strlen($m) > 32) { - $this->output->writeln(sprintf("status mask (%s) too long", $mask)); - return false; - } - $mask_xor = str_replace(' ', '0', ltrim(str_replace(array('0', 'x'), array(' ', ' '), $m))); - $mask_and = str_replace(' ', '0', ltrim(str_replace(array('x', '0'), array(' ', '1'), $m))); - if ($mask_xor && $mask_and) { - $wheres[] = '((r.`status` ^ 0b' . $mask_xor . ') & 0b' . $mask_and . ') != 0'; - } elseif ($mask_xor) { - $wheres[] = '(r.`status` ^ 0b' . $mask_xor . ') != 0'; - } elseif ($mask_and) { - $wheres[] = '(r.`status` & 0b' . $mask_and . ') != 0'; - } else { - $this->output->writeln(sprintf("empty status mask")); - return false; + // filter on status + if (($status = get_in($job, ['status'])) !== null) { + $m = preg_replace('/[^0-1]/', 'x', trim($status)); + if (strlen($m) == 0 || strlen($m) > 32) { + $this->output->writeln(sprintf("invalid status (%s)", $status)); + return false; + } + $mask_xor = str_replace(' ', '0', ltrim(str_replace(['0', 'x'], [' ', ' '], $m))); + $mask_and = str_replace(' ', '0', ltrim(str_replace(['x', '0'], [' ', '1'], $m))); + if ($mask_xor && $mask_and) { + $wheres[] = '((r.`status` ^ 0b' . $mask_xor . ') & 0b' . $mask_and . ') = 0'; + } + elseif ($mask_xor) { + $wheres[] = '(r.`status` ^ 0b' . $mask_xor . ') = 0'; + } + elseif ($mask_and) { + $wheres[] = '(r.`status` & 0b' . $mask_and . ') = 0'; + } } - // set status - $set_status = "`status`"; - $set_or = str_replace(' ', '0', ltrim(str_replace(array('0', 'x'), array(' ', ' '), $m))); - $set_nand = str_replace(' ', '0', ltrim(str_replace(array('x', '1', '0'), array(' ', ' ', '1'), $m))); - if($set_or) { - $set_status = "(" . $set_status . " | 0b" . $set_or . ")"; + + // filter on negated set_status + if(($set_status = get_in($job, ['set_status'])) !== null) { + $m = preg_replace('/[^0-1]/', 'x', trim($set_status)); + if (strlen($m) == 0 || strlen($m) > 32) { + $this->output->writeln(sprintf("invalid set_status (%s)", $set_status)); + return false; + } + $mask_xor = str_replace(' ', '0', ltrim(str_replace(['0', 'x'], [' ', ' '], $m))); + $mask_and = str_replace(' ', '0', ltrim(str_replace(['x', '0'], [' ', '1'], $m))); + if ($mask_xor && $mask_and) { + $wheres[] = '((r.`status` ^ 0b' . $mask_xor . ') & 0b' . $mask_and . ') != 0'; + } + elseif ($mask_xor) { + $wheres[] = '(r.`status` ^ 0b' . $mask_xor . ') != 0'; + } + elseif ($mask_and) { + $wheres[] = '(r.`status` & 0b' . $mask_and . ') != 0'; + } + + // set status by actions api + foreach (str_split(strrev($m)) as $bit => $val) { + if ($val == '0' || $val == '1') { + if(!array_key_exists('status', $actions)) { + $actions['status'] = []; + } + $actions['status'][] = ['bit' => $bit, 'state' => $val=='1']; + } + } } - if($set_nand) { - $set_status = "(" . $set_status . " & ~0b" . $set_nand . ")"; + + // filter on negated set_collection + if($set_collection = get_in($job, ['set_collection'])) { + /** @var collection $coll */ + if (($coll = get_in($this->databoxes[$sbas_id], ['collections', $set_collection])) !== null) { + $wheres[] = "r.`coll_id`!=" . $dbox->get_connection()->quote($coll->get_coll_id()); + + // change collection by actions api + $actions['base_id'] = $coll->get_coll_id(); + } + else { + $this->output->writeln(sprintf("unknown collection (%s)", $c)); + return false; + } } // clause on expiration date @@ -270,18 +304,30 @@ private function playJobOwners($jobname, $job) $this->output->writeln(sprintf("dry mode: updates on %d records NOT executed", $stmt->rowCount())); } + if(empty($actions)) { + $this->output->writeln(sprintf("no actions defined")); + return false; + } + while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { $record = $dbox->get_record($row['record_id']); $row['collection'] = $record->getCollection()->get_name(); $row['title'] = $record->get_title(); $records[] = $row; - $sql = "UPDATE `record` SET `status`=" . $set_status . " WHERE record_id=" . $dbox->get_connection()->quote($row['record_id']); - if ($this->input->getOption('show-sql')) { - $this->output->writeln(sprintf("sql: %s", $sql)); - } - if (!$this->input->getOption('dry')) { - $dbox->get_connection()->exec($sql); + // update by api + if(!empty($actions)) { + $js = json_encode($actions); + $this->output->writeln(sprintf("on databox(%s), record(%s) :%s js=%s \n", + $sbas_id, + $row['record_id'], + $this->input->getOption('dry') ? " [DRY]" : '', + $js + )); + + if(!$this->input->getOption('dry')) { + $record->setMetadatasByActions(json_decode($js, false)); // false: setMetadatasByActions expects object, not array ! + } } } $stmt->closeCursor(); @@ -575,12 +621,11 @@ private function sanitizeJob($job) private function sanitizeJobOwners($job) { - return $this->sanitize( - $job, - [ - 'set_status' => "is_string", - ] - ); + if(get_in($job, ['set_status']) === null && get_in($job, ['set_collection']) === null) { + $this->output->writeln(sprintf("missing 'set_status' or 'set_collection' setting")); + return false; + } + return true; } private function sanitizeJobDownloaders($job)