| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: ed_readmore.module,v 1.5.8.2.2.11.2.13 2009/11/24 06:51:46 toddnienkerk Exp $ 3 4 /** 5 * @file 6 * Customize the "Read more" link shown in teasers. 7 * 8 * Project homepage: 9 * http://drupal.org/project/ed_readmore 10 * 11 * This provides the customization described at: 12 * http://www.angrydonuts.com/the_nuisance_of_the_read_more_fl 13 * 14 * Conversion from 4.7 to 5.x done by themoebius (zacwitte@gmail.com) 15 * Conversion from 5.x to 6.x done by Exodus Development and tomaszx 16 * (tomaszx provided initial conversion and patches -- thanks!) 17 * 6.x bug fixes, UI/theme improvements, and added functionality by Four Kitchens 18 * 19 * Exodus Development 20 * http://exodusdev.com 21 * exodusdev@gmail.com 22 * 23 * Four Kitchens 24 * http://fourkitchens.com 25 * shout@fourkitchens.com 26 */ 27 28 29 define('ED_READMORE_PLACEMENT_DEFAULT', 'inline'); 30 define('ED_READMORE_TEXT_DEFAULT', t('<strong>Read more »</strong>')); 31 define('ED_READMORE_TITLE_DEFAULT', t('Read the whole post')); 32 define('ED_READMORE_SEPARATOR_DEFAULT', ''); 33 34 35 /** 36 * Implementation of hook_menu(). 37 */ 38 function ed_readmore_menu() { 39 $items['admin/settings/ed_readmore'] = array( 40 'title' => 'Read More link', 41 'description' => 'Configures the <strong>Read More</strong> link that appears in node teasers.', 42 'page callback' => 'drupal_get_form', 43 'page arguments' => array('ed_readmore_admin_settings'), 44 'access arguments' => array('administer site configuration'), 45 'type' => MENU_NORMAL_ITEM, 46 ); 47 return $items; 48 } 49 50 51 /** 52 * Displays the settings form. 53 */ 54 function ed_readmore_admin_settings() { 55 $form = array(); 56 57 $elements = array( 58 'address' => '<address>', 59 'blockquote' => '<blockquote>', 60 'cite' => '<cite>', 61 'div' => '<div>', 62 'h1' => '<h1>', 63 'h2' => '<h2>', 64 'h3' => '<h3>', 65 'h4' => '<h4>', 66 'h5' => '<h5>', 67 'h6' => '<h6>', 68 'p' => '<p>', 69 'span' => '<span>', 70 ); 71 72 $form['ed_readmore_display'] = array( 73 '#type' => 'fieldset', 74 '#title' => t('Read More link display options'), 75 '#collapsible' => FALSE, 76 ); 77 $form['ed_readmore_display']['ed_readmore_remove'] = array( 78 '#type' => 'checkbox', 79 '#title' => t('Remove Read More link from links section'), 80 '#default_value' => variable_get('ed_readmore_remove', TRUE), 81 '#description' => t('Enabling this option will remove Drupal\'s default Read More link from the node links (the <code>$links</code> output).'), 82 ); 83 $form['ed_readmore_display']['ed_readmore_placement'] = array( 84 '#type' => 'radios', 85 '#title' => t('Link placement'), 86 '#options' => array( 87 'inline' => t('Inline: Try to add the Read More link after the last word of the teaser. If this fails, add the link on a new line after the teaser.'), 88 'after' => t('On a new line: Add the Read More link on a new line after the teaser.'), 89 'disable' => t('Disable the link: Do not add a Read More link to the teaser.'), 90 ), 91 '#default_value' => variable_get('ed_readmore_placement', ED_READMORE_PLACEMENT_DEFAULT), 92 '#description' => t('The inline option will attempt to add the Read More link after the last word of the teaser and before any CCK fields. The HTML elements into which the Read More link may be inserted can be chosen in the "Advanced options for inline placement" interface below.'), 93 ); 94 $form['ed_readmore_display']['ed_readmore_placement_advanced'] = array( 95 '#type' => 'fieldset', 96 '#title' => t('Advanced options for inline placement'), 97 '#collapsible' => TRUE, 98 '#collapsed' => TRUE, 99 ); 100 $form['ed_readmore_display']['ed_readmore_placement_advanced']['ed_readmore_elements'] = array( 101 '#type' => 'select', 102 '#title' => t('Elements eligible for inline placement'), 103 '#description' => t('Select the elements into which the Read More link may be inserted. The "Inline" placement option must be selected above.'), 104 '#multiple' => TRUE, 105 '#options' => $elements, 106 '#default_value' => variable_get('ed_readmore_elements', array('p')), 107 '#size' => 10, 108 ); 109 110 $form['ed_readmore_formatting'] = array( 111 '#type' => 'fieldset', 112 '#title' => t('Read More link formatting and attributes'), 113 '#collapsible' => FALSE, 114 ); 115 $form['ed_readmore_formatting']['ed_readmore_text'] = array( 116 '#type' => 'textfield', 117 '#title' => t('Link text'), 118 '#default_value' => variable_get('ed_readmore_text', ED_READMORE_TEXT_DEFAULT), 119 '#description' => t('Enter the text you wish to display in the Read More link. The following HTML is allowed: <code>em</code>, <code>i</code>, <code>strong</code>, <code>b</code>, <code>cite</code>, <code>code</code>, <code>span</code>, <code>font</code>. Special characters should be encoded (like %raquo or %amp). Spaces will be changed to non-breaking spaces (%nbsp).', array('%raquo' => '»', '%amp' => '&', '%nbsp' => ' ')), 120 '#required' => TRUE, 121 ); 122 $form['ed_readmore_formatting']['ed_readmore_title'] = array( 123 '#type' => 'textfield', 124 '#title' => t('Link title'), 125 '#default_value' => variable_get('ed_readmore_title', ED_READMORE_TITLE_DEFAULT), 126 '#description' => t('Enter the text you wish to be used as the title for the Read More link (the value of the %title attribute). It is used for accessibility and search engine optimization purposes and appears as a tooltip in some browsers.', array('%title' => 'title=""')), 127 '#required' => FALSE, 128 ); 129 if (module_exists('token')) { 130 $form['ed_readmore_formatting']['tokens'] = array( 131 '#type' => 'fieldset', 132 '#collapsible' => TRUE, 133 '#collapsed' => TRUE, 134 '#title' => t('Placeholder tokens'), 135 '#description' => t('The following placeholder tokens can be used in the Read More link text and title. They will be replaced with the appropriate values.'), 136 ); 137 $form['ed_readmore_formatting']['tokens']['ed_readmore_tokens'] = array( 138 '#type' => 'checkbox', 139 '#title' => t('Enable placeholder tokens'), 140 '#default_value' => variable_get('ed_readmore_tokens', TRUE), 141 '#description' => t('This option will allow you to use the placeholder tokens listed below.'), 142 ); 143 $form['ed_readmore_formatting']['tokens']['help'] = array( 144 '#value' => theme('token_help', 'node'), 145 ); 146 // Add Token-specific help text 147 $token_description = t('<a href="@tokens">Tokens</a> are supported if you enable them below.', array('@tokens' => url('http://drupal.org/project/token'))); 148 $form['ed_readmore_formatting']['ed_readmore_text']['#description'] .= ' ' . $token_description; 149 $form['ed_readmore_formatting']['ed_readmore_title']['#description'] .= ' ' . $token_description; 150 } 151 $form['ed_readmore_formatting']['ed_readmore_nofollow'] = array( 152 '#type' => 'checkbox', 153 '#title' => t('Make link nofollow'), 154 '#default_value' => variable_get('ed_readmore_nofollow', TRUE), 155 '#description' => t('Adds %nofollow to the link\'s attributes. Often used for search engine optimization purposes.', array('%nofollow' => 'rel="nofollow"')), 156 ); 157 $form['ed_readmore_formatting']['ed_readmore_separator'] = array( 158 '#type' => 'textfield', 159 '#title' => t('Separator'), 160 '#description' => t('Enter the text you wish to be inserted between the teaser and the Read More link when the link is displayed inline. If you enter nothing, the link will be separated using a space character. May contain HTML. Special characters should be encoded (like %nbsp or %raquo). ', array('%nbsp' => ' ', '%raquo' => '»')), 161 '#default_value' => variable_get('ed_readmore_separator', ED_READMORE_SEPARATOR_DEFAULT), 162 ); 163 164 return system_settings_form($form); 165 } 166 167 168 /** 169 * Implementation of hook_link_alter(). 170 */ 171 function ed_readmore_link_alter(&$links, $node) { 172 // Remove the link from the node's $links output if the option is enabled 173 if (variable_get('ed_readmore_remove', TRUE)) { 174 unset($links['node_read_more']); 175 } 176 } 177 178 179 /** 180 * Implementation of template_preprocess_node(). 181 */ 182 function ed_readmore_preprocess_node(&$variables) { 183 $display = variable_get('ed_readmore_placement', ED_READMORE_PLACEMENT_DEFAULT); 184 185 // Don't do anything if placing the link is disabled 186 if ($display != 'disable') { 187 // Check to make sure that this is a teaser and there's actually more to read 188 if ($variables['teaser'] && $variables['readmore']) { 189 $variables['content'] = ed_readmore_link_place($variables['content'], $variables['node'], $display); 190 } 191 } 192 } 193 194 195 /** 196 * Place the "Read more" link in the correct location in the teaser. 197 * 198 * @param $teaser 199 * The teaser to place the "Read more" link into. 200 * @param $link 201 * The node containing information necessary to generate a link. 202 * @param $display 203 * Link display mode: inline, after, or disable. 204 * If 'inline,' try to insert into teaser. If 'added,' just add after the teaser. 205 */ 206 function ed_readmore_link_place($teaser, $node, $display) { 207 if ($display == 'inline') { 208 $elements_array = variable_get('ed_readmore_elements', array('p')); 209 $elements = '(?:'. implode('|', $elements_array) .')'; 210 211 // Get last position of the last closing marker in teaser 212 if (preg_match('!</?'. $elements .'[^>]*>$!i', $node->content['body']['#value'], $match, PREG_OFFSET_CAPTURE)) { 213 // Recalculate the position in $teaser. We do this because there may be extra CCK fields appended to the teaser. 214 $insert_point = strpos($teaser, $node->content['body']['#value']) + $match[0][1]; 215 // Insert the link 216 $teaser = substr_replace($teaser, ed_readmore_link_render($node, $display), $insert_point, 0); 217 } 218 else { 219 $display = 'after'; 220 $teaser .= ed_readmore_link_render($node, $display); // Not found, so just append it 221 } 222 } 223 else { 224 $teaser .= ed_readmore_link_render($node, $display); // Not inline, so just append it 225 } 226 227 return $teaser; 228 } 229 230 231 /** 232 * Prepares the link for theming and returns a rendered link. 233 * 234 * XSS checking and other safety measures are performed here to prevent 235 * themers from omitting them. 236 */ 237 function ed_readmore_link_render($node, $display = 'inline') { 238 // Filter link text for cross-site scripting (XSS) 239 // Replace spaces with non-breaking entities to prevent a wrapping in the link 240 $allowed_tags = array('em', 'i', 'strong', 'b', 'cite', 'code', 'span', 'font'); 241 $link_text = t(filter_xss(variable_get('ed_readmore_text', ED_READMORE_TEXT_DEFAULT), $allowed_tags)); 242 243 // Make sure the text is plain 244 $link_title = t(check_plain(variable_get('ed_readmore_title', ED_READMORE_TITLE_DEFAULT))); 245 246 // Replace tokens with values if the Token module and the token options are enabled 247 if (module_exists('token') && variable_get('ed_readmore_tokens', TRUE)) { 248 $link_text = token_replace($link_text, 'node', $node); 249 $link_title = token_replace($link_title, 'node', $node); 250 } 251 252 // Replace double quotes with single quotes to prevent breaking of the title attribute 253 $link_title = str_replace('"', '\'', $link_title); 254 255 // Build link options array 256 $link_options = array( 257 'attributes' => array( 258 'title' => $link_title, 259 ), 260 'html' => TRUE, 261 ); 262 263 // Add rel="nofollow" to link if the option is enabled 264 if (variable_get('ed_readmore_nofollow', TRUE)) { 265 $link_options['attributes']['rel'] = 'nofollow'; 266 } 267 268 // Filter separator for cross-site scripting (XSS) 269 $separator = filter_xss(variable_get('ed_readmore_separator', ED_READMORE_SEPARATOR_DEFAULT)); 270 271 // Send prepared data to the theme function 272 return theme('ed_readmore_link', $node, $link_text, $link_options, $separator, $display); 273 } 274 275 276 /** 277 * Implementation of hook_theme(). 278 */ 279 function ed_readmore_theme($existing, $type, $theme, $path) { 280 return array( 281 'ed_readmore_link' => array( 282 'arguments' => array( 283 'link_text' => NULL, 284 'link_destination' => NULL, 285 'link_options' => NULL, 286 'display' => NULL, 287 ), 288 ), 289 ); 290 } 291 292 293 /** 294 * Theme function that wraps the rendered link. 295 */ 296 function theme_ed_readmore_link($node, $link_text, $link_options, $separator, $display) { 297 // Use a <div> (block-level) element for links appended after the teaser 298 if ($display == 'after') { 299 $element = 'div'; 300 $separator = ''; 301 } 302 else { 303 // Use a <span> (inline) element for links that appear inside the teaser 304 $element = 'span'; 305 if (empty($separator)) { 306 $separator = ' '; 307 } 308 } 309 310 return $separator . '<' . $element . ' class="read-more">' . l($link_text, 'node/'. $node->nid, $link_options) . '</' . $element . '>'; 311 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |