/[drupal]/drupal/modules/search/search.api.php
ViewVC logotype

Contents of /drupal/modules/search/search.api.php

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.18 - (show annotations) (download) (as text)
Sun Oct 11 03:07:19 2009 UTC (6 weeks, 5 days ago) by webchick
Branch: MAIN
CVS Tags: DRUPAL-7-0-UNSTABLE-10, HEAD
Changes since 1.17: +3 -3 lines
File MIME type: text/x-php
#557292 by peximo, plach, catch, and yched: Convert node title to Field API.
1 <?php
2 // $Id: search.api.php,v 1.17 2009/10/09 01:00:02 dries Exp $
3
4 /**
5 * @file
6 * Hooks provided by the Search module.
7 */
8
9 /**
10 * @addtogroup hooks
11 * @{
12 */
13
14 /**
15 * Define a custom search routine.
16 *
17 * This hook allows a module to perform searches on content it defines
18 * (custom node types, users, or comments, for example) when a site search
19 * is performed.
20 *
21 * Note that you can use form API to extend the search. You will need to use
22 * hook_form_alter() to add any additional required form elements. You can
23 * process their values on submission using a custom validation function.
24 * You will need to merge any custom search values into the search keys
25 * using a key:value syntax. This allows all search queries to have a clean
26 * and permanent URL. See node_form_search_form_alter() for an example.
27 *
28 * The example given here is for node.module, which uses the indexed search
29 * capabilities. To do this, node module also implements hook_update_index()
30 * which is used to create and maintain the index.
31 *
32 * @return
33 * Array with the optional keys 'title' for the tab title and 'path' for
34 * the path component after 'search/'. Both will default to the module
35 * name.
36 *
37 * @ingroup search
38 */
39 function hook_search_info() {
40 return array(
41 'title' => 'Content',
42 'path' => 'node',
43 );
44 }
45
46 /**
47 * Define access to a custom search routine.
48 *
49 * This hook allows a module to deny access to a user to a search tab.
50 *
51 * @ingroup search
52 */
53 function hook_search_access() {
54 return user_access('access content');
55 }
56
57 /**
58 * The search index is going to be rebuilt.
59 *
60 * Modules which use hook_update_index() should update their indexing
61 * bookkeeping so that it starts from scratch the next time
62 * hook_update_index() is called.
63 *
64 * @ingroup search
65 */
66 function hook_search_reset() {
67 db_update('search_dataset')
68 ->fields(array('reindex' => REQUEST_TIME))
69 ->condition('type', 'node')
70 ->execute();
71 }
72
73 /**
74 * Report the stutus of indexing.
75 *
76 * @return
77 * An associative array with the key-value pairs:
78 * - 'remaining': The number of items left to index.
79 * - 'total': The total number of items to index.
80 *
81 * @ingroup search
82 */
83 function hook_search_status() {
84 $total = db_query('SELECT COUNT(*) FROM {node} WHERE status = 1')->fetchField();
85 $remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0")->fetchField();
86 return array('remaining' => $remaining, 'total' => $total);
87 }
88
89 /**
90 * Add elements to the search administration form.
91 *
92 * @return
93 * The form array for the Search settings page at admin/config/search/settings.
94 *
95 * @ingroup search
96 */
97 function hook_search_admin() {
98 // Output form for defining rank factor weights.
99 $form['content_ranking'] = array(
100 '#type' => 'fieldset',
101 '#title' => t('Content ranking'),
102 );
103 $form['content_ranking']['#theme'] = 'node_search_admin';
104 $form['content_ranking']['info'] = array(
105 '#value' => '<em>' . t('The following numbers control which properties the content search should favor when ordering the results. Higher numbers mean more influence, zero means the property is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') . '</em>'
106 );
107
108 // Note: reversed to reflect that higher number = higher ranking.
109 $options = drupal_map_assoc(range(0, 10));
110 foreach (module_invoke_all('ranking') as $var => $values) {
111 $form['content_ranking']['factors']['node_rank_' . $var] = array(
112 '#title' => $values['title'],
113 '#type' => 'select',
114 '#options' => $options,
115 '#default_value' => variable_get('node_rank_' . $var, 0),
116 );
117 }
118 return $form;
119 }
120
121 /**
122 * Execute a search for a set of key words.
123 *
124 * We call do_search() with the keys, the module name, and extra SQL fragments
125 * to use when searching. See hook_update_index() for more information.
126 *
127 * @param $keys
128 * The search keywords as entered by the user.
129 *
130 * @return
131 * An array of search results. To use the default search result
132 * display, each item should have the following keys':
133 * - 'link': Required. The URL of the found item.
134 * - 'type': The type of item.
135 * - 'title': Required. The name of the item.
136 * - 'user': The author of the item.
137 * - 'date': A timestamp when the item was last modified.
138 * - 'extra': An array of optional extra information items.
139 * - 'snippet': An excerpt or preview to show with the result (can be
140 * generated with search_excerpt()).
141 *
142 * @ingroup search
143 */
144 function hook_search_execute($keys = NULL) {
145 // Build matching conditions
146 $query = db_search()->extend('PagerDefault');
147 $query->join('node', 'n', 'n.nid = i.sid');
148 $query
149 ->condition('n.status', 1)
150 ->addTag('node_access')
151 ->searchExpression($keys, 'node');
152
153 // Insert special keywords.
154 $query->setOption('type', 'n.type');
155 $query->setOption('language', 'n.language');
156 if ($query->setOption('term', 'tn.nid')) {
157 $query->join('taxonomy_term_node', 'tn', 'n.vid = tn.vid');
158 }
159 // Only continue if the first pass query matches.
160 if (!$query->executeFirstPass()) {
161 return array();
162 }
163
164 // Add the ranking expressions.
165 _node_rankings($query);
166
167 // Add a count query.
168 $inner_query = clone $query;
169 $count_query = db_select($inner_query->fields('i', array('sid')));
170 $count_query->addExpression('COUNT(*)');
171 $query->setCountQuery($count_query);
172 $find = $query
173 ->limit(10)
174 ->execute();
175
176 // Load results.
177 $results = array();
178 foreach ($find as $item) {
179 // Build the node body.
180 $node = node_load($item->sid);
181 node_build_content($node, 'search_result');
182 $node->body = drupal_render($node->content);
183
184 // Fetch comments for snippet.
185 $node->rendered .= ' ' . module_invoke('comment', 'node_update_index', $node);
186 // Fetch terms for snippet.
187 $node->rendered .= ' ' . module_invoke('taxonomy', 'node_update_index', $node);
188
189 $extra = module_invoke_all('node_search_result', $node);
190
191 $results[] = array(
192 'link' => url('node/' . $item->sid, array('absolute' => TRUE)),
193 'type' => check_plain(node_type_get_name($node)),
194 'title' => $node->title[FIELD_LANGUAGE_NONE][0]['value'],
195 'user' => theme('username', array('account' => $node)),
196 'date' => $node->changed,
197 'node' => $node,
198 'extra' => $extra,
199 'score' => $item->calculated_score,
200 'snippet' => search_excerpt($keys, $node->body),
201 );
202 }
203 return $results;
204 }
205
206 /**
207 * Preprocess text for the search index.
208 *
209 * This hook is called both for text added to the search index, as well as
210 * the keywords users have submitted for searching.
211 *
212 * This is required for example to allow Japanese or Chinese text to be
213 * searched. As these languages do not use spaces, it needs to be split into
214 * separate words before it can be indexed. There are various external
215 * libraries for this.
216 *
217 * @param $text
218 * The text to split. This is a single piece of plain-text that was
219 * extracted from between two HTML tags. Will not contain any HTML entities.
220 * @return
221 * The text after processing.
222 *
223 * @ingroup search
224 */
225 function hook_search_preprocess($text) {
226 // Do processing on $text
227 return $text;
228 }
229
230 /**
231 * Update Drupal's full-text index for this module.
232 *
233 * Modules can implement this hook if they want to use the full-text indexing
234 * mechanism in Drupal.
235 *
236 * This hook is called every cron run if search.module is enabled. A module
237 * should check which of its items were modified or added since the last
238 * run. It is advised that you implement a throttling mechanism which indexes
239 * at most 'search_cron_limit' items per run (see example below).
240 *
241 * You should also be aware that indexing may take too long and be aborted if
242 * there is a PHP time limit. That's why you should update your internal
243 * bookkeeping multiple times per run, preferably after every item that
244 * is indexed.
245 *
246 * Per item that needs to be indexed, you should call search_index() with
247 * its content as a single HTML string. The search indexer will analyse the
248 * HTML and use it to assign higher weights to important words (such as
249 * titles). It will also check for links that point to nodes, and use them to
250 * boost the ranking of the target nodes.
251 *
252 * @ingroup search
253 */
254 function hook_update_index() {
255 $limit = (int)variable_get('search_cron_limit', 100);
256
257 $result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", 0, $limit);
258
259 foreach ($result as $node) {
260 $node = node_load($node->nid);
261
262 // Save the changed time of the most recent indexed node, for the search
263 // results half-life calculation.
264 variable_set('node_cron_last', $node->changed);
265
266 // Render the node.
267 node_build_content($node, 'search_index');
268 $node->rendered = drupal_render($node->content);
269
270 $text = '<h1>' . check_plain($node->title[FIELD_LANGUAGE_NONE][0]['value']) . '</h1>' . $node->rendered;
271
272 // Fetch extra data normally not visible
273 $extra = module_invoke_all('node_update_index', $node);
274 foreach ($extra as $t) {
275 $text .= $t;
276 }
277
278 // Update index
279 search_index($node->nid, 'node', $text);
280 }
281 }
282 /**
283 * @} End of "addtogroup hooks".
284 */

  ViewVC Help
Powered by ViewVC 1.1.2