You are here

radioactivity_node.module in Radioactivity 6

Same filename and directory in other branches
  1. 5 plugins/radioactivity_node.module

Node radioactivity

File

plugins/radioactivity_node.module
View source
<?php

/**
 * @file
 * Node radioactivity
 */
function radioactivity_node_perm() {
  return array(
    'administer node energy',
  );
}
function radioactivity_node_help($path, $arg) {
  $output = '';
  switch ($path) {
    case "admin/help#radioactivity_node":
      $output = '<p>' . t('This module makes nodes radioactive. See the <em>energy settings</em> in radioactivity profiles. ' . 'This module also provides views support for node energy and simple abuse control.') . '</p>';
      break;
  }
  return $output;
}
function radioactivity_node_radioactivity_info() {

  // Get node types as node subclasses.
  $subclasses = array();

  // This code purposefully doesn't use node_get_types and doesn't
  // use db_rewrite_sql so it works on cached pages with i18n.
  $types = db_query('SELECT type FROM {node_type}');
  while ($node_type = db_fetch_object($types)) {
    $subclasses[$node_type->type] = array();
  }
  return array(
    'targets' => array(
      'node' => array(
        'subclass_resolver' => '_radioactivity_node_resolve_node_type',
        'subclasses' => $subclasses,
      ),
    ),
    'sources' => array(
      'node' => array(
        'view' => array(
          'title_placeholder' => 'node view',
          'description' => 'Energy for node page view request by any client.',
        ),
        'view_auth' => array(
          'title_placeholder' => 'node view by authenticated user',
          'description' => 'Energy for node page view request by authenticated client. ' . 'Note that this is in addition to <em>node view</em>.',
        ),
        'node_create' => array(
          'title_placeholder' => 'submitted node',
          'description' => 'Initial energy for submitted node.',
        ),
        'comment_insert' => array(
          'title_placeholder' => 'submitted comment',
          'description' => 'Energy for submitted comment.',
        ),
        'comment_publish' => array(
          'title_placeholder' => 'published comment',
          'description' => 'Energy for published comment. Added also for submitted ' . 'comment when the user has <em>post comments without approval</em> ' . 'access.',
        ),
      ),
    ),
  );
}
function radioactivity_node_menu() {
  $items = array();
  $items['admin/settings/radioactivity/node_radioactivity'] = array(
    'title' => 'Node settings',
    'description' => 'Node-specific radioactivity settings.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'radioactivity_node_admin_form',
    ),
    'access arguments' => array(
      RADIOACTIVITY_PERM_ADMIN,
    ),
    'weight' => 10,
    'type' => MENU_LOCAL_TASK,
    'file' => 'radioactivity_node-admin-ui.inc',
  );
  $items['radioactivity_node.php'] = array(
    'page callback' => 'radioactivity_node_ajax_callback',
    'type' => MENU_CALLBACK,
    'access arguments' => array(
      'access content',
    ),
  );
  return $items;
}
function _radioactivity_node_get_click_duration() {
  $click_duration = (int) variable_get('radioactivity_node_click_duration', 0);
  if ($click_duration <= 0) {
    $click_duration = 0;
  }
  return $click_duration;
}
function _radioactivity_node_resolve_node_type($nid, $oclass) {
  if (!isset($cached_types[$nid])) {
    $type = db_result(db_query("SELECT type FROM {node} WHERE nid = %d", $nid));
    $cached_types[$nid] = $type;
  }
  return $cached_types[$nid];
}
function radioactivity_node_cron() {
  $timestamp = time();

  // delete old enough clicks that gave energy to nodes
  db_query("DELETE FROM {radioactivity_node_clicks} WHERE click_timestamp < %d", $timestamp - _radioactivity_node_get_click_duration());
}

/**
 * Gives energy to node, if abuse control is passed.
 */
