From 0614fcda520b17b4f14c015448dc44f6661fd608 Mon Sep 17 00:00:00 2001
From: the_g_bomb <gareth_alexander@hotmail.com>
Date: Thu, 22 Nov 2012 12:30:23 +0000
Subject: [PATCH] Issue #1468892 by the_g_bomb: Refactoring code and include
 support for issue linking.

---
 README.txt   |   24 +++++++
 dopl.css     |   33 ++++++++++
 dopl.install |    4 +
 dopl.module  |  192 ++++++++++++++++++++++++++++++++-------------------------
 4 files changed, 169 insertions(+), 84 deletions(-)
 create mode 100644 README.txt
 create mode 100644 dopl.css

diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..2928cf8
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,24 @@
+About
+-----------
+The Dopl module adds filters to text formats to facilitate linking to Drupal.org
+projects, nodes and users.
+
+Installation
+------------
+Dopl can be installed like any other Drupal module -- place it in the
+modules directory for your site and enable it on the `admin/build/modules` page.
+
+Once the module is enabled, go to `admin/config/content/formats` to enable the
+filter on one or more formats.
+
+Basic usage
+-----------
+
+* Module : module_name.module eg. panels.module
+* Theme : theme_name.theme eg. zen.theme
+* Translation : name.translation eg. fr.translation
+* Installation profile : name.installprofile eg. uberDrupal.installprofile
+* Issue on Drupal.org : node_id.issue eg. 1468892.issue
+* Node on Drupal.org : node_id.do eg. 345196.do
+* Node on groups.drupal.org : node_id.gdo eg. 345196.gdo
+* Users : user_id.user eg. 48488.user
\ No newline at end of file
diff --git a/dopl.css b/dopl.css
new file mode 100644
index 0000000..97da83c
--- /dev/null
+++ b/dopl.css
@@ -0,0 +1,33 @@
+
+.project-issue-status-info a, .project-issue-status-info .project-issue-assigned-user {
+  background-color: #CDCDCD;
+  border-radius: 4px 4px 4px 4px;
+  padding: 2px 4px;
+}
+.project-issue-status-info .project-issue-assigned-user {
+  white-space: nowrap;
+}
+.project-issue-status-1 a {
+  background-color: #FFFFFF;
+}
+.project-issue-status-2 a {
+  background-color: #C0FFC0;
+}
+.project-issue-status-3 a, .project-issue-status-4 a, .project-issue-status-5 a, .project-issue-status-6 a {
+  background-color: #DDDDFF;
+}
+.project-issue-status-7 a {
+  background-color: #FFC9C9;
+}
+.project-issue-status-8 a {
+    background-color: #FFFFDD;
+}
+.project-issue-status-13 a {
+  background-color: #FFE7DD;
+}
+.project-issue-status-14 a {
+  background-color: #E7FFDD;
+}
+.project-issue-status-2, .project-issue-status-3, .project-issue-status-5, .project-issue-status-6, .project-issue-status-7 {
+  text-decoration: line-through;
+}
diff --git a/dopl.install b/dopl.install
index a980b03..45328a0 100644
--- a/dopl.install
+++ b/dopl.install
@@ -1,5 +1,9 @@
 <?php
 
+/**
+ * @file
+ * dopl module installation hooks
+ */
 function dopl_install() {
   drupal_set_message(t('In order to activate the Drupal.org project link filter, you must !activate_it in the input formats admin screen.', array('!activate_it' => l(t('activate it'), 'admin/settings/filters'))));
 }
