diff --git a/bridges/FilterMoreBridge.php b/bridges/FilterMoreBridge.php new file mode 100644 index 0000000..aa11251 --- /dev/null +++ b/bridges/FilterMoreBridge.php @@ -0,0 +1,157 @@ + array( + 'name' => 'Feed URL', + 'required' => true, + ), + 'conj_type' => array( + 'name' => 'Conjunction type type', + 'type' => 'list', + 'required' => false, + 'values' => array( + 'All conditions must be met' => 'and', + 'Any condition must be met' => 'or', + ), + 'defaultValue' => 'permit', + ), + + 'title_re' => array( + 'name' => 'Filter item title (regular expression, see php.net/pcre_match for details)', + 'required' => false, + 'exampleValue' => '/breaking\ news/i', + ), + 'body_re' => array( + 'name' => 'Filter body (regular expression)', + 'required' => false, + ), + 'author_re' => array( + 'name' => 'Filter author (regular expression)', + 'required' => false, + 'exampleValue' => '/(technology|politics)/i', + ), + 'newer_than' => array( + 'name' => 'Filter date: ok if newer than the value (see php.net/strtotime for details)', + 'required' => false, + 'exampleValue' => '-14 days', + ), + 'older_than' => array( + 'name' => 'Filter date: ok if older than the value (see php.net/strtotime for details)', + 'required' => false, + 'exampleValue' => '-1 hour', + ), + + 'invert_filter' => array( + 'name' => 'Invert filter result', + 'type' => 'checkbox', + 'required' => false, + 'defaultValue' => false, + ), + )); + + protected function parseItem($newItem){ + $item = parent::parseItem($newItem); + + $filters = ['filterByTitle', 'filterByBody', 'filterByAuthor', 'filterByDateNewer', 'filterByDateOlder']; + $results = []; + + foreach($filters as $filter) { + $filter_res = $this->$filter($item); + if($filter_res === null) continue; + $results[] = $filter_res; + } + if(count($results) === 0) { + return $item; + } + if($this->getConjType() === 'and') { + $result = !in_array(false, $results); + } else { // or + $result = in_array(true, $results); + } + if($this->getInvertResult()) { + $result = !$result; + } + if($result) + return $item; + else + return null; + } + + private function cmp($a, $b) { + if($a > $b) return 1; + if($a < $b) return -1; + return 0; + } + private function filterByFieldRegexp($field, $re){ + if($re === "") return null; + if(preg_match($re, $field)) { + return true; + } + return false; + } + protected function filterByTitle($item){ + $re = $this->getInput('title_re'); + return $this->filterByFieldRegexp($item['title'], $re); + } + protected function filterByBody($item){ + $re = $this->getInput('body_re'); + return $this->filterByFieldRegexp($item['content'], $re); + } + protected function filterByAuthor($item){ + $re = $this->getInput('author_re'); + return $this->filterByFieldRegexp($item['author'], $re); + } + private function filterByDate($item, $input, $expected){ + $val = $this->getInput($input); + if($val === "") return null; + $ts = strtotime($val); + if($ts === false) { + throw new Exception("Invalid time specification: " . $val); + } + $cmp = $this->cmp($item['timestamp'], $ts); // 1 if newer, -1 if older + return $cmp === $expected; + } + protected function filterByDateNewer($item){ + return $this->filterByDate($item, 'newer_than', 1); + } + protected function filterByDateOlder($item){ + return $this->filterByDate($item, 'older_than', -1); + } + + protected function getConjType(){ + return $this->getInput('conj_type'); + } + protected function getInvertResult(){ + return $this->getInput('invert_filter'); + } + + public function getURI(){ + $url = $this->getInput('url'); + + if(empty($url)) { + $url = parent::getURI(); + } + return $url; + } + + public function collectData(){ + if($this->getInput('url') && substr($this->getInput('url'), 0, strlen('http')) !== 'http') { + // just in case someone find a way to access local files by playing with the url + returnClientError('The url parameter must either refer to http or https protocol.'); + } + try{ + $this->collectExpandableDatas($this->getURI()); + } catch (HttpException $e) { + $this->collectExpandableDatas($this->getURI()); + } + } +} +