You are here

ed_readmore.module in Read More Link (Drupal 6 and earlier) 5

Same filename and directory in other branches
  1. 6.5 ed_readmore.module
  2. 6.2 ed_readmore.module
  3. 6.3 ed_readmore.module

Customize the "Read more" link shown in teasers.

Project homepage: http://drupal.org/project/ed_readmore

This provides the customization described at: http://www.angrydonuts.com/the_nuisance_of_the_read_more_fl

Conversion from 4.7 to 5.x done by themoebius (zacwitte@gmail.com)

Exodus Development http://exodusdev.com exodusdev@gmail.com

Four Kitchens http://fourkitchens.com shout@fourkitchens.com.com

File

ed_readmore.module
View source
<?php

/**
 * @file
 * Customize the "Read more" link shown in teasers.
 *
 * Project homepage: 
 * http://drupal.org/project/ed_readmore
 *
 * This provides the customization described at:
 * http://www.angrydonuts.com/the_nuisance_of_the_read_more_fl
 *
 * Conversion from 4.7 to 5.x done by themoebius (zacwitte@gmail.com)
 *
 * Exodus Development
 * http://exodusdev.com
 * exodusdev@gmail.com
 *
 * Four Kitchens
 * http://fourkitchens.com
 * shout@fourkitchens.com.com
 */
define('ED_READMORE_READMORE_TWEAK_DEFAULT', TRUE);
define('ED_READMORE_READMORE_INLINE_DEFAULT', TRUE);

// use this for "fancy" default
define('ED_READMORE_TEXT_DEFAULT', '&nbsp;read&nbsp;more&nbsp;&raquo;');

//define('ED_READMORE_TEXT_DEFAULT', 'read more &raquo;');
define('ED_READMORE_READMORE_RSS_DEFAULT', TRUE);

/**
 * Place the teaser in the correct location in $thing
 * @param $thing The thing to place the read more link into
 * @param $link The link HTML to place
 * @param $inlineflag if true, try to place at end of text; otherwise, just append
 */
function _ed_readmore_place_readmore_link($thing, $link, $inlineflag) {
  $read_more = " <span class='read-more'>" . $link . "</span>";
  if ($inlineflag) {

    // deal with broken strrpos on php4
    if (_ed_readmore_is_php4()) {
      $find_last = '_ed_readmore_strrpos_string';
    }
    else {
      $find_last = 'strrpos';
    }

    // int strrpos ( string haystack, string needle [, int offset] )
    // substr_replace ( mixed string, string replacement, int start [, int length] )
    // this is lame - need to look for any tag allowed by the current filter
    $marker_to_insert_at = '</p>';
    $final_p_pos = $find_last($thing, $marker_to_insert_at);

    // php4 gotcha - will search only for first char of marker!  (supports only single char search)
    if (!($final_p_pos === FALSE)) {
      $thing = substr_replace($thing, $read_more, $final_p_pos, 0);

      // account for length of </p> string
    }
    else {
      $thing .= $read_more;

      // not found, so just append it
    }
  }
  else {
    $thing .= $read_more;

    // just append it at bottom
  }
  return $thing;
}

/**
 * Fix "read more" flag
 * From the most excellent angry donuts site: http://www.angrydonuts.com/the_nuisance_of_the_read_more_fl
 * From author: Note that I'm using a lot of arguments to l() -- I'm telling it to provide an 'absolute' 
 * path, because these teasers often go out to RSS, and providing an absolute path is much, much safer.
 */
function ed_readmore_nodeapi(&$node, $op, $teaser, $page) {
  $enabled = variable_get('ed_readmore_readmore_tweak', ED_READMORE_READMORE_TWEAK_DEFAULT);
  if ($enabled) {
    $link_text = t(variable_get('ed_readmore_text', ED_READMORE_TEXT_DEFAULT));
    if (variable_get('ed_readmore_readmore_strong', 1)) {
      $link_text = '<strong>' . $link_text . '</strong>';
    }
    $inlineflag = variable_get('ed_readmore_readmore_inline', ED_READMORE_READMORE_INLINE_DEFAULT);
    $rss_enabled = variable_get('ed_readmore_readmore_rss_enabled', ED_READMORE_READMORE_RSS_DEFAULT);
    if ($rss_enabled && $op == 'rss item') {

      // Since this is an RSS item, we need an absolute URL.
      // And, while we're at it, we make it a _blank target as does node.module node_feed() function.
      $options['target'] = '_blank';
      $item_length = variable_get('feed_item_length', 'teaser');

      // from node.module node_feed() code
      switch ($item_length) {
        case 'teaser':
          if (strlen($node->teaser) < strlen($node->body)) {
            $readmore_url = l($link_text, "node/{$node->nid}", $options, NULL, NULL, TRUE, TRUE);
            $node->teaser = _ed_readmore_place_readmore_link($node->teaser, $readmore_url, $inlineflag);
          }
          break;
      }
      return;
    }
    if ($op == 'view') {
      if ($teaser && $node->readmore) {
        if (variable_get('ed_readmore_readmore_remove', TRUE)) {
          $node->readmore = FALSE;

          // since we are blowing away some of the implicit info ($node->readmore) let's remember that this was a teaser
          $node->is_teaser = TRUE;
        }
        $readmore_url = l($link_text, "node/{$node->nid}", NULL, NULL, NULL, TRUE, TRUE);
        $node->content[body]['#value'] = _ed_readmore_place_readmore_link($node->content[body]['#value'], $readmore_url, $inlineflag);
      }
    }
  }
}

