You are here

function smart_trim_field_formatter_view in Smart Trim 7

Implements hook_field_formatter_view().

Need a better way to handle doing count by words instead of characters (see views_trim_text().

File

./smart_trim.module, line 40
Module functionality.

Code

function smart_trim_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();
  $settings = $display['settings'];
  switch ($display['type']) {
    case 'smart_trim_format':
      foreach ($items as $delta => $item) {

        // The default behaviour is to use the main body field, but the summary
        // option allows users to use the summary field IFF it is not empty.
        $break_pos = strpos($item['value'], '<!--break-->');
        $has_summary_or_break = !empty($item['summary']) || $break_pos !== FALSE;
        $honor_trim = empty($settings['summary_handler']) || $settings['summary_handler'] != 'full' ? TRUE : FALSE;
        if (!empty($settings['summary_handler']) && $settings['summary_handler'] != 'ignore' && $has_summary_or_break) {
          if (empty($item['summary'])) {
            $output = check_markup(substr($item['value'], 0, $break_pos), $item['format'], $langcode, FALSE);
          }
          else {
            $output = _text_sanitize($instance, $langcode, $item, 'summary');
          }
        }
        else {
          $output = _text_sanitize($instance, $langcode, $item, 'value');
        }

        // Process additional options (currently only HTML on/off).
        if (!empty($settings['trim_options'])) {
          if (!empty($settings['trim_options']['text'])) {

            // Strip tags.
            $preserve_tags = !empty($settings['trim_preserve_tags']) ? $settings['trim_preserve_tags'] : '';
            $output = strip_tags(str_replace('<', ' <', $output), $preserve_tags);

            // Strip out line breaks.
            $output = preg_replace('/\\n|\\r|\\t/m', ' ', $output);

            // Strip out non-breaking spaces.
            $output = str_replace('&nbsp;', ' ', $output);
            $output = str_replace(" ", ' ', $output);

            // Strip out extra spaces.
            $output = trim(preg_replace('/\\s\\s+/', ' ', $output));
          }
        }

        // Make the trim, provided we're honoring trim settings
        // or there's no summary or break available.
        $shortened = FALSE;
        if ($honor_trim || $has_summary_or_break === FALSE) {
          if ($settings['trim_type'] == 'words') {

            // Only bother with this is we have to.
            if ($settings['trim_length'] < str_word_count($output)) {

              // Use \s or use PREG_CLASS_UNICODE_WORD_BOUNDARY?
              $words = preg_split('/\\s/', $output, NULL, PREG_SPLIT_NO_EMPTY);
              $output2 = implode(" ", array_slice($words, 0, $settings['trim_length']));
              $output2 = _filter_htmlcorrector($output2);
            }
            else {
              $output2 = $output;
            }
          }
          else {

            // Use views_trim_text() if available.
            if (module_exists('views')) {
              $output2 = views_trim_text(array(
                'max_length' => $settings['trim_length'],
                'word_boundary' => TRUE,
                'ellipsis' => FALSE,
                'html' => TRUE,
              ), $output);
            }
            else {

              // @see http://api.drupal.org/api/drupal/modules%21field%21modules%21text%21text.module/function/text_summary/7
              // text_summary is smart about looking for paragraphs, sentences,
              // etc, not strictly just length. Uses truncate_utf8 as well.
              $output2 = text_summary($output, $instance['settings']['text_processing'] ? $item['format'] : NULL, $settings['trim_length']);
            }
          }

          // Verify if we actually performed any shortening.
          if (drupal_strlen(drupal_html_to_text($output)) != drupal_strlen(drupal_html_to_text($output2))) {
            $shortened = TRUE;
          }
          $output = $output2;
        }

        // Only include the extension if the text was truncated.
        $extension = '';
        if ($shortened) {
          $extension = filter_xss($settings['trim_suffix']);
        }

        // Don't duplicate period at end of text and beginning of extension.
        if (substr($output, -1, 1) == '.' && substr($extension, 0, 1) == '.') {
          $extension = substr($extension, 1);
        }

        // Final checks if we need to display a more link.
        $needs_more = FALSE;
        switch ($settings['more_link']) {

          // If the user always wants the link, include it.
          case SMART_TRIM_ALWAYS:
            $needs_more = TRUE;
            break;
          case SMART_TRIM_IFNEEDED:
            if ($shortened) {
              $needs_more = TRUE;
            }
            else {

              // If a summary is used (whether truncated or not), and it's
              // different from the main body, we need to show the more link.
              if (!empty($item['summary']) && $settings['summary_handler'] != 'ignore') {
                $summary_output = _text_sanitize($instance, $langcode, $item, 'summary');
                $full_output = _text_sanitize($instance, $langcode, $item, 'value');
                if (strcmp($summary_output, $full_output) != 0) {
                  $needs_more = TRUE;
                }
              }
            }
            break;
        }
        $uri = entity_uri($entity_type, $entity);
        if ($uri && $needs_more) {
          $extension .= l(t('@more_text', array(
            '@more_text' => $settings['more_text'],
          )), $uri['path'], array(
            'html' => TRUE,
            'attributes' => array(
              'class' => array(
                'more-link',
              ),
            ),
          ));
        }
        $output_appended = preg_replace('#^(.*)(\\s?)(</[^>]+>)$#Us', '$1' . $extension . '$3', $output);

        // Check if the regex did anything. if not, append manually.
        if ($output_appended == $output) {
          $output_appended = $output . $extension;
        }

        // If linking to content is selected the trimmed text will have tags
        // removed from the trimmed text. Need to find a more elegant way of
        // doing this without conflicting the other settings.
        if (!empty($settings['trim_link']) && !empty($uri['path'])) {
          $output_appended = strip_tags($output_appended);
          $output = l($output_appended, $uri['path']);
          $element[$delta] = array(
            '#markup' => $output,
          );
          return $element;
        }
        $element[$delta] = array(
          '#markup' => $output_appended,
        );
      }
      break;
  }
  return $element;
}