You are here

nodesinblock.module in Nodes In Block 6

Same filename and directory in other branches
  1. 7 nodesinblock.module

Nodes in block makes it possible to add multiple nodes in one block.

File

nodesinblock.module
View source
<?php

/**
 * @file
 * Nodes in block makes it possible to add multiple nodes in one block.
 */
define('NIB_RENDER_TEASER_WITH_LINKS', '1');
define('NIB_RENDER_PAGE_WITH_LINKS', '2');
define('NIB_RENDER_TEASER_WITHOUT_LINKS', '3');
define('NIB_RENDER_PAGE_WITHOUT_LINKS', '4');

/**
 * Implementation of hook_perm().
 */
function nodesinblock_perm() {
  return array(
    'administer nodes in block configuration',
    'administer nodes in block queue',
    'deny configuration on node form',
  );
}

/**
 * Implementation of hook_theme().
 */
function nodesinblock_theme() {
  return array(
    'nodesinblock_queue' => array(
      'arguments' => array(
        'form' => NULL,
      ),
    ),
  );
}

/**
 * Implementation of hook_menu().
 */
function nodesinblock_menu() {
  $items = array();
  $items['node/%node/nodesinblock'] = array(
    'title' => 'Nodes in block',
    'description' => 'Nodes in block queue.',
    'title callback' => 'nodesinblock_tabtitle',
    'title arguments' => array(
      1,
    ),
    'page callback' => 'nodesinblock_nodequeue',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'nodesinblock_nodequeue_access',
    'access arguments' => array(
      1,
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
  );
  $items['admin/settings/nodesinblock'] = array(
    'title' => 'Nodes in block',
    'description' => 'Configure settings for nodes in block.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'nodesinblock_settings',
    ),
    'access arguments' => array(
      'administer nodes in block configuration',
    ),
    'file' => 'nodesinblock.admin.inc',
  );
  $items['admin/settings/nodesinblock/default'] = array(
    'title' => 'Configuration',
    'description' => 'Configure settings for node in block.',
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items['admin/settings/nodesinblock/queue'] = array(
    'title' => 'Queue',
    'description' => 'Nodes in block queue.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'nodesinblock_queue',
    ),
    'access arguments' => array(
      'administer nodes in block queue',
    ),
    'file' => 'nodesinblock.admin.inc',
    'type' => MENU_LOCAL_TASK,
  );
  $items['admin/settings/nodesinblock/clear'] = array(
    'title' => 'Clear settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'nodesinblock_settings_clear_confirm',
    ),
    'access arguments' => array(
      'administer nodes in block configuration',
    ),
    'file' => 'nodesinblock.admin.inc',
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implementation of hook_form_alter().
 * Add Nodes in block fieldset.
 */
function nodesinblock_form_alter(&$form, $form_state, $form_id) {
  $saved_types = variable_get('nodesinblock_contenttypes', array());
  if (isset($form['#node']) && $form['#node']->type . '_node_form' == $form_id && isset($saved_types[$form['#node']->type]) && $saved_types[$form['#node']->type] != '0') {
    $a = 1;
    $i = 0;
    $block_options[-1] = t('None');
    $deltas = variable_get('nodesinblock_' . $form['#node']->type . '_block', array());
    foreach ($deltas as $key => $value) {
      if ($deltas[$a] != 0) {
        $block_name = check_plain(variable_get('nodesinblock_friendlyname_' . $i, t('Nodes in block ' . $a)));
        $type = variable_get('nodesinblock_visibility_' . $i, '1') == '1' ? t('(Pos)') : t('(Neg)');
        $block_options[$i] = $block_name . ' ' . $type;
      }
      $a++;
      $i++;
    }
    if (!empty($block_options)) {
      $node_info = array(
        'weight' => 0,
        'visibility' => '*',
        'delta' => -1,
        'render' => NIB_RENDER_PAGE_WITHOUT_LINKS,
      );
      if (!empty($form_state['values'])) {
        $node_info['visibility'] = $form_state['values']['nodesinblock_visibility'];
        $node_info['weight'] = $form_state['values']['nodesinblock_weight'];
        $node_info['delta'] = $form_state['values']['nodesinblock_delta'];
        $node_info['render'] = $form_state['values']['nodesinblock_render'];
      }
      elseif (!empty($form['nid']['#value'])) {
        $node_info = db_fetch_array(db_query("SELECT * FROM {nodesinblock} WHERE nid = %d", $form['nid']['#value']));
      }
      else {
        if (variable_get('nodesinblock_referer', FALSE) && isset($_SERVER['HTTP_REFERER'])) {
          $end = '';
          if (substr($_SERVER['HTTP_REFERER'], -1) === '/') {
            $end = '/';
          }
          $base = url(NULL, array(
            'absolute' => TRUE,
          )) . $end;
          if (strpos($_SERVER['HTTP_REFERER'], $base) === 0) {
            $node_info['visibility'] = str_replace($base, '', $_SERVER['HTTP_REFERER']);
          }
        }
        $node_info['render'] = '';
      }
      $form['nodesinblock'] = array(
        '#type' => 'fieldset',
        '#title' => check_plain(variable_get('nodesinblock_' . $form['#node']->type . '_label', t('Nodes in block'))),
        '#collapsible' => variable_get('nodesinblock_' . $form['#node']->type . '_collapsible', TRUE),
        '#collapsed' => variable_get('nodesinblock_' . $form['#node']->type . '_collapsed', TRUE),
      );
      $nodesinblock_enable = TRUE;
      if (user_access('deny configuration on node form') && $GLOBALS['user']->uid != 1) {
        $nodesinblock_enable = FALSE;
        $form['nodesinblock']['#access'] = FALSE;
      }
      $form['nodesinblock']['nodesinblock_enable'] = array(
        '#type' => 'hidden',
        '#value' => $nodesinblock_enable,
      );
      $form['nodesinblock']['nodesinblock_delta'] = array(
        '#type' => 'select',
        '#title' => t('Select region'),
        '#options' => $block_options,
        '#default_value' => $node_info['delta'],
        '#description' => t('The code between the round brackets indicate the visibility setting of the block.<br />Pos = Show on only the listed pages.<br />Neg = Show on every page except the listed pages.'),
      );
      $form['nodesinblock']['nodesinblock_weight'] = array(
        '#type' => 'value',
        '#value' => $node_info['weight'],
      );
      $form['nodesinblock']['nodesinblock_render'] = array(
        '#type' => 'select',
        '#title' => t('Render node as'),
        '#options' => _nodesinblock_render_status(0),
        '#default_value' => $node_info['render'],
      );
      if (variable_get('nodesinblock_' . $form['#node']->type . '_render', '0') != '0') {
        $form['nodesinblock']['nodesinblock_render']['#type'] = 'value';
        $form['nodesinblock']['nodesinblock_render']['#value'] = variable_get('nodesinblock_' . $form['#node']->type . '_render', 0);
      }
      $form['nodesinblock']['nodesinblock_visibility'] = array(
        '#title' => t('Visibility'),
        '#type' => 'textarea',
        '#description' => t('Enter one page per line as Drupal paths. The \'*\' character is a wildcard. Example paths are blog for the blog page and blog/* for every personal blog. &lt;front&gt; is the front page.'),
        '#default_value' => $node_info['visibility'],
        '#wysiwyg' => FALSE,
      );
    }
  }
}

/**
 * Implementation of hook_nodeapi().
 */
function nodesinblock_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {

  // Save nodesinblock settings.
  if (isset($node->nodesinblock_enable)) {
    switch ($op) {
      case 'validate':
        _nodesinblock_validate($node);
        break;
      case 'insert':
      case 'update':
        _nodesinblock_save($node, $op);
        break;
    }
  }

  // Delete nodesinblock data.
  if ($op == 'delete') {
    _nodeisblock_load($node);
    if (isset($node->nodesinblock)) {
      $node->nodesinblock_delta = $node->nodesinblock;
      _nodesinblock_save($node, 'delete');
    }
  }
}

/**
 * Implementation of hook_block().
 */
function nodesinblock_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      $number_of_blocks = variable_get('nodesinblock_nrofblocks', 1);
      for ($i = 0, $a = 1; $i < $number_of_blocks; $i++, $a++) {
        $blocks[$i] = array(
          'info' => check_plain(variable_get('nodesinblock_friendlyname_' . $i, t('Nodes in block ' . $a))),
          'weight' => 0,
          'enabled' => 0,
          'region' => 'left',
          'cache' => BLOCK_CACHE_PER_PAGE,
        );
      }
      return $blocks;
      break;
    case 'view':
      $a = $delta + 1;
      $block = array(
        'subject' => check_plain(variable_get('nodesinblock_friendlyname_' . $delta, t('Nodes in block ' . $a))),
        'content' => _nodesinblock_show($delta, variable_get('nodesinblock_visibility_' . $delta, '1')),
      );
      return $block;
      break;
  }
}