###################################################

#

# DESCRIPTION:

# This function returns the last occurance of a string,

# rather than the last occurance of a single character like

# strrpos does. It also supports an offset from where to

# start the searching in the haystack string.

#

# ARGS:

# $haystack (required) -- the string to search upon

# $needle (required) -- the string you are looking for

# $offset (optional) -- the offset to start from

#

# RETURN VALS:

# returns integer on success

# returns false on failure to find the string at all

#

# lifted from http://us3.php.net/manual/en/function.strrpos.php#67559

#

###################################################
function _ed_readmore_strrpos_string($haystack, $needle, $offset = 0) {
  if (trim($haystack) != "" && trim($needle) != "" && $offset <= strlen($haystack)) {
    $last_pos = $offset;
    $found = false;
    while (($curr_pos = strpos($haystack, $needle, $last_pos)) !== false) {
      $found = true;
      $last_pos = $curr_pos + 1;
    }
    if ($found) {
      return $last_pos - 1;
    }
    else {
      return false;
    }
  }
  else {
    return false;
  }
}
function _ed_readmore_php_ver_major() {
  return substr(PHP_VERSION, 0, 1);
}
function _ed_readmore_is_php4() {
  return _ed_readmore_php_ver_major() == '4';
}

/**
 * Implementation of hook_menu
 */
function ed_readmore_menu() {
  $items[] = array(
    'path' => 'admin/settings/ed_readmore',
    'title' => t('Read More link'),
    'description' => t('Relocate the teaser "read more" link from links section?'),
    'callback' => 'drupal_get_form',
    'callback arguments' => array(
      'ed_readmore_admin_settings',
    ),
    'access' => user_access('administer site configuration'),
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}

/**
 * Displays the settings form
 */
function ed_readmore_admin_settings() {
  $form = array();
  $form['ed_readmore_readmore_tweak'] = array(
    '#type' => 'checkbox',
    '#title' => t('Relocate <strong>Read More</strong> link from links section?'),
    '#default_value' => variable_get('ed_readmore_readmore_tweak', ED_READMORE_READMORE_TWEAK_DEFAULT),
    '#description' => t('Move <strong>Read More</strong> from links to end of teaser?  See <a target="_blank" href="http://www.angrydonuts.com/the_nuisance_of_the_read_more_fl">AngryDonuts.com</a> for details.'),
    '#required' => FALSE,
  );
  $form['ed_readmore_readmore_inline'] = array(
    '#type' => 'checkbox',
    '#title' => t('Put <strong>Read More</strong> inline in teaser?'),
    '#default_value' => variable_get('ed_readmore_readmore_inline', ED_READMORE_READMORE_INLINE_DEFAULT),
    '#description' => t('If relocation is enabled, and this option is set, place <strong>Read More</strong> text on last line of teaser text using a &lt;span&gt; element.'),
    '#required' => FALSE,
  );
  $form['ed_readmore_readmore_remove'] = array(
    '#type' => 'checkbox',
    '#title' => t('Remove <strong>Read More</strong> link from links section'),
    '#default_value' => variable_get('ed_readmore_readmore_remove', TRUE),
    '#description' => t('Also remove Drupal\'s default <strong>Read More</strong> link from node links.'),
  );
  $form['ed_readmore_readmore_rss_enabled'] = array(
    '#type' => 'checkbox',
    '#title' => t('Put <strong>Read More</strong> inline in RSS feeds?'),
    '#default_value' => variable_get('ed_readmore_readmore_rss_enabled', ED_READMORE_READMORE_RSS_DEFAULT),
    '#description' => t('If relocation is enabled, and this option is set, place <strong>Read More</strong> text on last line of rss text using a &lt;span&gt; element.'),
    '#required' => FALSE,
  );
  $form['ed_readmore_text'] = array(
    '#type' => 'textfield',
    '#title' => t('The <strong>Read More</strong> text to display in the teaser'),
    '#default_value' => variable_get('ed_readmore_text', t(ED_READMORE_TEXT_DEFAULT)),
    '#description' => t('Enter the text you wish to display in the <strong>Read More</strong> link.  May contain HTML.'),
    '#required' => TRUE,
  );
  $form['ed_readmore_readmore_strong'] = array(
    '#type' => 'checkbox',
    '#title' => t('Bold this text'),
    '#default_value' => variable_get('ed_readmore_readmore_strong', 1),
    '#required' => FALSE,
  );
  return system_settings_form($form);
}

Functions

Namesort descending Description
ed_readmore_admin_settings Displays the settings form
ed_readmore_menu Implementation of hook_menu
ed_readmore_nodeapi Fix "read more" flag From the most excellent angry donuts site: http://www.angrydonuts.com/the_nuisance_of_the_read_more_fl From author: Note that I'm using a lot of arguments to l() -- I'm telling it to provide an…
_ed_readmore_is_php4
_ed_readmore_php_ver_major
_ed_readmore_place_readmore_link Place the teaser in the correct location in $thing
_ed_readmore_strrpos_string

Constants