word_link.module in Word Link 7
Same filename and directory in other branches
This module allows users to replace previously defined words to the links.
File
word_link.moduleView 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_", '', $comment->node_type);
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_update().
*/
function word_link_node_update($node) {
$types = variable_get('word_link_node_types', array());
// Check if for this node selected any field to convert words.
if (!empty($types[$node->type]['fields'])) {
$cache_key = "word_link_nid_{$node->nid}";
cache_clear_all($cache_key, 'cache', TRUE);
}
}
/**
* 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)) {
// Add style if need.
$css_status = variable_get('word_link_css', 1);
if ($css_status) {
drupal_add_css(drupal_get_path('module', 'word_link') . '/css/word_link.css');
}
// Convert words for each field.
word_link_process_node_fields($node, $types, $words);
}
}
}
}
/**
* Find node fields content and pass it for processing.
*
* @param object $node
* Full node object.
* @param array $types
* Content types in which need to convert words.
* @param array $words
* User defined words.
*/
function word_link_process_node_fields(&$node, $types, $words) {
foreach ($types[$node->type]['fields'] as $field_name => $field) {
// Check if we process a field.
if (!is_array($field)) {
// Check if field has some text.
if (!empty($node->content[$field]['#items'])) {
// Convert words for each field value.
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.
$cache_key = "word_link_nid_{$node->nid}_{$field}_{$delta}_" . strlen($node->content[$field][$delta]['#markup']);
$cached = cache_get($cache_key);
if (isset($cached->data)) {
$node->content[$field][$delta]['#markup'] = $cached->data;
}
else {
$words = word_link_get_link();
$node->content[$field][$delta]['#markup'] = word_link_replace_text($words, $node->content[$field][$delta]['#markup']);
cache_set($cache_key, $node->content[$field][$delta]['#markup']);
}
}
}
}
}
else {
foreach ($field as $fc) {
// Check if field have some value.
if (!empty($node->content[$field_name]['#items'])) {
// Convert words for each field value.
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) {
// Change field value if output format is not plain text.
if ($fc_field_value['format'] != 'plain_text' && !empty($fc_field[$fc_field_delta]['#markup'])) {
$cache_key = "word_link_nid_{$node->nid}_{$field}_{$fc_delta}_" . strlen($node->content[$field][$delta]['#markup']);
$cached = cache_get($cache_key);
if (isset($cached->data)) {
$value = $cached->data;
}
else {
$words = word_link_get_link();
$value = word_link_replace_text($words, $fc_field[$fc_field_delta]['#markup']);
cache_set($cache_key, $value);
}
$fc_field[$fc_field_delta]['#markup'] = $value;
}
}
}
}
}
}
}
}
}
/**
* Find and convert defined word to link.
*
* @param array $words
* Array with words.
* @param string $subject
* String in which need convert words to links.
*
* @return string
* String with converted words.
*/
function word_link_replace_text($words, $subject) {
// 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);
// Implode all disallowed tags to string.
$not = '';
if (!empty($disallowed_tags)) {
$not = array();
foreach ($disallowed_tags as $ancestor) {
$not[] = 'and not(ancestor::' . $ancestor . ')';
}
$not = implode(' ', $not);
}
// Get word link limit.
$limit = variable_get('word_link_limit', 0);
$preg_limit = $limit == 0 ? -1 : $limit;
// Get current path.
$path = drupal_strtolower(drupal_get_path_alias());
$current_path = current_path();
// Get highlight status.
$highlight = variable_get('word_link_highlight', 0);
// Create array of links and replace patterns for each word.
foreach ($words as $word) {
$url = drupal_get_path_alias($word->url);
$match = FALSE;
// Check if current path matches word except path.
if (!empty($word->except)) {
$match = drupal_match_path($path, $word->except);
if ($path != $current_path) {
$match = $match || drupal_match_path($current_path, $word->except);
}
}
// Get visibility status and check if need to convert word on this page.
$visibility = empty($word->except) || !isset($word->visibility) ? FALSE : $word->visibility;
if ($url != $path && !$match && !$visibility || $url != $path && $visibility && $match) {
// Pattern which will be used to replace words.
$pattern = '$0';
// If highlight is off build links.
if (!$highlight) {
// Build external link.
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,
),
'rel' => $word->rel,
'title' => $word->url_title,
'target' => '_blank',
)),
'external' => TRUE,
));
}
else {
$replace[] = l($pattern, $word->url, array(
'attributes' => array_filter(array(
'class' => array(
$word->class,
),
'rel' => $word->rel,
'title' => $word->url_title,
)),
));
}
}
else {
$replace[] = '<span title="' . $word->url_title . '" class="' . $word->class . '">' . $pattern . '</span>';
}
// Build a patterns array.
$pattern = '/((\\b)|(?<=))(' . preg_quote($word->text, '/') . ')(?!(".*>)|[\'"&’^])\\b/u';
if ($word->case_sensitive) {
$search[] = $pattern;
}
else {
$search[] = $pattern . 'i';
}
}
}
// Find and convert words if $searh and $replace arrays are not empty.
if (isset($search) && isset($replace)) {
// Replace '&' to '&';
$subject = preg_replace('/&(?![a-z])/u', '&', $subject);
// Replace '&' to '&#38;';
$subject = str_replace('&', '&#38;', $subject);
// Turn off errors.
libxml_use_internal_errors(TRUE);
// Load string to DOMDocument.
$dom = filter_dom_load($subject);
$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);
}
}
// Convert a DOM object back to an HTML snippet.
$subject = filter_dom_serialize($dom);
}
// Remove '#38;' entity.
$subject = str_replace('#38;', '', $subject);
return $subject;
}
/**
* Get links from DB.
*
* @param int $id
* (optional) ID of a word.
* @param array $header
* (optional) header to build a table.
* @param int $limit
* (optional) determines the number of fields to get.
*
* @return array
* Formatted array with links.
*/
function word_link_get_link($id = NULL, $header = array(), $limit = NULL) {
$words = drupal_static(__FUNCTION__);
$key = FALSE;
// Get only one link by given id.
if ($id) {
$query = isset($words['id'][$id]) ? $words['id'][$id] : db_select('word_link', 'wl')
->fields('wl')
->condition('id', $id, '=')
->execute()
->fetchAll();
$key = 'id_' . $id;
}
elseif (empty($id) && empty($header) && empty($limit)) {
$query = isset($words['empty']) ? $words['empty'] : db_select('word_link', 'wl')
->fields('wl')
->execute()
->fetchAll();
$key = 'empty';
}
else {
$header_serialized = serialize($header);
$query = isset($words['header'][$header_serialized]) ? $words['header'][$header_serialized] : ($query = db_select('word_link', 'wl')
->extend('PagerDefault')
->limit($limit)
->extend('TableSort')
->orderByHeader($header)
->fields('wl')
->execute()
->fetchAll());
$key = 'header_' . $header_serialized;
}
$words[$key] = $query;
$links = array();
if (isset($words['ready'][$key])) {
$links = $words['ready'][$key];
}
elseif (count($query) > 0) {
foreach ($query as $value) {
$links[$value->id] = $value;
}
$words['ready'][$key] = $links;
}
return $links;
}
/**
* Verify by text if link already exists.
*
* @param string $text
* Word text which need to find.
* @param int $id
* (optional) ID of a word.
*
* @return bool
* Return word ID if word exist or FALSE if not.
*/
function word_link_word_exist($text, $id = 0) {
if ($text) {
$result = db_select('word_link', 'wl')
->fields('wl', array(
'text',
'case_sensitive',
'id',
))
->condition('id', $id, '!=')
->condition('text', $text, '=')
->execute()
->fetchAll();
}
if (empty($result)) {
return FALSE;
}
if (count($result) > 1) {
return $result[0]->id;
}
elseif (drupal_strtolower($text) == drupal_strtolower($result[0]->text)) {
return $result[0]->id;
}
return FALSE;
}
/**
* Add/Update link to DB.
*
* @param string $action
* Action which need to do.
* Can be 'insert' or 'update'.
* @param array $values
* Array with values that need to process.
* @param int $id
* (optional) ID of a word.
*/
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.
*
* @param int $id
* ID of a word.
*/
function word_link_del_link($id) {
db_delete('word_link')
->condition('id', $id)
->execute();
}
/**
* Get textarea fields of given content type.
*
* @param string $type
* The bundle name for which to return fields.
*
* @return array
* Array with textarea fields or empty array if it's not found.
*/
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
Name![]() |
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_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_update | Implements hook_node_update(). |
word_link_node_view | Implements hook_node_view(). |
word_link_permission | Implements hook_permission(). |
word_link_process_node_fields | Find node fields content and pass it for processing. |
word_link_replace_text | Find and convert defined word to link. |
word_link_word_exist | Verify by text if link already exists. |