/**
 * Tab title.
 *
 * @param stdClass $node The current node.
 * @return title.
 */
function nodesinblock_tabtitle($node) {
  $i = $node->nodesinblock;
  $a = $i + 1;
  $title = check_plain(variable_get('nodesinblock_friendlyname_' . $i, t('Nodes in block ' . $a)));
  return $title;
}

/**
 * Access callback: check that user has access to configure nodes in block queue.
 *
 * @param stdClass $node The current node.
 * @return TRUE or FALSE
 */
function nodesinblock_nodequeue_access($node) {
  _nodeisblock_load($node);
  $saved_types = variable_get('nodesinblock_contenttypes', array());
  if (node_access('update', $node) && user_access('administer nodes in block queue') && isset($node->nodesinblock) && isset($saved_types[$node->type]) && $saved_types[$node->type] != '0') {
    return TRUE;
  }
  return FALSE;
}

/**
 * Nodes in block queue tab.
 */
function nodesinblock_nodequeue($node) {
  module_load_include('inc', 'nodesinblock', 'nodesinblock.admin');
  return drupal_get_form('nodesinblock_queue', $node->nodesinblock, FALSE, FALSE);
}

/**
 * Function callback: validate node. Returns error if visibility is empty and status is enabled.
 */
function _nodesinblock_validate($node) {
  $visibility = $node->nodesinblock_visibility;
  if ($node->nodesinblock_delta != -1 && empty($visibility)) {
    form_set_error('nodesinblock_visibility', t('Visibility field is required.'));
  }
}

