Subversion Repositories oidplus

Rev

Rev 1293 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
635 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
1086 daniel-mar 5
 * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
635 daniel-mar 6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
1050 daniel-mar 20
namespace ViaThinkSoft\OIDplus;
635 daniel-mar 21
 
1086 daniel-mar 22
// phpcs:disable PSR1.Files.SideEffects
23
\defined('INSIDE_OIDPLUS') or die;
24
// phpcs:enable PSR1.Files.SideEffects
25
 
635 daniel-mar 26
class OIDplusPagePublicSearch extends OIDplusPagePluginPublic {
27
 
1116 daniel-mar 28
        /**
29
         * @param bool $html
30
         * @return void
31
         * @throws OIDplusException
32
         */
33
        public function init(bool $html=true) {
635 daniel-mar 34
                OIDplus::config()->prepareConfigKey('search_min_term_length', 'Minimum length of a search term', '3', OIDplusConfig::PROTECTION_EDITABLE, function($value) {
35
                        if (!is_numeric($value) || ($value < 0)) {
36
                                throw new OIDplusException(_L('Please enter a valid value.'));
37
                        }
38
                });
39
        }
40
 
1116 daniel-mar 41
        /**
1130 daniel-mar 42
         * @param array $params
43
         * @param bool $is_searching
1116 daniel-mar 44
         * @return void
45
         */
1130 daniel-mar 46
        private function prepareSearchParams(array &$params, bool $is_searching) {
635 daniel-mar 47
                $params['term'] = isset($params['term']) ? trim($params['term']) : '';
48
                $params['namespace'] = isset($params['namespace']) ? trim($params['namespace']) : '';
49
 
50
                // Default criteria selection:
51
                if ($is_searching) {
52
                        $params['search_title'] = isset($params['search_title']) && $params['search_title'];
53
                        $params['search_description'] = isset($params['search_description']) && $params['search_description'];
54
                        $params['search_asn1id'] = isset($params['search_asn1id']) && $params['search_asn1id'];
55
                        $params['search_iri'] = isset($params['search_iri']) && $params['search_iri'];
56
                } else {
57
                        $params['search_title'] = true;
58
                        $params['search_description'] = false;
59
                        $params['search_asn1id'] = true;
60
                        $params['search_iri'] = true;
61
                }
62
        }
63
 
1116 daniel-mar 64
        /**
1130 daniel-mar 65
         * @param string $html
66
         * @param string $term
67
         * @return string
1116 daniel-mar 68
         */
1130 daniel-mar 69
        private function highlight_match(string $html, string $term): string {
1311 daniel-mar 70
                //return str_replace(htmlentities($term), '<font color="red">'.htmlentities($term).'</font>', $html);
71
                // Case insensitive:
72
                return preg_replace('@('.preg_quote(htmlentities($term),'@').')@i', '<font color="red">\\1</font>', $html);
704 daniel-mar 73
        }
74
 
1116 daniel-mar 75
        /**
1130 daniel-mar 76
         * @param array $params
1116 daniel-mar 77
         * @return string
78
         * @throws OIDplusException
79
         */
1130 daniel-mar 80
        private function doSearch(array $params): string {
635 daniel-mar 81
                $output = '';
82
 
83
                // Note: The SQL collation defines if search is case sensitive or case insensitive
84
 
85
                $min_length = OIDplus::config()->getValue('search_min_term_length');
86
 
87
                $this->prepareSearchParams($params, true);
88
 
89
                if (strlen($params['term']) == 0) {
90
                        $output .= '<p><font color="red">'._L('Error: You must enter a search term.').'</font></p>';
91
                } else if (strlen($params['term']) < $min_length) {
92
                        $output .= '<p><font color="red">'._L('Error: Search term minimum length is %1 characters.',$min_length).'</font></p>';
93
                } else {
94
                        if ($params['namespace'] == 'oidplus:ra') {
704 daniel-mar 95
                                $output .= '<h2>'._L('Search results for RA %1','<font color="red">'.htmlentities($params['term']).'</font>').'</h2>';
635 daniel-mar 96
 
97
                                $sql_where = array(); $prep_where = array();
98
 
1311 daniel-mar 99
                                $sql_where[] = OIDplus::db()->getSlang()->lowerCase('email')." like ?";   $prep_where[] = '%'.$params['term'].'%';
100
                                $sql_where[] = OIDplus::db()->getSlang()->lowerCase('ra_name')." like ?"; $prep_where[] = '%'.$params['term'].'%';
101
 
635 daniel-mar 102
                                if (count($sql_where) == 0) $sql_where[] = '1=0';
103
                                $res = OIDplus::db()->query("select * from ###ra where (".implode(' or ', $sql_where).")", $prep_where);
104
 
105
                                $count = 0;
106
                                while ($row = $res->fetch_object()) {
107
                                        $email = str_replace('@', '&', $row->email);
1219 daniel-mar 108
                                        $output .= '<p><a '.OIDplus::gui()->link('oidplus:rainfo$'.str_replace('@','&',$email)).'>'.$this->highlight_match(htmlentities($email),$params['term']).'</a>: <b>'.$this->highlight_match(htmlentities($row->ra_name??''),$params['term']).'</b></p>';
635 daniel-mar 109
                                        $count++;
110
                                }
111
                                if ($count == 0) {
112
                                        $output .= '<p>'._L('Nothing found').'</p>';
113
                                }
114
                        } else {
704 daniel-mar 115
                                $output .= '<h2>'._L('Search results for %1 (%2)','<font color="red">'.htmlentities($params['term']).'</font>',htmlentities($params['namespace'])).'</h2>';
635 daniel-mar 116
 
117
                                $sql_where = array(); $prep_where = array();
1311 daniel-mar 118
                                $sql_where[] = OIDplus::db()->getSlang()->lowerCase('id')." like ?"; $prep_where[] = '%'.$params['term'].'%'; // TODO: should we rather do findFitting(), so we can e.g. find GUIDs with different notation?
119
                                if ($params["search_title"])       { $sql_where[] = OIDplus::db()->getSlang()->lowerCase('title')." like ?";       $prep_where[] = '%'.$params['term'].'%'; }
120
                                if ($params["search_description"]) { $sql_where[] = OIDplus::db()->getSlang()->lowerCase('description')." like ?"; $prep_where[] = '%'.$params['term'].'%'; }
635 daniel-mar 121
 
122
                                if ($params["search_asn1id"]) {
1311 daniel-mar 123
                                        $res = OIDplus::db()->query("select * from ###asn1id where ".OIDplus::db()->getSlang()->lowerCase('name')." like ?", array('%'.$params['term'].'%'));
635 daniel-mar 124
                                        while ($row = $res->fetch_object()) {
125
                                                $sql_where[] = "id = ?"; $prep_where[] = $row->oid;
126
                                        }
127
                                }
128
 
129
                                if ($params["search_iri"]) {
1311 daniel-mar 130
                                        $res = OIDplus::db()->query("select * from ###iri where ".OIDplus::db()->getSlang()->lowerCase('name')." like ?", array('%'.$params['term'].'%'));
635 daniel-mar 131
                                        while ($row = $res->fetch_object()) {
132
                                                $sql_where[] = "id = ?"; $prep_where[] = $row->oid;
133
                                        }
134
                                }
135
 
136
                                if (count($sql_where) == 0) $sql_where[] = '1=0';
137
                                array_unshift($prep_where, $params['namespace'].':%');
138
 
1311 daniel-mar 139
                                $res = OIDplus::db()->query("select * from ###objects where ".OIDplus::db()->getSlang()->lowerCase('id')." like ? and (".implode(' or ', $sql_where).")", $prep_where);
635 daniel-mar 140
 
141
                                $count = 0;
142
                                while ($row = $res->fetch_object()) {
704 daniel-mar 143
                                        $output .= '<p><a '.OIDplus::gui()->link($row->id).'>'.$this->highlight_match(htmlentities($row->id),$params['term']).'</a>';
635 daniel-mar 144
 
145
                                        $asn1ids = array();
146
                                        $res2 = OIDplus::db()->query("select name from ###asn1id where oid = ?", array($row->id));
147
                                        while ($row2 = $res2->fetch_object()) {
148
                                                $asn1ids[] = $row2->name;
149
                                        }
150
                                        if (count($asn1ids) > 0) {
151
                                                $asn1ids = implode(', ', $asn1ids);
704 daniel-mar 152
                                                $output .= ' ('.$this->highlight_match(htmlentities($asn1ids),$params['term']).')';
635 daniel-mar 153
                                        }
154
 
1219 daniel-mar 155
                                        if (htmlentities($row->title) != '') $output .= ': <b>'.$this->highlight_match(htmlentities($row->title??''),$params['term']).'</b></p>';
635 daniel-mar 156
                                        $count++;
157
                                }
158
                                if ($count == 0) {
159
                                        $output .= '<p>'._L('Nothing found').'</p>';
160
                                }
161
                        }
162
                }
163
 
164
                return $output;
165
        }
166
 
1116 daniel-mar 167
        /**
1293 daniel-mar 168
         * @param array $params
169
         * @return array
170
         * @throws OIDplusException
171
         */
172
        private function action_Search(array $params): array {
173
                $ret = $this->doSearch($params);
174
                return array("status" => 0, "output" => $ret);
175
        }
176
 
177
        /**
1116 daniel-mar 178
         * @param string $actionID
179
         * @param array $params
180
         * @return array
181
         * @throws OIDplusException
182
         */
183
        public function action(string $actionID, array $params): array {
635 daniel-mar 184
                if ($actionID == 'search') {
1293 daniel-mar 185
                        return $this->action_Search($params);
1116 daniel-mar 186
                } else {
187
                        return parent::action($actionID, $params);
635 daniel-mar 188
                }
189
        }
190
 
1116 daniel-mar 191
        /**
192
         * @param string $id
193
         * @param array $out
194
         * @param bool $handled
195
         * @return void
196
         * @throws OIDplusException
197
         */
198
        public function gui(string $id, array &$out, bool &$handled) {
635 daniel-mar 199
                if (explode('$',$id)[0] == 'oidplus:search') {
200
                        $handled = true;
201
 
202
                        $out['title'] = _L('Search');
801 daniel-mar 203
                        $out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : '';
635 daniel-mar 204
 
205
                        $out['text'] = '';
206
 
207
                        try {
208
                                $params = $_POST;
209
 
210
                                $this->prepareSearchParams($params, isset($params['search']));
211
 
962 daniel-mar 212
                                $out['text'] .= '<form id="searchForm" action="?goto=oidplus%3Asearch" method="POST">
635 daniel-mar 213
                                                 <input type="hidden" name="search" value="1">
214
                                                 '._L('Search for').': <input type="text" id="term" name="term" value="'.htmlentities($params['term']).'"><br><br>
215
                                                 <script>
216
                                                 function searchNsSelect(ns) {
217
                                                     $("#search_options_oid")[0].style.display = (ns == "oid") ? "block" : "none";
218
                                                     $("#search_options_object")[0].style.display = (ns == "oidplus:ra") ? "none" : "block";
219
                                                     $("#search_options_ra")[0].style.display = (ns == "oidplus:ra") ? "block" : "none";
220
                                                 }
221
                                                 $( document ).ready(function() {
222
                                                     searchNsSelect($("#namespace")[0].value);
223
                                                 });
224
                                                 </script>
225
                                                 '._L('Search in').': <select name="namespace" id="namespace" onchange="searchNsSelect(this.value);"><br><br>';
226
 
227
                                foreach (OIDplus::getEnabledObjectTypes() as $ot) {
228
                                        $out['text'] .= '<option value="'.htmlentities($ot::ns()).'"'.(($params['namespace'] == $ot::ns()) ? ' selected' : '').'>'.htmlentities($ot::objectTypeTitle()).'</option>';
229
                                }
230
                                $out['text'] .= '<option value="oidplus:ra"'.(($params['namespace'] == 'oidplus:ra') ? ' selected' : '').'>'._L('Registration Authority').'</option>
231
                                                 </select><br><br>
232
                                <div id="search_options_ra">
233
                                <!-- TODO: RA specific selection criterias -->
234
                                </div>
235
                                <div id="search_options_object">
236
                                            <input type="checkbox" name="search_title" id="search_title" value="1"'.($params["search_title"] ? ' checked' : '').'> <label for="search_title">'._L('Search in field "Title"').'</label><br>
237
                                            <input type="checkbox" name="search_description" id="search_description" value="1"'.($params["search_description"] ? ' checked' : '').'> <label for="search_description">'._L('Search in field "Description"').'</label><br>
238
                                <div id="search_options_oid">
239
                                    <input type="checkbox" name="search_asn1id" id="search_asn1id" value="1"'.($params["search_asn1id"] ? ' checked' : '').'> <label for="search_asn1id">'._L('Search in field "ASN.1 identifier" (only OIDs)').'</label><br>
240
                                    <input type="checkbox" name="search_iri" id="search_iri" value="1"'.($params["search_iri"] ? ' checked' : '').'> <label for="search_iri">'._L('Search in field "Unicode label" (only OIDs)').'</label><br>
241
                                </div>
242
                                </div>
243
                                 <br>
244
 
245
                                <input type="submit" value="'._L('Search').'" onclick="return OIDplusPagePublicSearch.search_button_click()">
246
                                </form>';
247
 
248
                                $out['text'] .= '<div id="search_output">'; // will be filled with either AJAX or staticly (HTML form submit)
249
                                if (isset($params['search'])) {
250
                                        // Search with NoJS/HTML
251
                                        $out['text'] .= $this->doSearch($params);
252
                                }
253
                                $out['text'] .= '</div>';
1050 daniel-mar 254
                        } catch (\Exception $e) {
1201 daniel-mar 255
                                $htmlmsg = $e instanceof OIDplusException ? $e->getHtmlMessage() : htmlentities($e->getMessage());
256
                                $out['text'] = _L('Error: %1',$htmlmsg);
635 daniel-mar 257
                        }
258
                }
259
        }
260
 
1116 daniel-mar 261
        /**
262
         * @param array $out
263
         * @return void
264
         */
265
        public function publicSitemap(array &$out) {
635 daniel-mar 266
                $out[] = 'oidplus:search';
267
        }
268
 
1116 daniel-mar 269
        /**
270
         * @param array $json
271
         * @param string|null $ra_email
272
         * @param bool $nonjs
273
         * @param string $req_goto
274
         * @return bool
275
         * @throws OIDplusException
276
         */
277
        public function tree(array &$json, string $ra_email=null, bool $nonjs=false, string $req_goto=''): bool {
800 daniel-mar 278
                if (file_exists(__DIR__.'/img/main_icon16.png')) {
801 daniel-mar 279
                        $tree_icon = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon16.png';
635 daniel-mar 280
                } else {
281
                        $tree_icon = null; // default icon (folder)
282
                }
283
 
284
                $json[] = array(
285
                        'id' => 'oidplus:search',
286
                        'icon' => $tree_icon,
287
                        'text' => _L('Search')
288
                );
289
 
290
                return true;
291
        }
292
 
1116 daniel-mar 293
        /**
294
         * @param string $request
295
         * @return array|false
296
         */
297
        public function tree_search(string $request) {
635 daniel-mar 298
                return false;
299
        }
300
}