function radioactivity_node_user_node_view($nid) {
  global $user;
  if (_radioactivity_node_get_click_duration() > 0) {
    $nid = (int) $nid;
    $uid = $user->uid;
    $sid = session_id();
    $remote_address = $_SERVER['REMOTE_ADDR'];

    // check if click is found
    if ($user->uid > 0) {

      // not anonymous: use nid/sid
      $result = db_query("SELECT count(*) FROM {radioactivity_node_clicks} WHERE nid=%d AND sid='%s'", $nid, $sid);
    }
    else {

      // anonymous, use nid/sid or nid/hostname
      $result = db_query("SELECT count(*) FROM {radioactivity_node_clicks} WHERE nid=%d AND (sid='%s' OR hostname='%s')", $nid, $sid, $remote_address);
    }
    $passed = 0 == db_result($result);
    if ($passed) {

      // ok, record click
      db_query("INSERT INTO {radioactivity_node_clicks} (nid, sid, hostname, click_timestamp) " . "VALUES (%d, '%s', '%s', %d)", $nid, $sid, $remote_address, time());
    }
    else {

      // don't add energy, because click was found
      return FALSE;
    }
  }

  // ok, abuse control passed
  if (!function_exists('radioactivity_add_energy')) {

    // load radioactivity.inc, because radioactivity_add_energy does not exist
    $radioactivity_inc = substr(drupal_get_filename('module', 'radioactivity'), 0, -6) . 'inc';
    require_once $radioactivity_inc;
  }
  radioactivity_add_energy($nid, 'node', 'view');
  if ($user->uid > 0) {
    radioactivity_add_energy($nid, 'node', 'view_auth');
  }
  return TRUE;
}
function radioactivity_node_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  switch ($op) {
    case 'insert':
      radioactivity_add_energy($node->nid, 'node', 'node_create');
      break;
    case 'update':
      if (user_access('administer node energy')) {
        foreach ($node->radioactivity_node as $key => $value) {
          $energy = array(
            'id' => $node->nid,
            'class' => 'node',
            'decay_profile' => $key,
            'energy' => $value['energy'],
          );
          $energy = (object) $energy;
          drupal_write_record('radioactivity', $energy, 'id');
        }
      }
      break;
    case 'delete':
      radioactivity_delete_energy($node->nid, 'node');
      break;
    case 'load':
      return array(
        'radioactivity' => radioactivity_get_radioactivity_array($node->nid, 'node'),
      );
  }
}

/**
 * Implements hook_form_alter().
 */
function radioactivity_node_form_alter(&$form, &$form_state, $form_id) {
  $node = isset($form['#node']) ? $form['#node'] : FALSE;
  if (user_access('administer node energy') && $node && $form_id == $node->type . '_node_form') {
    $form['radioactivity_node'] = array(
      '#type' => 'fieldset',
      '#tree' => TRUE,
      '#title' => t('Radioactivity'),
      '#description' => isset($node->nid) ? t('You can modify this nodes energy by changing the values below.') : t('Once the node has been created you will be able to edit the energy for each decay profile here.'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );

    // We only allow editing of energy on existing nodes.
    if (isset($node->nid)) {
      $decay_profiles = radioactivity_get_decay_profiles();
      foreach ($decay_profiles as $key => $profile) {
        $form['radioactivity_node'][$key]['energy'] = array(
          '#type' => 'textfield',
          '#title' => t('Energy for @profile decay profile', array(
            '@profile' => $profile['label'],
          )),
          '#default_value' => $node->radioactivity['energy'][$key],
        );
      }
    }
  }
}
function radioactivity_node_comment(&$a1, $op) {
  switch ($op) {
    case 'insert':
      $nid = $a1['nid'];
      radioactivity_add_energy($nid, 'node', 'comment_insert');
      if ($a1['status'] == COMMENT_PUBLISHED) {
        radioactivity_add_energy($nid, 'node', 'comment_publish');
      }
      break;
    case 'publish':
      $nid = $a1->nid;
      radioactivity_add_energy($nid, 'node', 'comment_publish');
      break;
  }
}
function radioactivity_node_exit() {
  drupal_bootstrap(DRUPAL_BOOTSTRAP_PATH);
  global $user;

  // We don't use this hook for anonymous users if hook_mode is not 'normal'. In other modes,
  // other hooks are used, e.g., AJAX-hook for statically cached pages.
  if ($user->uid == 0 && variable_get('radioactivity_node_anon_hook_mode', 'normal') != 'normal') {
    return;
  }

  // we're only interested in full page views
  if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == '') {
    radioactivity_node_user_node_view(arg(1));
  }
}
function radioactivity_node_views_api() {
  return array(
    'api' => 2.0,
  );
}
function radioactivity_node_views_handlers() {
  return array(
    'handlers' => array(
      'radioactivity_node_views_handler_sort_left_or_inner' => array(
        'parent' => 'views_handler_sort',
      ),
    ),
  );
}