/**
 * Helper function to return the status.
 *
 * @param integer $status The current status of a node.
 * @param boolean $return Whether to return the complete array or a string.
 * @return string or array Complete array or Human name of render status.
 */
function _nodesinblock_render_status($status, $return = FALSE) {
  static $render_states = array();
  if (empty($render_states)) {
    $render_states = array(
      NIB_RENDER_TEASER_WITH_LINKS => t('Teaser with links'),
      NIB_RENDER_TEASER_WITHOUT_LINKS => t('Teaser without links'),
      NIB_RENDER_PAGE_WITH_LINKS => t('Page with links'),
      NIB_RENDER_PAGE_WITHOUT_LINKS => t('Page without links'),
    );

    // Node Displays support.
    if (module_exists('nd')) {
      $render_states = array();
      if (function_exists('ds_get_build_modes')) {
        $build_modes = ds_get_build_modes('nd');
        foreach ($build_modes as $key => $build_mode) {
          $render_states[$key] = $build_mode['title'];
        }
      }
      else {

        // For the sake of people who might use very older versions.
        $build_modes = nd_get_build_modes();
        foreach ($build_modes as $key => $build_mode) {
          $render_states[$key] = $build_mode['build modes'][$key]['title'];
        }
      }
    }
  }
  if ($return == TRUE) {
    return $render_states[$status];
  }
  else {
    return $render_states;
  }
}

/**
 * Helper function to load node data for nodesinblock.
 */
function _nodeisblock_load(&$node) {
  $delta = db_fetch_object(db_query("SELECT delta, nid FROM {nodesinblock} WHERE nid = %d", $node->nid));
  if (isset($delta->nid)) {
    $node->nodesinblock = $delta->delta;
  }
}

/**
 * Function callback: save node settings into nodesinblock table and update block visibility pages.
 */
function _nodesinblock_save($node, $op) {

  // Delete old record.
  db_query("DELETE FROM {nodesinblock} WHERE nid = %d", $node->nid);

  // Save if node is not deleted
  if ($op != 'delete' && $node->nodesinblock_delta != -1) {
    $nodeinblock = new stdClass();
    $nodeinblock->nid = $node->nid;
    $nodeinblock->delta = $node->nodesinblock_delta;
    $nodeinblock->weight = $node->nodesinblock_weight;
    $nodeinblock->visibility = trim($node->nodesinblock_visibility);
    $nodeinblock->render = $node->nodesinblock_render;
    drupal_write_record('nodesinblock', $nodeinblock);
  }

  // Get visibility paths.
  $visibility = array();
  $result = db_query("SELECT visibility FROM {nodesinblock} nib INNER JOIN {node} n on n.nid = nib.nid WHERE nib.delta = %d AND n.status = 1", $node->nodesinblock_delta);
  while ($row = db_fetch_object($result)) {
    $node_visibility = explode("\n", $row->visibility);
    foreach ($node_visibility as $path) {
      $visibility[] = trim($path);
    }
  }

  // Update blocks table.
  $visibility = array_unique($visibility);
  db_query("UPDATE {blocks} set visibility = %d, pages = '%s' WHERE module = 'nodesinblock' AND delta = %d", variable_get('nodesinblock_visibility_' . $node->nodesinblock_delta, '1'), implode("\n", $visibility), $node->nodesinblock_delta);
}

