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

Diff of /contributions/modules/bio/bio.module

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

revision 1.7, Wed Feb 14 06:23:31 2007 UTC revision 1.8, Sat Apr 11 01:32:10 2009 UTC
# Line 1  Line 1 
1  <?php  <?php
2  // $Id: bio.module,v 1.6 2007/02/01 18:08:45 vauxia Exp $  // $Id: bio.module,v 1.2.2.28 2008/03/24 19:16:34 dww Exp $
3    
4  /* hook_init()  /**
5     * @file
6     * Bio module optionally creates a "Biography" node per user.
7     *
8     * Use cases for this module include:
9     * - Add a Biography for each of your employees.
10     * - Make user profiles into nodes, for extra functionality.
11     * - Add CCK fields to the user registration form.
12     */
13    
14    // Panels integration.
15    if (module_exists('panels')) {
16      include_once drupal_get_path('module', 'bio') .'/bio_panels.inc';
17    }
18    
19    /**
20     * Implementation of hook_init().
21   */   */
22  function bio_init() {  function bio_init() {
23    if ($_GET['q'] == 'node/add/'.variable_get('bio_nodetype', 'bio')) {    // TODO: This interferes with aggressive caching. Can we do this in
24      // hook_menu() instead? Looks like we'd need to make bio follow after node.
25      // Could cause problems w/ registration and/or CRUD functions.
26    
27      // Don't allow non-admin users to create more than one bio.
28      if ($_GET['q'] == 'node/add/'. bio_get_type()) {
29      if (($nid = bio_for_user()) && !user_access('administer nodes')) {      if (($nid = bio_for_user()) && !user_access('administer nodes')) {
30        drupal_goto('node/'.$nid.'/edit');        drupal_goto('node/'. $nid .'/edit');
31      }      }
32    }    }
33  }  }
34    
35  /* hook_menu()  /**
36     * Implementation of hook_menu().
37   */   */
38  function bio_menu($may_cache) {  function bio_menu($may_cache) {
39      global $user;
40      $items = array();
41    
42    if ($may_cache) {    if ($may_cache) {
43      return array(      $items[] = array(
44        array(        'path'  => 'admin/user/bio',
45          'path'  => 'admin/user/bio',        'title' => t('User biographies'),
46          'title' => t('User biographies'),        'description' => t('User biographies'),
47          'description' => t('User biographies'),        'callback' => 'drupal_get_form',
48          'callback' => 'drupal_get_form',        'callback arguments' => array('bio_settings'),
         'callback arguments' => array('bio_settings'),  
       ),  
49      );      );
50    }    }
51    else {    else {
52      if (variable_get('bio_profile', 0) && (arg(0) == 'user') && (is_numeric(arg(1)))) {      if (variable_get('bio_profile', 0) && (arg(0) == 'user') && (is_numeric(arg(1)))) {
53        $type = variable_get('bio_nodetype','bio');        $type = bio_get_type();
54        $nid  = bio_for_user(arg(1));        $nid  = bio_for_user(arg(1));
55        $node = $nid ? node_load($nid) : (object) array('type' => $type, 'uid' => arg(1)) ;  
56        return array(        // Determine access based on whether user has a bio.
57          array(        if ($nid) {
58            'path'  => 'user/'.arg(1).'/bio',          $node = node_load($nid);
59            'title' => node_get_types('name', $type),          $access = node_access('update', $node);
60            'callback' => 'drupal_get_form',        }
61            'callback arguments' => array($type.'_node_form', $node),        else {
62            'type' => MENU_LOCAL_TASK,          $node = (object) array('type' => $type, 'uid' => arg(1));
63            'access' => node_access('update', $node),          $access = (($user->uid == arg(1)) && node_access('create', $type)) || user_access('administer nodes');
64          ),        }
65          $items[] = array(
66            'path'  => 'user/'. arg(1) .'/bio',
67            'title' => node_get_types('name', $type),
68            'callback' => 'node_page_edit',
69            'callback arguments' => array($node),
70            'type' => MENU_LOCAL_TASK,
71            'access' => $access,
72        );        );
73      }      }
74        elseif (variable_get('bio_profile', 0) && (arg(0) == 'node') && is_numeric(arg(1)) && !arg(2)) {
75          // If we're about to visit a bio node page, but we've got "use bios for profiles" selected,
76          // redirect to the user page.
77          $node = node_load(arg(1));
78          if (user_access('access user profiles') && $node->type == bio_get_type()) {
79            drupal_goto('user/'. $node->uid);
80          }
81        }
82      }
83      return $items;
84    }
85    
86    /**
87     * Implementation of hook_form_alter().
88     */
89    function bio_form_alter($form_id, &$form) {
90      if ($form_id == bio_get_type() .'_node_form' && arg(0) == 'user') {
91        // We're editing the bio in the user area... be sure we end up here when we
92        // finish submission, and disallow changing the author.
93        $account = user_load(array('uid' => arg(1)));
94        $form['#redirect'] = "user/$account->uid";
95        if (isset($form['author']['name'])) {
96          $form['author']['name']['#default_value'] = $account->name;
97          $form['author']['name']['#value'] = $account->name;
98          $form['author']['name']['#disabled'] = TRUE;
99          unset($form['author']['name']['#autocomplete_path']);
100          $form['author']['name']['#description'] = t('This field is disabled. You cannot alter the author of this entry from within the user area.');
101        }
102    }    }
103  }  }
104    
105  /* hook_node_info()  /**
106     * Returns a FAPI form array for use on the user registration form.
107     *
108     * @see bio_user().
109     */
110    function bio_user_register_form() {
111      $form = array();
112      if (variable_get('bio_regstration_form', 0) && module_exists('content')) {
113        $widget_types = _content_widget_types();
114        $fields = _bio_get_fields();
115        $default_values = variable_get('bio_regstration_form_fields', array());
116    
117        // Create a dummy node to pass along to the cck hooks.
118        $node = new stdClass();
119        $node->type = bio_get_type();
120    
121        $bio_type_name = node_get_types('name', bio_get_type());
122        $form['bio_info'] = array(
123          '#type' => 'fieldset',
124          '#title' => t('@bio_type_name information', array('@bio_type_name' => $bio_type_name)),
125        );
126    
127        foreach ($fields as $field_name => $field) {
128          if ($field['required'] || !empty($default_values[$field_name])) {
129            $node_field = content_default_value($node, $field, array());
130    
131            // Figure out what widget function to call.
132            $module = $widget_types[$field['widget']['type']]['module'];
133            $function = $module .'_widget';
134    
135            // Get the form field and add it to the form.
136            $cck_field = $function('prepare form values', $node, $field, $node_field);
137            $cck_field = $function('form', $node, $field, $node_field);
138            $form['bio_info'][] = $cck_field;
139          }
140        }
141    
142        // Add custom validate handler.
143        $form['#validate']['bio_user_register_validate'] = array();
144      }
145      return $form;
146    }
147    
148    /**
149     * Validate handler for user registration form. Validate CCK fields.
150     */
151    function bio_user_register_validate($form_id, $form_values) {
152      // Create a dummy node to pass along to CCK.
153      $node = new stdClass();
154      $node->type = bio_get_type();
155      foreach ($form_values as $field_name => $value) {
156        if (preg_match('/^field_/', $field_name)) {
157          $node->$field_name = $form_values[$field_name];
158        }
159      }
160    
161      // Call validation routines on the CCK fields.
162      content_validate($node);
163    }
164    
165    /**
166     * Submit handler for user registration form. Automatically creates a bio node
167     * on registration if any bio fields are set to show on the registration form.
168     */
169    function bio_user_register_submit($form_values) {
170      // Create bio node for this user.
171      $node = new StdClass;
172      $node->type = bio_get_type();
173      $node->uid = db_result(db_query("SELECT uid FROM {users} WHERE name = '%s'", $form_values['name']));
174      $node->title = $form_values['name'];
175      $node->name = $form_values['name'];
176      node_object_prepare($node);
177    
178      $node_options = variable_get('node_options_'. $node->type, array('status', 'promote'));
179      foreach (array('status', 'promote', 'sticky') as $key) {
180        $node->$key = in_array($key, $node_options);
181      }
182      // Always use the default revision setting.
183      $node->revision = in_array('revision', $node_options);
184    
185      foreach ($form_values as $field_name => $value) {
186        if (preg_match('/^field_/', $field_name)) {
187          $node->$field_name = $form_values[$field_name];
188        }
189      }
190    
191      // Create the node.
192      $node = node_submit($node);
193      node_save($node);
194    
195      // Give us a nice log message.
196      if ($node->nid) {
197        watchdog('content', t('Bio: added %user bio upon registration.', array('%user' => $node->name)), WATCHDOG_NOTICE, l(t('view'), "node/$node->nid"));
198      }
199    }
200    
201    /**
202     * Implementation of hook_profile_alter().
203     */
204    function bio_profile_alter(&$account, &$fields) {
205      // Replace user profile with user bio.
206      if (variable_get('bio_profile_takeover', 0) && $bio = bio_for_user($account->uid)) {
207        $bio = node_load($bio);
208        $typename = node_get_types('name', bio_get_type());
209        foreach ($fields as $key => $val) {
210          if ($key != $typename) {
211            unset($fields[$key]);
212          }
213        }
214        $account->name = $bio->title;
215      }
216    }
217    
218    /**
219     * Implementation of hook_node_info().
220   */   */
221  function bio_node_info() {  function bio_node_info() {
222    // The default bio node type is simple so we'll just use node as the base.    if (bio_get_type() == 'bio') {
223    if (variable_get('bio_nodetype', 'bio') == 'bio') {      // Create a default bio type that's as simple as possible.
224      return array('bio' => array(      return array(
225        'name' => t('Biography'),        'bio' => array(
226        'module' => 'node',          'name' => t('Biography'),
227        'has_title' => TRUE,          'module' => 'node',
228        'has_body' => TRUE,          'has_title' => TRUE,
229        'custom' => TRUE,          'has_body' => TRUE,
230        'modified' => TRUE,          'custom' => TRUE,
231        'locked' => FALSE,          'modified' => TRUE,
232      ));          'locked' => FALSE,
233          ),
234        );
235    }    }
236  }  }
237    
238  /* hook_nodeapi()  /**
239     * Implementation of hook_nodeapi().
240   */   */
241  function bio_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {  function bio_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
242    if ($node->type != variable_get('bio_nodetype', 'bio')) return;    if ($node->type != bio_get_type()) return;
243    
244    switch ($op) {    switch ($op) {
245      case 'validate':      case 'validate':
246        // This user already has a bio node and this isn't it        // Ensure this user doesn't already have a bio node.
247        $nid = bio_for_user($node->uid);        $account = user_load(array('name' => $node->name));
248          $nid = bio_for_user($account->uid);
249        if ($nid && ($nid != $node->nid)) {        if ($nid && ($nid != $node->nid)) {
250          form_set_error('name', t('This user already has a @bio. Edit it <a href="@link">here</a> or assign this entry to another user.', array('@bio' => node_get_types('name', $node), '@link' => url('node/'.$nid.'/edit'))));          form_set_error('name', t('This user already has a @bio. Edit it <a href="@link">here</a> or assign this entry to another user.', array('@bio' => node_get_types('name', $node), '@link' => url('node/'. $nid .'/edit'))));
251        }        }
252          break;
253        case 'insert':
254          // Record user's bio in bio table.
255          db_query('INSERT INTO {bio} (nid, uid) VALUES (%d, %d)', $node->nid, $node->uid);
256          break;
257        case 'delete':
258          // Remove the user's entry from the bio table when the user is deleted.
259          db_query('DELETE FROM {bio} where nid = %d', $node->nid);
260        break;        break;
261    }    }
262  }  }
263    
264  /* hook_user()  /**
265     * Implementation hook_user().
266   */   */
267  function bio_user($op, &$edit, &$user, $category = NULL) {  function bio_user($op, &$edit, &$account, $category = NULL) {
268    if (!variable_get('bio_profile', 0)) return;    // If there's no bio for this user, nothing to do here.
269      if ($op != 'register' &&  $op != 'insert' && !$nid = bio_for_user($account->uid)) {
270        return;
271      }
272    
273    switch ($op) {    switch ($op) {
274      case 'view':      case 'view':
275        if (!$nid = bio_for_user($user->uid)) return;        // Add bio to main user profile page, if option is enabled and bio is accessible.
276        if (!node_access('view', $node = node_load($nid))) return;        if (variable_get('bio_profile', 0) && node_access('view', $node = node_load($nid))) {
277        return array($name => array('bio' => array( 'value' => node_view($node, FALSE, TRUE, FALSE))));          $name = node_get_types('name', bio_get_type());
278            $bio[$name]['bio']['value'] = node_view($node, FALSE, TRUE, FALSE);
279            return $bio;
280          }
281          break;
282    
283        case 'delete':
284          node_delete($nid);
285          break;
286    
287        case 'update':
288          // Publish or unpublish the bio node on changes to the user's status
289          // (active vs. blocked).
290          if (isset($edit['status']) && $edit['status'] != $account->status) {
291            $node = node_load($nid);
292            $node->status = (int)$edit['status'];
293            node_save($node);
294          }
295          break;
296    
297        case 'register':
298          // Display CCK fields on the user registration form, if they've been
299          // marked as such.
300          return bio_user_register_form();
301          break;
302    
303        case 'insert':
304          return bio_user_register_submit($edit);
305          break;
306    }    }
307  }  }
308    
309  /* hook_link()  /**
310     * Implementation of hook_link().
311   */   */
312  function bio_link($type, $node = NULL, $teaser = FALSE) {  function bio_link($type, $node = NULL, $teaser = FALSE) {
313    if ($type == 'node' && $node->type != variable_get('bio_nodetype', 'bio')) {    if ($type == 'node' && $node->type != bio_get_type()) {
314        // Add "View *username*'s biography" link to nodes.
315      $bio_link = variable_get('bio_link', array($node->type => 1));      $bio_link = variable_get('bio_link', array($node->type => 1));
316      if ($bio_link[$node->type] && ($nid = bio_for_user($node->uid))) {      if ($bio_link[$node->type] && ($nid = bio_for_user($node->uid))) {
317        $user = user_load(array('uid' => $node->uid));        $account = user_load(array('uid' => $node->uid));
318        return array('bio' => array(        return array(
319          'title' => t('by @user', array('@user' => $user->name)),          'bio' => array(
320          'href'  => 'node/'.$nid,            'title' => t('by @user', array('@user' => $account->name)),
321          'attributes' => array('title' => t('View @user\'s biography.', array('@user' => $user->name)))));            'href'  => 'node/'. $nid,
322              'attributes' => array(
323                'title' => t('View @user\'s @bio.', array('@user' => $account->name, '@bio' => node_get_types('name', bio_get_type()))),
324              ),
325            ),
326          );
327      }      }
328    }    }
329  }  }
330    
331  function bio_for_user($uid = NULL){  /**
332    if (is_null($uid)){   * Find bio for given user.
333     *
334     * @param $uid
335     *   User ID.
336     * @return
337     *   Node ID of bio, or FALSE if no bio node was found.
338     */
339    function bio_for_user($uid = NULL) {
340      if (is_null($uid)) {
341      global $user;      global $user;
342      $uid = $user->uid;      $uid = $user->uid;
343    }    }
344    return db_result(db_query("SELECT nid FROM {node} WHERE uid = %d AND type = '%s'", $uid, variable_get('bio_nodetype', 'bio')));  
345      return db_result(db_query('SELECT nid FROM {bio} WHERE uid = %d', $uid));
346  }  }
347    
348    /**
349     * Menu callback; administration settings page.
350     */
351  function bio_settings() {  function bio_settings() {
352      // Bio node type.
353    $types = array();    $types = array();
354    foreach(node_get_types() as $key => $type) {    foreach (node_get_types() as $key => $type) {
355      $types[$key] = $type->name;      $types[$key] = $type->name;
356    }    }
   $form = array();  
357    $form['bio_nodetype'] = array(    $form['bio_nodetype'] = array(
358      '#type' => 'select',      '#type' => 'select',
359      '#title' => t('Content type for user biographies'),      '#title' => t('Content type for user biographies'),
360      '#description' => t('The content type for user biographies.  Each user may create only one node of this type'),      '#description' => t('The content type for user biographies. Each user may create only one node of this type'),
361      '#options' => $types,      '#options' => $types,
362      '#default_value' => variable_get('bio_nodetype', 'bio'),      '#default_value' => bio_get_type(),
363    );    );
364    
365      // Link to author's bio.
366    $form['bio_link'] = array(    $form['bio_link'] = array(
367      '#type' => 'checkboxes',      '#type' => 'checkboxes',
368      '#title' => t('Display bio link'),      '#title' => t('Display bio link'),
369      '#description' => t('Display a link to author\'s bio if it is available.'),      '#description' => t("Display a link to author's bio if it is available."),
370      '#options' => $types,      '#options' => $types,
371      '#default_value' => variable_get('bio_link', $types),      '#default_value' => variable_get('bio_link', $types),
372    );    );
373    
374      // Bio profile options.
375    $form['bio_profile'] = array(    $form['bio_profile'] = array(
376      '#type' => 'checkbox',      '#type' => 'checkbox',
377      '#title' => t('Use bio for user profiles'),      '#title' => t('Use bio for user profiles'),
378      '#description' => t('View and edit biography information on the user account page.'),      '#description' => t('View, edit, and display biography information on the user account page.'),
379      '#default_value' => variable_get('bio_profile', 0),      '#default_value' => variable_get('bio_profile', 0),
380    );    );
381    return system_settings_form($form);    $form['bio_profile_takeover'] = array(
382        '#type' => 'checkbox',
383        '#title' => t('Takeover profile.'),
384        '#description' => t('Display nothing but the bio node on the user profile page.'),
385        '#default_value' => variable_get('bio_profile_takeover', 0),
386      );
387    
388      // Show fields on the registration form.
389      if (module_exists('content')) {
390        $form['bio_regstration_form'] = array(
391          '#type' => 'radios',
392          '#title' => t('Show fields on registration form'),
393          '#options' => array(t('Disabled'), t('Enabled')),
394          '#default_value' => variable_get('bio_regstration_form', 0),
395          '#description' => t('Enable this option to display bio fields on the user registration form. This will automatically create a bio record for a user when they register.'),
396        );
397    
398        // Determine the options and default values.
399        $fields = _bio_get_fields();
400        $default_values = variable_get('bio_regstration_form_fields', array());
401        foreach ($fields as $field_name => $properties) {
402          $options[$field_name] = check_plain($properties['widget']['label']);
403          // Required fields are always shown on registration form.
404          if ($properties['required'] || !empty($default_values[$field_name])) {
405            $default_values[$field_name] = $field_name;
406          }
407          else {
408            $default_vales[$field_name] = 0;
409          }
410        }
411        // Display list of fields.
412        $form['bio_regstration_form_fields'] = array(
413          '#type' => 'checkboxes',
414          '#title' => t('Registration form fields'),
415          '#options' => $options,
416          '#default_value' => $default_values,
417          '#description' => t('Fields checked here will be displayed on the user registration form. Required fields are always shown.'),
418          '#theme' => 'bio_registration_fields',
419        );
420      }
421    
422      // Strange hack for invalidating Views cache.
423      $add_a_submit = system_settings_form($form);
424      $add_a_submit['#validate']['bio_settings_validate_xxx'] = array();
425      return $add_a_submit;
426    }
427    
428    /**
429     * Theme function for bio registration form options that adds a disabled flag
430     * to required fields.
431     *
432     * @ingroup themeable
433     */
434    function theme_bio_registration_fields($form) {
435      $fields = _bio_get_fields();
436      foreach (element_children($form) as $field_name) {
437        // Disable required fields; they always show up.
438        if ($fields[$field_name]['required']) {
439          $form[$field_name]['#attributes'] = array('disabled' => 'disabled');
440          $form[$field_name]['#value'] = $field_name;
441        }
442      }
443    
444      return drupal_render($form);
445    }
446    
447    /**
448     * Invalidate Views cache when bio settings form is submitted.
449     *
450     * This is required in case the bio node type has changed. We need the _xxx
451     * suffix to keep it from interfering with the #base in system_settings_form().
452     * Also, we do it in the validate phase because submits were interfering with
453     * the #base attribute. Yuck.
454     *
455     * @todo Less hackish way to do this?
456     */
457    function bio_settings_validate_xxx($form_id, $form_values) {
458      if (module_exists('views')) {
459        views_invalidate_cache();
460      }
461    }
462    
463    /**
464     * Retrieve field info for Bio CCK type.
465     */
466    function _bio_get_fields() {
467      $bio_nodetype = bio_get_type();
468      $type = content_types($bio_nodetype);
469      return $type['fields'];
470    }
471    
472    /**
473     * Short-hand function to return bio node type.
474     *
475     * @return $string
476     *   Node type short name currently assigned as the Bio type.
477     */
478    function bio_get_type() {
479      return variable_get('bio_nodetype', 'bio');
480    }
481    
482    /*
483     * Views integration for Bio module.
484     *
485     * Bio module's Views integration works by cloning many features of Views
486     * module's existing node integration. To avoid a large amount of code being
487     * loaded on every page, these functions therefore merely call private
488     * functions in bio_views.inc.
489     */
490    
491    /**
492     * Implementation of hook_views_table_alter().
493     *
494     * @see _bio_views_tables_alter()
495     */
496    function bio_views_tables_alter(&$tables) {
497      require_once drupal_get_path('module', 'bio') .'/bio_views.inc';
498      return _bio_views_tables_alter($tables);
499    }
500    
501    /**
502     * Copy of views_handler_filter_isnew($op, $filter, $filterinfo, &$query)
503     *
504     * @see _bio_handler_filter_isnew()
505     */
506    function bio_handler_filter_isnew($op, $filter, $filterinfo, &$query) {
507      require_once drupal_get_path('module', 'bio') .'/bio_views.inc';
508      return _bio_handler_filter_isnew($op, $filter, $filterinfo, $query);
509    }
510    
511    /**
512     * Implementation of hook_views_query_alter().
513     *
514     * @see _bio_views_query_alter()
515     */
516    function bio_views_query_alter(&$query, $view, $summary, $level) {
517      require_once drupal_get_path('module', 'bio') .'/bio_views.inc';
518      return _bio_views_query_alter($query, $view, $summary, $level);
519    }
520    
521    /**
522     * Implementation of hook_views_default_views().
523     *
524     * @see _bio_views_default_views()
525     */
526    function bio_views_default_views() {
527      require_once drupal_get_path('module', 'bio') .'/bio_views.inc';
528      return _bio_views_default_views();
529    }
530    
531    /**
532     * Implementation of hook_views_tables().
533     *
534     * @see _bio_views_tables()
535     */
536    function bio_views_tables() {
537      require_once drupal_get_path('module', 'bio') .'/bio_views.inc';
538      return _bio_views_tables();
539  }  }

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.8

  ViewVC Help
Powered by ViewVC 1.1.2