| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- <?php
- declare(strict_types=1);
- /**
- * Logic to apply filter actions (for feeds, categories, user configuration...).
- */
- trait FreshRSS_FilterActionsTrait {
- /** @var list<FreshRSS_FilterAction>|null $filterActions */
- private ?array $filterActions = null;
- /**
- * @return list<FreshRSS_FilterAction>
- */
- private function filterActions(): array {
- if (empty($this->filterActions)) {
- $this->filterActions = [];
- $filters = $this->attributeArray('filters') ?? [];
- foreach ($filters as $filter) {
- $filterAction = FreshRSS_FilterAction::fromJSON($filter);
- if ($filterAction != null) {
- $this->filterActions[] = $filterAction;
- }
- }
- }
- return $this->filterActions;
- }
- /**
- * @param array<FreshRSS_FilterAction>|null $filterActions
- */
- private function _filterActions(?array $filterActions): void {
- $this->filterActions = is_array($filterActions) ? array_values($filterActions) : null;
- if ($this->filterActions !== null && !empty($this->filterActions)) {
- $this->_attribute('filters', array_map(
- static fn(?FreshRSS_FilterAction $af) => $af == null ? null : $af->toJSON(),
- $this->filterActions));
- } else {
- $this->_attribute('filters', null);
- }
- }
- /** @return list<FreshRSS_BooleanSearch> */
- public function filtersAction(string $action): array {
- $action = trim($action);
- if ($action == '') {
- return [];
- }
- $filters = [];
- $filterActions = $this->filterActions();
- for ($i = count($filterActions) - 1; $i >= 0; $i--) {
- $filterAction = $filterActions[$i];
- if (in_array($action, $filterAction->actions(), true)) {
- $filters[] = $filterAction->booleanSearch();
- }
- }
- return $filters;
- }
- /**
- * @param array<string> $filters
- */
- public function _filtersAction(string $action, array $filters): void {
- $action = trim($action);
- if ($action === '') {
- return;
- }
- $filters = array_unique(array_map('trim', $filters), SORT_STRING);
- $filterActions = $this->filterActions();
- //Check existing filters
- for ($i = count($filterActions) - 1; $i >= 0; $i--) {
- $filterAction = $filterActions[$i];
- if ($filterAction == null || !is_array($filterAction->actions()) ||
- $filterAction->booleanSearch() == null || trim($filterAction->booleanSearch()->getRawInput()) == '') {
- array_splice($filterActions, $i, 1);
- continue;
- }
- $actions = $filterAction->actions();
- //Remove existing rules with same action
- for ($j = count($actions) - 1; $j >= 0; $j--) {
- if ($actions[$j] === $action) {
- array_splice($actions, $j, 1);
- }
- }
- //Update existing filter with new action
- for ($k = count($filters) - 1; $k >= 0; $k--) {
- $filter = $filters[$k];
- if ($filter === $filterAction->booleanSearch()->getRawInput()) {
- $actions[] = $action;
- array_splice($filters, $k, 1);
- }
- }
- //Save result
- if (empty($actions)) {
- array_splice($filterActions, $i, 1);
- } else {
- $filterAction->_actions($actions);
- }
- }
- //Add new filters
- for ($k = count($filters) - 1; $k >= 0; $k--) {
- $filter = $filters[$k];
- if ($filter != '') {
- $filterAction = FreshRSS_FilterAction::fromJSON([
- 'search' => $filter,
- 'actions' => [$action],
- ]);
- if ($filterAction != null) {
- $filterActions[] = $filterAction;
- }
- }
- }
- if (empty($filterActions)) {
- $filterActions = null;
- }
- $this->_filterActions($filterActions);
- }
- /**
- * @param bool $applyLabel Parameter by reference, which will be set to true if the callers needs to apply a label to the article entry.
- * @param-out bool $applyLabel
- */
- public function applyFilterActions(FreshRSS_Entry $entry, ?bool &$applyLabel = null): void {
- $applyLabel = false;
- foreach ($this->filterActions() as $filterAction) {
- if ($entry->matches($filterAction->booleanSearch())) {
- foreach ($filterAction->actions() as $action) {
- switch ($action) {
- case 'read':
- if (!$entry->isRead()) {
- $entry->_isRead(true);
- Minz_ExtensionManager::callHook(Minz_HookType::EntryAutoRead, $entry, 'filter');
- }
- break;
- case 'star':
- if (!$entry->isUpdated()) {
- // Do not apply to updated articles, to avoid overruling a user manual action
- $entry->_isFavorite(true);
- }
- break;
- case 'label':
- if (!$entry->isUpdated()) {
- // Do not apply to updated articles, to avoid overruling a user manual action
- $applyLabel = true;
- }
- break;
- }
- }
- }
- }
- }
- }
|