Commit 6ffda4d5 authored by merlinofchaos's avatar merlinofchaos
Browse files

Inline menu system overhaul. More efficient, more powerful. Adds tabs to views...

Inline menu system overhaul. More efficient, more powerful. Adds tabs to views for administrators. Needs testing!
parent b7bf1ed6
......@@ -20,7 +20,6 @@ function views_help($section) {
*/
function views_menu($may_cache) {
$items = array();
global $locale;
if ($may_cache) {
views_load_cache();
......@@ -29,111 +28,172 @@ function views_menu($may_cache) {
if (arg(0) == 'admin' && arg(2) == 'modules') {
views_invalidate_cache();
}
views_menu_standard_items($items);
}
else {
views_menu_inline_items($items);
}
return $items;
}
$result = db_query("SELECT * FROM {view_view} WHERE page = 1");
/**
* Add the menu items for all non-inline views to the menu
*/
function views_menu_standard_items(&$items) {
$result = db_query("SELECT * FROM {view_view} WHERE page = 1");
while ($view = db_fetch_object($result)) {
// Skip views with arguments.
if (strrpos($view->url, '$arg') !== FALSE) {
continue;
}
while ($view = db_fetch_object($result)) {
// This happens before the next check; even if it's put off for later
// it is still used.
$used[$view->name] = true;
// unpack the array
$view->access = ($view->access ? explode(', ', $view->access) : array());
// Skip views with inline arguments.
if ($view->url{0} == '$' || strpos($view->url, '/$') !== FALSE) {
continue;
}
// This happens before the next check; even if it's put off for later
// it is still used.
$used[$view->name] = true;
// unpack the array
$view->access = ($view->access ? explode(', ', $view->access) : array());
_views_create_menu_item($items, $view, $view->url);
}
$default_views = _views_get_default_views();
$views_status = variable_get('views_defaults', array());
// Process default views
foreach ($default_views as $name => $view) {
if ($view->page && !$used[$name] &&
($views_status[$name] == 'enabled' || (!$view->disabled && $views_status[$name] != 'disabled'))) {
// skip views with inline args
if ($view->url{0} == '$' || strpos($view->url, '/$') !== FALSE) {
continue;
}
_views_create_menu_item($items, $view, $view->url);
}
$default_views = _views_get_default_views();
$views_status = variable_get('views_defaults', array());
}
}
foreach ($default_views as $name => $view) {
if ($view->page && !$used[$name] &&
($views_status[$name] == 'enabled' || (!$view->disabled && $views_status[$name] != 'disabled'))) {
function views_menu_inline_items(&$items) {
// I don't think we gain anything by caching these, there should never
// be all that many, and caching == a database hit.
$tokens = module_invoke_all('views_url_tokens');
if (strrpos($view->url, '$arg') !== FALSE) {
continue;
}
$args = explode('/', $_GET['q']);
$urls = views_get_all_urls();
foreach ($urls as $view_name => $url) {
if ($url{0} != '$' && strpos($url, '/$') === FALSE) {
if (module_exists('views_ui') && user_access('administer views')) {
$view_args = $args;
_views_create_menu_item($items, $view, $view->url);
foreach (explode('/', $url) as $num => $element) {
if ($element != $args[$num]) {
continue 2;
}
unset($view_args[$num]);
}
views_menu_admin_items($items, $view_name, $view_args, $args);
}
}
}
else {
$data = cache_get("views_with_inline_args:$locale", 'cache_views');
if ($data == 0) {
// There's no cache for our language, regenerate it.
views_reset_inline_args_cache($locale);
$data = cache_get("views_with_inline_args:$locale", 'cache_views');
}
$views = unserialize($data->data);
if (is_array($views)) {
foreach ($views as $view) {
// Do substitution on args.
$view_args = array();
$menu_path = array();
foreach (explode('/', $view->url) as $num => $element) {
if ($element == '$arg') {
$menu_path[] = arg($num);
$view_args[] = arg($num);
$view->args[] = arg($num);
else {
// Do substitution on args.
$use_view = $use_menu = FALSE;
$view_args = $menu_path = array();
foreach (explode('/', $url) as $num => $element) {
if ($element{0} == '$') {
// If we pass the token check, this view is definitely being used.
list($token, $argument) = explode('-', $element);
if ($tokens[$token] && function_exists($tokens[$token])) {
if (!($use_view = $use_menu = $tokens[$token]($element, $argument, arg($num)))) {
break;
}
}
else {
$menu_path[] = $element;
$menu_path[] = $view_args[] = arg($num);
}
else {
$menu_path[] = $element;
if ($element != arg($num)) {
$use_menu = FALSE;
}
}
// we are only using views that match our URL, up to the
// point where we hit an inline arg.
if (!$use_view && $element != arg($num)) {
break;
}
unset($menu_args[$num]);
}
if ($use_view) {
$path = implode('/', $menu_path);
$view = views_get_view($view_name);
$view->args = $view_args;
_views_create_menu_item($items, $view, $path, MENU_CALLBACK, $view_args);
}
if (module_exists('views_ui') && user_access('administer views') && $use_menu) {
views_menu_admin_items($items, $view_name, $menu_args, $args);
}
}
}
return $items;
}
/**
* Reset the views with inline arguments cache for a locale.
* Add the adminstrative items to a view.
*/
function views_reset_inline_args_cache($locale = 'en') {
$result = db_query("SELECT * FROM {view_view} WHERE page = 1");
$views_with_inline_args = array();
while ($view = db_fetch_object($result)) {
// Skip over any non-argument views
if (strrpos($view->url, '$arg') === FALSE) {
continue;
}
// unpack the array
$view->access = ($view->access ? explode(', ', $view->access) : array());
function views_menu_admin_items(&$items, $view_name, $view_args, $args) {
// See what the last arg is.
$last_arg = array_pop($args);
if (in_array($last_arg, array('edit', 'view', 'clone', 'export'))) {
array_pop($view_args);
}
else {
$args[] = $last_arg;
}
// This happens before the next check; even if it's put off for later
// it is still used.
$used[$view->name] = true;
$path = implode('/', $args);
$view = views_get_view($view_name);
views_ui_add_menu_items($items, $view, $path, $path != $_GET['q'] && !empty($view_args), $view_args);
}
/**
* Load all of the URLs we use; this is cached in a special manner
* in an attempt to make the menu system both flexible and yet not
* overly intensive.
*/
function views_get_all_urls() {
$cache = cache_get("views_urls", 'cache_views');
if ($cache == 0) {
$views = array();
$used = array();
$result = db_query("SELECT name, url FROM {view_view} WHERE page = 1");
$arg_result = db_query("SELECT * FROM {view_argument} WHERE vid = %d", $view->vid);
while ($arg = db_fetch_array($arg_result)) {
$view->argument[] = $arg;
while ($view = db_fetch_object($result)) {
$used[$view->name] = TRUE;
$views[$view->name] = $view->url;
}
$views_with_inline_args[$view->name] = $view;
}
views_load_cache();
$default_views = _views_get_default_views();
$views_status = variable_get('views_defaults', array());
views_load_cache();
$default_views = _views_get_default_views();
$views_status = variable_get('views_defaults', array());
foreach ($default_views as $name => $view) {
if ($view->page && !$used[$name] && ($views_status[$name] == 'enabled' || (!$view->disabled && $views_status[$name] != 'disabled'))) {
if (strrpos($view->url, '$arg') !== FALSE) {
$views_with_inline_args[$view->name] = $view;
foreach ($default_views as $name => $view) {
if ($view->page && !$used[$name] && ($views_status[$name] == 'enabled' || (!$view->disabled && $views_status[$name] != 'disabled'))) {
if ($view->url{0} == '$' || strpos($view->url, '/$') !== FALSE) {
$views[$view->name] = $view->url;
}
}
}
cache_set("views_urls", 'cache_views', serialize($views));
}
else {
$views = unserialize($cache->data);
}
cache_set("views_with_inline_args:$locale", 'cache_views', serialize($views_with_inline_args));
return $views;
}
/**
......@@ -141,16 +201,22 @@ function views_reset_inline_args_cache($locale = 'en') {
*/
function _views_create_menu_item(&$items, $view, $path, $local_task_type = MENU_NORMAL_ITEM, $args = array()) {
static $roles = NULL;
if ($roles == NULL) {
if ($roles === NULL) {
global $user;
$roles = array_keys($user->roles);
if ($user->uid) {
$roles[] = DRUPAL_AUTHENTICATED_RID;
}
else {
$roles[] = DRUPAL_ANONYMOUS_RID;
}
}
$title = views_get_title($view, 'menu');
$type = _views_menu_type($view);
if ($type == MENU_LOCAL_TASK || $type == MENU_DEFAULT_LOCAL_TASK) {
$weight = $view->menu_tab_weight;
}
$access = !$view->access || array_intersect($view->access, $roles);
$access = user_access('access all views') || !$view->access || array_intersect($view->access, $roles);
$items[] = _views_menu_item($path, $title, $view, $args, $access, $type, $weight);
if ($type == MENU_DEFAULT_LOCAL_TASK) {
......@@ -197,6 +263,13 @@ function _views_menu_type($view) {
return $type;
}
/**
* Implementation of hook_perm
*/
function views_perm() {
return array('access all views');
}
/**
* Implementation of hook_block()
*/
......@@ -1385,25 +1458,6 @@ function views_get_summary_link($argtype, $item, $base) {
return $arginfo[$argtype]['handler']('link', $item, $argtype, $base);
}
/**
* In a summary view, each entry links to a more specific entry
* in that view. Construct the base of that link.
*/
/*
function views_get_summary_link_base($argtype, $url, $level, $args) {
$arginfo = _views_get_arguments();
if (!function_exists($arginfo[$argtype]['handler'])) {
return NULL;
}
$arg = $url;
for ($i = 0; $i < $level; $i++) {
$arg .= "/$args[$i]";
}
return $arg;
}
*/
/**
* Display a summary version of a view.
*/
......@@ -1680,6 +1734,57 @@ function views_views_style_plugins() {
);
}
/**
* Default Views URL tokens
*/
function views_views_url_tokens() {
return array(
'$arg' => 'views_url_arg',
'$node' => 'views_url_node',
'$user' => 'views_url_user',
);
}
/**
* Handle '$arg' in a URL. Any non-empty value is true.
*/
function views_url_arg($token, $argument, $arg) {
return $arg !== '' && $arg !== NULL;
}
/**
* Handle '$node' in a URL. Any valid node wil ldo.
*/
function views_url_node($token, $argument, $arg) {
if (!is_numeric($arg)) {
return FALSE;
}
$node = node_load($arg);
if (!$node) {
return FALSE;
}
if ($argument && $node->type != $argument) {
return FALSE;
}
// if a node loads, return true.
return TRUE;
}
/**
* Handle '$user' in a URL. Any valid user wil ldo.
*/
function views_url_user($token, $argument, $arg) {
if (!is_numeric($arg)) {
return FALSE;
}
// if a user loads, return true.
return (bool) user_load($arg);
}
/**
* A list of options to be used in LIKE queries
*/
......
......@@ -109,27 +109,11 @@ function views_ui_menu($may_cache) {
'callback' => 'views_ui_admin_add_page',
'access' => user_access('administer views'),
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'admin/build/views/clone',
'title' => t('Clone'),
'callback' => 'views_ui_admin_clone_page',
'access' => user_access('administer views'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/build/views/edit',
'title' => t('Edit view'),
'callback' => 'views_ui_admin_edit_page',
'access' => user_access('administer views'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/build/views/import',
'title' => t('Import'),
'callback' => 'views_ui_admin_import_page',
'access' => user_access('administer views'),
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'admin/build/views/export',
'title' => t('Export view'),
'callback' => 'drupal_get_form',
'callback arguments' => array('views_ui_admin_export_page'),
'access' => user_access('administer views'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/build/views/delete',
'title' => t('Edit view'),
'callback' => 'drupal_get_form',
......@@ -144,11 +128,63 @@ function views_ui_menu($may_cache) {
'callback' => 'views_ui_admin_disable_page',
'access' => user_access('administer views'),
'type' => MENU_CALLBACK);
}
else {
if (user_access('administer views') &&
arg(0) == 'admin' &&
arg(1) == 'build' &&
arg(2) == 'views') {
$view = views_load_view(arg(3));
if ($view) {
views_ui_add_menu_items($items, $view, 'admin/build/views/' . arg(3), TRUE);
}
}
}
return $items;
}
function views_ui_add_menu_items(&$items, $view, $url, $base = TRUE, $args = array()) {
if (user_access('administer views')) {
if ($base) {
// we also have to add the administrative 'view' of the view in some
// cases
$items[] = array('path' => $url,
'title' => t('View'),
'callback' => 'views_page',
'callback arguments' => array_merge(array($view->name), $args),
'access' => user_access('administer views'),
'type' => MENU_CALLBACK);
}
$items[] = array('path' => "$url/view",
'title' => t('View'),
'callback' => 'views_page',
'callback arguments' => array_merge(array($view->name), $args),
'access' => user_access('administer views'),
'weight' => -10,
'type' => MENU_DEFAULT_LOCAL_TASK);
$items[] = array('path' => "$url/edit",
'title' => t('Edit'),
'callback' => 'views_ui_admin_edit_page',
'callback arguments' => array($view->name),
'access' => user_access('administer views'),
'weight' => -5,
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => "$url/export",
'title' => t('Export'),
'callback' => 'drupal_get_form',
'callback arguments' => array('views_ui_admin_export_page', $view->name),
'access' => user_access('administer views'),
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => "$url/clone",
'title' => t('Clone'),
'callback' => 'views_ui_admin_clone_page',
'callback arguments' => array($view->name),
'access' => user_access('administer views'),
'type' => MENU_LOCAL_TASK);
}
}
// ---------------------------------------------------------------------------
// Administrative Pages
......@@ -183,10 +219,10 @@ function views_ui_admin_page() {
implode(', ', $provides),
$url,
theme('links', array(
array('title' => t('Edit'), 'href' => "admin/build/views/edit/$view->vid"),
array('title' => t('Export'), 'href' => "admin/build/views/export/$view->vid"),
array('title' => t('Edit'), 'href' => "admin/build/views/$view->vid/edit"),
array('title' => t('Export'), 'href' => "admin/build/views/$view->vid/export"),
array('title' => t('Delete'), 'href' => "admin/build/views/delete/$view->vid"),
array('title' => t('Clone'), 'href' => "admin/build/views/clone/$view->vid"),
array('title' => t('Clone'), 'href' => "admin/build/views/$view->vid/clone"),
))
);
}
......@@ -1720,7 +1756,9 @@ function views_edit_view_submit($form_id, $form) {
}
if ($form['op'] == t('Save')) {
return 'admin/build/views';
$args = explode('/', $_GET['q']);
array_pop($args);
return implode('/', $args);
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment