Found out where the jQuery BBQ library is actually kept.
[mkdru-moved-to-drupal.org.git] / mkdru.module
1 <?php
2 // $Id$
3
4
5
6 // Module metainfo
7 /**
8 * Implements hook_node_info()
9 */
10 function mkdru_node_info() {
11   return array(
12     'mkdru' => array(
13       'name' => t("Pazpar2 metasearch interface"),
14       'base' => 'mkdru',
15       'description' => t("Metasearch interface for Z39.50/SRU and other targets via a Pazpar2/Service Proxy backend"),
16     )
17   );
18 }
19
20 function mkdru_ting_search_show($params) {
21    $path = drupal_get_path('module', 'mkdru');
22   // Include client library.
23   drupal_add_js(variable_get('pz2_js_path', 'pazpar2/js') . '/pz2.js',
24     array('type' => 'file', 'scope' => 'footer'));
25   drupal_add_library('overlay', 'jquery-bbq');
26   drupal_add_js($path . '/mkdru.theme.js',
27     array('type' => 'file', 'scope' => 'footer'));
28   drupal_add_js($path . '/mkdru.client.js',
29     array('type' => 'file', 'scope' => 'footer'));
30   $html = theme('mkdru_results');
31   drupal_add_js(array('mkdru' => 
32     array('use_sessions' => '1', 'query' => $params['keys']
33     )), 'setting');
34   return array("content" => $html);
35 }
36
37 /**
38 * Implements hook_permission()
39 */
40 function mkdru_permission() {
41   return array(
42     'administer metasearch interfaces' => array(
43       'title' => t('Administer Pazpar2 metasearch integration'),
44     ),
45     'create metasearch interface' => array(
46       'title' => t('Create metasearch interface'),
47     ),
48     'edit any metasearch interface' => array(
49       'title' => t('Edit any metasearch interface'),
50     ),
51     'edit own metasearch interface' => array(
52       'title' => t('Edit own metasearch interface'),
53     ),
54   );
55 }
56
57 /**
58 * Implements hook_node_access()
59 */
60 function mkdru_node_access($node, $op, $account) {
61   if ($op == 'create') {
62     // Only users with permission to do so may create this node type.
63     return user_access('create metasearch interface', $account);
64   }
65
66   // Users who create a node may edit or delete it later, assuming they have the
67   // necessary permissions.
68   if ($op == 'update' || $op == 'delete') {
69     if (user_access('edit own metasearch interface', $account) && ($account->uid == $node->uid)) {
70       return TRUE;
71     }
72     elseif (user_access('edit any metasearch interface', $account)) {
73       return TRUE;
74     }
75   }
76 }
77
78 /**
79 * Implements hook_menu()
80 */
81 function mkdru_menu() {
82   $items['admin/settings/mkdru'] = array(
83     'title' => 'mkdru Settings',
84     'description' => 'Settings for mkdru.',
85     'page callback' => 'drupal_get_form',
86     'page arguments' => array('mkdru_admin_settings'),
87     'access arguments' => array('administer site configuration'),
88     'type' => MENU_NORMAL_ITEM,
89     'file' => 'mkdru.admin.inc',
90   );
91   return $items;
92 }
93
94 /**
95 * Implementation of hook_init()
96 */
97 function mkdru_init() {
98   // Applies our module specific CSS to all pages. This works best because
99   // all CSS is aggregated and cached so we reduce the number of HTTP 
100   // requests and the size is negligible.
101   drupal_add_css(drupal_get_path('module', 'mkdru') .'/mkdru.css');
102 }
103
104
105
106 // Node config
107 /**
108 * Implements hook_form()
109 */
110 function mkdru_form(&$node, $form_state) {
111   $type = node_type_get_type($node);
112
113   $form['title'] = array(
114     '#type' => 'textfield',
115     '#title' => check_plain($type->title_label),
116     '#required' => FALSE,
117     '#default_value' => $node->title,
118     '#weight' => -5
119   );
120
121   $form['search_settings']  = array(
122     '#type' => 'fieldset',
123     '#title' => t('Pazpar2/Service Proxy search settings'),
124     '#collapsible' => TRUE,
125     '#collapsed' => FALSE
126   );
127   $form['search_settings']['pz2_path'] = array(
128     '#type' => 'textfield',
129     '#title' => t('Pazpar2/Service Proxy path'),
130     '#description' => t('Path that takes Pazpar2 commands via HTTP'),
131     '#required' => TRUE,
132     '#default_value' => isset($node->mkdru->pz2_path) ? $node->mkdru->pz2_path : '/pazpar2/search.pz2',
133   );
134   $form['search_settings']['use_sessions'] = array(
135     '#type' => 'checkbox',
136     '#title' => t('Session handling'),
137     '#description' => t('Disable for use with Service Proxy'),
138     '#default_value' => isset($node->mkdru->use_sessions) ? $node->mkdru->use_sessions : 1,
139   );
140
141   $form['sp_settings']  = array(
142     '#type' => 'fieldset',
143     '#title' => t('Service Proxy specific settings'),
144     '#collapsible' => TRUE,
145     '#collapsed' => TRUE
146   );
147   $form['sp_settings']['sp_user'] = array(
148     '#type' => 'textfield',
149     '#title' => t('Service Proxy username'),
150     '#description' => t('Service Proxy username'),
151     '#required' => FALSE,
152     '#default_value' => isset($node->mkdru->sp_user) ? 
153       $node->mkdru->sp_user : '',
154   );
155   $form['sp_settings']['sp_pass'] = array(
156     '#type' => 'textfield',
157     '#title' => t('Service Proxy password'),
158     '#description' => t('Service Proxy password'),
159     '#required' => FALSE,
160     '#default_value' => isset($node->mkdru->sp_pass) ? 
161       $node->mkdru->sp_pass : '',
162   );
163
164   $form['display_settings']  = array(
165     '#type' => 'fieldset',
166     '#title' => t('Display settings'),
167     '#collapsible' => TRUE,
168     '#collapsed' => FALSE
169   );
170   $form['display_settings']['source_max'] = array(
171     '#type' => 'textfield',
172     '#title' => t('Number of sources to display'),
173     '#required' => TRUE,
174     '#default_value' => isset($node->mkdru->source_max) ? $node->mkdru->source_max : 10,
175     '#size' => 3,
176     '#maxlength' => 3,
177   );
178   $form['display_settings']['author_max'] = array(
179     '#type' => 'textfield',
180     '#title' => t('Number of authors to display'),
181     '#required' => TRUE,
182     '#default_value' => isset($node->mkdru->author_max) ? $node->mkdru->author_max : 10,
183     '#size' => 3,
184     '#maxlength' => 3,
185   );
186   $form['display_settings']['subject_max'] = array(
187     '#type' => 'textfield',
188     '#title' => t('Number of subjects to display'),
189     '#required' => TRUE,
190     '#default_value' => isset($node->mkdru->subject_max) ? $node->mkdru->subject_max : 10,
191     '#size' => 3,
192     '#maxlength' => 3,
193   );
194   return $form;
195 }
196
197
198 /**
199 * Implements hook_validate()
200 */
201 function mkdru_validate($node) {
202   if (!is_numeric($node->source_max)) {
203     form_set_error('source_max', t('Please enter a number.'));
204   }
205   if (!is_numeric($node->author_max)) {
206     form_set_error('author_max', t('Please enter a number.'));
207   }
208   if (!is_numeric($node->subject_max)) {
209     form_set_error('subject_max', t('Please enter a number.'));
210   }
211 }
212
213 /**
214 * Implements hook_insert().
215 */
216 function mkdru_insert($node) {
217   drupal_write_record('mkdru', $node);
218 }
219
220 /**
221 * Implements hook_update().
222 */
223 function mkdru_update($node) {
224   if ($node->revision) {
225     // New revision; treat it as a new record.
226     mkdru_insert($node);
227   }
228   else {
229     drupal_write_record('mkdru', $node, 'vid');
230   }
231 }
232
233 /**
234  * Implements hook_node_revision_delete()
235  */
236 function mkdru_node_revision_delete($node) {
237   db_delete('mkdru')
238     ->condition('vid', $node->vid)
239     ->execute();
240 }
241
242 /**
243  * Implements hook_delete()
244  */
245 function mkdru_delete($node) {
246   // Deleting by nid covers all revisions.
247   db_delete('mkdru')
248     ->condition('nid', $node->nid)
249     ->execute();
250 }
251
252
253
254 // Node rendering
255 /**
256 * Implements hook_load()
257 */
258 function mkdru_load($nodes) {
259   $result = db_query('SELECT * FROM {mkdru} WHERE nid IN (:nids)', array(':nids' => array_keys($nodes)));
260   foreach ($result as $record) {
261     $nodes[$record->nid]->mkdru = $record;
262   }
263 }
264
265 /**
266 * Implements hook_theme().
267 */
268 function mkdru_theme() {
269   return array(
270     'mkdru_form' => array(
271       'template' => 'mkdru-form',
272       'variables' => array(),
273     ),
274     'mkdru_results' => array(
275       'template' => 'mkdru-results',
276       'variables' => array(),
277     ),
278     'mkdru_js' => array(
279       'variables' => array('node' => NULL),
280     ),
281     'mkdru_block_search' => array(
282       'template' => 'mkdru-block-search',
283       'variables' => array('nid' => NULL, 'path' => NULL),
284     ),
285     'mkdru_block_facet' => array(
286       'template' => 'mkdru-block-facet',
287       'variables' => array('class' => NULL)
288     )
289   );
290 }
291
292 /**
293 * Theme function to include Javascript search client and deps
294 */
295 function theme_mkdru_js(&$variables) {
296   $path = drupal_get_path('module', 'mkdru');
297   // Pazpar2 client library
298   drupal_add_js(variable_get('pz2_js_path', 'pazpar2/js') . '/pz2.js', array(
299     'type' => 'file', 'scope' => 'footer', 'defer' => TRUE, 'preprocess' => FALSE));
300   // jQuery plugin for query string/history manipulation.
301   drupal_add_library('system', 'jquery.bbq');
302   drupal_add_js($path . '/mkdru.theme.js', array(
303     'type' => 'file', 'scope' => 'footer', 'defer' => TRUE, 'preprocess' => FALSE));
304   drupal_add_js($path . '/mkdru.client.js', array(
305     'type' => 'file', 'scope' => 'footer', 'defer' => TRUE, 'preprocess' => FALSE));
306   drupal_add_js(array('mkdru' => $variables['node']->mkdru), 'setting');
307 }
308
309 /** 
310 * Implements hook_view()
311 */
312 function mkdru_view($node, $view_mode) {
313   if ($view_mode == 'full') {
314     $node->content['mkdru_js'] = array(
315       '#markup' => theme('mkdru_js', array('node' => $node)), 
316       '#weight' => 0,
317     );
318     $node->content['mkdru_form'] = array(
319       '#markup' => theme('mkdru_form'), 
320       '#weight' => 1,
321     );
322     $node->content['mkdru_results'] = array(
323       '#markup' => theme('mkdru_results'), 
324       '#weight' => 2,
325     );
326   }
327   return $node;
328 }
329
330
331
332 // Blocks
333 /** 
334 * Implements hook_block_info()
335 */
336 function mkdru_block_info() {
337   // facet blocks
338   $facets = variable_get('mkdru_facets');
339   foreach ($facets as $facet) {
340     // NB: block caching is redundant for static content
341     $blocks['mkdru_facet_' . $facet]['info'] = "mkdru - $facet " . t('facet');
342     $blocks['mkdru_facet_' . $facet]['cache'] = DRUPAL_NO_CACHE;
343   }
344
345   // search blocks
346   $result = db_query("SELECT title, nid FROM {node} WHERE type = 'mkdru';");
347   foreach($result as $node) {
348     $blocks['mkdru_search_' . $node->nid]['info'] = 
349         t('mkdru - search box for "' . $node->title . '"');
350     $blocks['mkdru_sources']['cache'] = DRUPAL_NO_CACHE;
351   };
352
353   return $blocks;
354 }
355
356 /** 
357 * Implements hook_block_view()
358 */
359 function mkdru_block_view($delta) {
360   if (substr($delta, 0, 12) == 'mkdru_facet_') {
361     $facet = substr($delta, 12);
362     $block['subject'] = t(ucwords($facet));
363     $block['content'] = theme('mkdru_block_facet',
364                                array('class' => 'mkdru-facet-' . $facet));
365     return $block;
366   }
367   elseif (substr($delta, 0, 13) == 'mkdru_search_') {
368     $nid = substr($delta, 13);
369     $block['content'] = theme('mkdru_block_search',
370         array('nid' => $nid, 'path' => '/node/' . $nid));
371     return $block;
372   }
373 }