Index: patterns.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/patterns/patterns.module,v
retrieving revision 1.1.2.2.2.1
diff -u -r1.1.2.2.2.1 patterns.module
--- patterns.module	26 Nov 2008 06:34:12 -0000	1.1.2.2.2.1
+++ patterns.module	26 Nov 2008 14:14:08 -0000
@@ -100,6 +100,12 @@
     'access arguments' => array('administer patterns'),
     'type' => MENU_CALLBACK
   );
+  $items['admin/build/patterns/modules/get_module'] = array(
+    'title' => 'Get Module',
+    'page callback' => '_patterns_get_module',
+    'access arguments' => array('administer patterns'),
+    'type' => MENU_CALLBACK
+  );
     
 //     $items[] = array('path' => 'admin/build/patterns/revert',
 //       'access' => user_access('administer patterns'),
@@ -321,6 +327,7 @@
       $actions[] = l(t('Run Update'), 'admin/build/patterns/enable/'. $pid);
     }    
     $actions[] = l(t('Edit'), 'admin/build/patterns/edit/'. $pid);
+    $actions[] = l(t('Modules'), 'admin/build/patterns/modules/'. $pid, array('attributes' => array('title' => 'View modules required to run this pattern.')));    
     $actions = implode('&nbsp;&nbsp;', $actions);
     
     $cells = array();
@@ -505,6 +512,10 @@
   drupal_set_title($pattern->title .' '. t('(Pattern Modules)'));
   
   $modules = patterns_modules($pattern);
+  if(!$modules) {
+    drupal_set_message("This pattern doesn't seem to have any modules");
+    drupal_goto("/admin/build/patterns");
+  }    
   $modules_info = module_rebuild_cache();
   $modules_list = module_list();
   
@@ -516,10 +527,15 @@
     $delete = is_array($module) ? $module['delete'] : false;
     $module = is_array($module) ? $module['value'] : $module;
     $available = array_key_exists($module, $modules_info);
+    if(!$available) {
+      $module_info = _patterns_get_module_links(array($module));
+    }    
     $enabled = array_key_exists($module, $modules_list);
-    $row[] = $module;
-    $row[] = $available ? t('Yes') : '<span class="alert">'. t('No') .'</span>';
-    $row[] = $enabled ? t('Yes') : '<span class="alert">'. t('No') .'</span>';
+    $row[] = $available ? $module : $module . "<br />" . "Likely location: " . $module_info[$module]['link'];
+    $row[] = $available ? t('Yes') : '<span class="alert">'. t('No') . " (" .
+      l("download", "admin/build/patterns/modules/get_module", array('query' => 'pid='. $pid ."&url=".$module_info[$module]['link']))
+      . ")" . '</span>';
+    $row[] = $enabled ? t('Yes') : '<span class="alert">'. t('No') . '</span>';
     $row[] = $delete ? t('Delete') : t('Enable');
     $rows[] = $row;
     
@@ -535,7 +551,9 @@
     drupal_set_message(t('All modules required by this module are available. Click !here to run this pattern.', array('!here' => l(t('here'), 'admin/build/patterns/enable/'. $pid))));
   }
   
-  return theme('table', array(t('Name'), t('Available'), t('Enabled'), t('Pattern Action')), $rows, t('Modules used for this pattern'));
+  //return theme('table', array(t('Name'), t('Available'), t('Enabled'), t('Pattern Action')), $rows, t('Modules used for this pattern'));
+  $output = theme('table', array(t('Name'), t('Available'), t('Enabled'), t('Pattern Action')), $rows, t('Modules used for this pattern'));
+  return $output;
 }
 
 function patterns_load_components() {
@@ -1417,3 +1435,75 @@
     )
   );
 }
+
+function _patterns_get_module_links($modules) {
+  $links = Array();
+  foreach($modules as $module) {
+    $url = "http://www.drupal.org/project/" . $module;
+    $page = drupal_http_request($url);
+    //TODO: better checking of results here
+    if($page->data) {    
+      //TODO: Select version depending on Drupal version dynamically
+      $did_match = preg_match("/http.*?".$module.".*?6.x.*?gz/", $page->data, $module_link);
+    }
+    if($did_match) {
+      $links[$module]['found'] = TRUE;
+      $links[$module]['link'] = $module_link[0];
+    }
+    else {
+      $links[$module]['found'] = FALSE;
+    }
+  }
+  return $links;
+}
+
+function _patterns_get_module() {
+  $url = check_plain($_GET['url']);
+  if(!empty($url) && is_string($url)) {
+    $result = _patterns_http_get_file($url);
+  }
+  if($result) {
+    drupal_set_message("Retrieved $url");
+    chdir($_SERVER['DOCUMENT_ROOT'] . "/sites/all/modules/");
+    exec("tar zxvf " . $result, $_null, $exec_result);
+    if($exec_result !== 0) {
+      drupal_set_message("Decompression failed", "error");
+    }
+    else {
+      drupal_set_message("Decompressed $result");
+    }
+    exec("rm " . $result, $_null, $exec_result);
+    if($exec_result !== 0) {
+      drupal_set_message("Cleanup failed", "error");
+    }
+    else {
+      drupal_set_message("Removed $result");
+    }
+    chdir($_SERVER['DOCUMENT_ROOT']);
+  }
+
+  $pid = check_plain($_GET['pid']);  
+  if (!empty($pid) && is_numeric($pid)) {
+    drupal_goto('/admin/build/patterns/modules/'. $pid);
+  }
+  else {
+    drupal_goto('/admin/build/patterns/');
+  } 
+}
+
+function _patterns_http_get_file($url)  {
+  define('BUFSIZ', 4095);
+  $dir = $_SERVER['DOCUMENT_ROOT'] . "/sites/all/modules/";
+  $module_dir_is_writable = file_check_directory($dir);
+  if(!$module_dir_is_writable) {
+    drupal_set_message("Modules directory is not writable", "error");
+    return FALSE;
+  }
+  $rfile = fopen($url, 'r');
+  $lfile = fopen($dir . '/'. basename($url), 'w');
+  while(!feof($rfile))
+  fwrite($lfile, fread($rfile, BUFSIZ), BUFSIZ);
+  fclose($rfile);
+  fclose($lfile);
+  return $dir . '/' . basename($url);
+}

