You are here

function smart_paging_field_attach_view_alter in Smart Paging 7

Same name and namespace in other branches
  1. 7.2 smart_paging.module \smart_paging_field_attach_view_alter()

Implements hook_field_attach_view_alter().

File

./smart_paging.module, line 610
Provides smart paging capability to Drupal contents.

Code

function smart_paging_field_attach_view_alter(&$build, $context) {

  // Teaser view and comment entity type (it has its own pagination) are not included
  if ($context['entity_type'] != 'comment' && $context['view_mode'] == 'full') {
    global $pager_page_array, $pager_total;
    $suffix;
    $display_suffix;
    $total_page = 0;
    $output_index = 0;
    $current_page = 0;

    // Element index of our pager in multiple pagers on one page.
    $pager_element = 1;

    // Determine the user's current viewing page number
    if (isset($_GET['page'])) {
      $pager_page_array = explode(',', $_GET['page']);
      if (count($pager_page_array) == 1) {
        $pager_page_array = array(
          $pager_page_array[0],
          0,
        );
        $current_page = 0;
      }
      else {
        $current_page = $pager_page_array[$pager_element];
      }
      $output_index = $current_page;
    }

    // Get display settings
    $display_stored = field_bundle_settings($build['#entity_type'], $build['#bundle']);
    $display_defaults = smart_paging_field_extra_fields(TRUE);
    if (isset($display_stored['extra_fields']['display']['smart_paging'][$context['display']])) {
      $display_settings = $display_stored['extra_fields']['display']['smart_paging'][$context['display']];
    }
    elseif (isset($display_stored['extra_fields']['display']['smart_paging']['default'])) {
      $display_settings = $display_stored['extra_fields']['display']['smart_paging']['default'];
    }
    else {
      $display_settings = $display_defaults['extra_fields']['display']['smart_paging'];
    }

    // Sort array fields according to weight
    $fields = array();
    foreach (element_children($build) as $field_name) {
      if (isset($build[$field_name]['#weight'])) {
        $fields[$field_name] = $build[$field_name]['#weight'];
      }
    }
    asort($fields);
    foreach (array_keys($fields) as $field_name) {
      foreach ($build[$field_name] as $delta => $field_content) {
        if (is_numeric($delta) && isset($field_content['#markup'])) {
          if (strpos($field_content['#markup'], '<!--smart_paging_autop_filter-->') !== FALSE) {
            $use_autop = TRUE;
            $field_content['#markup'] = str_replace('<!--smart_paging_autop_filter-->', '', $field_content['#markup']);
          }
          $is_smart_paging_filter_found = strpos($field_content['#markup'], '<!--smart_paging_filter-->');
          $is_smart_paging_filter_done_found = strpos($field_content['#markup'], '<!--smart_paging_filter_done-->');
          if ($is_smart_paging_filter_found !== FALSE || $is_smart_paging_filter_done_found !== FALSE) {
            $entity_type = $context['entity_type'];
            $entity_info = entity_get_info($entity_type);
            $entity_id = $context['entity']->{$entity_info['entity keys']['id']};
            $language = isset($build[$field_name]['#language']) ? $build[$field_name]['#language'] : 'und';
            if ($display_settings['settings']['smart_paging_settings_context'] == 'content_type') {

              // Use Smart Paging settings stored at Manage Display
              if (isset($display_settings['settings']['smart_paging_method'])) {
                $smart_paging_method = $display_settings['settings']['smart_paging_method'];
              }
              else {
                $smart_paging_method = variable_get('smart_paging_method', SMART_PAGING_PLACEHOLDER_METHOD);
              }
              if (isset($display_settings['settings']['smart_paging_pagebreak'])) {
                $placeholder = $display_settings['settings']['smart_paging_pagebreak'];
              }
              else {
                $placeholder = variable_get('smart_paging_pagebreak', '<!--pagebreak-->');
              }
              if (isset($display_settings['settings']['smart_paging_title_display_suffix'])) {
                $display_suffix = $display_settings['settings']['smart_paging_title_display_suffix'];
              }
              else {
                $display_suffix = variable_get('smart_paging_title_display_suffix', TRUE);
              }
              if (isset($display_settings['settings']['smart_paging_title_suffix'])) {
                $suffix = $display_settings['settings']['smart_paging_title_suffix'];
              }
              else {
                $suffix = variable_get('smart_paging_title_suffix', t(': Page '));
              }
              if (isset($display_settings['settings']['smart_paging_character_count'])) {
                $max_char = $display_settings['settings']['smart_paging_character_count'];
              }
              else {
                $max_char = variable_get('smart_paging_character_count', SMART_PAGING_MAX_CHAR_LIMIT);
              }
              if (isset($display_settings['settings']['smart_paging_word_count'])) {
                $max_words = $display_settings['settings']['smart_paging_word_count'];
              }
              else {
                $max_words = variable_get('smart_paging_word_count', SMART_PAGING_MAX_WORD_LIMIT);
              }
            }
            else {

              // Retrieve the stored Smart Paging settings for this content
              $smart_paging_config = smart_paging_get_content_configuration($entity_type, $entity_id);
              $smart_paging_use_default = isset($smart_paging_config['use_default']) ? $smart_paging_config['use_default'] : TRUE;
              $smart_paging_method = $smart_paging_use_default ? variable_get('smart_paging_method', SMART_PAGING_PLACEHOLDER_METHOD) : $smart_paging_config['method'];
              $placeholder = $smart_paging_use_default ? variable_get('smart_paging_pagebreak', '<!--pagebreak-->') : $smart_paging_config['pagebreak'];
              $display_suffix = $smart_paging_use_default ? variable_get('smart_paging_title_display_suffix', TRUE) : $smart_paging_config['title_display_suffix'];
              $suffix = $smart_paging_use_default ? variable_get('smart_paging_title_suffix', t(': Page ')) : $smart_paging_config['title_suffix'];
              $max_char = $smart_paging_use_default ? variable_get('smart_paging_character_count', SMART_PAGING_MAX_CHAR_LIMIT) : $smart_paging_config['character_count'];
              $max_words = $smart_paging_use_default ? variable_get('smart_paging_word_count', SMART_PAGING_MAX_WORD_LIMIT) : $smart_paging_config['word_count'];
            }
            $markup_content = $field_content['#markup'];
          }

          // Check first if Smart Paging is allowed as input filter
          if ($is_smart_paging_filter_found !== FALSE) {

            // Remove the Smart Paging input filter marker
            $markup_content = str_replace('<!--smart_paging_filter-->', '', $markup_content);

            // Default this to 'no method' if it's being called as a full page
            $query_parameters = drupal_get_query_parameters();
            if (isset($query_parameters['nopaging'])) {

              // @TODO: Somewhat duplicated from below pagination code. Refactor candidate.
              $get = drupal_get_query_parameters();

              // Do we want nopaging as canonical instead of current page?
              if (variable_get('smart_paging_use_nopaging_canonical', FALSE)) {
                $get['nopaging'] = 1;
              }

              // Build url representation of current page. Using an absolute url allows outbound
              // url hooks to modify the domain if necessary (domain module).
              $link_current_page = url($_GET['q'], array(
                'absolute' => TRUE,
                'query' => $get,
              ));

              // By default add a canonical head element here. We will clean up any duplicates
              // in the hook.
              drupal_add_html_head(array(
                '#attributes' => array(
                  'rel' => 'canonical',
                  'href' => $link_current_page,
                ),
                '#tag' => 'link',
                '#attached' => array(
                  'drupal_add_http_header' => array(
                    array(
                      'Link',
                      '<' . $link_current_page . '>; rel="canonical"',
                      1,
                    ),
                  ),
                ),
              ), 'smart_paging_link_canonical');

              // If set, use "Convert line breaks into HTML" filter
              if (isset($use_autop)) {
                $build[$field_name][$delta]['#markup'] = _filter_autop($markup_content);
              }
              return;
            }
            if ($smart_paging_method == SMART_PAGING_NO_METHOD) {

              // Do nothing, no paging is desired
              $cached_field = cache_get("field:{$entity_type}:{$entity_id}", 'cache_field');
              $cached_field->data[$field_name][$language][$delta]['safe_value'] = '<!--smart_paging_filter_done-->' . $markup_content;
              cache_set("field:{$entity_type}:{$entity_id}", $cached_field->data, 'cache_field');
              return;
            }
            if ($smart_paging_method != SMART_PAGING_PLACEHOLDER_METHOD) {

              // Check if breaking the page is based on number of characters
              if ($smart_paging_method == SMART_PAGING_CHARACTER_LIMIT_METHOD) {
                static $char_count = 0;
              }
              elseif ($smart_paging_method == SMART_PAGING_WORD_LIMIT_METHOD) {
                static $word_count = 0;
              }

              // Remove user defined Smart Paging placeholder, we don't need it here
              $markup_content = str_replace($placeholder, '', $markup_content);
              $split_tags = preg_split('/<(!--.*?--|[^>]+?)>/s', $markup_content, -1, PREG_SPLIT_DELIM_CAPTURE);
              $markup_content = '';
              foreach ($split_tags as $split_tags_key => $split_tags_value) {
                if ($split_tags_key & 1) {
                  $markup_content .= '<' . $split_tags_value . '>';
                }
                else {
                  if ($smart_paging_method == SMART_PAGING_CHARACTER_LIMIT_METHOD) {
                    $split_htmlcodes = preg_split('/(&[a-zA-Z]+;)/s', $split_tags_value, -1, PREG_SPLIT_DELIM_CAPTURE);
                    foreach ($split_htmlcodes as $split_htmlcodes_key => $split_htmlcodes_value) {
                      if ($split_htmlcodes_key & 1) {

                        // Count html charater as 1
                        $char_count++;
                        $markup_content .= $split_htmlcodes_value;
                      }
                      else {
                        $split_text = explode(' ', $split_htmlcodes_value);
                        $split_text_size = count($split_text);
                        foreach ($split_text as $text_value) {
                          $char_count += drupal_strlen($text_value);
                          $markup_content .= $text_value;
                          if ($split_text_size > 1) {

                            // Count the space
                            $char_count++;
                            $markup_content .= ' ';
                          }
                          if ($char_count >= $max_char) {
                            $markup_content .= $placeholder;
                            $char_count = 0;
                          }
                        }
                      }
                    }
                  }
                  else {
                    $split_text = explode(' ', $split_tags_value);
                    $split_text_size = count($split_text);
                    foreach ($split_text as $text_value) {

                      // Exclude whitespace
                      if (preg_match('/\\S/s', $text_value)) {
                        ++$word_count;
                      }
                      $markup_content .= $text_value;
                      if ($split_text_size > 1) {
                        $markup_content .= ' ';
                      }
                      if ($word_count >= $max_words) {
                        $markup_content .= $placeholder;
                        $word_count = 0;
                      }
                    }
                  }
                }
              }
            }
            do {

              // Look for consecutive placeholder and closing tag. Eg. <!--pagebreak--></p>
              $placeholder_regex = preg_quote($placeholder, '#');
              preg_match_all("#({$placeholder_regex})([ \t\r\n]*)(</[a-zA-Z]+>)#", $markup_content, $match);
              if (isset($match[1][0]) && isset($match[3][0])) {

                // Move the placeholder to the end of closing tag. From the above example </p><!--pagebreak-->
                $match_regex = preg_quote($match[1][0] . (isset($match[2][0]) ? $match[2][0] : '') . $match[3][0], '#');
                $markup_content = preg_replace("#{$match_regex}#", (isset($match[2][0]) ? $match[2][0] : '') . $match[3][0] . $match[1][0], $markup_content);
              }
            } while (!empty($match[0]) && !empty($match[1]) && !empty($match[2]) && !empty($match[3]));

            // Break HTML content properly and insert placeholder
            $markup_content = smart_page_break_insert_placeholder($markup_content);

            // Check if last page is an empty tag
            $pagebreak = array_filter(explode($placeholder, $markup_content));
            $pagebreak_end = count($pagebreak) - 1;
            $last_page = '';
            if (isset($pagebreak[$pagebreak_end])) {
              $last_page = strip_tags($pagebreak[$pagebreak_end]);
            }
            if (empty($last_page)) {

              // Remove the last page with only an empty tag content
              unset($pagebreak[$pagebreak_end]);
            }
            if (isset($use_autop)) {

              // Use "Convert line breaks into HTML" filter
              foreach ($pagebreak as $index => $content_value) {
                $pagebreak[$index] = _filter_autop($content_value);
              }
            }
            $markup_content = implode($placeholder, $pagebreak);

            // Don't save to cache when node is in Preview mode
            if (isset($context['entity']->op) && $context['entity']->op != 'Preview') {

              // Save the processed page break content to cache
              $cached_field = cache_get("field:{$entity_type}:{$entity_id}", 'cache_field');
              $cached_field->data[$field_name][$language][$delta]['safe_value'] = '<!--smart_paging_filter_done-->' . $markup_content;
              cache_set("field:{$entity_type}:{$entity_id}", $cached_field->data, 'cache_field');
            }

            // Set the field content output
            $build[$field_name][$delta]['#markup'] = $markup_content;
          }
          if ($is_smart_paging_filter_found !== FALSE || $is_smart_paging_filter_done_found !== FALSE) {

            // Remove the Smart Paging input filter done marker
            $markup_content = str_replace('<!--smart_paging_filter_done-->', '', $markup_content);
            if (empty($pagebreak)) {

              // Break the content based on user's included page break placeholders
              $pagebreak = array_filter(explode($placeholder, $markup_content));
            }
            $pagebreak_count = count($pagebreak);
            if ($pagebreak_count > 1) {
              if ($total_page) {

                // At this point, we are in next succeeding fields. This field
                // content will be shown at the last page of the previous field
                $output_index = $current_page - $total_page;
              }
              $output = '';
              if (isset($pagebreak[$output_index])) {
                $output = $pagebreak[$output_index];
              }

              // Record total number of pages
              $total_page += count($pagebreak);

              // Final field content output
              $build[$field_name][$delta]['#markup'] = $output;
            }
          }
        }

        // Smart Paging as better SEO friendly targeting meta tags and URL (sub pages):
        // Sample: <!--smartpagingmeta {"link_rel_canonical_href":"","meta_name_description_content":"Tips for breakfast facts and nutrition information","meta_name_keywords_content":"breakfast, breakfast nutrition, healthy, healthy eating habits"}-->
        // Sample: <!--smartpagingurl "Breakfast-Facts-for-Nutrition"-->
        if (is_array($build[$field_name][$delta]) && isset($build[$field_name][$delta]['#markup']) && isset($placeholder)) {
          $content_break = explode($placeholder, $field_content['#markup']);
          $custom_url_page = array();
          foreach ($content_break as $page_num => $sub_page_content) {
            preg_match_all('#<!--smartpagingurl [[:punct:][:alnum:][:space:]]*-->#', $sub_page_content, $matched_tags);
            if (!empty($matched_tags[0])) {
              $custom_url_page[$page_num] = preg_replace('#<!--smartpagingurl |-->|"|\'#', '', $matched_tags[0][0]);
            }
          }
          smart_paging_get_url_fragment($custom_url_page);
          $sub_content = $build[$field_name][$delta]['#markup'];
          preg_match_all('#<!--smartpagingmeta [[:punct:][:alnum:][:space:]]*-->#', $sub_content, $matched_tags);
          if (!empty($matched_tags[0])) {
            $smart_paging_seo = preg_replace('#<!--smartpagingmeta |<!--smartpagingurl [[:punct:][:alnum:][:space:]]*-->|-->#', '', $matched_tags[0][0]);
            if (!module_exists('metatag')) {
              drupal_add_html_head(array(
                '#attributes' => array(
                  'name' => 'Smart_Paging',
                  'content' => $smart_paging_seo,
                ),
                '#tag' => 'meta',
              ), 'smart_paging_seo');

              // Call this function to register the additional html head
              drupal_get_html_head();
            }
            else {
              $output =& drupal_static('smart_paging');
              $output = json_decode($smart_paging_seo, TRUE);
            }
          }
        }
      }
    }
    if (!empty($total_page)) {
      global $base_url;
      $current_url = function_exists("path_alias_xt_get_path_alias") ? path_alias_xt_get_path_alias($_GET['q']) : drupal_get_path_alias($_GET['q']);
      $current_url = preg_replace('#(^/)|(/$)#', '', $current_url);
      $clean_url = variable_get('clean_url', 0);
      $current_url = $clean_url ? $current_url : "?q={$current_url}";
      $pager_details = array(
        'first_element' => empty($pager_page_array[0]) ? 0 : $pager_page_array[0],
        'current_page' => $current_page,
        'base_url' => $base_url,
        'current_url' => $current_url,
        'path_prefix' => variable_get('smart_paging_path_prefix', 'page'),
        'custom_url_page' => $custom_url_page,
      );
      $enable_clean_url = variable_get('smart_paging_enable_clean_url', TRUE);
      if (variable_get('smart_paging_use_js_pager', TRUE) && $enable_clean_url) {
        drupal_add_js(drupal_get_path('module', 'smart_paging') . '/js/smart_paging-pager.js');
        drupal_add_js(array(
          'smart_paging' => $pager_details,
        ), 'setting');
      }

      // Set up pager arguments.
      $total_page_offset = $total_page - 1;
      if ($enable_clean_url) {
        $pager_prefix = $pager_details['path_prefix'] . '/' . $pager_details['first_element'];
      }
      else {
        $pager_prefix = 'page=' . $pager_details['first_element'];
      }
      $get = drupal_get_query_parameters();
      $q = $_GET['q'];

      // Do we want nopaging as canonical instead of current page?
      if (variable_get('smart_paging_use_nopaging_canonical', FALSE)) {
        $get['nopaging'] = 1;
      }
      elseif ($current_page != 0) {

        // No. Make current paginated page canonical.
        if ($enable_clean_url) {
          $q .= "/{$pager_prefix}/{$current_page}";
        }
        else {
          $get[$pager_prefix] = $current_page;
        }
      }

      // Build url representation of current page. Using an absolute url allows outbound
      // url hooks to modify the domain if necessary (domain module).
      $link_current_page = url($_GET['q'], array(
        'absolute' => TRUE,
        'query' => $get,
      ));

      // By default add a canonical head element here. We will clean up any duplicates in the hook.
      drupal_add_html_head(array(
        '#attributes' => array(
          'rel' => 'canonical',
          'href' => $link_current_page,
        ),
        '#tag' => 'link',
        '#attached' => array(
          'drupal_add_http_header' => array(
            array(
              'Link',
              '<' . $link_current_page . '>; rel="canonical"',
              1,
            ),
          ),
        ),
      ), 'smart_paging_link_canonical');
      if (variable_get('smart_paging_use_link_rel', TRUE)) {

        // Pagination with rel="next" and rel="prev"
        // Ref: http://googlewebmastercentral.blogspot.co.uk/2011/09/pagination-with-relnext-and-relprev.html
        if ($current_page == 0) {

          // We are on first page
          $link_rel_next_page = $enable_clean_url ? "{$pager_prefix}/1" : "{$pager_prefix}%2C1";
        }
        else {
          if ($current_page == $total_page_offset) {

            // We are on last page
            $link_rel_prev_page = $total_page_offset - 1;
            if ($link_rel_prev_page) {
              $link_rel_prev_page = $enable_clean_url ? "{$pager_prefix}/{$link_rel_prev_page}" : "{$pager_prefix}%2C{$link_rel_prev_page}";
            }
          }
          else {

            // We are on middle page
            $link_rel_next_page = $current_page + 1;
            if ($link_rel_next_page) {
              $link_rel_next_page = $enable_clean_url ? "{$pager_prefix}/{$link_rel_next_page}" : "{$pager_prefix}%2C{$link_rel_next_page}";
            }
            $link_rel_prev_page = $current_page - 1;
            if ($link_rel_prev_page) {
              $link_rel_prev_page = $enable_clean_url ? "{$pager_prefix}/{$link_rel_prev_page}" : "{$pager_prefix}%2C{$link_rel_prev_page}";
            }
          }
        }
        if (isset($link_rel_prev_page)) {
          if ($enable_clean_url) {
            $href = $link_rel_prev_page ? "{$base_url}/{$current_url}/{$link_rel_prev_page}" : "{$base_url}/{$current_url}";
          }
          else {
            $href = $link_rel_prev_page ? "{$base_url}/{$current_url}?{$link_rel_prev_page}" : "{$base_url}/{$current_url}";
          }
          drupal_add_html_head(array(
            '#attributes' => array(
              'rel' => 'prev',
              'href' => $href,
            ),
            '#tag' => 'link',
          ), 'smart_paging_link_rel_prev');
        }
        if (isset($link_rel_next_page)) {
          if ($enable_clean_url) {
            $href = $link_rel_next_page ? "{$base_url}/{$current_url}/{$link_rel_next_page}" : "{$base_url}/{$current_url}";
          }
          else {
            $href = $link_rel_next_page ? "{$base_url}/{$current_url}?{$link_rel_next_page}" : "{$base_url}/{$current_url}";
          }
          drupal_add_html_head(array(
            '#attributes' => array(
              'rel' => 'next',
              'href' => $href,
            ),
            '#tag' => 'link',
          ), 'smart_paging_link_rel_next');
        }
      }
      $pager_total[$pager_element] = $total_page;
      if ($display_suffix && $current_page > 0) {
        $title_suffix = theme('smart_paging_page_title_suffix', array(
          'page' => array(
            'suffix' => $suffix,
            'current_page' => $current_page,
            'total_page' => $total_page,
          ),
        ));
      }
      $variables['tags'] = array();
      $variables['element'] = $pager_element;
      $variables['quantity'] = 10;
      $build['smart_paging']['#markup'] = '<div class="smart-paging-pager">' . theme('pager', $variables) . '</div>';
      $build['smart_paging']['#weight'] = isset($display_settings['weight']) ? $display_settings['weight'] : 0;
      $build['smart_paging']['#access'] = isset($display_settings['visible']) ? $display_settings['visible'] : TRUE;
    }
  }
  else {
    foreach (element_children($build) as $field_name) {
      foreach ($build[$field_name] as $delta => $field_content) {
        if (is_numeric($delta)) {

          // Check first if there's a Smart Paging filter placeholder
          if (isset($field_content['#markup']) && strpos($field_content['#markup'], '<!--smart_paging_filter-->') !== FALSE) {
            $markup_content = $field_content['#markup'];

            // Remove the Smart Paging input filter marker and placeholder for comment entity
            $markup_content = str_replace('<!--smart_paging_filter-->', '', $markup_content);
            $markup_content = str_replace(variable_get('smart_paging_pagebreak', '<!--pagebreak-->'), '', $markup_content);
            $build[$field_name][$delta]['#markup'] = $markup_content;
          }
          if (isset($field_content['#markup']) && strpos($field_content['#markup'], '<!--smart_paging_autop_filter-->') !== FALSE) {
            $markup_content = $build[$field_name][$delta]['#markup'];
            $markup_content = str_replace('<!--smart_paging_autop_filter-->', '', $markup_content);
            $build[$field_name][$delta]['#markup'] = _filter_autop($markup_content);
          }
        }
      }
    }
  }
}