Keep filter when clicking pager links
[phinde.git] / www / index.php
1 <?php
2 namespace phinde;
3 // web interface to search
4 require 'www-header.php';
5
6 if (!isset($_GET['q'])) {
7     $_GET['q'] = '';
8 }
9 $query = trim($_GET['q']);
10
11 $page = 0;
12 if (isset($_GET['page'])) {
13     if (!is_numeric($_GET['page'])) {
14         throw new Exception_Input('List page is not numeric');
15     }
16     //PEAR Pager begins at 1
17     $page = (int)$_GET['page'] - 1;
18 }
19
20 $perPage = 10;//$GLOBALS['phinde']['perPage'];
21 $site = null;
22 $siteParam = false;
23 $baseLink = '?q=' . urlencode($query);
24
25 if (preg_match('#site:([^ ]*)#', $query, $matches)) {
26     $site = $matches[1];
27     $cleanQuery = trim(str_replace('site:' . $site, '', $query));
28     $site = Helper::noSchema($site);
29 } else if (isset($_GET['site']) && trim(isset($_GET['site'])) != '') {
30     $site = trim($_GET['site']);
31     $siteParam = true;
32     $cleanQuery = $query;
33     $baseLink .= '&site=' . urlencode($site);
34 } else {
35     $cleanQuery = $query;
36 }
37
38 if (isset($_GET['sort'])
39     && ($_GET['sort'] === 'date' || $_GET['sort'] === 'score')
40 ) {
41     $sortMode = $_GET['sort'];
42 } else {
43     $sortMode = $GLOBALS['phinde']['defaultSort'];
44 }
45 $sort = $sortMode;
46 if ($sortMode !== $GLOBALS['phinde']['defaultSort']) {
47     $baseLink .= '&sort=' . $sortMode;
48 }
49
50 $filters = array();
51 if (isset($_GET['filter'])) {
52     $allowedFilter = array('domain', 'language', 'tags', 'term');
53     foreach ($_GET['filter'] as $type => $value) {
54         if (in_array($type, $allowedFilter)) {
55             $filters[$type] = filter_var($value, FILTER_SANITIZE_STRING);
56         }
57     }
58 }
59 $activeFilters = array();
60 foreach ($filters as $type => $value) {
61     $activeFilters[$type] = array(
62         'label' => $value,
63         'removeUrl' => buildLink($baseLink, $filters, $type, null),
64     );
65 }
66
67 function buildLink($baseLink, $filters, $addFilterType, $addFilterValue)
68 {
69     if ($addFilterValue === null) {
70         if (array_key_exists($addFilterType, $filters)) {
71             unset($filters[$addFilterType]);
72         }
73     } else {
74         $filters[$addFilterType] = $addFilterValue;
75     }
76
77     $params = http_build_query(array('filter' => $filters));
78     if (strlen($params)) {
79         return $baseLink . '&' . $params;
80     }
81     return $baseLink;
82 }
83
84 if (preg_match('#site:([^ ]*)#', $query, $matches)) {
85     $site = $matches[1];
86     $cleanQuery = trim(str_replace('site:' . $site, '', $query));
87     $site = Helper::noSchema($site);
88     $urlNoSite = buildLink('?q=' . urlencode($cleanQuery), $filters, null, null);
89 } else {
90     $cleanQuery = $query;
91     $urlNoSite = null;
92 }
93
94 $timeBegin = microtime(true);
95 $es = new Elasticsearch($GLOBALS['phinde']['elasticsearch']);
96 $res = $es->search($cleanQuery, $filters, $site, $page, $perPage, $sort);
97 $timeEnd = microtime(true);
98
99 $pager = new Html_Pager(
100     $res->hits->total, $perPage, $page + 1,
101     buildLink($baseLink, $filters, null, null)
102 );
103
104 foreach ($res->hits->hits as &$hit) {
105     $doc = $hit->_source;
106     if (!isset($doc->title) || $doc->title == '') {
107         $doc->title = '(no title)';
108         $doc->htmlTitle = '(no title)';
109     }
110     if (isset($hit->highlight->title[0])) {
111         $doc->htmlTitle = $hit->highlight->title[0];
112     } else {
113         $doc->htmlTitle = htmlspecialchars($doc->title);
114     }
115     if (isset($hit->highlight->text[0])) {
116         $doc->htmlText = $hit->highlight->text[0];
117     } else {
118         $doc->htmlText = null;
119     }
120
121     $doc->extra = new \stdClass();
122     $doc->extra->cleanUrl = preg_replace('#^.*://#', '', $doc->url);
123     if (isset($doc->status->modate)) {
124         $doc->extra->day = substr($doc->status->modate, 0, 10);
125     }
126 }
127
128 foreach ($res->aggregations as $key => &$aggregation) {
129     foreach ($aggregation->buckets as &$bucket) {
130         $bucket->url = buildLink($baseLink, $filters, $key, $bucket->key);
131     }
132 }
133
134 if ($site !== null) {
135     $urlNoSite = buildLink('?q=' . urlencode($cleanQuery), $filters, null, null);
136 } else {
137     $urlNoSite = null;
138 }
139
140 $urlSortBase = buildLink(
141     preg_replace('#&sort=[^&]+#', '', $baseLink), $filters, null, null
142 );
143 $urlSorts = [];
144 foreach (['date', 'score'] as $sortMode) {
145     if ($sortMode === $GLOBALS['phinde']['defaultSort']) {
146         $urlSorts[$sortMode] = $urlSortBase;
147     } else {
148         $urlSorts[$sortMode] = $urlSortBase . '&sort=' . $sortMode;
149     }
150 }
151
152 if (isset($_GET['format']) && $_GET['format'] == 'opensearch') {
153     $template = 'opensearch';
154     $baseLink .= '&format=opensearch';
155     header('Content-type: application/atom+xml');
156 } else {
157     $template = 'search';
158 }
159
160 render(
161     $template,
162     array(
163         'queryTime' => round($timeEnd - $timeBegin, 2) . 's',
164         'query' => $query,
165         'fullUrl' => Helper::fullUrl($baseLink),
166         'cleanQuery' => $cleanQuery,
167         'urlNoSite' => $urlNoSite,
168         'site' => $site,
169         'siteParam' => $siteParam,
170         'hitcount' => $res->hits->total,
171         'hits' => $res->hits->hits,
172         'aggregations' => $res->aggregations,
173         'activeFilters' => $activeFilters,
174         'pager' => $pager,
175         'sort' => $sort,
176         'urlSorts' => $urlSorts,
177         'hitTemplate' => 'search/' . $GLOBALS['phinde']['hitTemplate'],
178         'sidebarinclude' => $GLOBALS['phinde']['sidebarinclude'],
179     )
180 );
181 ?>