mirror of
https://github.com/FreshRSS/FreshRSS.git
synced 2025-12-23 21:47:44 -05:00
Rework encoding of search filters (#8324)
Rework: * https://github.com/FreshRSS/FreshRSS/pull/8222 now that we have: * https://github.com/FreshRSS/FreshRSS/pull/8293 Follow-up of: * https://github.com/FreshRSS/FreshRSS/pull/8311 * More simplification * Deprecate getRawInput
This commit is contained in:
committed by
GitHub
parent
6952a13958
commit
4bd5035914
@@ -110,7 +110,7 @@ class FreshRSS_category_Controller extends FreshRSS_ActionController {
|
||||
$category->_attribute('read_when_same_title_in_category', null);
|
||||
}
|
||||
|
||||
$category->_filtersAction('read', Minz_Request::paramTextToArray('filteractions_read')); // Keep as HTML
|
||||
$category->_filtersAction('read', Minz_Request::paramTextToArray('filteractions_read', plaintext: true));
|
||||
|
||||
if (Minz_Request::paramBoolean('use_default_purge_options')) {
|
||||
$category->_attribute('archiving', null);
|
||||
|
||||
@@ -164,8 +164,8 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController {
|
||||
'site' => Minz_Request::paramBoolean('mark_open_site'),
|
||||
'focus' => Minz_Request::paramBoolean('mark_focus'),
|
||||
];
|
||||
FreshRSS_Context::userConf()->_filtersAction('read', Minz_Request::paramTextToArray('filteractions_read')); // Keep as HTML
|
||||
FreshRSS_Context::userConf()->_filtersAction('star', Minz_Request::paramTextToArray('filteractions_star')); // Keep as HTML
|
||||
FreshRSS_Context::userConf()->_filtersAction('read', Minz_Request::paramTextToArray('filteractions_read', plaintext: true));
|
||||
FreshRSS_Context::userConf()->_filtersAction('star', Minz_Request::paramTextToArray('filteractions_star', plaintext: true));
|
||||
FreshRSS_Context::userConf()->save();
|
||||
invalidateHttpCache();
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController {
|
||||
};
|
||||
$searchString = $operator . ':' . ($offset < 0 ? '/' : '') . date('Y-m-d', $timestamp + ($offset * 86400)) . ($offset > 0 ? '/' : '');
|
||||
return Minz_Url::display(Minz_Request::modifiedCurrentRequest([
|
||||
'search' => FreshRSS_Context::$search->getRawInput() === '' ? $searchString :
|
||||
'search' => FreshRSS_Context::$search->__toString() === '' ? $searchString :
|
||||
FreshRSS_Context::$search->enforce(new FreshRSS_Search($searchString))->__toString(),
|
||||
]));
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ class FreshRSS_subscription_Controller extends FreshRSS_ActionController {
|
||||
]);
|
||||
}
|
||||
|
||||
$feed->_filtersAction('read', Minz_Request::paramTextToArray('filteractions_read')); // Keep as HTML
|
||||
$feed->_filtersAction('read', Minz_Request::paramTextToArray('filteractions_read', plaintext: true));
|
||||
|
||||
$feed->_kind(Minz_Request::paramInt('feed_kind') ?: FreshRSS_Feed::KIND_RSS);
|
||||
if ($feed->kind() === FreshRSS_Feed::KIND_HTML_XPATH || $feed->kind() === FreshRSS_Feed::KIND_XML_XPATH) {
|
||||
@@ -418,17 +418,22 @@ class FreshRSS_subscription_Controller extends FreshRSS_ActionController {
|
||||
$filteractions = Minz_Request::paramTextToArray('filteractions_read', plaintext: true);
|
||||
$filteractions = array_map(fn(string $action): string => trim($action), $filteractions);
|
||||
$filteractions = array_filter($filteractions, fn(string $action): bool => $action !== '');
|
||||
$search = "f:$id (";
|
||||
$actionsSearch = new FreshRSS_BooleanSearch('', operator: 'AND');
|
||||
foreach ($filteractions as $action) {
|
||||
$search .= "($action) OR ";
|
||||
$actionSearch = new FreshRSS_BooleanSearch($action, operator: 'OR');
|
||||
if ($actionSearch->__toString() === '') {
|
||||
continue;
|
||||
}
|
||||
$actionsSearch->add($actionSearch);
|
||||
}
|
||||
$search = preg_replace('/ OR $/', '', $search);
|
||||
$search .= ')';
|
||||
$search = new FreshRSS_BooleanSearch('');
|
||||
$search->add(new FreshRSS_Search("f:$id"));
|
||||
$search->add($actionsSearch);
|
||||
Minz_Request::forward([
|
||||
'c' => 'index',
|
||||
'a' => 'index',
|
||||
'params' => [
|
||||
'search' => $search,
|
||||
'search' => $search->__toString(),
|
||||
],
|
||||
], redirect: true);
|
||||
}
|
||||
|
||||
@@ -525,6 +525,7 @@ class FreshRSS_BooleanSearch implements \Stringable {
|
||||
}
|
||||
|
||||
/** @return string Plain text search query. Must be XML-encoded or URL-encoded depending on the situation */
|
||||
#[Deprecated('Use __tostring() instead')]
|
||||
public function getRawInput(): string {
|
||||
return $this->raw_input;
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@ class FreshRSS_FilterAction {
|
||||
}
|
||||
}
|
||||
|
||||
/** @return array{'search'?:string,'actions'?:array<string>} */
|
||||
/** @return array{search?:string,actions?:array<string>} */
|
||||
public function toJSON(): array {
|
||||
if (is_array($this->actions) && $this->booleanSearch != null) {
|
||||
return [
|
||||
'search' => $this->booleanSearch->getRawInput(),
|
||||
'search' => $this->booleanSearch->__toString(),
|
||||
'actions' => $this->actions,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -71,8 +71,7 @@ trait FreshRSS_FilterActionsTrait {
|
||||
//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()) == '') {
|
||||
if ($filterAction === null || !is_array($filterAction->actions()) || $filterAction->booleanSearch()->__toString() === '') {
|
||||
array_splice($filterActions, $i, 1);
|
||||
continue;
|
||||
}
|
||||
@@ -86,7 +85,7 @@ trait FreshRSS_FilterActionsTrait {
|
||||
//Update existing filter with new action
|
||||
for ($k = count($filters) - 1; $k >= 0; $k--) {
|
||||
$filter = $filters[$k];
|
||||
if ($filter === $filterAction->booleanSearch()->getRawInput()) {
|
||||
if ($filter === $filterAction->booleanSearch()->__toString()) {
|
||||
$actions[] = $action;
|
||||
array_splice($filters, $k, 1);
|
||||
}
|
||||
|
||||
@@ -452,6 +452,7 @@ class FreshRSS_Search implements \Stringable {
|
||||
return trim($result);
|
||||
}
|
||||
|
||||
#[Deprecated('Use __tostring() instead')]
|
||||
public function getRawInput(): string {
|
||||
return $this->raw_input;
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ class FreshRSS_UserQuery {
|
||||
'get' => $this->get,
|
||||
'name' => $this->name,
|
||||
'order' => $this->order,
|
||||
'search' => $this->search->getRawInput(),
|
||||
'search' => $this->search->__toString(),
|
||||
'state' => $this->state,
|
||||
'url' => $this->url,
|
||||
'token' => $this->token,
|
||||
@@ -221,7 +221,7 @@ class FreshRSS_UserQuery {
|
||||
* Check if there is a search in the search object
|
||||
*/
|
||||
public function hasSearch(): bool {
|
||||
return $this->search->getRawInput() !== '';
|
||||
return $this->search->__toString() !== '';
|
||||
}
|
||||
|
||||
public function getGet(): string {
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
|
||||
<div id="dropdown-search" class="dropdown-target"></div>
|
||||
|
||||
<a id="toggle-search" class="dropdown-toggle btn<?= (strlen(FreshRSS_Context::$search->getRawInput()) > 0) ? ' active' : ''; ?>" title="<?= _t('gen.menu.search') ?>"
|
||||
<a id="toggle-search" class="dropdown-toggle btn<?= FreshRSS_Context::$search->__toString() !== '' ? ' active' : ''; ?>" title="<?= _t('gen.menu.search') ?>"
|
||||
href="#dropdown-search"><?= _i('search') ?></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="item">
|
||||
@@ -56,7 +56,7 @@
|
||||
<?php } ?>
|
||||
<div class="stick search">
|
||||
<input type="search" name="search"
|
||||
value="<?= htmlspecialchars(htmlspecialchars_decode(FreshRSS_Context::$search->getRawInput(), ENT_QUOTES), ENT_COMPAT, 'UTF-8'); ?>"
|
||||
value="<?= htmlspecialchars(FreshRSS_Context::$search->__toString(), ENT_COMPAT, 'UTF-8') ?>"
|
||||
placeholder="<?= _t('gen.menu.search') ?>" title="<?= _t('gen.menu.search') ?>" /><button class="btn" type="submit" title="<?= _t('index.menu.search_short') ?>"><?= _i('search') ?></button>
|
||||
</div>
|
||||
<p class="help"><?= _i('help') ?> <a href="<?= _url('search', 'index') ?>"><?= _t('gen.menu.advanced_search') ?></a></p>
|
||||
@@ -121,7 +121,7 @@
|
||||
'get' => $get,
|
||||
'nextGet' => FreshRSS_Context::$next_get,
|
||||
'idMax' => FreshRSS_Context::$id_max,
|
||||
'search' => htmlspecialchars_decode(FreshRSS_Context::$search->getRawInput(), ENT_QUOTES),
|
||||
'search' => FreshRSS_Context::$search->__toString(),
|
||||
'state' => FreshRSS_Context::$state,
|
||||
'sort' => FreshRSS_Context::$sort,
|
||||
'order' => FreshRSS_Context::$order,
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<input type="hidden" id="queries_<?= $key ?>_shareRss" name="queries[<?= $key ?>][shareRss]" value="<?= $query->shareRss() ? '1' : '0' ?>"/>
|
||||
<input type="hidden" id="queries_<?= $key ?>_shareOpml" name="queries[<?= $key ?>][shareOpml]" value="<?= $query->shareOpml() ? '1' : '0' ?>"/>
|
||||
<input type="hidden" id="queries_<?= $key ?>_url" name="queries[<?= $key ?>][url]" value="<?= $query->getUrl() ?>"/>
|
||||
<input type="hidden" id="queries_<?= $key ?>_search" name="queries[<?= $key ?>][search]" value="<?= urlencode($query->getSearch()->getRawInput()) ?>"/>
|
||||
<input type="hidden" id="queries_<?= $key ?>_search" name="queries[<?= $key ?>][search]" value="<?= urlencode($query->getSearch()->__toString()) ?>"/>
|
||||
<input type="hidden" id="queries_<?= $key ?>_state" name="queries[<?= $key ?>][state]" value="<?= $query->getState() ?>"/>
|
||||
<input type="hidden" id="queries_<?= $key ?>_order" name="queries[<?= $key ?>][order]" value="<?= $query->getOrder() ?>"/>
|
||||
<input type="hidden" id="queries_<?= $key ?>_get" name="queries[<?= $key ?>][get]" value="<?= $query->getGet() ?>"/>
|
||||
@@ -44,7 +44,7 @@
|
||||
<?php } else { ?>
|
||||
<ul class="box-content scrollbar-thin">
|
||||
<?php if ($query->hasSearch()) { ?>
|
||||
<li class="item"><?= _t('conf.query.search', htmlspecialchars($query->getSearch()->getRawInput(), ENT_NOQUOTES, 'UTF-8')) ?></li>
|
||||
<li class="item"><?= _t('conf.query.search', htmlspecialchars($query->getSearch()->__toString(), ENT_NOQUOTES, 'UTF-8')) ?></li>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($query->getState()) { ?>
|
||||
|
||||
@@ -349,7 +349,7 @@
|
||||
<div class="group-controls">
|
||||
<textarea name="filteractions_read" id="filteractions_read" class="w100"><?php
|
||||
foreach (FreshRSS_Context::userConf()->filtersAction('read') as $filterRead) {
|
||||
echo $filterRead->getRawInput(), PHP_EOL;
|
||||
echo htmlspecialchars($filterRead->__toString(), ENT_NOQUOTES, 'UTF-8'), PHP_EOL;
|
||||
}
|
||||
?></textarea>
|
||||
<p class="help"><?= _i('help') ?> <?= _t('sub.feed.filteractions.help') ?></p>
|
||||
@@ -366,7 +366,7 @@
|
||||
<div class="group-controls">
|
||||
<textarea name="filteractions_star" id="filteractions_star" class="w100"><?php
|
||||
foreach (FreshRSS_Context::userConf()->filtersAction('star') as $filterStar) {
|
||||
echo $filterStar->getRawInput(), PHP_EOL;
|
||||
echo htmlspecialchars($filterStar->__toString(), ENT_NOQUOTES, 'UTF-8'), PHP_EOL;
|
||||
}
|
||||
?></textarea>
|
||||
<p class="help"><?= _i('help') ?> <?= _t('sub.feed.filteractions.help') ?></p>
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
<div class="group-controls">
|
||||
<textarea name="filteractions_read" id="filteractions_read" class="w100"><?php
|
||||
foreach ($this->category->filtersAction('read') as $filterRead) {
|
||||
echo $filterRead->getRawInput(), PHP_EOL;
|
||||
echo htmlspecialchars($filterRead->__toString(), ENT_NOQUOTES, 'UTF-8'), PHP_EOL;
|
||||
}
|
||||
?></textarea>
|
||||
<p class="help"><?= _i('help') ?> <?= _t('sub.feed.filteractions.help') ?></p>
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
<div class="form-group">
|
||||
<label class="group-name" for=""><?= _t('conf.query.filter.search') ?></label>
|
||||
<div class="group-controls">
|
||||
<input type="text" class="w100" id="query_search" name="query[search]" value="<?= htmlspecialchars($this->query->getSearch()->getRawInput(), ENT_COMPAT, 'UTF-8') ?>"/>
|
||||
<input type="text" class="w100" id="query_search" name="query[search]" value="<?= htmlspecialchars($this->query->getSearch()->__toString(), ENT_COMPAT, 'UTF-8') ?>"/>
|
||||
<p class="help"><?= _i('help') ?> <?= _t('gen.menu.search_help') ?></a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -89,7 +89,7 @@ function feedsToOutlines(array $feeds, bool $excludeMutedFeeds = false): array {
|
||||
if (!empty($feed->filtersAction('read'))) {
|
||||
$filters = '';
|
||||
foreach ($feed->filtersAction('read') as $filterRead) {
|
||||
$filters .= $filterRead->getRawInput() . "\n";
|
||||
$filters .= $filterRead->__toString() . "\n";
|
||||
}
|
||||
$filters = trim($filters);
|
||||
$outline['frss:filtersActionRead'] = $filters;
|
||||
|
||||
@@ -304,7 +304,7 @@
|
||||
<textarea name="filteractions_read" id="filteractions_read" class="w100"
|
||||
placeholder="<?= _t('gen.short.blank_to_disable') ?>"><?php
|
||||
foreach ($this->feed->filtersAction('read') as $filterRead) {
|
||||
echo $filterRead->getRawInput(), PHP_EOL;
|
||||
echo htmlspecialchars($filterRead->__toString(), ENT_NOQUOTES, 'UTF-8'), PHP_EOL;
|
||||
}
|
||||
?></textarea>
|
||||
<p class="help"><?= _i('help') ?> <?= _t('sub.feed.filteractions.help') ?></p>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
'get' => FreshRSS_Context::currentGet(),
|
||||
'nextGet' => FreshRSS_Context::$next_get,
|
||||
'idMax' => FreshRSS_Context::$id_max,
|
||||
'search' => htmlspecialchars_decode(FreshRSS_Context::$search->getRawInput(), ENT_QUOTES),
|
||||
'search' => FreshRSS_Context::$search->__toString(),
|
||||
'state' => FreshRSS_Context::$state,
|
||||
'sort' => FreshRSS_Context::$sort,
|
||||
'order' => FreshRSS_Context::$order,
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<div class="group-controls">
|
||||
<textarea name="filteractions_label" id="filteractions_label" class="w100"><?php
|
||||
foreach ($this->tag->filtersAction('label') as $filterRead) {
|
||||
echo $filterRead->getRawInput(), PHP_EOL;
|
||||
echo htmlspecialchars($filterRead->__toString(), ENT_NOQUOTES, 'UTF-8') . PHP_EOL;
|
||||
}
|
||||
?></textarea>
|
||||
<p class="help"><?= _i('help') ?> <?= _t('sub.feed.filteractions.help') ?></p>
|
||||
|
||||
@@ -117,7 +117,7 @@ $view = new FreshRSS_View();
|
||||
|
||||
try {
|
||||
FreshRSS_Context::updateUsingRequest(false);
|
||||
Minz_Request::_param('search', $userSearch->getRawInput()); // Restore user search
|
||||
Minz_Request::_param('search', $userSearch->__toString()); // Restore user search
|
||||
$view->entries = FreshRSS_index_Controller::listEntriesByContext();
|
||||
} catch (Minz_Exception) {
|
||||
Minz_Error::error(400, 'Bad user query!');
|
||||
|
||||
@@ -10,7 +10,7 @@ final class SearchTest extends \PHPUnit\Framework\TestCase {
|
||||
#[DataProvider('provideEmptyInput')]
|
||||
public static function test__construct_whenInputIsEmpty_getsOnlyNullValues(string $input): void {
|
||||
$search = new FreshRSS_Search($input);
|
||||
self::assertSame('', $search->getRawInput());
|
||||
self::assertSame('', $search->__toString());
|
||||
self::assertNull($search->getIntitle());
|
||||
self::assertNull($search->getMinDate());
|
||||
self::assertNull($search->getMaxDate());
|
||||
@@ -327,7 +327,6 @@ final class SearchTest extends \PHPUnit\Framework\TestCase {
|
||||
self::assertSame($max_pubdate_value, $search->getMaxPubdate());
|
||||
self::assertSame($tags_value, $search->getTags());
|
||||
self::assertSame($search_value, $search->getSearch());
|
||||
self::assertSame($input, $search->getRawInput());
|
||||
}
|
||||
|
||||
/** @return list<list<mixed>> */
|
||||
@@ -1033,7 +1032,9 @@ final class SearchTest extends \PHPUnit\Framework\TestCase {
|
||||
*/
|
||||
public static function provideBooleanSearchEnforce(): array {
|
||||
return [
|
||||
['', '', ''],
|
||||
['', 'intitle:b', 'intitle:b'],
|
||||
['intitle:a', '', 'intitle:a'],
|
||||
['intitle:a', 'intitle:b', 'intitle:b'],
|
||||
['a', 'intitle:b', 'intitle:b a'],
|
||||
['intitle:a intext:a', 'intitle:b', 'intitle:b intext:a'],
|
||||
|
||||
Reference in New Issue
Block a user