/[drupal]/contributions/modules/helptip/helptip.module
ViewVC logotype

Contents of /contributions/modules/helptip/helptip.module

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


Revision 1.13 - (show annotations) (download) (as text)
Mon May 21 00:30:36 2007 UTC (2 years, 6 months ago) by yogadex
Branch: MAIN
CVS Tags: HEAD
Changes since 1.12: +2 -2 lines
File MIME type: text/x-php
Eliminate a database warning from apache logs.
Fix to #127433, provided by dkruglyak
1 <?php
2 // $Id: helptip.module,v 1.12 2007/01/05 03:28:50 yogadex Exp $
3
4 /**
5 * @file
6 * Creates and displays context sensitive help in Drupal blocks.
7 *
8 * Introduces a new node type called "help tip" and blocks for
9 * displaying help tips. Each tip is configured to appear only on one
10 * or more pages, allowing it to be context sensitive.
11 *
12 * Blocks may show one help tip or, if more than one help tip applies
13 * to a given page, a block may show several.
14 *
15 * If so configured, a user may hide a tip they do not wish to see it
16 * again.
17 */
18
19 /**
20 * Helpful hint: configure your menus to always expand "create content".
21 * Then clicking the add "help tip" link will have the path of the referring
22 * page already filled in.
23 */
24
25 /**
26 * How many blocks should this module provide?
27 */
28 function _helptip_num_blocks() {
29 $num = variable_get('helptip_num_blocks', 1);
30 if (!$num > 0) {
31 return 1;
32 }
33 else
34 return $num;
35 }
36
37 /**
38 * Retrieve the settings for a given helptip block. Provide defaults
39 * if necessary.
40 */
41 function _helptip_get_block_settings($delta) {
42 $var_name = "helptip_block_".$delta."_settings";
43 $defaults = array('how_many' => 1,
44 'title' => '%title',
45 'min_weight' => -10,
46 'max_weight' => 10);
47
48 $settings = variable_get($var_name,
49 array());
50 // array_merge ensures all defaults will be found.
51 return array_merge($defaults, $settings);
52 }
53
54 /**
55 * Implementation of hook_block().
56 */
57 function helptip_block($op = 'list', $delta = 0, $edit = array()) {
58 $var_name = "helptip_block_".$delta."_settings";
59 if ($op == 'list') {
60 $blocks[0]['info'] = t('Help tips');
61 for ($i = 1; $i < _helptip_num_blocks(); $i++) {
62 $blocks[$i]['info'] = t('Help tips !num', array('!num' => $i+1));
63 }
64 return $blocks;
65 }
66 else if ($op == 'configure') {
67 $defaults = _helptip_get_block_settings($delta);
68 $form[$var_name] = array('#tree' => true);
69 $form[$var_name]['title'] =
70 array('#type' => 'textfield',
71 '#title' => t('Title'),
72 '#default_value' => $defaults['title'],
73 '#size' => 64,
74 '#maxlength' => 128,
75 '#description' => t('Block title. For example "Tip of the Day". Use %title for the title of the first help tip.'),
76 );
77 $form[$var_name]['how_many'] =
78 array('#type' => 'textfield',
79 '#title' => t('Number of help tips'),
80 '#default_value' => $defaults['how_many'],
81 '#size' => 2,
82 '#maxlength' => 2,
83 '#description' => t('How many tips to display? If more than one tip applies to the current page, more than one can be displayed. Tips of equal weight will be displayed in random order.'),
84 );
85 $form[$var_name]['min_weight'] =
86 array('#type' => 'weight',
87 '#title' => t('Minimum Weight'),
88 '#default_value' => $defaults['min_weight'],
89 '#description' => t('Show only helptips with this weight or greater. This allows you to define multiple helptip blocks, and position helptips on the page by their weight.'),
90 );
91 $form[$var_name]['max_weight'] =
92 array('#type' => 'weight',
93 '#title' => t('Maximum Weight'),
94 '#default_value' => $defaults['max_weight'],
95 '#description' => t('Show only helptips with this weight or less. This allows you to define multiple helptip blocks, and position helptips on the page by their weight.'),
96 );
97 return $form;
98 }
99 else if ($op == 'save') {
100 variable_set($var_name, $edit[$var_name]);
101 }
102 else if ($op == 'view') {
103 global $user;
104 if (!user_access(HELPTIP_ACCESS_VIEW))
105 return;
106
107 $settings = _helptip_get_block_settings($delta);
108 $paths = _helptip_get_current_paths();
109 $path_clause = "('" . implode("' LIKE ht.path OR '", $paths) . "' LIKE ht.path)";
110 // use db_rewrite_sql for people with node_access modules
111 $result = db_query(db_rewrite_sql("SELECT n.nid FROM {node} n LEFT JOIN {helptip} ht ON ht.nid = n.nid LEFT JOIN {helptip_user_data} ht_hidden ON ht_hidden.uid=$user->uid AND ht_hidden.nid=n.nid AND ht_hidden.relation='hidden' WHERE n.status = 1 AND ht_hidden.relation IS NULL AND $path_clause AND weight >= $settings[min_weight] AND weight <= $settings[max_weight] ORDER BY ht.weight, RAND() LIMIT %d"),
112 $settings['how_many']);
113 $block = array();
114 while ($data = db_fetch_object($result)) {
115 $node = node_load($data->nid);
116 if ($body = theme('helptip_body', $node)) {
117 // there is a helptip to display
118 if (!$block['subject'])
119 $block['subject'] = t($settings['title'],
120 array('%title' => check_plain($node->title)));
121 $items[] = $body;
122 }
123 }
124 if (count($items)) {
125 $block['content'] = theme('helptip_list', $items);
126 }
127 return $block;
128 }
129 }
130
131
132 /**
133 * Implementation of hook_help().
134 */
135 function helptip_help($section) {
136 switch ($section) {
137 case 'admin/help#helptip':
138 return t('TODO: Create admin help text.');
139 case 'admin/modules#description':
140 return t('context sensitive help messages (display and edit)');
141 }
142 }
143
144 // some values we'll refer to many times
145 define('HELPTIP_ACCESS_VIEW', 'view help tips');
146 define('HELPTIP_ACCESS_CREATE', 'create help tips');
147 define('HELPTIP_ACCESS_EDIT_OWN', 'edit own help tips');
148 define('HELPTIP_ACCESS_ADMINISTER', 'administer help tips');
149
150
151 /**
152 * Implementation of hook_menu().
153 */
154 function helptip_menu($may_cache) {
155 global $user;
156 $items = array();
157
158 if ($may_cache) {
159 $items[] = array
160 (
161 'path' => 'node/add/helptip',
162 'title' => t('Help Tip'),
163 'access' => user_access(HELPTIP_ACCESS_CREATE),
164 'type' => MENU_NORMAL_ITEM,
165 );
166 $items[] = array
167 (
168 'path' => 'helptip/hide',
169 'title' => t('Hide Help Tip'),
170 'callback' => 'helptip_hide_cb',
171 'access' => user_access(HELPTIP_ACCESS_VIEW),
172 'type' => MENU_CALLBACK,
173 );
174 $items[] = array
175 ('path' => 'admin/settings/helptip',
176 'title' => t('Helptip Settings'),
177 'description' => t('Configure the Helptip module.'),
178 'callback' => 'drupal_get_form',
179 'callback arguments' => 'helptip_settings_form',
180 'access' => user_access(HELPTIP_ACCESS_ADMINISTER),
181 'type' => MENU_NORMAL_ITEM,
182 );
183 }
184
185 return $items;
186 }
187
188 /**
189 * User has requested to hide the given helptip
190 */
191 function helptip_hide_cb($nid) {
192 global $user;
193 if ($user->uid && $nid > 0) {
194 db_query("DELETE FROM {helptip_user_data} WHERE nid=%d AND uid=%d AND relation='hidden'", $nid, $user->uid);
195 db_query("INSERT INTO {helptip_user_data} (nid, uid, relation) VALUES (%d, %d, 'hidden')", $nid, $user->uid);
196 }
197 // copied following from devel module
198 header('Location: '. referer_uri());
199 exit();
200 }
201
202 /**
203 * Implementation of hook_perm().
204 */
205 function helptip_perm() {
206 return array(HELPTIP_ACCESS_CREATE, HELPTIP_ACCESS_EDIT_OWN,
207 HELPTIP_ACCESS_ADMINISTER, HELPTIP_ACCESS_VIEW);
208 }
209
210
211 /**
212 * Implementation of hook_access().
213 */
214 function helptip_access($op, $node) {
215 global $user;
216
217 if (!($ret_val = user_access(HELPTIP_ACCESS_ADMINISTER))) {
218 switch ($op) {
219 case 'create':
220 $ret_val = user_access(HELPTIP_ACCESS_CREATE);
221 break;
222 case 'delete':
223 case 'update':
224 $ret_val = user_access(HELPTIP_ACCESS_EDIT_OWN);
225 break;
226 case 'view':
227 $ret_val = user_access(HELPTIP_ACCESS_VIEW);
228 break;
229 }
230 }
231
232 return $ret_val;
233 }
234
235
236 /**
237 * Implementation of hook_delete().
238 */
239 function helptip_delete(&$node) {
240 db_query("DELETE FROM {helptip} WHERE nid = %d", $node->nid);
241 }
242
243
244 /**
245 * Implementation of hook_form().
246 */
247 function helptip_form(&$node, &$param) {
248 $form['title'] = array('#type' => 'textfield', '#title' => t('Title'), '#required' => TRUE, '#default_value' => $node->title, '#weight' => -5);
249
250 if (!$node->helptip->path) {
251 // for convenience, default path to the previous page
252 global $base_url;
253 $referer = $_SERVER['HTTP_REFERER'];
254 $pattern = "|$base_url\/(\?q=)?([^\?\&]*)|";
255 $result = preg_match($pattern, $referer, $matches);
256 if ($result && (strpos($matches[2], 'node/add') !== 0))
257 $node->helptip->path = $matches[2];
258 }
259
260 $form['helptip'] = array('#tree' => true);
261
262 $form['helptip']['path'] = array('#type' => 'textfield',
263 '#title' => t('Context Sensitive Path'),
264 '#default_value' => $node->helptip->path,
265 '#description' => t('Where to display this help. Use "%" as wildcard.'),
266 '#required' => true);
267
268 $form['helptip']['weight'] = array('#type' => 'weight',
269 '#title' => t('Weight'),
270 '#default_value' => $node->helptip->weight,
271 '#description' => t('When more than one help tip applies to a page, this controls the order in which they are displayed. It may also determine in which block the helptip appears.'),
272 '#required' => false);
273
274 $form['helptip']['settings'] = array('#tree' => true);
275 $form['helptip']['settings']['may_hide'] =
276 array('#type' => 'checkbox',
277 '#title' => t('User May Hide'),
278 '#default_value' => $node->helptip->settings['may_hide'],
279 '#description' => t('Enable "do not show again" link.'));
280
281 $form['body_filter']['body'] = array('#type' => 'textarea', '#title' => t('Body'), '#default_value' => $node->body, '#rows' => 20, '#required' => TRUE);
282 $form['body_filter']['format'] = filter_form($node->format);
283 return $form;
284
285 }
286
287
288 /**
289 * Implementation of hook_insert().
290 */
291 function helptip_insert($node) {
292 $helptip = (object) $node->helptip;
293 db_query("INSERT INTO {helptip} (nid, path, weight, settings) VALUES (%d, '%s', %d, '%s')",
294 $node->nid,
295 $helptip->path,
296 $helptip->weight,
297 serialize($helptip->settings));
298 }
299
300
301 /**
302 * Implementation of hook_update().
303 */
304 function helptip_update($node) {
305 $helptip = (object) $node->helptip;
306 db_query("REPLACE INTO {helptip} (nid, path, weight, settings) VALUES (%d, '%s', %d, '%s')",
307 $node->nid,
308 $helptip->path,
309 $helptip->weight,
310 serialize($helptip->settings));
311 }
312
313 /**
314 * Implementation of hook_load().
315 */
316 function helptip_load($node) {
317 $data = db_fetch_object(db_query('SELECT * FROM {helptip} WHERE nid=%d',
318 $node->nid));
319 $data->settings = unserialize($data->settings);
320 return array('helptip' => $data);
321 }
322
323
324 /**
325 * Implementation of hook_node_info().
326 */
327 function helptip_node_info() {
328 return array('helptip' => array('name' => t('Help Tip'),
329 'module' => 'helptip',
330 'description' => t('A helptip is text which can appear in a block on context-sensitive pages. For example, to provide detailed instructions to users on a specific page.'),
331 ),
332 );
333 }
334
335 /**
336 * Implementation of hook_validate().
337 */
338 function helptip_validate(&$node) {
339 // TODO
340 }
341
342
343 /**
344 * Implementation of hook_view().
345 */
346 function helptip_view(&$node, $teaser = FALSE, $page = FALSE) {
347 $node = node_prepare($node, $teaser);
348 return $node;
349 }
350
351 /**
352 * Provide form for module settings.
353 */
354 function helptip_settings_form() {
355 $form['helptip_num_blocks'] =
356 array('#type' => 'textfield',
357 '#title' => t('Number of blocks'),
358 '#default_value' => variable_get('helptip_num_blocks', 1),
359 '#size' => 1,
360 '#maxlength' => 1,
361 '#description' => t('How many helptip blocks would you like? For example, if you want help tips to appear in the header on some pages, and in a sidebar on others, you need two blocks.'),
362 );
363 return system_settings_form($form);
364 }
365
366 /**
367 * Display the body of the help tip. In this implementation, we show teaser.
368 */
369 function theme_helptip_body($node) {
370 if ($node->teaser = check_markup($node->teaser, $node->format, FALSE)) {
371 // calculate body, too, as it controls the 'read more' link.
372 $node->body = check_markup($node->body, $node->format, FALSE);
373 return '<div class="helptip">' . $node->teaser .
374 theme('helptip_links', $node) . "</div>\n";
375 }
376 }
377
378 /**
379 * This is like hook_links when displaying a node, but applies to
380 * helptips shown in help blocks.
381 *
382 * Responsible for displaying readmore and don't show anymore links
383 */
384 function theme_helptip_links($node) {
385 global $user;
386
387 if ($node->body != $node->teaser) {
388 $links['helptip_read_more'] = array('title' => t('read more'),
389 'attributes' => array('class' => 'read-more',
390 'title' => t('Read the rest of this help tip.')),
391 'href' => "node/$node->nid",
392 );
393 }
394
395 // some helptips can be hidden by the user. Ideally some javascript
396 // will come along and replace this link with an ajaxy thing that
397 // does not require a page reload
398 if ($user->uid &&
399 $node->helptip->settings['may_hide'])
400 $links['helptip_hide'] =
401 array('title' => t('do not show again'),
402 'href' => "helptip/hide/$node->nid",
403 'attributes' => array('title' => t('Do not display this message again'),
404 'class' => 'helptip_hide'),
405 );
406
407 // for admin convenience, let them edit this tip
408 if (user_access(HELPTIP_ACCESS_ADMINISTER) ||
409 ($user->uid == $node->uid && user_access(HELPTIP_ACCESS_EDIT_OWN)))
410 $links['helptip_edit'] =
411 array('title' => t('edit'),
412 'href' => "node/$node->nid/edit",
413 'attributes' => array('title' => t('edit this help tip')),
414 );
415
416 return '<div class="helptip_links">'.theme('links', $links)."</div>\n";
417 }
418
419 /**
420 * If more than one helptip body is being shown, this is how we do it.
421 */
422 function theme_helptip_list($items) {
423 if (count($items) == 1)
424 return $items[0];
425 else
426 return theme('item_list', $items);
427 }
428
429 /**
430 * Returns an array of paths which match the current page,
431 * escaped for use in database queries.
432 */
433 function _helptip_get_current_paths() {
434 $paths = array(db_escape_string($_GET['q']));
435 if ($alias = drupal_lookup_path('alias', $_GET['q']))
436 $paths[] = db_escape_string($alias);
437 return $paths;
438 }

  ViewVC Help
Powered by ViewVC 1.1.2