You are here

adsense_injector.module in Content Injector (formerly AdSense Injector) 5

File

adsense_injector.module
View source
<?php

/**
 * Inject adsense ads into node content automatically.
 *
 * Copyright (c) 2006, 2007 Exodus Development, Inc.  All Rights Reserved.
 * Licensed under the terms of the GNU Public License (GPL) version 2.  Please see LICENSE.txt for
 * license terms.  Posession and use of this code signifies acceptance of license
 * terms.
 *
 * Visit Exodus Development at
 * http://exodusdev.com exodusdev@gmail.com
 *
 * Project homepage:
 * http://exodusdev.com/drupal/4.7/modules/adsense_injector.module
 *
 * The purpose of this module is to provide a simple method of automatically placing 'inline'
 * adsense module content into a full-page view of selected node types.
 * It does this by intercepting node rendering using hook_nodeapi during 'page' rendering,
 * and injecting selected text into the $node->body field.
 *
 * It uses a very simple scheme at present (just string concatenation)
 * and could be enhanced greatly by using regular expressions, templates,
 * or other techniques in a later revision.
 */
define('ADSENSE_INJECTOR_MODULE_VERSION', '$Id$');
define('ADSENSE_INJECTOR_INSERT_BODY_AD_DEFAULT', TRUE);
define('ADSENSE_INJECTOR_BODY_INSERTION_TEMPLATE_DEFAULT', '<div class="ad-auto-inserted" style="float:left; margin: 0 1em .25em 0;">[adsense:120x240:1:1]</div>%body<br class="clear"/>[adsense:468x60:1:1]');
define('ADSENSE_INJECTOR_BODY_MINWORDS_DEFAULT', 75);
define('ADSENSE_INJECTOR_APPEND_IN_LISTVIEW_DEFAULT', FALSE);
define('ADSENSE_INJECTOR_LISTVIEW_INSERTION_TEMPLATE_DEFAULT', '%teaser<div class="adsense-injector-list-ad">[adsense:468x60:1:1]</div>');

/**
 * Prefix for variable table entries - append node type name, store as boolean
 * value, nonzero means insert ad content
 */
define('ADSENSE_INJECTOR_INSERT_AD_NODETYPE', 'adsense_injector_nodetype_');
if (!function_exists('_dbg')) {
  function _dbg($var, $title = NULL) {
    drupal_set_message('<pre>' . htmlspecialchars(print_r($var, true)) . '</pre>');
  }
}

/**
 * Count words in a string.
 * @param $str ref to a string (ref so no copy)
 * @param $max max # of words we care about.  Return value will never exceed this.
 * @return the count of words, where delimiter is one or more spaces
 * @todo Efficiency, find better way to do this
 */
function _adsense_injector_count_words(&$str, $max) {
  return count(explode(' ', $str, $max));

  // lifted from node.module node_validate() function.
}

/**
 * Get the minimum node body wordcount for insertion.
 * May be content-type specific, but at present, it's
 * global to all node types.
 * @param $nodetype the node type
 * @param $defval the default value
 * @return The minimum insertion wordcount
 */
function _adsense_injector_minwords_cfg($nodetype, $defval = 75) {
  return variable_get('adsense_injector_body_minwords', $defval);
}
function _adsense_injector_process_tags($template) {
  if (function_exists('_adsense_process_tags')) {
    $template = _adsense_process_tags($template);
  }
  else {
    watchdog('adsense_injector', t('adsense module function _adsense_process_tags() not found'), WATCHDOG_ERROR);
  }
  return $template;
}
function theme_adsense_injector_transform($page, $teaser, $node) {

  // Process adsense module tags in the template text, if enabled and possible
  // TODO: look for %body:x-y where x = start and y = end 'paragraph'
  // So, we could have a template like %body:start-3[adsense:120x240:1:1]%body:4-end
  // Find ending 'block' elements
  // <p><br><blockquote> or newlines since the line break filter may be in operation
  if ($page) {
    $body = $node->content['body']['#value'];
    if (variable_get('adsense_injector_insert_body_ad', ADSENSE_INJECTOR_INSERT_BODY_AD_DEFAULT)) {
      $minwords = _adsense_injector_minwords_cfg($node->type);
      $wordcount = _adsense_injector_count_words($body, $minwords);
      if ($wordcount >= $minwords) {
        $template = variable_get('adsense_injector_body_template', ADSENSE_INJECTOR_BODY_INSERTION_TEMPLATE_DEFAULT);
        $template = _adsense_injector_process_tags($template);
        $content = strtr($template, array(
          '%body' => $body,
        ));
      }
      else {
        $content = "<!-- adsense_injector: node body word count ({$wordcount}) is insufficient ({$minwords} required), so we won't insert an ad. -->" . $body;
      }
    }
  }
  else {
    if ($teaser && variable_get('adsense_injector_append_in_listview', ADSENSE_INJECTOR_APPEND_IN_LISTVIEW_DEFAULT)) {
      $template = variable_get('adsense_injector_listview_insertion_template', ADSENSE_INJECTOR_LISTVIEW_INSERTION_TEMPLATE_DEFAULT);

      // Process adsense module tags in the template text, if enabled and possible
      $template = _adsense_injector_process_tags($template);
      $content = strtr($template, array(
        '%teaser' => $node->teaser,
      ));
    }
  }
  return $content;
}

