global change view world
[project/views.git] / views.module
index 68962d2..0993c2f 100644 (file)
@@ -23,7 +23,7 @@ function views_theme() {
   $path = drupal_get_path('module', 'views');
   require_once "./$path/theme/theme.inc";
 
-    // Some quasi clever array merging here.
+  // Some quasi clever array merging here.
   $base = array(
     'file' => 'theme.inc',
     'path' => "$path/theme",
@@ -38,7 +38,7 @@ function views_theme() {
   $arguments = array(
     'display' => array('view' => NULL),
     'style' => array('view' => NULL, 'options' => NULL, 'rows' => NULL, 'title' => NULL),
-    'row' => array('view' => NULL, 'options' => NULL, 'row' => NULL),
+    'row' => array('view' => NULL, 'options' => NULL, 'row' => NULL, 'field_alias' => NULL),
   );
 
   // Default view themes
@@ -59,6 +59,12 @@ function views_theme() {
           'path' => $def['theme path'],
           'arguments' => $arguments[$type],
         );
+
+        $include = './' . $def['theme path'] . '/' . $def['theme file'];
+        if (file_exists($include)) {
+          require_once $include;
+        }
+
         if (!function_exists('theme_' . $def['theme'])) {
           $hooks[$def['theme']]['template'] = views_css_safe($def['theme']);
         }
@@ -76,6 +82,7 @@ function views_theme() {
             'path' => $def['theme path'],
             'arguments' => $arguments[$theme_type],
           );
+
           if (!function_exists('theme_' . $theme)) {
             $hooks[$theme]['template'] = views_css_safe($theme);
           }
@@ -93,7 +100,7 @@ function views_theme() {
   $hooks['views_more'] = $base + array(
     'template' => 'views-more',
     'pattern' => 'views_more__',
-    'arguments' => array('more_url' => NULL),
+    'arguments' => array('more_url' => NULL, 'link_text' => 'more'),
   );
   return $hooks;
 }
@@ -112,7 +119,7 @@ function views_preprocess_node(&$vars) {
     $vars['view'] = &$vars['node']->view;
     $vars['template_files'][] = 'node-view-' . $vars['node']->view->name;
     if(!empty($vars['node']->view->current_display)) {
-      $vars['template_files'][] = 'node-view-' . $vars['node']->view->name . '-'. $vars['node']->view->current_display;
+      $vars['template_files'][] = 'node-view-' . $vars['node']->view->name . '-' . $vars['node']->view->current_display;
     }
   }
 }
@@ -127,7 +134,7 @@ function views_preprocess_comment(&$vars) {
     $vars['view'] = &$vars['node']->view;
     $vars['template_files'][] = 'comment-view-' . $vars['node']->view->name;
     if(!empty($vars['node']->view->current_display)) {
-      $vars['template_files'][] = 'comment-view-' . $vars['node']->view->name . '-'. $vars['node']->view->current_display;
+      $vars['template_files'][] = 'comment-view-' . $vars['node']->view->name . '-' . $vars['node']->view->current_display;
     }
   }
 }
@@ -135,8 +142,8 @@ function views_preprocess_comment(&$vars) {
 /*
  * Implementation of hook_perm()
  */
-function views_ui_perm() {
-  return array('access all views');
+function views_perm() {
+  return array('access all views', 'administer views');
 }
 
 /**
@@ -150,8 +157,7 @@ function views_menu() {
   $items['views/ajax'] = array(
     'title' => 'Views',
     'page callback' => 'views_ajax',
-    'access callback' => 'user_access',
-    'access arguments' => array('access content'),
+    'access callback' => TRUE,
     'description' => 'Ajax callback for view loading.',
     'file' => 'includes/ajax.inc',
     'type' => MENU_CALLBACK,
@@ -295,6 +301,11 @@ function views_block($op = 'list', $delta = 0, $edit = array()) {
       $items = array();
       $views = views_get_all_views();
       foreach ($views as $view) {
+        // disabled views get nothing.
+        if (!empty($view->disabled)) {
+          continue;
+        }
+
         $view->init_display();
         foreach ($view->display as $display_id => $display) {
 
@@ -339,7 +350,7 @@ function views_block($op = 'list', $delta = 0, $edit = array()) {
 
       return $items;
     case 'view':
-      $start = microtime();
+      $start = views_microtime();
       // if this is 32, this should be an md5 hash.
       if (strlen($delta) == 32) {
         $hashes = variable_get('views_block_hashes', array());
@@ -371,7 +382,7 @@ function views_block($op = 'list', $delta = 0, $edit = array()) {
       if ($view = views_get_view($name)) {
         if ($view->access($display_id)) {
           $output = $view->execute_display($display_id);
-          vpr("Block $view->name execute time: " . (microtime() - $start) * 1000 . "ms");
+          vpr("Block $view->name execute time: " . (views_microtime() - $start) * 1000 . "ms");
           $view->destroy();
           return $output;
         }
@@ -385,7 +396,7 @@ function views_block($op = 'list', $delta = 0, $edit = array()) {
  * Implementation of hook_flush_caches().
  */
 function views_flush_caches() {
-  return array('cache_views');
+  return array('cache_views', 'cache_views_data');
 }
 
 /**
@@ -507,7 +518,6 @@ function views_include($file) {
  * Load views files on behalf of modules.
  */
 function views_module_include($file) {
-  $views_path = drupal_get_path('module', 'views') . '/modules';
   foreach (views_get_module_apis() as $module => $info) {
     if (file_exists("./$info[path]/$module.$file")) {
       require_once "./$info[path]/$module.$file";
@@ -541,7 +551,11 @@ function views_get_module_apis() {
  * Include views .css files.
  */
 function views_add_css($file) {
-  drupal_add_css(drupal_get_path('module', 'views') . "/css/$file.css");
+  // We set preprocess to FALSE because we are adding the files conditionally,
+  // and we don't want to generate duplicate cache files.
+  // TODO: at some point investigate adding some files unconditionally and
+  // allowing preprocess.
+  drupal_add_css(drupal_get_path('module', 'views') . "/css/$file.css", 'module', 'all', FALSE);
 }
 
 /**
@@ -771,11 +785,16 @@ function views_get_applicable_views($type) {
 
 /**
  * Return an array of all views as fully loaded $view objects.
+ *
+ * @param $reset
+ *   If TRUE, reset the static cache forcing views to be reloaded.
  */
-function views_get_all_views() {
+function views_get_all_views($reset = FALSE) {
   static $views = array();
 
-  if (empty($views)) {
+  if (empty($views) || $reset) {
+    $views = array();
+
     // First, get all applicable views.
     views_include('view');
     $views = view::load_views();
@@ -852,7 +871,12 @@ function views_debug($message) {
     else {
       $output = var_export($message, TRUE);
     }
-    drupal_set_content(variable_get('views_devel_region', 'footer'), '<pre>' . $output . '</pre>');
+    if (variable_get('views_devel_region', 'footer') != 'watchdog') {
+      drupal_set_content(variable_get('views_devel_region', 'footer'), '<pre>' . $output . '</pre>');
+    }
+    else {
+      watchdog('views_logging', '<pre>' . $output . '</pre>');
+    }
   }
 }
 
@@ -899,6 +923,15 @@ function vpr_trace() {
  * Be sure that $view and $display are references.
  */
 function views_exposed_form(&$form_state) {
+  // Don't show the form when batch operations are in progress.
+  $batch =& batch_get();
+  if (!empty($batch)) {
+    return array(
+      // Set the theme callback to be nothing to avoid errors in template_preprocess_views_exposed_form().
+      '#theme' => '',
+    );
+  }
+
   // Make sure that we validate because this form might be submitted
   // multiple times per page.
   $form_state['must_validate'] = TRUE;
@@ -909,6 +942,10 @@ function views_exposed_form(&$form_state) {
 
   // Let form plugins know this is for exposed widgets.
   $form_state['exposed'] = TRUE;
+  // Check if the form was already created
+  if ($cache = views_exposed_form_cache($view->name, $view->current_display)) {
+    return $cache;
+  }
 
   $form['#info'] = array();
 
@@ -933,6 +970,7 @@ function views_exposed_form(&$form_state) {
     '#name' => '', // prevent from showing up in $_GET.
     '#type' => 'submit',
     '#value' => t('Apply'),
+    '#id' => form_clean_id('edit-submit-' . $view->name),
   );
 
   $form['#action'] = url($view->get_url());
@@ -945,6 +983,10 @@ function views_exposed_form(&$form_state) {
     drupal_add_js('misc/jquery.form.js');
   }
   views_add_js('dependent');
+
+  // Save the form
+  views_exposed_form_cache($view->name, $view->current_display, $form);
+
   return $form;
 }
 
@@ -980,6 +1022,31 @@ function views_exposed_form_submit(&$form, &$form_state) {
   }
 }
 
+/**
+ * Save the Views exposed form for later use.
+ *
+ * @param $views_name
+ *   String. The views name.
+ * @param $display_name
+ *   String. The current view display name.
+ * @param $form_output
+ *   Array (optional). The form structure. Only needed when inserting the value.
+ * @return
+ *   Array. The form structure, if any. Otherwise, return FALSE.
+ */
+function views_exposed_form_cache($views_name, $display_name, $form_output = NULL) {
+  static $views_exposed;
+
+  // Save the form output
+  if (!empty($form_output)) {
+    $views_exposed[$views_name][$display_name] = $form_output;
+    return;
+  }
+
+  // Return the form output, if any
+  return empty($views_exposed[$views_name][$display_name]) ? FALSE : $views_exposed[$views_name][$display_name];
+}
+
 // ------------------------------------------------------------------
 // Misc helpers
 
@@ -1014,6 +1081,7 @@ function drupal_build_form($form_id, &$form_state) {
 function views_views_query_substitutions($view) {
   global $language;
   return array(
+    '***CURRENT_VERSION***' => VERSION,
     '***CURRENT_TIME***' => time(),
     '***CURRENT_LANGUAGE***' => $language->language,
     '***DEFAULT_LANGUAGE***' => language_default('language'),
@@ -1049,7 +1117,7 @@ function views_embed_view($name, $display_id = 'default') {
   }
 
   $view = views_get_view($name);
-  if (!$view) {
+  if (!$view || !$view->access($display_id)) {
     return;
   }
 
@@ -1059,7 +1127,7 @@ function views_embed_view($name, $display_id = 'default') {
 /**
  * Export a field.
  */
-function views_var_export($var, $prefix = '') {
+function views_var_export($var, $prefix = '', $init = TRUE) {
   if (is_array($var)) {
     if (empty($var)) {
       $output = 'array()';
@@ -1067,7 +1135,7 @@ function views_var_export($var, $prefix = '') {
     else {
       $output = "array(\n";
       foreach ($var as $key => $value) {
-        $output .= "  '$key' => " . views_var_export($value, '  ') . ",\n";
+        $output .= "  '$key' => " . views_var_export($value, '  ', FALSE) . ",\n";
       }
       $output .= ')';
     }
@@ -1075,6 +1143,13 @@ function views_var_export($var, $prefix = '') {
   else if (is_bool($var)) {
     $output = $var ? 'TRUE' : 'FALSE';
   }
+  else if (is_string($var) && strpos($var, "\n") !== FALSE) {
+    // Replace line breaks in strings with a token for replacement
+    // at the very end. This protects multi-line strings from
+    // unintentional indentation.
+    $var = str_replace("\n", "***BREAK***", $var);
+    $output = var_export($var, TRUE);
+  }
   else {
     $output = var_export($var, TRUE);
   }
@@ -1083,6 +1158,10 @@ function views_var_export($var, $prefix = '') {
     $output = str_replace("\n", "\n$prefix", $output);
   }
 
+  if ($init) {
+    $output = str_replace("***BREAK***", "\n", $output);
+  }
+
   return $output;
 }
 
@@ -1119,6 +1198,9 @@ function views_views_exportables($op = 'list', $views = NULL, $name = 'foo') {
     $code .= " */\n";
     $code .= "function " . $name . "_views_default_views() {\n";
     foreach ($views as $view => $truth) {
+      $code .= "  /*\n";
+      $code .= "   * View ". var_export($all_views[$view]->name, TRUE) ."\n";
+      $code .= "   */\n";
       $code .= $all_views[$view]->export('  ');
       $code .= '  $views[$view->name] = $view;' . "\n\n";
     }
@@ -1128,3 +1210,11 @@ function views_views_exportables($op = 'list', $views = NULL, $name = 'foo') {
     return $code;
   }
 }
+
+/**
+ * Microtime helper function to return a float time value (php4 & php5 safe).
+ */
+function views_microtime() {
+  list($usec, $sec) = explode(' ', microtime());
+  return (float)$sec + (float)$usec;
+}