implement multiple rule/action filters

This commit is contained in:
Andrew Dolgov 2012-08-30 18:50:56 +04:00
parent f9ebb32ca0
commit 6aff784575
14 changed files with 1129 additions and 721 deletions

View File

@ -444,132 +444,6 @@ class Dlg extends Handler_Protected {
</div>";
}
function quickAddFilter() {
$active_feed_id = (int) db_escape_string($_REQUEST["feed"]);
$cat_filter = db_escape_string($_REQUEST["is_cat"]) == "true";
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-filters\">";
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"quiet\" value=\"1\">";
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"add\">";
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"csrf_token\" value=\"".$_SESSION['csrf_token']."\">";
$result = db_query($this->link, "SELECT id,description
FROM ttrss_filter_types ORDER BY description");
$filter_types = array();
while ($line = db_fetch_assoc($result)) {
//array_push($filter_types, $line["description"]);
$filter_types[$line["id"]] = __($line["description"]);
}
print "<div class=\"dlgSec\">".__("Match")."</div>";
print "<div class=\"dlgSecCont\">";
print "<span id=\"filterDlg_dateModBox\" style=\"display : none\">";
$filter_params = array(
"before" => __("before"),
"after" => __("after"));
print_select_hash("filter_date_modifier", "before",
$filter_params, 'dojoType="dijit.form.Select"');
print "&nbsp;</span>";
print "<input dojoType=\"dijit.form.ValidationTextBox\"
required=\"true\" id=\"filterDlg_regExp\"
style=\"font-size : 16px\"
name=\"reg_exp\" value=\"$reg_exp\"/>";
print "<span id=\"filterDlg_dateChkBox\" style=\"display : none\">";
print "&nbsp;<button dojoType=\"dijit.form.Button\"
onclick=\"return filterDlgCheckDate()\">".
__('Check it')."</button>";
print "</span>";
print "<hr/>" . __("on field") . " ";
print_select_hash("filter_type", 1, $filter_types,
'onchange="filterDlgCheckType(this)" dojoType="dijit.form.Select"');
print "<hr/>";
print __("in") . " ";
print "<span id='filterDlg_feeds'>";
print_feed_select($this->link, "feed_id",
$cat_filter ? "CAT:$active_feed_id" : $active_feed_id,
'dojoType="dijit.form.FilteringSelect"');
print "</span>";
print "<span id='filterDlg_cats' style='display : none'>";
print_feed_cat_select($this->link, "cat_id", $active_cat_id,
'dojoType="dijit.form.FilteringSelect"');
print "</span>";
print "</div>";
print "<div class=\"dlgSec\">".__("Perform Action")."</div>";
print "<div class=\"dlgSecCont\">";
print "<select name=\"action_id\" dojoType=\"dijit.form.Select\"
onchange=\"filterDlgCheckAction(this)\">";
$result = db_query($this->link, "SELECT id,description FROM ttrss_filter_actions
ORDER BY name");
while ($line = db_fetch_assoc($result)) {
printf("<option value='%d'>%s</option>", $line["id"], __($line["description"]));
}
print "</select>";
print "<span id=\"filterDlg_paramBox\" style=\"display : none\">";
print " " . __("with parameters:") . " ";
print "<input dojoType=\"dijit.form.TextBox\"
id=\"filterDlg_actionParam\"
name=\"action_param\">";
print_label_select($this->link, "action_param_label", $action_param,
'id="filterDlg_actionParamLabel" dojoType="dijit.form.Select"');
print "</span>";
print "&nbsp;"; // tiny layout hack
print "</div>";
print "<div class=\"dlgSec\">".__("Options")."</div>";
print "<div class=\"dlgSecCont\">";
print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"enabled\" id=\"enabled\" checked=\"1\">
<label for=\"enabled\">".__('Enabled')."</label><hr/>";
print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"inverse\" id=\"inverse\">
<label for=\"inverse\">".__('Inverse match')."</label><hr/>";
# print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"cat_filter\" id=\"cat_filter\" onchange=\"filterDlgCheckCat(this)\">
# <label for=\"cat_filter\">".__('Apply to category')."</label><hr/>";
print "</div>";
print "<div class=\"dlgButtons\">";
print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').test()\">".
__('Test')."</button> ";
print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').execute()\">".
__('Create')."</button> ";
print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').hide()\">".
__('Cancel')."</button>";
print "</div>";
}
function inactiveFeeds() {
if (DB_TYPE == "pgsql") {

View File

@ -159,7 +159,7 @@ class Opml extends Handler_Protected {
$out .= "</outline>";
$out .= "<outline title=\"tt-rss-filters\" schema-version=\"".SCHEMA_VERSION."\">";
/* $out .= "<outline title=\"tt-rss-filters\" schema-version=\"".SCHEMA_VERSION."\">";
$result = db_query($this->link, "SELECT filter_type,
reg_exp,
@ -191,7 +191,7 @@ class Opml extends Handler_Protected {
}
$out .= "</outline>";
$out .= "</outline>"; */
}
$out .= "</body></opml>";
@ -287,7 +287,7 @@ class Opml extends Handler_Protected {
}
}
private function opml_import_filter($doc, $node, $owner_uid) {
/* private function opml_import_filter($doc, $node, $owner_uid) {
$attrs = $node->attributes;
$filter_name = db_escape_string($attrs->getNamedItem('filter-name')->nodeValue);
@ -355,7 +355,7 @@ class Opml extends Handler_Protected {
}
}
}
}
} */
private function opml_import_category($doc, $root_node, $owner_uid, $parent_id) {
$body = $doc->getElementsByTagName('body');
@ -413,7 +413,7 @@ class Opml extends Handler_Protected {
$this->opml_import_label($doc, $node, $owner_uid);
break;
case "tt-rss-filters":
$this->opml_import_filter($doc, $node, $owner_uid);
//$this->opml_import_filter($doc, $node, $owner_uid);
break;
default:
$this->opml_import_feed($doc, $node, $dst_cat_id, $owner_uid);

File diff suppressed because it is too large Load Diff

View File

@ -192,10 +192,10 @@ class Pref_Labels extends Handler_Protected {
$old_caption = db_escape_string($old_caption);
db_query($this->link, "UPDATE ttrss_filters SET
db_query($this->link, "UPDATE ttrss_filters2_actions SET
action_param = '$caption' WHERE action_param = '$old_caption'
AND action_id = 7
AND owner_uid = " . $_SESSION["uid"]);
AND filter_id IN (SELECT id FROM ttrss_filters2 WHERE owner_uid = ".$_SESSION["uid"].")");
print $_REQUEST["value"];
} else {

View File

@ -1,6 +1,6 @@
<?php
define('EXPECTED_CONFIG_VERSION', 26);
define('SCHEMA_VERSION', 95);
define('SCHEMA_VERSION', 96);
$fetch_last_error = false;
@ -468,135 +468,88 @@
function get_article_filters($filters, $title, $content, $link, $timestamp, $author, $tags) {
$matches = array();
if ($filters["title"]) {
foreach ($filters["title"] as $filter) {
$reg_exp = $filter["reg_exp"];
$inverse = $filter["inverse"];
if ((!$inverse && @preg_match("/$reg_exp/i", $title)) ||
($inverse && !@preg_match("/$reg_exp/i", $title))) {
foreach ($filters as $filter) {
$match_any_rule = $filter["match_any_rule"];
$filter_match = false;
array_push($matches, array($filter["action"], $filter["action_param"]));
foreach ($filter["rules"] as $rule) {
$match = false;
$reg_exp = $rule["reg_exp"];
if (!$reg_exp)
continue;
switch ($rule["type"]) {
case "title":
$match = @preg_match("/$reg_exp/i", $title);
break;
case "content":
$match = @preg_match("/$reg_exp/i", $content);
break;
case "both":
$match = (@preg_match("/$reg_exp/i", $title) || @preg_match("/$reg_exp/i", $title));
break;
case "link":
$match = @preg_match("/$reg_exp/i", $link);
break;
case "author":
$match = @preg_match("/$reg_exp/i", $author);
break;
case "tag":
$tag_string = join(",", $tags);
$match = @preg_match("/$reg_exp/i", $tag_string);
break;
}
}
}
if ($filters["content"]) {
foreach ($filters["content"] as $filter) {
$reg_exp = $filter["reg_exp"];
$inverse = $filter["inverse"];
if ((!$inverse && @preg_match("/$reg_exp/i", $content)) ||
($inverse && !@preg_match("/$reg_exp/i", $content))) {
array_push($matches, array($filter["action"], $filter["action_param"]));
}
}
}
if ($filters["both"]) {
foreach ($filters["both"] as $filter) {
$reg_exp = $filter["reg_exp"];
$inverse = $filter["inverse"];
if ($inverse) {
if (!@preg_match("/$reg_exp/i", $title) && !preg_match("/$reg_exp/i", $content)) {
array_push($matches, array($filter["action"], $filter["action_param"]));
if ($match_any_rule) {
if ($match) {
$filter_match = true;
break;
}
} else {
if (@preg_match("/$reg_exp/i", $title) || preg_match("/$reg_exp/i", $content)) {
array_push($matches, array($filter["action"], $filter["action_param"]));
$filter_match = $match;
if (!$match) {
break;
}
}
}
}
if ($filters["link"]) {
$reg_exp = $filter["reg_exp"];
foreach ($filters["link"] as $filter) {
$reg_exp = $filter["reg_exp"];
$inverse = $filter["inverse"];
if ((!$inverse && @preg_match("/$reg_exp/i", $link)) ||
($inverse && !@preg_match("/$reg_exp/i", $link))) {
array_push($matches, array($filter["action"], $filter["action_param"]));
if ($filter_match) {
foreach ($filter["actions"] AS $action) {
array_push($matches, $action);
}
}
}
if ($filters["date"]) {
$reg_exp = $filter["reg_exp"];
foreach ($filters["date"] as $filter) {
$date_modifier = $filter["filter_param"];
$inverse = $filter["inverse"];
$check_timestamp = strtotime($filter["reg_exp"]);
# no-op when timestamp doesn't parse to prevent misfires
if ($check_timestamp) {
$match_ok = false;
if ($date_modifier == "before" && $timestamp < $check_timestamp ||
$date_modifier == "after" && $timestamp > $check_timestamp) {
$match_ok = true;
}
if ($inverse) $match_ok = !$match_ok;
if ($match_ok) {
array_push($matches, array($filter["action"], $filter["action_param"]));
}
}
}
}
if ($filters["author"]) {
foreach ($filters["author"] as $filter) {
$reg_exp = $filter["reg_exp"];
$inverse = $filter["inverse"];
if ((!$inverse && @preg_match("/$reg_exp/i", $author)) ||
($inverse && !@preg_match("/$reg_exp/i", $author))) {
array_push($matches, array($filter["action"], $filter["action_param"]));
}
}
}
if ($filters["tag"]) {
$tag_string = join(",", $tags);
foreach ($filters["tag"] as $filter) {
$reg_exp = $filter["reg_exp"];
$inverse = $filter["inverse"];
if ((!$inverse && @preg_match("/$reg_exp/i", $tag_string)) ||
($inverse && !@preg_match("/$reg_exp/i", $tag_string))) {
array_push($matches, array($filter["action"], $filter["action_param"]));
}
}
}
return $matches;
}
function find_article_filter($filters, $filter_name) {
foreach ($filters as $f) {
if ($f[0] == $filter_name) {
if ($f["type"] == $filter_name) {
return $f;
};
}
return false;
}
function find_article_filters($filters, $filter_name) {
$results = array();
foreach ($filters as $f) {
if ($f["type"] == $filter_name) {
array_push($results, $f);
};
}
return $results;
}
function calculate_article_score($filters) {
$score = 0;
foreach ($filters as $f) {
if ($f[0] == "score") {
$score += $f[1];
if ($f["type"] == "score") {
$score += $f["param"];
};
}
return $score;
@ -604,8 +557,8 @@
function assign_article_to_labels($link, $id, $filters, $owner_uid) {
foreach ($filters as $f) {
if ($f[0] == "label") {
label_add_article($link, $id, $f[1], $owner_uid);
if ($f["type"] == "label") {
label_add_article($link, $id, $f["param"], $owner_uid);
};
}
}
@ -3650,45 +3603,65 @@
return $text;
}
function load_filters($link, $feed, $owner_uid, $action_id = false) {
function load_filters($link, $feed_id, $owner_uid, $action_id = false) {
$filters = array();
$cat_id = getFeedCategory($link, $feed_id);
if ($action_id) $ftype_query_part = "action_id = '$action_id' AND";
$result = db_query($link, "SELECT reg_exp,
ttrss_filter_types.name AS name,
ttrss_filter_actions.name AS action,
inverse,
action_param,
filter_param
FROM ttrss_filters
LEFT JOIN ttrss_feeds ON (ttrss_feeds.id = '$feed'),
ttrss_filter_types,ttrss_filter_actions
WHERE
enabled = true AND
$ftype_query_part
ttrss_filters.owner_uid = $owner_uid AND
ttrss_filter_types.id = filter_type AND
ttrss_filter_actions.id = action_id AND
((cat_filter = true AND ttrss_feeds.cat_id = ttrss_filters.cat_id) OR
(cat_filter = true AND ttrss_feeds.cat_id IS NULL AND
ttrss_filters.cat_id IS NULL) OR
(cat_filter = false AND (feed_id IS NULL OR feed_id = '$feed')))
ORDER BY reg_exp");
$result = db_query($link, "SELECT * FROM ttrss_filters2 WHERE
owner_uid = $owner_uid AND enabled = true");
while ($line = db_fetch_assoc($result)) {
$filter_id = $line["id"];
if (!$filters[$line["name"]]) $filters[$line["name"]] = array();
$filter["reg_exp"] = $line["reg_exp"];
$filter["action"] = $line["action"];
$filter["action_param"] = $line["action_param"];
$filter["filter_param"] = $line["filter_param"];
$filter["inverse"] = sql_bool_to_bool($line["inverse"]);
$result2 = db_query($link, "SELECT
r.reg_exp, r.feed_id, r.cat_id, r.cat_filter, t.name AS type_name
FROM ttrss_filters2_rules AS r,
ttrss_filter_types AS t
WHERE
(cat_id IS NULL OR cat_id = '$cat_id') AND
(feed_id IS NULL OR feed_id = '$feed_id') AND
filter_type = t.id AND filter_id = '$filter_id'");
array_push($filters[$line["name"]], $filter);
$rules = array();
$actions = array();
while ($rule_line = db_fetch_assoc($result2)) {
# print_r($rule_line);
$rule = array();
$rule["reg_exp"] = $rule_line["reg_exp"];
$rule["type"] = $rule_line["type_name"];
array_push($rules, $rule);
}
$result2 = db_query($link, "SELECT a.action_param,t.name AS type_name
FROM ttrss_filters2_actions AS a,
ttrss_filter_actions AS t
WHERE
action_id = t.id AND filter_id = '$filter_id'");
while ($action_line = db_fetch_assoc($result2)) {
# print_r($action_line);
$action = array();
$action["type"] = $action_line["type_name"];
$action["param"] = $action_line["action_param"];
array_push($actions, $action);
}
$filter = array();
$filter["match_any_rule"] = sql_bool_to_bool($line["match_any_rule"]);
$filter["rules"] = $rules;
$filter["actions"] = $actions;
if (count($rules) > 0 && count($actions) > 0) {
array_push($filters, $filter);
}
}
return $filters;
}
@ -5595,4 +5568,16 @@
return $tempname;
}
function getFeedCategory($link, $feed) {
$result = db_query($link, "SELECT cat_id FROM ttrss_feeds
WHERE id = '$feed'");
if (db_num_rows($result) > 0) {
return db_fetch_result($result, 0, "cat_id");
} else {
return false;
}
}
?>

View File

@ -818,8 +818,8 @@
$entry_tags[$i] = mb_strtolower($entry_tags[$i], 'utf-8');
if ($debug_enabled) {
_debug("update_rss_feed: unfiltered tags found:");
print_r($entry_tags);
//_debug("update_rss_feed: unfiltered tags found:");
//print_r($entry_tags);
}
# sanitize content
@ -1190,9 +1190,9 @@
// check for manual tags (we have to do it here since they're loaded from filters)
foreach ($article_filters as $f) {
if ($f[0] == "tag") {
if ($f["type"] == "tag") {
$manual_tags = trim_array(explode(",", $f[1]));
$manual_tags = trim_array(explode(",", $f["param"]));
foreach ($manual_tags as $tag) {
if (tag_is_valid($tag)) {

View File

@ -545,7 +545,7 @@ function fatalError(code, msg, ext_info) {
}
}
function filterDlgCheckType(sender) {
/* function filterDlgCheckType(sender) {
try {
@ -565,7 +565,7 @@ function filterDlgCheckType(sender) {
exception_error("filterDlgCheckType", e);
}
}
} */
function filterDlgCheckAction(sender) {
@ -938,17 +938,163 @@ function quickAddFeed() {
}
}
function createNewRuleElement(parentNode, replaceNode) {
try {
var form = document.forms["filter_new_rule_form"];
var query = "backend.php?op=pref-filters&method=printrulename&rule="+
param_escape(dojo.formToJson(form));
console.log(query);
new Ajax.Request("backend.php", {
parameters: query,
onComplete: function (transport) {
try {
var li = dojo.create("li");
dojo.create("input", { type: "checkbox",
onclick: function() { toggleSelectListRow(this) },
}, li);
dojo.create("input", { type: "hidden",
name: "rule[]",
value: dojo.formToJson(form) }, li);
dojo.create("span", {
onclick: function() {
dijit.byId('filterEditDlg').editRule(this);
},
innerHTML: transport.responseText }, li);
if (replaceNode) {
parentNode.replaceChild(li, replaceNode);
} else {
parentNode.appendChild(li);
}
} catch (e) {
exception_error("createNewRuleElement", e);
}
} });
} catch (e) {
exception_error("createNewRuleElement", e);
}
}
function createNewActionElement(parentNode, replaceNode) {
try {
var form = document.forms["filter_new_action_form"];
if (form.action_id.value == 7) {
form.action_param.value = form.action_param_label.value;
}
var query = "backend.php?op=pref-filters&method=printactionname&action="+
param_escape(dojo.formToJson(form));
console.log(query);
new Ajax.Request("backend.php", {
parameters: query,
onComplete: function (transport) {
try {
var li = dojo.create("li");
dojo.create("input", { type: "checkbox",
onclick: function() { toggleSelectListRow(this) },
}, li);
dojo.create("input", { type: "hidden",
name: "action[]",
value: dojo.formToJson(form) }, li);
dojo.create("span", {
onclick: function() {
dijit.byId('filterEditDlg').editAction(this);
},
innerHTML: transport.responseText }, li);
if (replaceNode) {
parentNode.replaceChild(li, replaceNode);
} else {
parentNode.appendChild(li);
}
} catch (e) {
exception_error("createNewActionElement", e);
}
} });
} catch (e) {
exception_error("createNewActionElement", e);
}
}
function addFilterRule(replaceNode, ruleStr) {
try {
if (dijit.byId("filterNewRuleDlg"))
dijit.byId("filterNewRuleDlg").destroyRecursive();
var query = "backend.php?op=pref-filters&method=newrule&rule=" +
param_escape(ruleStr);
var rule_dlg = new dijit.Dialog({
id: "filterNewRuleDlg",
title: ruleStr ? __("Edit rule") : __("Add rule"),
style: "width: 600px",
execute: function() {
if (this.validate()) {
createNewRuleElement($("filterDlg_Matches"), replaceNode);
this.hide();
}
},
href: query});
rule_dlg.show();
} catch (e) {
exception_error("addFilterRule", e);
}
}
function addFilterAction(replaceNode, actionStr) {
try {
if (dijit.byId("filterNewActionDlg"))
dijit.byId("filterNewActionDlg").destroyRecursive();
var query = "backend.php?op=pref-filters&method=newaction&action=" +
param_escape(actionStr);
var rule_dlg = new dijit.Dialog({
id: "filterNewActionDlg",
title: actionStr ? __("Edit action") : __("Add action"),
style: "width: 600px",
execute: function() {
if (this.validate()) {
createNewActionElement($("filterDlg_Actions"), replaceNode);
this.hide();
}
},
href: query});
rule_dlg.show();
} catch (e) {
exception_error("addFilterAction", e);
}
}
function quickAddFilter() {
try {
var query = "";
if (!inPreferences()) {
query = "backend.php?op=dlg&method=quickAddFilter&feed=" +
query = "backend.php?op=pref-filters&method=newfilter&feed=" +
param_escape(getActiveFeedId()) + "&is_cat=" +
param_escape(activeFeedIsCat());
} else {
query = "backend.php?op=dlg&method=quickAddFilter";
query = "backend.php?op=pref-filters&method=newfilter";
}
console.log(query);
if (dijit.byId("feedEditDlg"))
dijit.byId("feedEditDlg").destroyRecursive();
@ -959,96 +1105,46 @@ function quickAddFilter() {
id: "filterEditDlg",
title: __("Create Filter"),
style: "width: 600px",
test: function() {
if (this.validate()) {
var query = "?op=rpc&method=verifyRegexp&reg_exp=" +
param_escape(dialog.attr('value').reg_exp);
notify_progress("Verifying regular expression...");
new Ajax.Request("backend.php", {
parameters: query,
onComplete: function(transport) {
var reply = JSON.parse(transport.responseText);
if (reply) {
notify('');
if (!reply['status']) {
alert("Invalid regular expression.");
return;
} else {
if (dijit.byId("filterTestDlg"))
dijit.byId("filterTestDlg").destroyRecursive();
tdialog = new dijit.Dialog({
id: "filterTestDlg",
title: __("Filter Test Results"),
style: "width: 600px",
href: "backend.php?savemode=test&" +
dojo.objectToQuery(dialog.attr('value')),
});
tdialog.show();
}
}
}});
}
editRule: function(e) {
var li = e.parentNode;
var rule = li.getElementsByTagName("INPUT")[1].value;
addFilterRule(li, rule);
},
editAction: function(e) {
var li = e.parentNode;
var action = li.getElementsByTagName("INPUT")[1].value;
addFilterAction(li, action);
},
addAction: function() { addFilterAction(); },
addRule: function() { addFilterRule(); },
deleteAction: function() {
$$("#filterDlg_Actions li.[class*=Selected]").each(function(e) { e.parentNode.removeChild(e) });
},
deleteRule: function() {
$$("#filterDlg_Matches li.[class*=Selected]").each(function(e) { e.parentNode.removeChild(e) });
},
execute: function() {
if (this.validate()) {
var query = "?op=rpc&method=verifyRegexp&reg_exp=" +
param_escape(dialog.attr('value').reg_exp);
var query = dojo.formToQuery("filter_new_form");
notify_progress("Verifying regular expression...");
console.log(query);
new Ajax.Request("backend.php", {
new Ajax.Request("backend.php", {
parameters: query,
onComplete: function(transport) {
var reply = JSON.parse(transport.responseText);
if (reply) {
notify('');
if (!reply['status']) {
alert("Invalid regular expression.");
return;
} else {
notify_progress("Saving data...", true);
console.log(dojo.objectToQuery(dialog.attr('value')));
new Ajax.Request("backend.php", {
parameters: dojo.objectToQuery(dialog.attr('value')),
onComplete: function(transport) {
dialog.hide();
notify_info(transport.responseText);
if (inPreferences()) {
updateFilterList();
}
}});
}
onComplete: function (transport) {
if (inPreferences()) {
updateFilterList();
}
}});
dialog.hide();
} });
}
},
href: query});
dialog.show();
var lh = dojo.connect(dialog, "onLoad",
function() {
dojo.disconnect(lh);
var title = $("PTITLE-FULL-" + active_post_id);
if (title) {
$("filterDlg_regExp").value = title.innerHTML;
}
});
} catch (e) {
exception_error("quickAddFilter", e);
}

View File

@ -136,9 +136,18 @@ function editFilter(id) {
id: "filterEditDlg",
title: __("Edit Filter"),
style: "width: 600px",
editRule: function(e) {
var li = e.parentNode;
var rule = li.getElementsByTagName("INPUT")[1].value;
addFilterRule(li, rule);
},
editAction: function(e) {
var li = e.parentNode;
var action = li.getElementsByTagName("INPUT")[1].value;
addFilterAction(li, action);
},
removeFilter: function() {
var title = this.attr('value').reg_exp;
var msg = __("Remove filter %s?").replace("%s", title);
var msg = __("Remove filter?");
if (confirm(msg)) {
this.hide();
@ -157,57 +166,29 @@ function editFilter(id) {
} });
}
},
test: function() {
if (this.validate()) {
if (dijit.byId("filterTestDlg"))
dijit.byId("filterTestDlg").destroyRecursive();
tdialog = new dijit.Dialog({
id: "filterTestDlg",
title: __("Filter Test Results"),
style: "width: 600px",
href: "backend.php?savemode=test&" +
dojo.objectToQuery(dialog.attr('value')),
});
tdialog.show();
}
addAction: function() { addFilterAction(); },
addRule: function() { addFilterRule(); },
deleteAction: function() {
$$("#filterDlg_Actions li.[class*=Selected]").each(function(e) { e.parentNode.removeChild(e) });
},
deleteRule: function() {
$$("#filterDlg_Matches li.[class*=Selected]").each(function(e) { e.parentNode.removeChild(e) });
},
execute: function() {
if (this.validate()) {
var query = "?op=rpc&method=verifyRegexp&reg_exp=" +
param_escape(dialog.attr('value').reg_exp);
notify_progress("Saving data...", true);
notify_progress("Verifying regular expression...");
var query = dojo.formToQuery("filter_edit_form");
new Ajax.Request("backend.php", {
console.log(query);
new Ajax.Request("backend.php", {
parameters: query,
onComplete: function(transport) {
var reply = JSON.parse(transport.responseText);
if (reply) {
notify('');
if (!reply['status']) {
alert("Match regular expression seems to be invalid.");
return;
} else {
notify_progress("Saving data...", true);
console.log(dojo.objectToQuery(dialog.attr('value')));
new Ajax.Request("backend.php", {
parameters: dojo.objectToQuery(dialog.attr('value')),
onComplete: function(transport) {
dialog.hide();
updateFilterList();
}});
}
}
}});
dialog.hide();
updateFilterList();
}});
}
},
href: query});
@ -605,6 +586,31 @@ function editSelectedFilter() {
}
function joinSelectedFilters() {
var rows = getSelectedFilters();
if (rows.length == 0) {
alert(__("No filters are selected."));
return;
}
var ok = confirm(__("Combine selected filters?"));
if (ok) {
notify_progress("Joining filters...");
var query = "?op=pref-filters&method=join&ids="+
param_escape(rows.toString());
console.log(query);
new Ajax.Request("backend.php", {
parameters: query,
onComplete: function(transport) {
updateFilterList();
} });
}
}
function editSelectedFeed() {
var rows = getSelectedFeeds();

View File

@ -9,6 +9,9 @@ drop table if exists ttrss_labels2;
drop table if exists ttrss_feedbrowser_cache;
drop table if exists ttrss_version;
drop table if exists ttrss_labels;
drop table if exists ttrss_filters2_actions;
drop table if exists ttrss_filters2_rules;
drop table if exists ttrss_filters2;
drop table if exists ttrss_filters;
drop table if exists ttrss_filter_types;
drop table if exists ttrss_filter_actions;
@ -259,6 +262,38 @@ create table ttrss_filters (id integer not null primary key auto_increment,
index (action_id),
foreign key (action_id) references ttrss_filter_actions(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
create table ttrss_filters2(id integer primary key auto_increment,
owner_uid integer not null,
match_any_rule boolean not null default false,
enabled boolean not null default true,
index(owner_uid),
foreign key (owner_uid) references ttrss_users(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
create table ttrss_filters2_rules(id integer primary key auto_increment,
filter_id integer not null references ttrss_filters2(id) on delete cascade,
reg_exp varchar(250) not null,
filter_type integer not null,
feed_id integer default null,
cat_id integer default null,
cat_filter boolean not null default false,
index (filter_id),
foreign key (filter_id) references ttrss_filters2(id) on delete cascade,
index (filter_type),
foreign key (filter_type) references ttrss_filter_types(id) ON DELETE CASCADE,
index (feed_id),
foreign key (feed_id) references ttrss_feeds(id) ON DELETE CASCADE,
index (cat_id),
foreign key (cat_id) references ttrss_feed_categories(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
create table ttrss_filters2_actions(id integer primary key auto_increment,
filter_id integer not null,
action_id integer not null default 1 references ttrss_filter_actions(id) on delete cascade,
action_param varchar(250) not null default '',
index (filter_id),
foreign key (filter_id) references ttrss_filters2(id) on delete cascade,
index (action_id),
foreign key (action_id) references ttrss_filter_actions(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
create table ttrss_tags (id integer primary key auto_increment,
owner_uid integer not null,
tag_name varchar(250) not null,
@ -270,7 +305,7 @@ create table ttrss_tags (id integer primary key auto_increment,
create table ttrss_version (schema_version int not null) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
insert into ttrss_version values (95);
insert into ttrss_version values (96);
create table ttrss_enclosures (id integer primary key auto_increment,
content_url text not null,

View File

@ -6,6 +6,9 @@ drop table if exists ttrss_labels2;
drop table if exists ttrss_feedbrowser_cache;
drop table if exists ttrss_version;
drop table if exists ttrss_labels;
drop table if exists ttrss_filters2_rules;
drop table if exists ttrss_filters2_actions;
drop table if exists ttrss_filters2;
drop table if exists ttrss_filters;
drop table if exists ttrss_filter_types;
drop table if exists ttrss_filter_actions;
@ -222,6 +225,24 @@ create table ttrss_filters (id serial not null primary key,
action_id integer not null default 1 references ttrss_filter_actions(id) on delete cascade,
action_param varchar(250) not null default '');
create table ttrss_filters2(id serial not null primary key,
owner_uid integer not null references ttrss_users(id) on delete cascade,
match_any_rule boolean not null default false,
enabled boolean not null default true);
create table ttrss_filters2_rules(id serial not null primary key,
filter_id integer not null references ttrss_filters2(id) on delete cascade,
reg_exp varchar(250) not null,
filter_type integer not null references ttrss_filter_types(id),
feed_id integer references ttrss_feeds(id) on delete cascade default null,
cat_id integer references ttrss_feed_categories(id) on delete cascade default null,
cat_filter boolean not null default false);
create table ttrss_filters2_actions(id serial not null primary key,
filter_id integer not null references ttrss_filters2(id) on delete cascade,
action_id integer not null default 1 references ttrss_filter_actions(id) on delete cascade,
action_param varchar(250) not null default '');
create table ttrss_tags (id serial not null primary key,
tag_name varchar(250) not null,
owner_uid integer not null references ttrss_users(id) on delete cascade,
@ -232,7 +253,7 @@ create index ttrss_tags_post_int_id_idx on ttrss_tags(post_int_id);
create table ttrss_version (schema_version int not null);
insert into ttrss_version values (95);
insert into ttrss_version values (96);
create table ttrss_enclosures (id serial not null primary key,
content_url text not null,

View File

@ -0,0 +1,38 @@
begin;
create table ttrss_filters2(id integer primary key auto_increment,
owner_uid integer not null,
match_any_rule boolean not null default false,
enabled boolean not null default true,
index(owner_uid),
foreign key (owner_uid) references ttrss_users(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
create table ttrss_filters2_rules(id integer primary key auto_increment,
filter_id integer not null references ttrss_filters2(id) on delete cascade,
reg_exp varchar(250) not null,
filter_type integer not null,
feed_id integer default null,
cat_id integer default null,
cat_filter boolean not null default false,
index (filter_id),
foreign key (filter_id) references ttrss_filters2(id) on delete cascade,
index (filter_type),
foreign key (filter_type) references ttrss_filter_types(id) ON DELETE CASCADE,
index (feed_id),
foreign key (feed_id) references ttrss_feeds(id) ON DELETE CASCADE,
index (cat_id),
foreign key (cat_id) references ttrss_feed_categories(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
create table ttrss_filters2_actions(id integer primary key auto_increment,
filter_id integer not null,
action_id integer not null default 1 references ttrss_filter_actions(id) on delete cascade,
action_param varchar(250) not null default '',
index (filter_id),
foreign key (filter_id) references ttrss_filters2(id) on delete cascade,
index (action_id),
foreign key (action_id) references ttrss_filter_actions(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
update ttrss_version set schema_version = 96;
commit;

View File

@ -0,0 +1,23 @@
begin;
create table ttrss_filters2(id serial not null primary key,
owner_uid integer not null references ttrss_users(id) on delete cascade,
match_any_rule boolean not null default false,
enabled boolean not null default true);
create table ttrss_filters2_rules(id serial not null primary key,
filter_id integer not null references ttrss_filters2(id) on delete cascade,
reg_exp varchar(250) not null,
filter_type integer not null references ttrss_filter_types(id),
feed_id integer references ttrss_feeds(id) on delete cascade default null,
cat_id integer references ttrss_feed_categories(id) on delete cascade default null,
cat_filter boolean not null default false);
create table ttrss_filters2_actions(id serial not null primary key,
filter_id integer not null references ttrss_filters2(id) on delete cascade,
action_id integer not null default 1 references ttrss_filter_actions(id) on delete cascade,
action_param varchar(250) not null default '');
update ttrss_version set schema_version = 95;
commit;

View File

@ -1426,3 +1426,19 @@ div.dialogNotice {
margin-bottom : 5px;
color : gray;
}
ul#filterDlg_Matches, ul#filterDlg_Actions {
max-height : 100px;
overflow : auto;
list-style-type : none;
border-style : solid;
border-color : #c0c0c0;
border-width : 0px 1px 1px 1px;
background-color : #ecf4ff;
margin : 0px 0px 5px 0px;
padding : 0px;
}
ul#filterDlg_Matches li, ul#filterDlg_Actions li {
cursor : pointer;
}

View File

@ -51,6 +51,7 @@
print " -update-self - update tt-rss installation to latest version\n";
print " -quiet - don't show messages\n";
print " -indexes - recreate missing schema indexes\n";
print " -convert-filters - convert type1 filters to type2\n";
print " -help - show this help\n";
return;
}
@ -237,6 +238,54 @@
update_self($link, in_array("-force", $op));
}
if (in_array("-convert-filters", $op)) {
_debug("WARNING: this will remove all existing type2 filters.");
_debug("Type 'yes' to continue.");
if (read_stdin() != 'yes')
exit;
_debug("converting filters...");
db_query($link, "DELETE FROM ttrss_filters2");
$result = db_query($link, "SELECT * FROM ttrss_filters ORDER BY id");
while ($line = db_fetch_assoc($result)) {
$owner_uid = $line["owner_uid"];
$filter = array();
if (sql_bool_to_bool($line["cat_filter"])) {
$feed_id = "CAT:" . (int)$line["cat_id"];
} else {
$feed_id = (int)$line["feed_id"];
}
$filter["enabled"] = $line["enabled"] ? "on" : "off";
$filter["rule"] = array(
json_encode(array(
"reg_exp" => $line["reg_exp"],
"feed_id" => $feed_id,
"filter_type" => $line["filter_type"])));
$filter["action"] = array(
json_encode(array(
"action_id" => $line["action_id"],
"action_param_label" => $line["action_param"],
"action_param" => $line["action_param"])));
// Oh god it's full of hacks
$_REQUEST = $filter;
$_SESSION["uid"] = $owner_uid;
$filters = new Pref_Filters($link, $_REQUEST);
$filters->add();
}
}
db_close($link);
if ($lock_handle != false) {