uuid_link.module in UUID Link 6
Same filename and directory in other branches
Provides a filter and UI for adding links to entities that are not affected by changes in URL alias.
File
uuid_link.moduleView source
<?php
/**
* @file
* Provides a filter and UI for adding links to entities that are not affected
* by changes in URL alias.
*/
/**
* Implements hook_permission().
*/
function uuid_link_permission() {
return array(
'access uuid link',
);
}
/**
* Implements hook_menu().
*/
function uuid_link_menu() {
$items = array();
$items['uuid-link/autocomplete'] = array(
'page callback' => 'uuid_link_autocomplete',
'access arguments' => array(
'access uuid link',
),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Implements hook_wysiwyg_plugin().
*/
function uuid_link_wysiwyg_plugin($editor, $version) {
if ($editor == 'ckeditor') {
return array(
'uuid_link' => array(
'path' => drupal_get_path('module', 'uuid_link') . '/plugins/link/',
'load' => TRUE,
'extensions' => array(
'uuid_link' => t('Link to site content'),
),
),
);
}
}
/**
* Implements hook_element_info_alter().
*/
function uuid_link_element_info_alter(&$type) {
if (!empty($type['text_format'])) {
$type['form']['#post_render'][] = 'uuid_link_form_post_render';
}
}
/**
* Implements hook_entity_info_alter().
*/
function uuid_link_entity_info_alter(&$entity_info) {
// The username should be the label for users.
$entity_info['user']['entity keys']['label'] = 'name';
}
/**
* Post render callback. Load javascript files and set module settings.
*/
function uuid_link_form_alter(&$form, $form_state, $form_id) {
drupal_set_message($form_id);
if (substr($form_id, -9) == 'node_form') {
$form['#after_build'][] = 'uuid_link_form_post_build';
}
}
function uuid_link_form_post_build($form) {
static $added;
if (empty($added) && ($js = drupal_add_js()) && isset($js['setting'])) {
$settings = call_user_func_array('array_merge_recursive', $js['setting']);
if (isset($settings['ckeditor']) || isset($settings['wysiwyg']['configs']['ckeditor'])) {
$added = TRUE;
drupal_add_js('misc/autocomplete.js');
$settings = array(
'autocomplete_path' => url('uuid-link/autocomplete'),
'type_name' => uuid_link_get_link_type_name(),
);
drupal_add_js(array(
'uuid_link' => $settings,
), 'setting');
}
}
return $form;
}
/**
* Get a list of available link types. In this case, a list of entity types.
*/
function uuid_link_get_link_type_name() {
$types = array(
'node' => 'Node',
'user' => 'User',
'term' => 'Term',
'vocabulary' => 'Vocabulary',
);
return $types;
}
/**
* Get URL to an entity.
*
* @param $entity_type
* Entity type.
* @param $entity
* Entity object.
*/
function uuid_link_entity_url($entity_type, $entity) {
switch ($entity_type) {
default:
$uri = entity_uri($entity_type, $entity);
if (is_array($uri)) {
return _uuid_link_entity_url($uri, $entity);
}
case 'file':
return file_create_url($entity->uri);
}
}
/**
* Implements hook_filter().
*/
function uuid_link_filter($op, $delta = 0, $format = -1, $text = '', $cache_id = 0) {
switch ($op) {
case 'list':
return uuid_link_filter_info();
case 'no cache':
return FALSE;
case 'description':
return uuid_link_filter_info($delta);
case 'prepare':
return uuid_link_filter_prepare($format, $text, $cache_id);
case 'process':
return uuid_link_filter_process($format, $text, $cache_id);
}
}
/**
* Returns information about filters.
*
* @param int $delta
* optional $delta parameter to request info about a particular filter. If
* not set, the function will return the list of filter names.
*
* @return array|string
* An array of defined filter names or the description for the filter $delta
* if the parameter is set.
*/
function uuid_link_filter_info($delta = NULL) {
$filters = array(
0 => t('UUID Link filter'),
);
$filter_info = array(
0 => t('Converts links added through UUID Link into actual link to content.'),
);
if ($delta === NULL) {
return $filters;
}
elseif (isset($filter_info[$delta])) {
return $filter_info[$delta];
}
return NULL;
}
/**
* Implements hook_filter_tips().
*/
function uuid_link_filter_tips($delta, $format, $long = FALSE) {
// Since we have only one filter, we can assume $delta is 0.
if (!$long) {
$output = uuid_link_filter_info($delta);
}
else {
$output = '<p>' . t('Tokens of the form [uuid-link:xxxx] will be transformed to links to the node with uuid xxxx.');
}
return $output;
}
/**
* Filter prepare callback. Replaces [uuid-link:xxxx] with links.
*/
function uuid_link_filter_prepare($format, $text, $cache_id) {
$pattern = "@\\[uuid-link:([^:]+):([^:\\]]+)\\]@";
return preg_replace_callback($pattern, 'uuid_link_replace_callback', $text);
}
/**
* Replace callback for uuid link tokens.
*/
function uuid_link_replace_callback($matches) {
$url = NULL;
$type = $matches[1];
$uuid = $matches[2];
if ($type == 'node' && ($nid = uuid_link_get_nid($uuid))) {
$url = url("node/{$nid}");
}
elseif ($type == 'user' && ($uid = uuid_link_get_uid($uuid))) {
$url = url("user/{$uid}");
}
if (empty($url)) {
$url = '#uuid-link-not-found';
}
return $url;
}
/**
* Returns the nid for a node based on a given uuid.
*
* @param string $uuid
* The uuid that needs to be mapped.
*/
function uuid_link_get_nid($uuid) {
static $static_cache = array();
if (empty($static_cache['uuid'])) {
$nid = db_result(db_query(db_rewrite_sql("SELECT n.nid\n FROM {node} AS n\n INNER JOIN {uuid_node} AS un ON n.nid = un.nid\n WHERE un.uuid = '%s'"), $uuid));
$static_cache[$uuid] = $nid;
}
return $static_cache[$uuid];
}
/**
* Returns the uid for a user based on a given uuid.
*
* @param string $uuid
* The uuid that needs to be mapped.
*/
function uuid_link_get_uid($uuid) {
static $static_cache = array();
if (empty($static_cache['uuid'])) {
$uid = db_result(db_query("SELECT u.uid\n FROM {users} AS u\n INNER JOIN {uuid_users} AS uu ON u.uid = uu.uid\n WHERE uu.uuid = '%s'", $uuid));
$static_cache[$uuid] = $uid;
}
return $static_cache[$uuid];
}
/**
* Filter process callback.
*/
function uuid_link_filter_process($format, $text, $cache_id) {
// Tokens are replaced on the prepare operation.
// Remove tags for links to content that no longer exists. Check the existence
// of the #uuid-link-not-found before doing this expensive job.
if (strpos($text, '#uuid-link-not-found') !== FALSE) {
$dom = filter_dom_load($text);
$xpath = new DOMXPath($dom);
foreach ($xpath
->query('//a[@href="#uuid-link-not-found"]') as $link) {
// Move all link tag content to its parent node just before it.
while ($link
->hasChildNodes()) {
$child = $link
->removeChild($link->firstChild);
$link->parentNode
->insertBefore($child, $link);
}
// Remove the link tag.
$link->parentNode
->removeChild($link);
}
$text = filter_dom_serialize($dom);
}
return $text;
}
/**
* Autocomplete callback for entities.
*/
function uuid_link_autocomplete($type, $string = '') {
$matches = array();
if ($type == 'node') {
$matches = _uuid_link_autocomplete_node($string);
}
elseif ($type == 'term') {
$matches = _uuid_link_autocomplete_term($string);
}
elseif ($type == 'vocabulary') {
$matches = _uuid_link_autocomplete_vocabulary($string);
}
elseif ($type == 'user') {
$matches = _uuid_link_autocomplete_user($string);
}
drupal_json($matches);
}
/**
* Callback for auto completing node links.
*
* @param string $string
* The partial string to auto complete.
*
* @return array
* An associative array of uuid => title.
*/
function _uuid_link_autocomplete_node($string) {
$matches = array();
$query = "SELECT DISTINCT(uu.uuid), title, language FROM {node} n INNER JOIN {uuid_node} u ON n.nid = u.nid";
$query .= " WHERE n.title LIKE '%s%%'";
// Only search for published nodes.
$query .= " AND n.status = 1";
$query .= " ORDER BY n.title";
$result = db_query_range(db_rewrite_sql($query), $string, 0, 15);
while ($row = db_fetch_object($result)) {
// If content is language specific show language code.
if (!empty($row->language)) {
$matches[$row->uuid] = t('[@language] @label', array(
'@language' => $row->language,
'@label' => $row->title,
));
}
else {
$matches[$row->uuid] = check_plain($row->title);
}
}
return $matches;
}
/**
* Callback for auto completing user links.
*
* @param string $string
* The partial string to auto complete.
*
* @return array
* An associative array of uuid => username.
*/
function _uuid_link_autocomplete_user($string) {
$matches = array();
$query = "SELECT DISTINCT(uu.uuid), name, language FROM {users} u INNER JOIN {uuid_users} uu ON u.uid = uu.uid";
$query .= " WHERE u.name LIKE '%s%%'";
// Only search for published nodes.
$query .= " AND u.status = 1";
$query .= " ORDER BY u.name";
$result = db_query_range(db_rewrite_sql($query), $string, 0, 15);
while ($row = db_fetch_object($result)) {
$matches[$row->uuid] = check_plain($row->name);
}
return $matches;
}
if (!function_exists('filter_dom_load')) {
/**
* Backport of filter_dom_load.
*
* @param string $text
* html text.
*
* @return DOMDocument
* The text parsed and structured as a DOMDocument.
*/
function filter_dom_load($text) {
$dom_document = new DOMDocument();
// Ignore warnings during HTML soup loading.
@$dom_document
->loadHTML('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>' . $text . '</body></html>');
return $dom_document;
}
}
if (!function_exists('filter_dom_serialize')) {
/**
* Backports filter_dom_serialize().
*/
function filter_dom_serialize($dom_document) {
$body_node = $dom_document
->getElementsByTagName('body')
->item(0);
$body_content = '';
foreach ($body_node
->getElementsByTagName('script') as $node) {
filter_dom_serialize_escape_cdata_element($dom_document, $node);
}
foreach ($body_node
->getElementsByTagName('style') as $node) {
filter_dom_serialize_escape_cdata_element($dom_document, $node, '/*', '*/');
}
foreach ($body_node->childNodes as $child_node) {
$body_content .= $dom_document
->saveXML($child_node);
}
return preg_replace('|<([^> ]*)/>|i', '<$1 />', $body_content);
}
}
if (!function_exists('filter_dom_serialize_escape_cdata_element')) {
/**
* Backports filter_dom_serialize_escape_cdata_element().
*/
function filter_dom_serialize_escape_cdata_element($dom_document, $dom_element, $comment_start = '//', $comment_end = '') {
foreach ($dom_element->childNodes as $node) {
if (get_class($node) == 'DOMCdataSection') {
// See drupal_get_js(). This code is more or less duplicated there.
$embed_prefix = "\n<!--{$comment_start}--><![CDATA[{$comment_start} ><!--{$comment_end}\n";
$embed_suffix = "\n{$comment_start}--><!]]>{$comment_end}\n";
// Prevent invalid cdata escaping as this would throw a DOM error.
// This is the same behavior as found in libxml2.
// Related W3C standard: http://www.w3.org/TR/REC-xml/#dt-cdsection
// Fix explanation: http://en.wikipedia.org/wiki/CDATA#Nesting
$data = str_replace(']]>', ']]]]><![CDATA[>', $node->data);
$fragment = $dom_document
->createDocumentFragment();
$fragment
->appendXML($embed_prefix . $data . $embed_suffix);
$dom_element
->appendChild($fragment);
$dom_element
->removeChild($node);
}
}
}
}
Functions
Name![]() |
Description |
---|---|
uuid_link_autocomplete | Autocomplete callback for entities. |
uuid_link_element_info_alter | Implements hook_element_info_alter(). |
uuid_link_entity_info_alter | Implements hook_entity_info_alter(). |
uuid_link_entity_url | Get URL to an entity. |
uuid_link_filter | Implements hook_filter(). |
uuid_link_filter_info | Returns information about filters. |
uuid_link_filter_prepare | Filter prepare callback. Replaces [uuid-link:xxxx] with links. |
uuid_link_filter_process | Filter process callback. |
uuid_link_filter_tips | Implements hook_filter_tips(). |
uuid_link_form_alter | Post render callback. Load javascript files and set module settings. |
uuid_link_form_post_build | |
uuid_link_get_link_type_name | Get a list of available link types. In this case, a list of entity types. |
uuid_link_get_nid | Returns the nid for a node based on a given uuid. |
uuid_link_get_uid | Returns the uid for a user based on a given uuid. |
uuid_link_menu | Implements hook_menu(). |
uuid_link_permission | Implements hook_permission(). |
uuid_link_replace_callback | Replace callback for uuid link tokens. |
uuid_link_wysiwyg_plugin | Implements hook_wysiwyg_plugin(). |
_uuid_link_autocomplete_node | Callback for auto completing node links. |
_uuid_link_autocomplete_user | Callback for auto completing user links. |