You are here

discussthis.fields.inc in Discuss This! 7.2

DiscussThis field declaration using Field Types API.

File

discussthis.fields.inc
View source
<?php

/**
 * @file
 * DiscussThis field declaration using Field Types API.
 */

/***************************************************************
 * Field Type API hooks
 ***************************************************************/

/**
 * Implements hook_field_info().
 *
 * Provides the description of the field.
 */
function discussthis_field_info() {
  return array(
    // We name our field as the associative name of the array.
    'field_discussthis' => array(
      'label' => t('DiscussThis link'),
      'description' => t('Provide a DiscussThis link to access discussions.'),
      'default_widget' => 'field_discussthis_form',
      'default_formatter' => 'field_discussthis_link',
    ),
  );
}

/**
 * Implements hook_field_settings_form().
 */
function discussthis_field_settings_form($field, $instance, $has_data) {
}

/**
 * Implements hook_form_alter().
 * 
 * Override the global field configuration form.
 */
function discussthis_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
  if ($form['#field']['type'] == 'field_discussthis') {
    $form['instance']['required']['#default_value'] = TRUE;
    $form['instance']['required']['#disabled'] = TRUE;
    $form['field']['cardinality']['#options'] = array(
      1 => 1,
    );
  }
}

/**
 * Implements hook_field_validate().
 *
 * Not used yet since nothing is to validate for now.
 */
function discussthis_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
}

/**
 * Implements hook_field_is_empty().
 *
 * hook_field_is_emtpy() is where Drupal asks us if this field is empty.
 * Return TRUE if it does not contain data, FALSE if it does. This lets
 * the form API flag an error when required fields are empty.
 */
function discussthis_field_is_empty($item, $field) {

  // @todo Add a return
}

/**
 * Implements hook_field_formatter_info().
 *
 * We need to tell Drupal that we have two different types of formatters
 * for this field. One will change the text color, and the other will
 * change the background color.
 *
 * @see field_example_field_formatter_view()
 */
function discussthis_field_formatter_info() {
  return array(
    // This formatter just displays the link to teh discussion
    'field_discussthis_link' => array(
      'label' => t('Simple text-based link to discussion'),
      'field types' => array(
        'field_discussthis',
      ),
    ),
  );
}

/**
 * Implements hook_field_formatter_view().
 */