/**
 * Function callback: get content for a block.
 */
function _nodesinblock_show($delta, $visibility) {
  static $nids = array();
  $output = '';
  $path = drupal_get_path_alias($_GET['q']);
  $query = "SELECT nib.nid, visibility, render, weight FROM {nodesinblock} nib\n    LEFT JOIN {node} n on n.nid = nib.nid\n    WHERE n.status = 1 AND delta = %d\n    ORDER BY weight\n  ";
  $i = 0;
  $result = db_query(db_rewrite_sql($query), $delta);
  $num_items = db_affected_rows();
  while ($row = db_fetch_object($result)) {
    $paths = explode("\n", trim($row->visibility));
    foreach ($paths as $key => $val) {

      // Match the path.
      $page_match = drupal_match_path($path, $val);
      if ($path != $_GET['q']) {
        $page_match = $page_match || drupal_match_path($_GET['q'], $val);
      }
      $page_match = !($visibility xor $page_match);

      // We have a match, load the node.
      if ($page_match && !isset($nids[$delta][$row->nid])) {
        $nids[$delta][$row->nid] = $row->nid;
        $node = node_load($row->nid);
        $node->nodesinblock = 1;

        // In case the the render selection has changed, make sure
        // we select the exact render mode.
        if (variable_get('nodesinblock_' . $node->type . '_render', '0') != '0') {
          $row->render = variable_get('nodesinblock_' . $node->type . '_render', '0');
        }

        // Assemble classes.
        $classes = array(
          'nodesinblock',
        );
        if ($i == 0) {
          $classes[] = 'first';
        }
        if ($i == $num_items - 1) {
          $classes[] = 'last';
        }
        if ($i % 2 == 0) {
          $classes[] = 'odd';
        }
        else {
          $classes[] = 'even';
        }
        $i++;
        $output .= '<div class="' . implode(' ', $classes) . '" id="nodesinblock-' . $node->nid . '">';

        // Support for Node Displays module.
        if (module_exists('nd')) {
          $node->build_mode = $row->render;
          $teaser = $node->build_mode != 'full' ? TRUE : FALSE;
          $show_links = ds_show_field('nd', $node->type, $node->build_mode, 'links');
          $output .= node_view($node, $teaser, FALSE, $show_links);
        }
        else {
          $links = FALSE;
          if ($row->render == NIB_RENDER_PAGE_WITH_LINKS || $row->render == NIB_RENDER_TEASER_WITH_LINKS) {
            $links = TRUE;
          }
          $output .= $row->render == NIB_RENDER_TEASER_WITH_LINKS || $row->render == NIB_RENDER_TEASER_WITHOUT_LINKS ? node_view($node, TRUE, FALSE, $links) : node_view($node, FALSE, TRUE, $links);
        }
        if (variable_get('nodesinblock_editbuttons', 0) && node_access('update', $node)) {
          $edit_button = variable_get('nodesinblock_editbuttons_text', t('(edit)'));
          $output .= l(t($edit_button), 'node/' . $node->nid . '/edit', array(
            'query' => array(
              'destination' => $path,
            ),
            'attributes' => array(
              'class' => 'nodesinblock-edit',
            ),
          ));
        }
        $output .= '</div>';
      }
    }
  }
  return $output;
}

Functions

Namesort descending Description
nodesinblock_block Implementation of hook_block().
nodesinblock_form_alter Implementation of hook_form_alter(). Add Nodes in block fieldset.
nodesinblock_menu Implementation of hook_menu().
nodesinblock_nodeapi Implementation of hook_nodeapi().
nodesinblock_nodequeue Nodes in block queue tab.
nodesinblock_nodequeue_access Access callback: check that user has access to configure nodes in block queue.
nodesinblock_perm Implementation of hook_perm().
nodesinblock_tabtitle Tab title.
nodesinblock_theme Implementation of hook_theme().
_nodeisblock_load Helper function to load node data for nodesinblock.
_nodesinblock_render_status Helper function to return the status.
_nodesinblock_save Function callback: save node settings into nodesinblock table and update block visibility pages.
_nodesinblock_show Function callback: get content for a block.
_nodesinblock_validate Function callback: validate node. Returns error if visibility is empty and status is enabled.

Constants

Namesort descending Description
NIB_RENDER_PAGE_WITHOUT_LINKS
NIB_RENDER_PAGE_WITH_LINKS
NIB_RENDER_TEASER_WITHOUT_LINKS
NIB_RENDER_TEASER_WITH_LINKS @file Nodes in block makes it possible to add multiple nodes in one block.