FilterActionsTrait.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * Logic to apply filter actions (for feeds, categories, user configuration...).
  5. */
  6. trait FreshRSS_FilterActionsTrait {
  7. /** @var array<FreshRSS_FilterAction>|null $filterActions */
  8. private ?array $filterActions = null;
  9. /**
  10. * @return array<FreshRSS_FilterAction>
  11. */
  12. private function filterActions(): array {
  13. if (empty($this->filterActions)) {
  14. $this->filterActions = [];
  15. $filters = $this->attributes('filters');
  16. if (is_array($filters)) {
  17. foreach ($filters as $filter) {
  18. $filterAction = FreshRSS_FilterAction::fromJSON($filter);
  19. if ($filterAction != null) {
  20. $this->filterActions[] = $filterAction;
  21. }
  22. }
  23. }
  24. }
  25. return $this->filterActions;
  26. }
  27. /**
  28. * @param array<FreshRSS_FilterAction>|null $filterActions
  29. */
  30. private function _filterActions(?array $filterActions): void {
  31. $this->filterActions = $filterActions;
  32. if (is_array($this->filterActions) && !empty($this->filterActions)) {
  33. $this->_attributes('filters', array_map(static function (?FreshRSS_FilterAction $af) {
  34. return $af == null ? null : $af->toJSON();
  35. }, $this->filterActions));
  36. } else {
  37. $this->_attributes('filters', null);
  38. }
  39. }
  40. /** @return array<FreshRSS_BooleanSearch> */
  41. public function filtersAction(string $action): array {
  42. $action = trim($action);
  43. if ($action == '') {
  44. return [];
  45. }
  46. $filters = [];
  47. $filterActions = $this->filterActions();
  48. for ($i = count($filterActions) - 1; $i >= 0; $i--) {
  49. $filterAction = $filterActions[$i];
  50. if ($filterAction != null && $filterAction->booleanSearch() != null &&
  51. $filterAction->actions() != null && in_array($action, $filterAction->actions(), true)) {
  52. $filters[] = $filterAction->booleanSearch();
  53. }
  54. }
  55. return $filters;
  56. }
  57. /**
  58. * @param array<string> $filters
  59. */
  60. public function _filtersAction(string $action, array $filters): void {
  61. $action = trim($action);
  62. if ($action === '') {
  63. return;
  64. }
  65. $filters = array_unique(array_map('trim', $filters), SORT_STRING);
  66. $filterActions = $this->filterActions();
  67. //Check existing filters
  68. for ($i = count($filterActions) - 1; $i >= 0; $i--) {
  69. $filterAction = $filterActions[$i];
  70. if ($filterAction == null || !is_array($filterAction->actions()) ||
  71. $filterAction->booleanSearch() == null || trim($filterAction->booleanSearch()->getRawInput()) == '') {
  72. array_splice($filterActions, $i, 1);
  73. continue;
  74. }
  75. $actions = $filterAction->actions();
  76. //Remove existing rules with same action
  77. for ($j = count($actions) - 1; $j >= 0; $j--) {
  78. if ($actions[$j] === $action) {
  79. array_splice($actions, $j, 1);
  80. }
  81. }
  82. //Update existing filter with new action
  83. for ($k = count($filters) - 1; $k >= 0; $k --) {
  84. $filter = $filters[$k];
  85. if ($filter === $filterAction->booleanSearch()->getRawInput()) {
  86. $actions[] = $action;
  87. array_splice($filters, $k, 1);
  88. }
  89. }
  90. //Save result
  91. if (empty($actions)) {
  92. array_splice($filterActions, $i, 1);
  93. } else {
  94. $filterAction->_actions($actions);
  95. }
  96. }
  97. //Add new filters
  98. for ($k = count($filters) - 1; $k >= 0; $k --) {
  99. $filter = $filters[$k];
  100. if ($filter != '') {
  101. $filterAction = FreshRSS_FilterAction::fromJSON([
  102. 'search' => $filter,
  103. 'actions' => [$action],
  104. ]);
  105. if ($filterAction != null) {
  106. $filterActions[] = $filterAction;
  107. }
  108. }
  109. }
  110. if (empty($filterActions)) {
  111. $filterActions = null;
  112. }
  113. $this->_filterActions($filterActions);
  114. }
  115. public function applyFilterActions(FreshRSS_Entry $entry): void {
  116. foreach ($this->filterActions() as $filterAction) {
  117. if ($entry->matches($filterAction->booleanSearch())) {
  118. foreach ($filterAction->actions() as $action) {
  119. switch ($action) {
  120. case 'read':
  121. if (!$entry->isRead()) {
  122. $entry->_isRead(true);
  123. Minz_ExtensionManager::callHook('entry_auto_read', $entry, 'filter');
  124. }
  125. break;
  126. case 'star':
  127. $entry->_isFavorite(true);
  128. break;
  129. case 'label':
  130. //TODO: Implement more actions
  131. break;
  132. }
  133. }
  134. }
  135. }
  136. }
  137. }