function discussthis_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $return_links = array();

  // Lookup for topic nid, if it exists (otherwise we get 0).
  $topic_nid = _discussthis_get_topic($entity->nid);
  switch ($display['type']) {

    // This formatter simply outputs the link to the discussion.
    case 'field_discussthis_link':
      foreach ($items as $delta => $item) {
        $links = array();

        // Verify that the type has a valid discussion forum selected.
        $forum_tid = _discussthis_get_forum($entity->nid, $entity->type);
        if (!$forum_tid) {
          return $links;
        }

        // Get the DiscusssThis! link text.
        $discussthis_link = variable_get('discussthis_link', '');
        if (!$discussthis_link) {
          $discussthis_link = t('Discuss This!');
        }

        // Get the participate in DiscusssThis! link text.
        $participate_link = variable_get('discussthis_participate', '');
        if (!$participate_link) {
          $participate_link = t('Participate in this discussion');
        }

        // If the user is connected and have permission
        if ($entity->uid && user_access('access discuss this links')) {
          if ($topic_nid) {
            $all = _discussthis_comment_num_all($topic_nid);
            if (variable_get('discussthis_showcounts', 1)) {
              $new = comment_num_new($topic_nid);
              $counts = t(' (@new new/@all total)', array(
                '@new' => $new,
                '@all' => $all,
              ));
            }
            $links = array(
              // use "Discuss This!" when no discussion started yet
              '#type' => 'link',
              '#title' => $all == 0 ? $discussthis_link : $participate_link . $counts,
              '#href' => 'node/' . $topic_nid,
              '#attributes' => array(
                '#class' => 'discussthis-link',
                '#title' => t('Participate to the discussion about this page'),
              ),
            );
          }
          elseif ($topic_nid == 0) {

            // Check whether the user has permission to initiate a new topics.
            if (user_access('initiate discuss this topics')) {
              $links = array(
                '#type' => 'link',
                '#title' => $discussthis_link,
                '#href' => 'discussthis/create/' . $entity->nid,
                '#attributes' => array(
                  '#class' => 'discussthis-link',
                  '#title' => t('Start a discussion about this page'),
                  '#rel' => 'nofollow',
                ),
              );
            }
          }
        }
        else {

          // This happens for anonymous users
          // If the user is not logged in, offer him to do so.
          // Otherwise, would have access to the link.
          if (variable_get('discussthis_login', 1) && user_access('access discuss this links')) {
            if ($topic_nid) {
              $all = _discussthis_comment_num_all($topic_nid);
              if (variable_get('discussthis_showcounts', 1)) {
                $new = comment_num_new($topic_nid);
                $counts = t(' (@new new/@all total)', array(
                  '@new' => $new,
                  '@all' => $all,
                ));
              }
              $destination = 'destination=node/' . $topic_nid;
              $appeal = $all == 0 ? $discussthis_link : $participate_link . $counts;
            }
            else {

              // The topic does not exist.
              $destination = 'destination=discussthis/new/' . $entity->nid;
              $appeal = $discussthis_link;
            }
            $attributes = array(
              'class' => 'discussthis-login',
              'title' => t('Log in or register and start a discussion about this page'),
              'rel' => 'nofollow',
            );
            if (variable_get('user_register', 1)) {
              if (variable_get('user_email_verification', 1)) {

                // Users can register themselves but have to go through e-mail verification process
                $href = t('!login or !register to @appeal', array(
                  '!login' => l(t('Log in'), 'user/login', array(
                    'query' => drupal_get_destination(),
                    'attributes' => $attributes,
                  )),
                  '!register' => l(t('Register'), 'user/register'),
                  '@appeal' => $appeal,
                ));
              }
              else {

                // Users can register themselves without e-mail verification
                $href = t('!login or !register to @appeal', array(
                  '!login' => l(t('Log in'), 'user/login', array(
                    'query' => drupal_get_destination(),
                  )),
                  '!register' => l(t('Register'), 'user/register', array(
                    'query' => drupal_get_destination(),
                    'attributes' => $attributes,
                  )),
                  '@appeal' => $appeal,
                ));
              }
            }
            else {

              // Only admins can add new users, no public registration.
              $href = t('!login to @appeal', array(
                '!login' => l('Log in', 'user/login', array(
                  'query' => drupal_get_destination(),
                  'attributes' => $attributes,
                )),
                '@appeal' => $appeal,
              ));
            }
            $links = array(
              '#type' => 'link',
              '#title' => $href,
              '#href' => '',
              '#options' => array(
                'html' => TRUE,
              ),
            );
          }
        }
        $return_links[$delta] = $links;
      }
      break;
  }
  return $return_links;
}

/**
 * Implements hook_field_widget_info().
 *
 * Describe the widget for DisucussThis! field.
 */
function discussthis_field_widget_info() {
  return array(
    'field_discussthis_widget' => array(
      'label' => t('DiscussThis!'),
      'field types' => array(
        'field_discussthis',
      ),
    ),
  );
}

/**
 * Implements hook_field_widget_form().
 *
 * Define the field widget configuration form.
 */