/**
 * Implementation of hook_nodeapi.
 * If rendering a full page, and the node type one of the configured types,
 * inject configured adsense content using simple string concatenation.
 * @todo: Evaluate efficiency of string concat vs. sprintf, other methods.
 */
function adsense_injector_nodeapi(&$node, $op, $teaser, $page) {

  // insert an ad into the body.
  if (module_exists('adsense') && _adsense_page_match() && variable_get(ADSENSE_INJECTOR_INSERT_AD_NODETYPE . $node->type, FALSE)) {
    if ($op == 'view') {
      $node->content['body']['#value'] = theme('adsense_injector_transform', $page, $teaser, $node);
    }
  }
}

/**
 * Implementation of hook_menu
 */
function adsense_injector_menu() {
  $items[] = array(
    'path' => 'admin/settings/adsense_injector',
    'title' => t('Google AdSense Injector'),
    'description' => t('Insert Google AdSense ads into full node views automatically.'),
    'callback' => 'drupal_get_form',
    'callback arguments' => array(
      'adsense_injector_admin_settings',
    ),
    'access' => user_access('administer site configuration'),
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}

/**
 * Implementation of hook_settings
 */
function adsense_injector_admin_settings() {
  $form = array();
  _adsense_injector_get_banner($form);
  $form['node_ad_body_insertion'] = array(
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#title' => t('Node body ad insertion'),
    '#description' => t('Requires adsense.module'),
  );
  if (module_exists('adsense')) {
    $form['node_ad_body_insertion']['adsense_injector_insert_body_ad'] = array(
      '#type' => 'checkbox',
      '#title' => t('Insert inline ad in node body on page views'),
      '#default_value' => variable_get('adsense_injector_insert_body_ad', ADSENSE_INJECTOR_INSERT_BODY_AD_DEFAULT),
      '#description' => t('Description'),
      '#required' => FALSE,
    );
    $form['node_ad_body_insertion']['adsense_injector_body_minwords'] = array(
      '#type' => 'textfield',
      '#title' => t('Minimum node body word count'),
      '#default_value' => variable_get('adsense_injector_body_minwords', ADSENSE_INJECTOR_BODY_MINWORDS_DEFAULT),
      '#description' => t('The minimum node body word count threshold - only inject if node body has at least this many words.'),
    );
    $form['node_ad_body_insertion']['adsense_injector_body_template'] = array(
      '#type' => 'textarea',
      '#title' => t('Node body ad insertion template'),
      '#rows' => 5,
      '#cols' => 40,
      '#default_value' => variable_get('adsense_injector_body_template', ADSENSE_INJECTOR_BODY_INSERTION_TEMPLATE_DEFAULT),
      '#description' => t('Ad insertion template.  Substitution variables: %body = full node body text.  Insert adsense module filter tags.  See the <a href="/admin/settings/adsense">adsense.module settings page</a> for a list of supported formats and help with filter tags.'),
      '#required' => TRUE,
    );

    /**
     * 'list' insertion (frontpage, taxonomy, etc.
     */
    $form['node_ad_list_insertion'] = array(
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
      '#title' => t('Node list ad insertion'),
      '#description' => t('Ad insertion in node lists or other non-page view, like front page, taxonomy views.'),
    );
    $form['node_ad_list_insertion']['adsense_injector_append_in_listview'] = array(
      '#type' => 'checkbox',
      '#title' => t('Append an ad after teaser on frontpage and taxonomy lists'),
      '#default_value' => variable_get('adsense_injector_append_in_listview', ADSENSE_INJECTOR_APPEND_IN_LISTVIEW_DEFAULT),
      '#description' => t('Note: this does not currently support Views module based lists.'),
      '#required' => FALSE,
    );
    $form['node_ad_list_insertion']['adsense_injector_listview_insertion_template'] = array(
      '#type' => 'textarea',
      '#title' => t('List ad insertion template'),
      '#rows' => 3,
      '#cols' => 40,
      '#default_value' => variable_get('adsense_injector_listview_insertion_template', ADSENSE_INJECTOR_LISTVIEW_INSERTION_TEMPLATE_DEFAULT),
      '#description' => t('Template to use when inserting adsense ad.  "%teaser" will be replaced with the node teaser.  Insert adsense filter tags.  See the <a href="/admin/settings/adsense">adsense.module settings page</a> for a list of supported formats and help with filter tags.'),
      '#required' => TRUE,
    );

    /**
     *  What kinds of nodes do we want to insert on...?
     */
    $form['injection_control'] = array(
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#title' => t('Select Node Types for Insertion'),
      '#description' => t('Nodes types to display inline ads - ads are inserted <strong>only</strong> in the selected node types.'),
    );

    /**
     * Enumerate node types, and set up form fields for each
     */
    $enabled_count = 0;
    $nodetypes = array();
    foreach (node_get_types() as $type => $typeObj) {
      $nodetypes[$type] = $typeObj->name;
      $enabled = variable_get(ADSENSE_INJECTOR_INSERT_AD_NODETYPE . $type, FALSE);
      if ($enabled) {
        $enabled_count++;
      }
      $form['injection_control']['node_types'][ADSENSE_INJECTOR_INSERT_AD_NODETYPE . $type] = array(
        '#type' => 'checkbox',
        '#title' => $typeObj->name,
        '#default_value' => $enabled,
        '#description' => t('Display inline ads on %nodetype nodes', array(
          '%nodetype' => $typeObj->name,
        )),
        '#required' => FALSE,
      );
    }

    // do some sanity checking
    if ($enabled_count == 0) {
      $msg = t('No node types selected (no ads will be inserted because you haven\'t selected any node types for automatic ad insertion.)');

      //      form_set_error('injection_control][node_types', $msg);
      $form['injection_control']['#collapsed'] = FALSE;
      $form['injection_control']['no_nodes_enabled'] = array(
        '#type' => 'markup',
        '#weight' => -1,
        '#value' => '<div id="message"><div class="messages error"><strong>' . $msg . '</strong></div></div>',
      );
    }
  }
  return system_settings_form($form);
}

/**
 * Get settings 'banner'
 */
function _adsense_injector_get_banner(&$form) {
  $name = 'adsense_injector-d5';
  $d = '<a target="_blank" href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=exodus.paypal%40gmail.com&item_name=' . $name . '&item_number= ' . $name . '-donation&page_style=PayPal&no_shipping=1&return=http%3A%2F%2Fexodusdev.com%2Fproducts&cancel_return=http%3A%2F%2Fexodusdev.com%2Fproducts&no_note=1&tax=0&currency_code=USD&lc=US&bn=PP%2dDonationsBF&charset=UTF%2d8"><img src="http://www.paypal.com/en_US/i/btn/x-click-but7.gif" alt="Your donations support ongoing development" title="Your donations support ongoing development"></a>';
  $form['module_banner'] = array(
    '#type' => 'markup',
    '#value' => '<div style="border: solid 1px #eee; margin: .5em; padding: .5em;"><div style="float:right;">' . $d . '</div><strong>Module development sponsored by <a href="http://exodusdev.com">Exodus Development</a></strong><br/>',
  );
  $form['module_id'] = array(
    '#type' => 'markup',
    '#value' => ADSENSE_INJECTOR_MODULE_VERSION . '<br/></div>',
  );
}

Functions

Namesort descending Description
adsense_injector_admin_settings Implementation of hook_settings
adsense_injector_menu Implementation of hook_menu
adsense_injector_nodeapi Implementation of hook_nodeapi. If rendering a full page, and the node type one of the configured types, inject configured adsense content using simple string concatenation. @todo: Evaluate efficiency of string concat vs. sprintf, other methods.
theme_adsense_injector_transform
_adsense_injector_count_words Count words in a string.
_adsense_injector_get_banner Get settings 'banner'
_adsense_injector_minwords_cfg Get the minimum node body wordcount for insertion. May be content-type specific, but at present, it's global to all node types.
_adsense_injector_process_tags

Constants