\ No newline at end of file
diff --git a/dopl.module b/dopl.module
index 2307efa..2e7f915 100644
--- a/dopl.module
+++ b/dopl.module
@@ -6,6 +6,24 @@
  */
 
 /**
+ * Implementation of hook_init().
+ */
+function dopl_init() {
+  drupal_add_css(drupal_get_path('module', 'dopl') . '/dopl.css');
+}
+
+/**
+ * Implementation of hook_help().
+ */
+function dopl_help($path, $arg) {
+  switch ($path) {
+    case 'admin/help#dopl':
+      // Return a line-break version of the module README.txt
+      return filter_filter('process', 1, NULL, file_get_contents(dirname(__FILE__) . "/README.txt"));
+  }
+}
+
+/**
  * Implementation of hook_filter().
  */
 function dopl_filter($op, $delta = 0, $format = -1, $text = '') {
@@ -15,7 +33,7 @@ function dopl_filter($op, $delta = 0, $format = -1, $text = '') {
     case 'list':
       return array(0 => t('Drupal.org project link filter'));
     case 'description':
-      return t('Facilitate linking to Drupal.org projects and nodes.');
+      return t('Facilitate linking to Drupal.org projects, issues and nodes.');
     case 'process':
       return dopl_process($text);
     default:
@@ -27,110 +45,116 @@ function dopl_filter($op, $delta = 0, $format = -1, $text = '') {
  * Implementation of hook_filter_tips().
  */
 function dopl_filter_tips($delta, $format, $long = false) {
-  return t('Use one of the forms <em>name.module</em>, <em>name.theme</em>, <em>name.translation</em>, <em>name.installprofile</em> or <em>name.project</em>, in order to link to <em>http://drupal.org/project/name</em> - Note that a link will be generated even if the project or node does not exist.<br />Use <em>[nid].do</em> to link to <em>http://drupal.org/node/[nid]</em>, and <em>[nid].gdo</em> to link to <em>http://groups.drupal.org/node/[nid]</em> - Links will only be generated for valid node IDs using this format.');
+  return t('Use one of the forms <em>name.module</em>, <em>name.theme</em>, <em>name.translation</em>, <em>name.installprofile</em> or <em>name.project</em>, in order to link to <em>http://drupal.org/project/name</em> - Note that a link will be generated even if the project or node does not exist.<br />Use <em>[nid].do</em> or <em>[nid].issue</em> to link to <em>http://drupal.org/node/[nid]</em>, and <em>[nid].gdo</em> to link to <em>http://groups.drupal.org/node/[nid]</em> - Links will only be generated for valid node IDs using this format.');
 }
 
-
 function dopl_process($text) {
   $pattern = '/(\b)(\w+)(\.(module|theme|translation|installprofile|project))(\b)/';
   // Old style. Kept for reference:
   // $replacement = '$1<a href="http://drupal.org/project/$2">$2$3</a>$5';
-  $text = preg_replace_callback($pattern, 'dopl_update_clone', $text);
-
-  // Link drupal.org nodes by nid
-  //$pattern = '/(\b)(\w+)(\.(node))(\b)/';
-  $pattern = '/(\b)([a-z0-9#\-]*)(\.(do))(\b)/';
-  $text = preg_replace_callback($pattern, 'dopl_get_dotitle', $text);
+  $text = preg_replace_callback($pattern, 'dopl_get_link', $text);
 
-  // Link groups.drupal.org nodes by nid
+  // Link drupal.org groups issues and nodes by nid
   //$pattern = '/(\b)(\w+)(\.(node))(\b)/';
-  $pattern = '/(\b)([a-z0-9#\-]*)(\.(gdo))(\b)/';
-  $text = preg_replace_callback($pattern, 'dopl_get_gdotitle', $text);
+  $pattern = '/(\b)([a-z0-9#\-]*)(\.(do|issue|gdo|user))(\b)/';
+  $text = preg_replace_callback($pattern, 'dopl_get_link', $text);
 
   return $text;
 }
 
-function dopl_update_clone($matches = array()){
-  $name = $matches[2]; // the plain module name (e.g., cck, views, dopl)
-  // First try to fetch data from cache
-  if ($link = cache_get('dopl:'. $matches[2])) {
-    return $link->data;
+/**
+ * Custom function to retrieve link information
+ */
+function dopl_get_link($matches = array()) {
+  $link_data = array();
+  $link_variables = array();
+  $issue = FALSE;
+  if ($data = cache_get('dopl:' . $matches[4] . '-' . $matches[2])) {
+    $link_variables = json_decode((array_key_exists(7, $matches)) ? $matches[7] : $data->data, TRUE);
   }
-  else if (module_exists('update')) {
-    module_load_include('inc', 'update', 'update.fetch');
-    // Try to fetch the project's full name, using update.module's functions:
-    $core_compatibility = array('7.x', '6.x', '5.x', '4.7.x');
-    $url = variable_get('update_fetch_url', UPDATE_DEFAULT_URL);
-    foreach ($core_compatibility as $key => $value) {
-      $current_url = $url . '/' . $name . '/' . $value;
-      $xml = drupal_http_request($current_url);
-      if (isset($xml->data)) {
-        $data[] = $xml->data;
-      }
-      if ($data) {
-        $parser = new update_xml_parser;
-        $available = $parser->parse($data);
-      }
-      if ($project_title = $available[$name]['title']) {
-        // Add a left to right mark before and after the link. See http://drupal.org/node/421454
-        $link = $matches[1] . '&lrm;<a href="http://drupal.org/project/' . $matches[2] . '">' . $project_title . '</a>&lrm;' . $matches[5];
-        // Update cache:
-        cache_set('dopl:'. $matches[2], $link);
-        return $link;
-      }
+  else {
+    switch ($matches[4]) {
+      case 'module' :
+      case 'theme' :
+      case 'translation' :
+      case 'installprofile' :
+      case 'project' :
+        $url = 'http://drupal.org/project/' . $matches[2];
+        break;
+      case 'do' :
+        $url = 'http://drupal.org/node/' . $matches[2];
+        break;
+      case 'gdo' :
+        $url = 'http://groups.drupal.org/node/' . $matches[2];
+        break;
+      case 'user' :
+        $url = 'http://drupal.org/user/' . $matches[2];
+        break;
+      case 'issue' :
+        $url = 'http://drupal.org/node/' . $matches[2] . "/project-issue/json";
+        $issue = TRUE;
+        break;
+    }
+
+    if ($link_data = dopl_get_link_data($url, $issue)) {
+      //if url returns a project page, we assume a project / node exists
+      cache_set('dopl:' . $matches[4] . '-' . $matches[2], json_encode($link_data));
+      $link_variables = (array_key_exists(7, $matches)) ? $matches[7] : $link_data;
     }
-    // if we reached here it means there is no active project of this name. Set the cache to express it (See: http://drupal.org/node/421456)
-    cache_set('dopl:'. $matches[2], $matches[0]);
-    return $matches[0];
   }
-  else {
-    return $matches[1] . '<a href="http://drupal.org/project/' . $matches[2] . '">' . $matches[2] . $matches[3] . '</a>' . $matches[5];
+  if (!empty($link_variables)) {
+    return $link_variables['prefix'] . l($link_variables['title'], $link_variables['url'], $link_variables['options']) . $link_variables['postfix'];
   }
+  return $matches[0];
 }
 
-function dopl_get_dotitle($matches = array()){
-  $name = $matches[2]; // the node path (e.g., node/[nid])
-  // First try to fetch data from cache
-  if ($link = cache_get('dopldo:'. $matches[2])) {
-    return $link->data;
+/*
+ * Custom function to collect data from url
+ */
+
+function dopl_get_link_data($filename, $issue = FALSE) {
+  $result = @drupal_http_request($filename);
+  if (isset($result->error) || !isset($result->data) || $result->code != 200) {
+    return FALSE;
   }
-  else {
-    $url = 'http://drupal.org/node/' . $matches[2] ;
-    $node_title = substr(dopl_get_page_title($url), 0, -13);
-    // Add a left to right mark before and after the link. See http://drupal.org/node/421454
-    $link = $matches[1] . '&lrm;<a href="http://drupal.org/node/' . $matches[2] . '">' . $node_title . '</a>&lrm;' . $matches[5];
-    // Update cache:
-    cache_set('dopldo:'. $matches[2], $link);
-    return $link;
+  else if ($issue) {
+    $issue_info = json_decode($result->data, TRUE);
+    $title = trim($issue_info['title']);
+    $id = trim($issue_info['id']);
+    $url = trim($issue_info['url']);
+    $status_id = trim($issue_info['statusId']);
+    $status = trim($issue_info['status']);
+    $options = array();
+    if (!empty($issue_info['assignedName']) && $issue_info['assignedName'] != 'Anonymous') {
+      $username = trim($issue_info['assignedName']);
+      // We have an assigned user, so include it in title.
+      // l() runs $attributes through drupal_attributes() which escapes the value.
+      $options['attributes'] = array('title' => t('Status: !status, Assigned to: !username', array('!status' => $status, '!username' => $username)));
+    }
+    else {
+      // Just the status.
+      $options['attributes'] = array('title' => t('Status: !status', array('!status' => $status)));
+    }
+    $link_data = array(
+      'options' => $options,
+      'title' => "#$id: $title",
+      'url' => $url,
+      'prefix' => '<span class="project-issue-status-' . $status_id . ' project-issue-status-info">',
+      'postfix' => '</span>',
+    );
+    return $link_data;
   }
-}
-
-function dopl_get_gdotitle($matches = array()){
-  $name = $matches[2]; // the node path (e.g., node/[nid])
-  // First try to fetch data from cache
-  if ($link = cache_get('doplgdo:'. $matches[2])) {
-    return $link->data;
+  else if (preg_match("#<title>(.+)<\/title>#iU", $result->data, $title)) {
+    $link_data = array(
+      'options' => array(),
+      'title' => substr(trim($title[1]), 0, -13),
+      'url' => $filename,
+      'prefix' => '',
+      'postfix' => '',
+    );
+    return $link_data;
   }
   else {
-    $url = 'http://groups.drupal.org/node/' . $matches[2] ;
-    $node_title = substr(dopl_get_page_title($url), 0, -20);
-    // Add a left to right mark before and after the link. See http://drupal.org/node/421454
-    $link = $matches[1] . '&lrm;<a href="http://groups.drupal.org/node/' . $matches[2] . '">' . $node_title . '</a>&lrm;' . $matches[5];
-    // Update cache:
-    cache_set('doplgdo:'. $matches[2], $link);
-    return $link;
-  }
-}
-
-function dopl_get_page_title($url){
-  $data = @file_get_contents($url);
-  if (FALSE === $data) {
     return FALSE;
-    dpm('boom!');
   }
-  else if (preg_match("#<title>(.+)<\/title>#iU", $data, $t))  {
-		return trim($t[1]);
-	} else {
-		return false;
-	}
-}
\ No newline at end of file
+}
-- 
1.7.9.msysgit.0