function discussthis_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $value = isset($items[$delta]['rgb']) ? $items[$delta]['rgb'] : '';
  $widget = $element;
  $widget['#delta'] = $delta;
  switch ($instance['widget']['type']) {
    case 'field_discussthis_widget':

      // If the user has no rights to override the Discuss This! settings: return.
      if (!user_access('override discuss this forums')) {
        return;
      }

      // We know it is a node, attempt loading info about it
      // WARNING: $nid can be NULL or 0 when creating a new node.
      $nid = $form['nid']['#value'];
      $type = $form['type']['#value'];

      // Only modify the form if this node type is discussthis-enabled.
      // Note that a type may be turned off, but if the node already
      // had a discussthis post attached to it, then it is still editable
      $forum_tid = _discussthis_get_forum($nid, $type);
      if (!$forum_tid) {
        return;
      }
      $widget += array(
        '#type' => 'fieldset',
        '#title' => t('DiscussThis!'),
        '#element_validate' => array(
          'field_discussthis_form_validate',
        ),
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
        '#tree' => TRUE,
        '#delta' => $delta,
        '#group' => 'additional_settings',
      );
      $name = '';

      // Retrieve the topic nid attached with this node.
      // NOTE: the topic is 0 if no comments as yet been done.
      $topic_nid = _discussthis_get_topic($nid);
      if ($topic_nid) {

        // there is a topic linked, is the node still available?
        $topic = node_load($topic_nid);
        if ($topic) {

          // TODO: also get the name of the forum to display to the user
          $name = '<strong>' . t('Current topic #@nid: @title', array(
            '@title' => $topic->title,
            '@nid' => $topic_nid,
          )) . '</strong><br /><br />';
        }
        else {
          $sql = "DELETE FROM {discussthis} WHERE nid = %d";
          db_delete('discussthis')
            ->condition('nid', $nid)
            ->execute();
          unset($topic_nid);
        }
      }

      // This case is when no topic exists for the current node: ie no yet comment.
      if (!$topic_nid) {

        // Let users override the default module of new discussion
        // (this is not shown unless there is a discussion).
        // Retrieve the , or "No Discuss This!"
        $discussthis_forums = _discussthis_build_forums_selection_list();
        $discussthis_forums[0] = 'No Discuss This!';
        $widget['discussthis_forum'] = array(
          '#type' => 'select',
          '#title' => t('Forum for new discussion'),
          '#required' => TRUE,
          '#description' => t('Select the forum where the first discussion about this node will be created. Or select "No Discuss This!" to prevent discussions on this node. Note: if a topic is attached to this node, then this parameter will have no effect.'),
          '#options' => $discussthis_forums,
          '#default_value' => $forum_tid,
        );
      }

      // let the user assign a forum topic to this node
      // this can be done at the time a node is being created
      // any forum is acceptable (although we could have flags to know whether that's the case...)
      $widget['discussthis_topic'] = array(
        '#type' => 'textfield',
        '#title' => t('Identifier of the forum topic to attach to this node'),
        '#description' => $name . t('Override default topic associated with this node. Leave empty for default topic. Enter a topic name and use autocompletion to associate this node with an existing topic.'),
        '#default_value' => $topic_nid ? $topic_nid : '',
        '#autocomplete_path' => 'discussthis/autocomplete',
        '#maxlength' => 255,
      );
      break;
  }
  $element['discussthis'] = $widget;
  return $element;
}

/**
 * Validate the individual fields and then convert them into a single HTML RGB
 * value as text.
 */
function field_discussthis_form_validate($element, &$form_state) {
  $delta = $element['#delta'];

  // TODO: Isn't there a better way to find out which element?
  $field = $form_state['field'][$element['#field_name']][$element['#language']]['field'];
  $field_name = $field['field_name'];
  if (user_access('override discuss this forums') && isset($form_state['node']->nid)) {
    db_delete('discussthis')
      ->condition('nid', $form_state['node']->nid)
      ->execute();
    if (isset($form_state['values'][$field_name][$element['#language']][$delta]['discussthis'])) {
      $discuss_conf = $form_state['values'][$field_name][$element['#language']][$delta]['discussthis'];
      if (isset($discuss_conf['discussthis_forum']) && $discuss_conf['discussthis_forum']) {
        _discussthis_set_forum($form_state['node']->nid, $form_state['values'][$field_name][$element['#language']][$delta]['discussthis']['discussthis_forum']);
      }
      if (isset($discuss_conf['discussthis_topic']) && $discuss_conf['discussthis_topic']) {
        _discussthis_set_topic($form_state['node']->nid, $form_state['values'][$field_name][$element['#language']][$delta]['discussthis']['discussthis_topic']);
      }
    }
  }
}

/**
 * Implements hook_field_widget_error().
 *
 * hook_field_widget_error() lets us figure out what to do with errors
 * we might have generated in hook_field_validate(). Generally, we'll just
 * call form_error().
 *
 * @see field_example_field_validate()
 * @see form_error()
 */
function discussthis_field_widget_error($element, $error, $form, &$form_state) {
  switch ($error['error']) {
    case 'field_example_invalid':
      form_error($element, $error['message']);
      break;
  }
}