Add note on search_total to data_search_wipe().
[project/data.git] / data_search / data_search.module
1 <?php
2 // $Id$
3
4 /**
5 * Implementation of hook_menu()
6 */
7 function data_search_menu() {
8 $items = array();
9 $items['admin/build/data/edit/%data_ui_table/search'] = array(
10 'title' => 'Configure search',
11 'description' => 'Administer data tables.',
12 'page callback' => 'drupal_get_form',
13 'page arguments' => array('data_search_admin_form', 4),
14 'file' => 'data_search.admin.inc',
15 'access arguments' => array('administer data tables'),
16 'type' => MENU_LOCAL_TASK,
17 );
18 return $items;
19 }
20
21 /**
22 * Implementation of hook_theme()
23 */
24 function data_search_theme() {
25 return array(
26 'data_search_admin_form' => array(
27 'arguments' => array('form' => array()),
28 ),
29 );
30 }
31
32 /**
33 * Implementation of hook_cron().
34 *
35 * Wipe all orphaned search records.
36 *
37 * @todo: Move clean up of deleted records into DataHandler::delete() once there
38 * is a build query > alter query > execute query pattern implemented.
39 */
40 function data_search_cron() {
41 $tables = data_search_get_tables();
42
43 foreach ($tables as $table) {
44 data_search_wipe($table);
45 }
46 }
47
48 /**
49 * Implementation of hook_views_data_alter().
50 */
51 function data_search_views_data_alter(&$data) {
52 $tables = data_search_get_tables();
53 foreach ($tables as $table) {
54 $name = $table->get('name');
55 $schema = $table->get('table_schema');
56 $base_field = current($schema['primary key']);
57
58 // Explain how the search index joins to data tables.
59 $data['search_index']['table']['join'][$name] = array(
60 'left_field' => $base_field,
61 'field' => 'sid',
62 );
63 }
64 }
65
66 /**
67 * Implementation of hook_update_index().
68 */
69 function data_search_update_index() {
70 $limit = (int)variable_get('search_cron_limit', 100);
71
72 $tables = data_search_get_tables();
73 foreach ($tables as $table) {
74 $name = $table->get('name');
75 $schema = $table->get('table_schema');
76
77 $fields = data_search_get_fields($table);
78 $fields = implode(', ', $fields);
79 $base_field = current($schema['primary key']);
80
81 $result = db_query_range("SELECT dt.{$base_field} id FROM {{$name}} dt LEFT JOIN {search_dataset} d ON d.type = '{$name}' AND d.sid = dt.{$base_field} WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, dt.{$base_field} ASC", 0, $limit);
82
83 while ($row = db_fetch_object($result)) {
84 $values = db_fetch_array(db_query("SELECT {$fields} FROM {{$name}} WHERE {$base_field} = '%s'", $row->id));
85 $fulltext = '';
86 foreach ($values as $field => $value) {
87 $fulltext .= "{$value}\n\n";
88 }
89 search_index($row->id, $name, $fulltext);
90 }
91 // Delete orphaned data search records, no nodeapi to take care of this as it occurs.
92 db_query("DELETE sd, si, snl FROM {search_dataset} sd LEFT JOIN {{$name}} dt ON sd.type = '{$name}' AND sd.sid = dt.{$base_field} LEFT JOIN {search_index} si ON sd.sid = si.sid AND sd.type = si.type LEFT JOIN {search_node_links} snl ON sd.sid = snl.sid AND sd.type = snl.type WHERE dt.{$base_field} IS NULL");
93 }
94 }
95
96 /**
97 * Implementation of hook_search().
98 */
99 function data_search_search($op = 'search', $keys = NULL) {
100 switch ($op) {
101 case 'name':
102 return t('Data');
103
104 case 'reset':
105 $tables = data_search_get_tables();
106 foreach ($tables as $table) {
107 $name = $table->get('name');
108 db_query("UPDATE {search_dataset} SET reindex = %d WHERE type = '%s'", time(), $name);
109 }
110 return;
111
112 case 'status':
113 $total = $remaining = 0;
114 $tables = data_search_get_tables();
115 foreach ($tables as $table) {
116 $name = $table->get('name');
117 $schema = $table->get('table_schema');
118 $base_field = current($schema['primary key']);
119
120 $total = $total + db_result(db_query("SELECT COUNT(*) FROM {{$name}}"));
121 $remaining = $remaining + db_result(db_query("SELECT COUNT(*) FROM {{$name}} dt LEFT JOIN {search_dataset} d ON d.type = '{$name}' AND d.sid = dt.{$base_field} WHERE (d.sid IS NULL OR d.reindex <> 0)"));
122 }
123 return array('remaining' => $remaining, 'total' => $total);
124 }
125 }
126
127 /**
128 * Wipe all orphaned entries for given Data table. Use instead of search_wipe()
129 * if all items that have been deleted from table $table should be wiped. In
130 * this case, data_search_wipe() is faster than search_wipe().
131 *
132 * Note: Like search_wipe(), this function does not reset the word counts in
133 * search_total.
134 *
135 * @param $table
136 * DataTable object.
137 */
138 function data_search_wipe($table) {
139 $schema = $table->get('table_schema');
140 $name = db_escape_table($table->get('name'));
141 $field = db_escape_string(current($schema['primary key']));
142
143 db_query("DELETE s FROM {search_dataset} s LEFT JOIN {{$name}} t ON s.sid = t.$field WHERE s.type = '%s' AND t.$field IS NULL", $table->get('name'));
144 db_query("DELETE s FROM {search_index} s LEFT JOIN {{$name}} t ON s.sid = t.$field WHERE s.type = '%s' AND t.$field IS NULL", $table->get('name'));
145 }
146
147 /**
148 * Gather all tables which might be eligible for searching.
149 */
150 function data_search_get_tables() {
151 $tables = array();
152 foreach (data_get_all_tables() as $table) {
153 $schema = $table->get('table_schema');
154 $fields = data_search_get_fields($table);
155 if (isset($schema['primary key']) && count($schema['primary key']) >= 1 && !empty($fields)) {
156 $tables[] = $table;
157 }
158 }
159 return $tables;
160 }
161
162 /**
163 * Gather all fields for a particular table which should be added to the search index.
164 */
165 function data_search_get_fields($table) {
166 $fields = array();
167 $schema = $table->get('table_schema');
168 $meta = $table->get('meta');
169 foreach (array_keys($schema['fields']) as $field_name) {
170 if (!empty($meta['fields'][$field_name]['search'])) {
171 $fields[] = $field_name;
172 }
173 }
174 return $fields;
175 }