From 99b55bfcac0820a8a8d3761b5cd8d23153f7687b Mon Sep 17 00:00:00 2001
From: Eric Rasmussen <ericrasmussen1@gmail.com>
Date: Wed, 30 May 2012 10:33:36 -0500
Subject: [PATCH] [gh-390] Fix UNL site list

Replace the run-at-request complicated JOIN db query with a cron task that fills in name and access in two new unl_sites db fields.
---
 sites/all/modules/unl/cron.php              |  73 ++++++++++++--
 sites/all/modules/unl/unl.install           |  41 +++++++-
 sites/all/modules/unl/unl_site_creation.php | 103 ++++----------------
 3 files changed, 121 insertions(+), 96 deletions(-)

diff --git a/sites/all/modules/unl/cron.php b/sites/all/modules/unl/cron.php
index 2e8965ec..8670589b 100644
--- a/sites/all/modules/unl/cron.php
+++ b/sites/all/modules/unl/cron.php
@@ -28,6 +28,7 @@ unl_remove_page_aliases();
 unl_add_sites();
 unl_add_aliases();
 unl_add_page_aliases();
+unl_update_unl_sites();
 
 function unl_add_sites() {
   $query = db_query('SELECT * FROM {unl_sites} WHERE installed=0');
@@ -215,7 +216,7 @@ function unl_add_site($site_path, $uri, $clean_url, $db_prefix, $site_id) {
   if ($site_mail) {
     $command .= " --site-mail=$site_mail";
   }
-  
+
   $result = shell_exec($command);
   echo $result;
   if (stripos($result, 'Drush command terminated abnormally due to an unrecoverable error.') !== FALSE) {
@@ -275,7 +276,7 @@ function unl_add_alias($site_uri, $base_uri, $path, $alias_id) {
   $alias_uri = $base_uri . $path;
   $real_config_dir = unl_get_sites_subdir($site_uri);
   $alias_config_dir = unl_get_sites_subdir($alias_uri, FALSE);
-  
+
   unl_add_alias_to_sites_php($alias_config_dir, $real_config_dir, $alias_id);
   if ($path) {
     unl_add_site_to_htaccess($alias_id, $path, TRUE);
@@ -289,7 +290,7 @@ function unl_remove_alias($base_uri, $path, $alias_id) {
    *       to the new method of creating aliases.
    */
   unlink(DRUPAL_ROOT . '/sites/' . $alias_config_dir);
-  
+
   unl_remove_alias_from_sites_php($alias_id);
   unl_remove_site_from_htaccess($alias_id, TRUE);
 }
@@ -318,7 +319,7 @@ function unl_add_site_to_htaccess($site_id, $site_path, $is_alias) {
   }
 
   unl_require_writable(DRUPAL_ROOT . '/.htaccess');
-  
+
   $stub_token = '  # %UNL_CREATION_TOOL_STUB%';
   $htaccess = file_get_contents(DRUPAL_ROOT . '/.htaccess');
   $stub_pos = strpos($htaccess, $stub_token);
@@ -346,7 +347,7 @@ function unl_remove_site_from_htaccess($site_id, $is_alias) {
   }
 
   unl_require_writable(DRUPAL_ROOT . '/.htaccess');
-  
+
   $htaccess = file_get_contents(DRUPAL_ROOT . '/.htaccess');
   $site_start_token = "\n  # %UNL_START_{$site_or_alias}_ID_{$site_id}%";
   $site_end_token = "  # %UNL_END_{$site_or_alias}_ID_{$site_id}%\n";
@@ -366,7 +367,7 @@ function unl_remove_site_from_htaccess($site_id, $is_alias) {
 
 function unl_add_page_alias_to_htaccess($site_id, $host, $path, $to_uri) {
   unl_require_writable(DRUPAL_ROOT . '/.htaccess');
-  
+
   $stub_token = '  # %UNL_CREATION_TOOL_STUB%';
   $htaccess = file_get_contents(DRUPAL_ROOT . '/.htaccess');
   $stub_pos = strpos($htaccess, $stub_token);
@@ -387,7 +388,7 @@ function unl_add_page_alias_to_htaccess($site_id, $host, $path, $to_uri) {
 
 function unl_remove_page_alias_from_htaccess($site_id) {
   unl_require_writable(DRUPAL_ROOT . '/.htaccess');
-  
+
   $htaccess = file_get_contents(DRUPAL_ROOT . '/.htaccess');
   $site_start_token = "\n  # %UNL_START_PAGE_ALIAS_ID_{$site_id}%";
   $site_end_token = "  # %UNL_END_PAGE_ALIAS_ID_{$site_id}%\n";
@@ -407,7 +408,7 @@ function unl_remove_page_alias_from_htaccess($site_id) {
 
 function unl_add_alias_to_sites_php($alias_site_dir, $real_site_dir, $alias_id) {
   unl_require_writable(DRUPAL_ROOT . '/sites/sites.php');
-  
+
   $stub_token = '# %UNL_CREATION_TOOL_STUB%';
   $sites_php = file_get_contents(DRUPAL_ROOT . '/sites/sites.php');
   $stub_pos = strpos($sites_php, $stub_token);
@@ -426,7 +427,7 @@ function unl_add_alias_to_sites_php($alias_site_dir, $real_site_dir, $alias_id)
 
 function unl_remove_alias_from_sites_php($alias_id) {
   unl_require_writable(DRUPAL_ROOT . '/sites/sites.php');
-  
+
   $sites_php = file_get_contents(DRUPAL_ROOT . '/sites/sites.php');
   $site_start_token = "\n# %UNL_START_ALIAS_ID_{$alias_id}%";
   $site_end_token = "# %UNL_END_ALIAS_ID_{$alias_id}%\n";
@@ -449,3 +450,57 @@ function unl_require_writable($path) {
     throw new Exception('The file "' . $path . '" needs to be writable and is not.');
   }
 }
+
+/**
+ * Updates the name and access fields in the default site unl_sites table for display on admin/sites/unl
+ */
+function unl_update_unl_sites() {
+  // Get all sites in production
+  $query = db_query('SELECT * FROM {unl_sites} WHERE installed=2');
+
+  // Get all custom made roles (roles other than authenticated, anonymous, administrator)
+  $roles = user_roles(TRUE);
+  unset($roles[DRUPAL_AUTHENTICATED_RID]);
+  unset($roles[variable_get('user_admin_role')]);
+
+  // Setup alternate db connection so we can query other sites' tables without a prefix being attached
+  $database_noprefix = array(
+    'database' => $GLOBALS['databases']['default']['default']['database'],
+    'username' => $GLOBALS['databases']['default']['default']['username'],
+    'password' => $GLOBALS['databases']['default']['default']['password'],
+    'host' => $GLOBALS['databases']['default']['default']['host'],
+    'port' => $GLOBALS['databases']['default']['default']['port'],
+    'driver' => $GLOBALS['databases']['default']['default']['driver'],
+  );
+  Database::addConnectionInfo('UNLNoPrefix', 'default', $database_noprefix);
+
+  // The master prefix that was specified during initial drupal install
+  $master_prefix = $GLOBALS['databases']['default']['default']['prefix'];
+
+  while ($row = $query->fetchAssoc()) {
+    // Switch to alt db connection
+    db_set_active('UNLNoPrefix');
+
+    // Get site name
+    $table = $row['db_prefix'].'_'.$master_prefix.'variable';
+    $name = db_query("SELECT value FROM ".$table." WHERE name = 'site_name'")->fetchField();
+
+    // Get last access timestamp (by a non-administrator)
+    $table_users = $row['db_prefix'].'_'.$master_prefix.'users u';
+    $table_users_roles = $row['db_prefix'].'_'.$master_prefix.'users_roles r';
+    if (!empty($roles)) {
+      $access = db_query('SELECT u.access FROM '.$table_users.', '.$table_users_roles.' WHERE u.uid = r.uid AND u.access > 0 AND r.rid IN (' . implode(',', array_keys($roles)) . ') ORDER BY u.access DESC')->fetchColumn();
+    } else {
+      $access = 0;
+    }
+
+    // Restore default db connection
+    db_set_active();
+
+    // Update unl_sites table of the default site
+    db_update('unl_sites')
+      ->fields(array('name' => @unserialize($name), 'access' => (int)$access))
+      ->condition('site_id', $row['site_id'])
+      ->execute();
+  }
+}
diff --git a/sites/all/modules/unl/unl.install b/sites/all/modules/unl/unl.install
index 613e7c0a..395d5d12 100644
--- a/sites/all/modules/unl/unl.install
+++ b/sites/all/modules/unl/unl.install
@@ -5,7 +5,7 @@ function unl_schema() {
   $schema['unl_sites'] = array(
     'description' => 'Table of tables to be programatically created',
     'fields' => array(
-      'site_id'  => array(
+      'site_id' => array(
         'type'     => 'serial',
         'unsigned' => TRUE,
         'not null' => TRUE,
@@ -38,6 +38,20 @@ function unl_schema() {
         'not null' => TRUE,
         'default'  => '',
       ),
+      'name' => array(
+        'description' => 'Site name entered on the site configuration page.',
+        'type'     => 'varchar',
+        'length'   => 255,
+        'not null' => TRUE,
+        'default'  => '',
+      ),
+      'access' => array(
+        'description' => 'Timestamp for previous time a non-admin role accessed the site.',
+        'type'     => 'int',
+        'length'   => 11,
+        'not null' => TRUE,
+        'default'  => 0,
+      ),
       'site_admin' => array(
         'type'     => 'varchar',
         'length'   => 255,
@@ -153,7 +167,7 @@ function unl_update_7100() {
   $table = array(
     'description' => 'Table of tables to be programatically created',
     'fields' => array(
-      'site_id'  => array(
+      'site_id' => array(
         'type'     => 'serial',
         'unsigned' => TRUE,
         'not null' => TRUE,
@@ -364,8 +378,7 @@ function unl_update_7109() {
 /**
  * Updates unl sites and site aliases to have trailing slashes.
  */
-function unl_update_7110()
-{
+function unl_update_7110() {
   db_query("UPDATE {unl_sites} SET site_path = CONCAT(site_path, '/') WHERE SUBSTRING(site_path, -1) != '/'");
   db_query("UPDATE {unl_sites} SET uri = CONCAT(uri, '/') WHERE SUBSTRING(uri, -1) != '/'");
   db_query("UPDATE {unl_sites_aliases} SET base_uri = CONCAT(base_uri, '/') WHERE SUBSTRING(base_uri, -1) != '/'");
@@ -389,3 +402,23 @@ function unl_update_7112() {
   );
   variable_set('unl_module_whitelist', $modules);
 }
+
+/**
+ * Add name and access fields to unl_sites table to hold site name and last access timestamp.
+ */
+function unl_update_7113() {
+  db_add_field('unl_sites', 'name', array(
+    'description' => 'Site name entered on the site configuration page.',
+    'type'     => 'varchar',
+    'length'   => 255,
+    'not null' => TRUE,
+    'default'  => '',
+  ));
+  db_add_field('unl_sites', 'access', array(
+    'description' => 'Timestamp for previous time a non-admin role accessed the site.',
+    'type'     => 'int',
+    'length'   => 11,
+    'not null' => TRUE,
+    'default'  => 0,
+  ));
+}
diff --git a/sites/all/modules/unl/unl_site_creation.php b/sites/all/modules/unl/unl_site_creation.php
index a4fc7b82..2e5aa139 100644
--- a/sites/all/modules/unl/unl_site_creation.php
+++ b/sites/all/modules/unl/unl_site_creation.php
@@ -95,32 +95,19 @@ function unl_site_create_submit($form, &$form_state) {
  * Site List appears on admin/sites/unl, admin/sites/unl/sites
  */
 function unl_site_list($form, &$form_state) {
-  // Get all the custom made roles
-  $roles = user_roles(TRUE);
-  unset($roles[DRUPAL_AUTHENTICATED_RID]);
-  unset($roles[variable_get('user_admin_role')]);
-  $roles_in = implode(',', array_keys($roles)); //For use in the DB query
-
-  // Setup alternate db connection so we can query other sites' tables without a prefix being attached
-  global $databases;
-  $database_noprefix = array(
-    'database' => $databases['default']['default']['database'],
-    'username' => $databases['default']['default']['username'],
-    'password' => $databases['default']['default']['password'],
-    'host' => $databases['default']['default']['host'],
-    'port' => $databases['default']['default']['port'],
-    'driver' => $databases['default']['default']['driver'],
-  );
-  Database::addConnectionInfo('UNLNoPrefix', 'default', $database_noprefix);
-  db_set_active('UNLNoPrefix');
-
   $header = array(
     'uri' => array(
       'data' => t('Default Path'),
       'field' => 's.uri',
     ),
-    'site_name' => t('Site Name'),
-    'last_access' => t('Last Access'),
+    'name' => array(
+      'data' => t('Site Name'),
+      'field' => 's.name',
+    ),
+    'access' =>  array(
+      'data' => t('Last Access'),
+      'field' => 's.access',
+    ),
     'installed' => array(
       'data' => t('Status'),
       'field' => 's.installed',
@@ -128,70 +115,19 @@ function unl_site_list($form, &$form_state) {
     'operations' => t('Operations'),
   );
 
-  // The master prefix that was specified during initial drupal install
-  $master_prefix = $databases['default']['default']['prefix'];
-
-  // Get all the db prefixes for every UNL site sorted by uri
-  $prefixes = db_query('SELECT db_prefix FROM ' . $master_prefix . 'unl_sites ORDER BY uri')->fetchCol();
-  if (isset($_GET['sort']) && $_GET['sort'] == 'desc' && (!isset($_GET['order']) || (isset($_GET['order']) && $_GET['order'] !== 'Status'))) {
-    $prefixes = array_reverse($prefixes);
-  }
-
-  // Get a portion of the prefixes based on the page
-  $prefixes = new ArrayIterator($prefixes);
-  $count = 50;
-  $offset = (isset($_GET['page']) ? (int)$_GET['page'] : 0) * $count;
-  $prefixIterator = new LimitIterator($prefixes, $offset, $count);
-
-  // Prepare the CASE expression for the following query
-  $case_expression = "CASE";
-  foreach ($prefixIterator as $key => $prefix) {
-    if (db_table_exists($prefix.'_'.$master_prefix.'variable')) {
-      $case_expression .= " WHEN {u}.db_prefix = '".$prefix."' THEN p".$key.".value";
-    }
-  }
-  $case_expression .= " ELSE '* Scheduled for creation (or Error)' END";
-
-  // Combines the site_id from the unl_sites table with the corresponding site_name from [unl_sites.db_prefix]_variable table
-  $subquery = db_select($master_prefix.'unl_sites', 'u');
-  $subquery->addField('u', 'site_id', 'site_id');
-  $subquery->addExpression($case_expression, 'site_name');
-  foreach ($prefixIterator as $key => $prefix) {
-    if (db_table_exists($prefix.'_'.$master_prefix.'variable')) {
-      $subquery->leftJoin($prefix.'_'.$master_prefix.'variable', 'p'.$key, 'p'.$key.'.name = :site_name', array('site_name'=>'site_name'));
-    }
-  }
-
-  // The query that will be displayed - uses the subquery above in a JOIN
-  $sites = db_select($master_prefix.'unl_sites', 's');
-  $sites->join($subquery, 'i', 'i.site_id=s.site_id');
-  $sites = $sites
-    ->fields('s', array('site_id', 'db_prefix', 'installed', 'site_path', 'uri'))
-    ->fields('i', array('site_name'))
-    ->extend('TableSort')->extend('PagerDefault')->limit($count)
+  $sites = db_select('unl_sites', 's')
+    ->fields('s', array('site_id', 'db_prefix', 'installed', 'site_path', 'uri', 'name', 'access'))
+    ->extend('TableSort')
     ->orderByHeader($header)
     ->execute()
     ->fetchAll();
 
-  // Generate an array of Last Access timestamps for each site based on time last accessed by someone in a non-admin role
-  foreach ($sites as $site) {
-    if (db_table_exists($site->db_prefix.'_'.$master_prefix.'users') &&
-        db_table_exists($site->db_prefix.'_'.$master_prefix.'users_roles') &&
-        !empty($roles_in)) {
-      $query = 'SELECT u.access FROM '.$site->db_prefix.'_'.$master_prefix.'users u, '.$site->db_prefix.'_'.$master_prefix.'users_roles r WHERE u.uid = r.uid AND u.access > 0 AND r.rid IN ('.$roles_in.') ORDER BY u.access DESC';
-      $last_access[$site->site_id] = db_query($query)->fetchColumn();
-    }
-  }
-
-  // Restore default db connection
-  db_set_active();
-
-  // Setup the form
+  $options = array();
   foreach ($sites as $site) {
     $options[$site->site_id] = array(
       'uri' => theme('unl_site_details', array('site_path' => $site->site_path, 'uri' => $site->uri, 'db_prefix' => $site->db_prefix)),
-      'site_name' => @unserialize($site->site_name),
-      'last_access' => (isset($last_access[$site->site_id]) && $last_access[$site->site_id]) ? t('@time ago', array('@time' => format_interval(REQUEST_TIME - $last_access[$site->site_id]))) : t('never'),
+      'site_name' => $site->name,
+      'last_access' => (isset($site->access) && $site->access > 0) ? t('@time ago', array('@time' => format_interval(REQUEST_TIME - $site->access))) : t('never'),
       'installed' => _unl_get_install_status_text($site->installed),
       'operations' => array(
         'data' => array(
@@ -211,7 +147,7 @@ function unl_site_list($form, &$form_state) {
 
   $form['unl_sites'] = array(
     '#type' => 'fieldset',
-    '#title' => t('Existing Sites: ') . count($prefixes),
+    '#title' => t('Existing Sites: ') . count($sites),
   );
   $form['unl_sites']['site_list'] = array(
     '#theme' => 'table',
@@ -219,16 +155,17 @@ function unl_site_list($form, &$form_state) {
     '#rows' => $options,
     '#empty' => t('No sites available.'),
   );
-  $form['unl_sites']['pager'] = array('#markup' => theme('pager', array('tags' => NULL)));
+
   return $form;
 }
 
 /**
- * Implements theme_CUSTOM() which works with unl_theme()
+ * Implements theme_CUSTOM() which works with unl_theme().
+ * This themes the Default Path column on the UNL Sites tables at admin/sites/unl
  */
 function theme_unl_site_details($variables) {
   $output = '<div><a href="' . $variables['uri'] . '">' . $variables['site_path'] . '</a></div>';
-  $output .= '<div style="display:none;">Database Prefix: ' . $variables['db_prefix'] . '_' . $GLOBALS['databases']['default']['default']['prefix'] . '</div>';
+  $output .= '<div class="db_prefix" style="display:none;">Database Prefix: ' . $variables['db_prefix'] . '_' . $GLOBALS['databases']['default']['default']['prefix'] . '</div>';
   return $output;
 }
 
@@ -884,7 +821,7 @@ function theme_unl_table($variables) {
       $form['#rows'][$row_index][$column_index] = drupal_render($form['rows'][$row_index][$column_index]);
     }
   }
-   
+
   return theme('table', $form);
 }
 
-- 
GitLab