/**
 * Implementation of hook_block().
 *
 * @see boost_block()
 */
function radioactivity_node_block($op = 'list', $delta = 0, $edit = array()) {
  global $user;
  switch ($op) {
    case 'list':
      return array(
        0 => array(
          'info' => t('Radioactivity Node: AJAX update'),
          'cache' => BLOCK_NO_CACHE,
        ),
      );
    case 'view':
      switch ($delta) {
        case 0:
          if (!(strpos($_SERVER['SCRIPT_FILENAME'], 'index.php') === FALSE || variable_get('site_offline', 0) || $_SERVER['REQUEST_METHOD'] != 'GET' && $_SERVER['REQUEST_METHOD'] != 'HEAD' || $_SERVER['SERVER_SOFTWARE'] === 'PHP CLI' || isset($_GET['nocache']) || !empty($user->uid) || variable_get('radioactivity_node_anon_hook_mode', '') != 'ajax')) {
            $block = array();
            $block['subject'] = '';
            $block['content'] = '<div id="node-radioactivity-update"></div>' . radioactivity_node_ajax_code();
            return $block;
          }
          break;
      }
  }
}

/**
 * AJAX Menu Callback.
 */
function radioactivity_node_ajax_callback() {
  if (!isset($_GET['nid'])) {
    return drupal_not_found();
  }
  $nid = isset($_GET['nid']) ? $_GET['nid'] : NULL;
  if (!isset($_GET['js'])) {
    header('Content-type: image/gif');
    header('Expires: Sun, 19 Nov 1978 05:00:00 GMT');
    header('Cache-Control: no-cache');
    header('Cache-Control: must-revalidate');
    header('Content-Length: 0');
    header('Connection: close');
  }
  global $conf;
  $conf['cache'] = CACHE_DISABLED;

  // Silent ignore if the mode is not ajax. Also, check that nid is numeric and >0.
  if (variable_get('radioactivity_node_anon_hook_mode', '') == 'ajax' && is_numeric($nid) && $nid) {
    radioactivity_node_user_node_view($nid);
  }
}

/**
 * Generate js/html for radioactivity counter.
 *
 * NOTE HTML code could be added to the $buffer directly. Would prevent 2x
 * counts on first view. Would be hard to do though.
 *
 * @see boost_stats_generate()
 */
function radioactivity_node_ajax_code() {
  global $base_path;

  // is node & node count enabled.
  if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == '') {
    $nid = arg(1);
  }
  else {
    $nid = 'NULL';
  }
  $page_js = array(
    'radioactivity_node' => array(
      'nid' => $nid,
    ),
  );
  $site_js = <<<ETO
\$.get(Drupal.settings.basePath + "radioactivity_node.php", {nocache: "1", js: "1", nid: Drupal.settings.radioactivity_node.nid}, function(response) {});
ETO;

  // page specific variables
  drupal_add_js($page_js, 'setting', 'header');

  // site-wide code
  drupal_add_js($site_js, 'inline', 'footer');

  // no script code
  $page_ns = '<noscript><div style="display:inline;"><img src="' . $base_path . 'radioactivity_node.php' . '?nocache=1' . '&amp;nid=' . $nid . '" alt="" /></div></noscript>';
  return $page_ns;
}