You are here

word_link.module in Word Link 8

Same filename and directory in other branches
  1. 7.2 word_link.module
  2. 7 word_link.module

This module allows users to replace previously defined words to the links.

File

word_link.module
View source
<?php

/**
 * @file
 * This module allows users to replace previously defined words to the links.
 */

/**
 * Implements hook_permission().
 */
function word_link_permission() {
  return array(
    'view word link' => array(
      'title' => t('View Word Link'),
    ),
    'create word link' => array(
      'title' => t('Create Word Link'),
    ),
    'edit word link' => array(
      'title' => t('Edit Word Link'),
    ),
    'delete word link' => array(
      'title' => t('Delete Word Link'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function word_link_menu() {
  $items = array();
  $items['admin/config/content/word-link'] = array(
    'title' => 'Word Link',
    'description' => 'Administer Words Link',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'word_link_list_page_form',
    ),
    'access arguments' => array(
      'view word link',
    ),
    'file' => 'word_link.admin.inc',
  );
  $items['admin/config/content/word-link/list'] = array(
    'title' => 'List',
    'description' => 'Words list',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'word_link_list_page_form',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'file' => 'word_link.admin.inc',
  );
  $items['admin/config/content/word-link/configuration'] = array(
    'title' => 'Configuration',
    'description' => 'Set the preferences for Word Link module.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'word_link_admin_settings',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'word_link.admin.inc',
    'weight' => 2,
  );
  $items['admin/config/content/word-link/add'] = array(
    'title' => 'Add new word',
    'description' => 'Add word',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'word_link_add_form',
    ),
    'access arguments' => array(
      'create word link',
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'word_link.admin.inc',
  );
  $items['admin/config/content/word-link/edit/%'] = array(
    'title' => 'Edit word',
    'description' => 'Word edit',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'word_link_add_form',
      5,
    ),
    'access arguments' => array(
      'edit word link',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'word_link.admin.inc',
  );
  $items['admin/config/content/word-link/delete/%'] = array(
    'title' => 'Are you sure you want to delete this word?',
    'description' => 'Word delete',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'word_link_del_form',
      5,
    ),
    'access arguments' => array(
      'delete word link',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'word_link.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_menu_local_tasks_alter().
 */
function word_link_menu_local_tasks_alter(&$data, $router_item, $root_path) {

  // Add action link to 'admin/config/content/word-link/add'
  // on 'admin/config/content/word-link/list' page.
  if ($root_path == 'admin/config/content/word-link') {
    $item = menu_get_item('admin/config/content/word-link/add');
    if ($item['access']) {
      $data['actions']['output'][] = array(
        '#theme' => 'menu_local_action',
        '#link' => $item,
      );
    }
  }
}

/**
 * Implements hook_comment_view().
 */
function word_link_comment_view($comment, $view_mode, $langcode) {
  $types = variable_get('word_link_node_types', array());

  // Get node type.
  $node_type = str_replace("comment_node_", '', $view_mode->bundle);
  if (isset($types[$node_type]['fields']['comments'])) {
    $words = word_link_get_link();

    // Check CSS status.
    if (variable_get('word_link_css', 1)) {
      drupal_add_css(drupal_get_path('module', 'word_link') . '/css/word_link.css');
    }

    // Rewrite value.
    $value = $comment->content['comment_body'][0]['#markup'];
    $comment->content['comment_body'][0]['#markup'] = word_link_replace_text($words, $value);
  }
}

/**
 * Implements hook_node_view().
 */
function word_link_node_view($node, $view_mode, $langcode) {

  // Replace words for every view mode except rss.
  if ($view_mode != 'rss') {
    $types = variable_get('word_link_node_types', array());

    // Check current content type.
    if (!empty($types[$node->type]['fields'])) {

      // Get all words from DB.
      $words = word_link_get_link();
      if (!empty($words)) {
        $css_status = variable_get('word_link_css', 1);
        if ($css_status) {
          drupal_add_css(drupal_get_path('module', 'word_link') . '/css/word_link.css');
        }
        foreach ($types[$node->type]['fields'] as $field_name => $field) {
          if (!is_array($field)) {

            // Check if field has some text.
            if (!empty($node->content[$field]['#items'])) {
              foreach ($node->content[$field]['#items'] as $delta => $item) {

                // If output format is not HTML, then don’t do anything.
                if ($item['format'] != 'plain_text' && !empty($node->content[$field][$delta]['#markup'])) {

                  // Change field value.
                  $node->content[$field][$delta]['#markup'] = word_link_replace_text($words, $node->content[$field][$delta]['#markup'], $node->langcode);
                }
              }
            }
          }
          else {

            // Process field collection.
            foreach ($field as $fc) {
              if (!empty($node->content[$field_name]['#items'])) {
                foreach ($node->content[$field_name]['#items'] as $fc_delta => $fc_item) {
                  if (!empty($node->content[$field_name][$fc_delta]['entity']['field_collection_item'][$fc_item['value']][$fc])) {
                    $fc_field =& $node->content[$field_name][$fc_delta]['entity']['field_collection_item'][$fc_item['value']][$fc];
                    foreach ($fc_field['#items'] as $fc_field_delta => $fc_field_value) {
                      if ($fc_field_value['format'] != 'plain_text' && !empty($fc_field[$fc_field_delta]['#markup'])) {
                        $value = word_link_replace_text($words, $fc_field[$fc_field_delta]['#markup'], $node->langcode);
                        $fc_field[$fc_field_delta]['#markup'] = $value;
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

/**
 * Find and replace defined word to link.
 */
function word_link_replace_text($words, $subject, $langcode = NULL) {

  // Get disallowed html tags and explode it to array.
  $disallowed_tags = variable_get('word_link_tags_except', NULL);
  $disallowed_tags = preg_split('/\\s+|<|>/', $disallowed_tags, -1, PREG_SPLIT_NO_EMPTY);
  if (!empty($disallowed_tags)) {
    foreach ($disallowed_tags as $ancestor) {
      $not[] = 'and not(ancestor::' . $ancestor . ')';
    }
    $not = implode(' ', $not);
  }
  else {
    $not = '';
  }

  // Get word link limit.
  $limit = variable_get('word_link_limit', 0);
  $preg_limit = $limit == 0 ? -1 : $limit;
  $current_path = current_path();
  $path = drupal_strtolower(drupal_container()
    ->get('path.alias_manager')
    ->getPathAlias($current_path, $langcode));
  foreach ($words as $word) {
    $url = drupal_container()
      ->get('path.alias_manager')
      ->getPathAlias($word->url, $langcode);
    $match = FALSE;
    if (!empty($word->except)) {
      $match = drupal_match_path($path, $word->except);
      if ($path != $current_path) {
        $match = $match || drupal_match_path($current_path, $word->except);
      }
    }
    $visibility = empty($word->except) ? FALSE : $word->visibility;
    if ($url != $path && !$match && !$visibility || $url != $path && $visibility && $match) {

      // Build a link.
      $pattern = '$0';
      if (strpos($word->url, 'http://') === 0 || strpos($word->url, 'https://') === 0) {
        $replace[] = l($pattern, $word->url, array(
          'attributes' => array_filter(array(
            'class' => array(
              $word->class,
            ),
            'title' => $word->url_title,
            'target' => '_blank',
          )),
          'external' => TRUE,
        ));
      }
      else {
        $replace[] = l($pattern, $word->url, array(
          'attributes' => array_filter(array(
            'class' => array(
              $word->class,
            ),
            'title' => $word->url_title,
          )),
        ));
      }
      $pattern = '/((\\b)|(?<=\\W))(' . preg_quote($word->text, '/') . ')(?!(<\\/a>)|(".*>)|[\'"&’^])\\b/u';
      if ($word->case_sensitive) {
        $search[] = $pattern;
      }
      else {
        $search[] = $pattern . 'i';
      }
    }
  }
  if (isset($search) && isset($replace)) {
    $dom = new DOMDocument();
    $subject = str_replace('&amp;', '&#38;#38;', preg_replace('/&(?![a-z])/u', '&amp;', $subject));

    // Comment <iframe> tag because it can cause error.
    $subject = str_replace(array(
      '<iframe',
      '</iframe>',
    ), array(
      '<!--word_link<iframe',
      '</iframe>word_link-->',
    ), $subject);
    libxml_use_internal_errors(TRUE);
    $dom
      ->loadHTML(mb_convert_encoding(htmlspecialchars_decode($subject), 'HTML-ENTITIES', 'UTF-8'));
    $xpath = new DOMXPath($dom);
    if ($limit != 0) {
      $counts = array_fill(0, count($search), 0);
      foreach ($xpath
        ->query('//text()[not(ancestor::a) ' . $not . ']') as $node) {
        $replaced = $node->wholeText;
        $del = array_filter($counts);
        foreach ($del as $key => $val) {
          if ($val >= $limit) {
            unset($search[$key], $replace[$key]);
          }
        }
        foreach ($search as $id => $search_word) {
          $new_preg_limit = $preg_limit - $counts[$id];
          $replaced = preg_replace($search_word, $replace[$id], $replaced, $new_preg_limit, $count);
          $counts[$id] += $count;
        }
        $new_node = $dom
          ->createDocumentFragment();
        $new_node
          ->appendXML($replaced);
        $node->parentNode
          ->replaceChild($new_node, $node);
      }
    }
    else {
      foreach ($xpath
        ->query('//text()[not(ancestor::a) ' . $not . ']') as $node) {
        $replaced = preg_replace($search, $replace, $node->wholeText);
        $new_node = $dom
          ->createDocumentFragment();
        $new_node
          ->appendXML($replaced);
        $node->parentNode
          ->replaceChild($new_node, $node);
      }
    }

    // Get only the body tag with its contents, then trim the body tag
    // itself to get only the original content.
    $subject = drupal_substr($dom
      ->saveXML($xpath
      ->query('//body')
      ->item(0)), 6, -7);
  }
  return str_replace(array(
    '<!--word_link<iframe',
    '</iframe>word_link-->',
  ), array(
    '<iframe',
    '</iframe>',
  ), $subject);
}

/**
 * Get links from DB.
 */
function word_link_get_link($id = NULL, $header = array(), $limit = NULL) {
  if ($id) {
    $query = db_select('word_link', 'wl')
      ->fields('wl')
      ->condition('id', $id, '=')
      ->execute()
      ->fetchAll();
  }
  elseif (empty($id) && empty($header) && empty($limit)) {
    $query = db_select('word_link', 'wl')
      ->fields('wl')
      ->execute()
      ->fetchAll();
  }
  else {
    $query = db_select('word_link', 'wl')
      ->extend('Drupal\\Core\\Database\\Query\\PagerSelectExtender')
      ->extend('Drupal\\Core\\Database\\Query\\TableSortExtender')
      ->fields('wl')
      ->limit($limit)
      ->orderByHeader($header)
      ->execute()
      ->fetchAll();
  }
  $links = array();
  if (count($query) > 0) {
    foreach ($query as $value) {
      $links[$value->id] = $value;
    }
  }
  return $links;
}

/**
 * Verify by text if link already exists.
 */
function word_link_get_link_text($text, $id = 0) {
  if ($text) {
    $result = db_select('word_link', 'wl')
      ->fields('wl', array(
      'text',
      'case_sensitive',
    ))
      ->condition('id', $id, '!=')
      ->condition('text', $text, '=')
      ->execute()
      ->fetchAll();
  }
  if (empty($result)) {
    return FALSE;
  }
  if (count($result) > 1) {
    return TRUE;
  }
  elseif (drupal_strtolower($text) == drupal_strtolower($result[0]->text)) {
    return TRUE;
  }
  return FALSE;
}

/**
 * Add/Update link to DB.
 */
function word_link_add_update_link($action, $values, $id = NULL) {
  if ($action == 'insert') {
    drupal_write_record('word_link', $values);
  }
  elseif ($action == 'update') {
    $values['id'] = $id;
    drupal_write_record('word_link', $values, 'id');
  }
}

/**
 * Delete link from DB.
 */
function word_link_del_link($id) {
  db_delete('word_link')
    ->condition('id', $id)
    ->execute();
}

/**
 * Get textarea fields of given content type.
 */
function word_link_get_node_fields($type) {
  $fields = field_info_instances('node', $type);
  $text_fields = array();
  foreach ($fields as $name => $field) {
    if ($field['widget']['type'] == 'text_textarea_with_summary' || $field['widget']['type'] == 'text_textarea') {
      $text_fields[$field['field_name']] = $field['label'];
    }
    elseif ($field['widget']['type'] == 'field_collection_embed') {
      $fc_fields = field_info_instances('field_collection_item', $field['field_name']);
      foreach ($fc_fields as $fc_name => $fc_field) {
        if ($fc_field['widget']['type'] == 'text_textarea_with_summary' || $fc_field['widget']['type'] == 'text_textarea') {
          $text_fields[$field['field_name']][$field['field_name'] . '__' . $fc_field['field_name']] = $fc_field['label'];
        }
      }
    }
  }
  return $text_fields ? $text_fields : array();
}

Functions

Namesort descending Description
word_link_add_update_link Add/Update link to DB.
word_link_comment_view Implements hook_comment_view().
word_link_del_link Delete link from DB.
word_link_get_link Get links from DB.
word_link_get_link_text Verify by text if link already exists.
word_link_get_node_fields Get textarea fields of given content type.
word_link_menu Implements hook_menu().
word_link_menu_local_tasks_alter Implements hook_menu_local_tasks_alter().
word_link_node_view Implements hook_node_view().
word_link_permission Implements hook_permission().
word_link_replace_text Find and replace defined word to link.