Browse Source

Move mod/search to src/Module/Search/Index

- Update BaseSeachModule not to depend on a single query string parameter
pull/7714/head
Hypolite Petovan 1 week ago
parent
commit
1e737ae888

+ 0
- 194
mod/search.php View File

@@ -1,194 +0,0 @@
1
-<?php
2
-/**
3
- * @file mod/search.php
4
- */
5
-
6
-use Friendica\App;
7
-use Friendica\Content\Nav;
8
-use Friendica\Content\Pager;
9
-use Friendica\Content\Text\HTML;
10
-use Friendica\Core\Cache;
11
-use Friendica\Core\Config;
12
-use Friendica\Core\L10n;
13
-use Friendica\Core\Logger;
14
-use Friendica\Core\Session;
15
-use Friendica\Core\Renderer;
16
-use Friendica\Database\DBA;
17
-use Friendica\Model\Item;
18
-use Friendica\Module\BaseSearchModule;
19
-use Friendica\Util\Strings;
20
-
21
-function search_init(App $a) {
22
-	$search = (!empty($_GET['q']) ? Strings::escapeTags(trim(rawurldecode($_GET['q']))) : '');
23
-
24
-	if (local_user()) {
25
-		/// @todo Check if there is a case at all that "aside" is prefilled here
26
-		if (!isset($a->page['aside'])) {
27
-			$a->page['aside'] = '';
28
-		}
29
-
30
-		$a->page['aside'] .= \Friendica\Content\Widget\SavedSearches::getHTML('search?q=' . $search, $search);
31
-	}
32
-}
33
-
34
-function search_content(App $a) {
35
-	if (Config::get('system','block_public') && !Session::isAuthenticated()) {
36
-		notice(L10n::t('Public access denied.') . EOL);
37
-		return;
38
-	}
39
-
40
-	if (Config::get('system','local_search') && !Session::isAuthenticated()) {
41
-		$e = new \Friendica\Network\HTTPException\ForbiddenException(L10n::t("Only logged in users are permitted to perform a search."));
42
-		$e->httpdesc = L10n::t("Public access denied.");
43
-		throw $e;
44
-	}
45
-
46
-	if (Config::get('system','permit_crawling') && !Session::isAuthenticated()) {
47
-		// Default values:
48
-		// 10 requests are "free", after the 11th only a call per minute is allowed
49
-
50
-		$free_crawls = intval(Config::get('system','free_crawls'));
51
-		if ($free_crawls == 0)
52
-			$free_crawls = 10;
53
-
54
-		$crawl_permit_period = intval(Config::get('system','crawl_permit_period'));
55
-		if ($crawl_permit_period == 0)
56
-			$crawl_permit_period = 10;
57
-
58
-		$remote = $_SERVER["REMOTE_ADDR"];
59
-		$result = Cache::get("remote_search:".$remote);
60
-		if (!is_null($result)) {
61
-			$resultdata = json_decode($result);
62
-			if (($resultdata->time > (time() - $crawl_permit_period)) && ($resultdata->accesses > $free_crawls)) {
63
-				throw new \Friendica\Network\HTTPException\TooManyRequestsException(L10n::t("Only one search per minute is permitted for not logged in users."));
64
-			}
65
-			Cache::set("remote_search:".$remote, json_encode(["time" => time(), "accesses" => $resultdata->accesses + 1]), Cache::HOUR);
66
-		} else
67
-			Cache::set("remote_search:".$remote, json_encode(["time" => time(), "accesses" => 1]), Cache::HOUR);
68
-	}
69
-
70
-	Nav::setSelected('search');
71
-
72
-	$search = (!empty($_REQUEST['q']) ? Strings::escapeTags(trim(rawurldecode($_REQUEST['q']))) : '');
73
-
74
-	$tag = false;
75
-	if (!empty($_GET['tag'])) {
76
-		$tag = true;
77
-		$search = (!empty($_GET['tag']) ? '#' . Strings::escapeTags(trim(rawurldecode($_GET['tag']))) : '');
78
-	}
79
-
80
-	// contruct a wrapper for the search header
81
-	$o = Renderer::replaceMacros(Renderer::getMarkupTemplate("content_wrapper.tpl"),[
82
-		'name' => "search-header",
83
-		'$title' => L10n::t("Search"),
84
-		'$title_size' => 3,
85
-		'$content' => HTML::search($search,'search-box',false)
86
-	]);
87
-
88
-	if (strpos($search,'#') === 0) {
89
-		$tag = true;
90
-		$search = substr($search,1);
91
-	}
92
-	if (strpos($search,'@') === 0) {
93
-		return BaseSearchModule::performSearch();
94
-	}
95
-	if (strpos($search,'!') === 0) {
96
-		return BaseSearchModule::performSearch();
97
-	}
98
-
99
-	if (parse_url($search, PHP_URL_SCHEME) != '') {
100
-		$id = Item::fetchByLink($search);
101
-		if (!empty($id)) {
102
-			$item = Item::selectFirst(['guid'], ['id' => $id]);
103
-			if (DBA::isResult($item)) {
104
-				$a->internalRedirect('display/' . $item['guid']);
105
-			}
106
-		}
107
-	}
108
-
109
-	if (!empty($_GET['search-option']))
110
-		switch($_GET['search-option']) {
111
-			case 'fulltext':
112
-				break;
113
-			case 'tags':
114
-				$tag = true;
115
-				break;
116
-			case 'contacts':
117
-				return BaseSearchModule::performSearch('@');
118
-			case 'forums':
119
-				return BaseSearchModule::performSearch('!');
120
-		}
121
-
122
-	if (!$search)
123
-		return $o;
124
-
125
-	if (Config::get('system','only_tag_search'))
126
-		$tag = true;
127
-
128
-	// Here is the way permissions work in the search module...
129
-	// Only public posts can be shown
130
-	// OR your own posts if you are a logged in member
131
-	// No items will be shown if the member has a blocked profile wall.
132
-
133
-	$pager = new Pager($a->query_string);
134
-
135
-	if ($tag) {
136
-		Logger::log("Start tag search for '".$search."'", Logger::DEBUG);
137
-
138
-		$condition = ["(`uid` = 0 OR (`uid` = ? AND NOT `global`))
139
-			AND `otype` = ? AND `type` = ? AND `term` = ?",
140
-			local_user(), TERM_OBJ_POST, TERM_HASHTAG, $search];
141
-		$params = ['order' => ['received' => true],
142
-			'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
143
-		$terms = DBA::select('term', ['oid'], $condition, $params);
144
-
145
-		$itemids = [];
146
-		while ($term = DBA::fetch($terms)) {
147
-			$itemids[] = $term['oid'];
148
-		}
149
-		DBA::close($terms);
150
-
151
-		if (!empty($itemids)) {
152
-			$params = ['order' => ['id' => true]];
153
-			$items = Item::selectForUser(local_user(), [], ['id' => $itemids], $params);
154
-			$r = Item::inArray($items);
155
-		} else {
156
-			$r = [];
157
-		}
158
-	} else {
159
-		Logger::log("Start fulltext search for '".$search."'", Logger::DEBUG);
160
-
161
-		$condition = ["(`uid` = 0 OR (`uid` = ? AND NOT `global`))
162
-			AND `body` LIKE CONCAT('%',?,'%')",
163
-			local_user(), $search];
164
-		$params = ['order' => ['id' => true],
165
-			'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
166
-		$items = Item::selectForUser(local_user(), [], $condition, $params);
167
-		$r = Item::inArray($items);
168
-	}
169
-
170
-	if (!DBA::isResult($r)) {
171
-		info(L10n::t('No results.') . EOL);
172
-		return $o;
173
-	}
174
-
175
-
176
-	if ($tag) {
177
-		$title = L10n::t('Items tagged with: %s', $search);
178
-	} else {
179
-		$title = L10n::t('Results for: %s', $search);
180
-	}
181
-
182
-	$o .= Renderer::replaceMacros(Renderer::getMarkupTemplate("section_title.tpl"),[
183
-		'$title' => $title
184
-	]);
185
-
186
-	Logger::log("Start Conversation for '".$search."'", Logger::DEBUG);
187
-	$o .= conversation($a, $r, $pager, 'search', false, false, 'commented', local_user());
188
-
189
-	$o .= $pager->renderMinimal(count($r));
190
-
191
-	Logger::log("Done '".$search."'", Logger::DEBUG);
192
-
193
-	return $o;
194
-}

+ 4
- 3
src/Module/BaseSearchModule.php View File

@@ -23,13 +23,14 @@ class BaseSearchModule extends BaseModule
23 23
 	/**
24 24
 	 * Performs a search with an optional prefix
25 25
 	 *
26
+	 * @param string $search Search query
26 27
 	 * @param string $prefix A optional prefix (e.g. @ or !) for searching
27 28
 	 *
28 29
 	 * @return string
29 30
 	 * @throws HTTPException\InternalServerErrorException
30 31
 	 * @throws \ImagickException
31 32
 	 */
32
-	public static function performSearch($prefix = '')
33
+	public static function performSearch($search, $prefix = '')
33 34
 	{
34 35
 		$a      = self::getApp();
35 36
 		$config = $a->getConfig();
@@ -38,7 +39,7 @@ class BaseSearchModule extends BaseModule
38 39
 
39 40
 		$localSearch = $config->get('system', 'poco_local_search');
40 41
 
41
-		$search = $prefix . Strings::escapeTags(trim(defaults($_REQUEST, 'search', '')));
42
+		$search = $prefix . $search;
42 43
 
43 44
 		if (!$search) {
44 45
 			return '';
@@ -62,7 +63,7 @@ class BaseSearchModule extends BaseModule
62 63
 			$header = L10n::t('Forum Search - %s', $search);
63 64
 		}
64 65
 
65
-		$pager = new Pager($a->query_string);
66
+		$pager = new Pager(self::getArgs()->getQueryString());
66 67
 
67 68
 		if ($localSearch && empty($results)) {
68 69
 			$pager->setItemsPerPage(80);

+ 4
- 1
src/Module/Search/Directory.php View File

@@ -6,6 +6,7 @@ use Friendica\Content\Widget;
6 6
 use Friendica\Core\L10n;
7 7
 use Friendica\Module\BaseSearchModule;
8 8
 use Friendica\Module\Login;
9
+use Friendica\Util\Strings;
9 10
 
10 11
 /**
11 12
  * Directory search module
@@ -19,6 +20,8 @@ class Directory extends BaseSearchModule
19 20
 			return Login::form();
20 21
 		}
21 22
 
23
+		$search = Strings::escapeTags(trim(rawurldecode($_REQUEST['search'] ?? '')));
24
+
22 25
 		$a = self::getApp();
23 26
 
24 27
 		if (empty($a->page['aside'])) {
@@ -28,6 +31,6 @@ class Directory extends BaseSearchModule
28 31
 		$a->page['aside'] .= Widget::findPeople();
29 32
 		$a->page['aside'] .= Widget::follow();
30 33
 
31
-		return self::performSearch();
34
+		return self::performSearch($search);
32 35
 	}
33 36
 }

+ 198
- 0
src/Module/Search/Index.php View File

@@ -0,0 +1,198 @@
1
+<?php
2
+
3
+namespace Friendica\Module\Search;
4
+
5
+use Friendica\Content\Nav;
6
+use Friendica\Content\Pager;
7
+use Friendica\Content\Text\HTML;
8
+use Friendica\Content\Widget;
9
+use Friendica\Core\Cache;
10
+use Friendica\Core\Cache\Cache as CacheClass;
11
+use Friendica\Core\Config;
12
+use Friendica\Core\L10n;
13
+use Friendica\Core\Logger;
14
+use Friendica\Core\Renderer;
15
+use Friendica\Core\Session;
16
+use Friendica\Database\DBA;
17
+use Friendica\Model\Item;
18
+use Friendica\Model\Term;
19
+use Friendica\Module\BaseSearchModule;
20
+use Friendica\Network\HTTPException;
21
+use Friendica\Util\Strings;
22
+
23
+class Index extends BaseSearchModule
24
+{
25
+	public static function content()
26
+	{
27
+		$search = (!empty($_GET['q']) ? Strings::escapeTags(trim(rawurldecode($_GET['q']))) : '');
28
+
29
+		if (Config::get('system', 'block_public') && !Session::isAuthenticated()) {
30
+			throw new HTTPException\ForbiddenException(L10n::t('Public access denied.'));
31
+		}
32
+
33
+		if (Config::get('system', 'local_search') && !Session::isAuthenticated()) {
34
+			$e = new HTTPException\ForbiddenException(L10n::t('Only logged in users are permitted to perform a search.'));
35
+			$e->httpdesc = L10n::t('Public access denied.');
36
+			throw $e;
37
+		}
38
+
39
+		if (Config::get('system', 'permit_crawling') && !Session::isAuthenticated()) {
40
+			// Default values:
41
+			// 10 requests are "free", after the 11th only a call per minute is allowed
42
+
43
+			$free_crawls = intval(Config::get('system', 'free_crawls'));
44
+			if ($free_crawls == 0)
45
+				$free_crawls = 10;
46
+
47
+			$crawl_permit_period = intval(Config::get('system', 'crawl_permit_period'));
48
+			if ($crawl_permit_period == 0)
49
+				$crawl_permit_period = 10;
50
+
51
+			$remote = $_SERVER['REMOTE_ADDR'];
52
+			$result = Cache::get('remote_search:' . $remote);
53
+			if (!is_null($result)) {
54
+				$resultdata = json_decode($result);
55
+				if (($resultdata->time > (time() - $crawl_permit_period)) && ($resultdata->accesses > $free_crawls)) {
56
+					throw new HTTPException\TooManyRequestsException(L10n::t('Only one search per minute is permitted for not logged in users.'));
57
+				}
58
+				Cache::set('remote_search:' . $remote, json_encode(['time' => time(), 'accesses' => $resultdata->accesses + 1]), CacheClass::HOUR);
59
+			} else {
60
+				Cache::set('remote_search:' . $remote, json_encode(['time' => time(), 'accesses' => 1]), CacheClass::HOUR);
61
+			}
62
+		}
63
+
64
+		if (local_user()) {
65
+			self::getApp()->page['aside'] .= Widget\SavedSearches::getHTML('search?q=' . $search, $search);
66
+		}
67
+
68
+		Nav::setSelected('search');
69
+
70
+		$tag = false;
71
+		if (!empty($_GET['tag'])) {
72
+			$tag = true;
73
+			$search = '#' . Strings::escapeTags(trim(rawurldecode($_GET['tag'])));
74
+		}
75
+
76
+		// contruct a wrapper for the search header
77
+		$o = Renderer::replaceMacros(Renderer::getMarkupTemplate('content_wrapper.tpl'), [
78
+			'name' => 'search-header',
79
+			'$title' => L10n::t('Search'),
80
+			'$title_size' => 3,
81
+			'$content' => HTML::search($search, 'search-box', false)
82
+		]);
83
+
84
+		if (strpos($search, '#') === 0) {
85
+			$tag = true;
86
+			$search = substr($search, 1);
87
+		}
88
+
89
+		if (strpos($search, '@') === 0 || strpos($search, '!') === 0) {
90
+			return self::performSearch($search);
91
+		}
92
+
93
+		if (parse_url($search, PHP_URL_SCHEME) != '') {
94
+			$id = Item::fetchByLink($search);
95
+			if (!empty($id)) {
96
+				$item = Item::selectFirst(['guid'], ['id' => $id]);
97
+				if (DBA::isResult($item)) {
98
+					self::getApp()->internalRedirect('display/' . $item['guid']);
99
+				}
100
+			}
101
+		}
102
+
103
+		if (!empty($_GET['search-option'])) {
104
+			switch ($_GET['search-option']) {
105
+				case 'fulltext':
106
+					break;
107
+				case 'tags':
108
+					$tag = true;
109
+					break;
110
+				case 'contacts':
111
+					return self::performSearch($search, '@');
112
+				case 'forums':
113
+					return self::performSearch($search, '!');
114
+			}
115
+		}
116
+
117
+		if (!$search) {
118
+			return $o;
119
+		}
120
+
121
+		$tag = $tag || Config::get('system', 'only_tag_search');
122
+
123
+		// Here is the way permissions work in the search module...
124
+		// Only public posts can be shown
125
+		// OR your own posts if you are a logged in member
126
+		// No items will be shown if the member has a blocked profile wall.
127
+
128
+		$pager = new Pager(self::getArgs()->getQueryString());
129
+
130
+		if ($tag) {
131
+			Logger::info('Start tag search for "' . $search . '"');
132
+
133
+			$condition = [
134
+				"(`uid` = 0 OR (`uid` = ? AND NOT `global`))
135
+				AND `otype` = ? AND `type` = ? AND `term` = ?",
136
+				local_user(), Term::OBJECT_TYPE_POST, Term::HASHTAG, $search
137
+			];
138
+			$params = [
139
+				'order' => ['received' => true],
140
+				'limit' => [$pager->getStart(), $pager->getItemsPerPage()]
141
+			];
142
+			$terms = DBA::select('term', ['oid'], $condition, $params);
143
+
144
+			$itemids = [];
145
+			while ($term = DBA::fetch($terms)) {
146
+				$itemids[] = $term['oid'];
147
+			}
148
+
149
+			DBA::close($terms);
150
+
151
+			if (!empty($itemids)) {
152
+				$params = ['order' => ['id' => true]];
153
+				$items = Item::selectForUser(local_user(), [], ['id' => $itemids], $params);
154
+				$r = Item::inArray($items);
155
+			} else {
156
+				$r = [];
157
+			}
158
+		} else {
159
+			Logger::info('Start fulltext search for "' . $search . '"');
160
+
161
+			$condition = [
162
+				"(`uid` = 0 OR (`uid` = ? AND NOT `global`))
163
+				AND `body` LIKE CONCAT('%',?,'%')",
164
+				local_user(), $search
165
+			];
166
+			$params = [
167
+				'order' => ['id' => true],
168
+				'limit' => [$pager->getStart(), $pager->getItemsPerPage()]
169
+			];
170
+			$items = Item::selectForUser(local_user(), [], $condition, $params);
171
+			$r = Item::inArray($items);
172
+		}
173
+
174
+		if (!DBA::isResult($r)) {
175
+			info(L10n::t('No results.'));
176
+			return $o;
177
+		}
178
+
179
+		if ($tag) {
180
+			$title = L10n::t('Items tagged with: %s', $search);
181
+		} else {
182
+			$title = L10n::t('Results for: %s', $search);
183
+		}
184
+
185
+		$o .= Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), [
186
+			'$title' => $title
187
+		]);
188
+
189
+		Logger::info('Start Conversation for "' . $search . '"');
190
+		$o .= conversation(self::getApp(), $r, $pager, 'search', false, false, 'commented', local_user());
191
+
192
+		$o .= $pager->renderMinimal(count($r));
193
+
194
+		Logger::info('Done "'.$search.'"');
195
+
196
+		return $o;
197
+	}
198
+}

+ 1
- 0
static/routes.config.php View File

@@ -189,6 +189,7 @@ return [
189 189
 	],
190 190
 
191 191
 	'/search' => [
192
+		'[/]'                  => [Module\Search\Index::class, [R::GET]],
192 193
 		'/acl'                 => [Module\Search\Acl::class,   [R::GET, R::POST]],
193 194
 		'/saved/add/{term}'    => [Module\Search\Saved::class, [R::GET]],
194 195
 		'/saved/remove/{term}' => [Module\Search\Saved::class, [R::GET]],

Loading…
Cancel
Save