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