Support module for design, markup, JavaScript, and CSS testing.
<?php
/**
* @file
* Support module for design, markup, JavaScript, and CSS testing.
*/
/**
* Implements hook_menu().
*
* This implementation turns every subdirectory of this module into a category
* that is exposed as a menu link. Each subdirectory contains include files that
* consist of a callback function that maps to the semantics of the category.
* The following categories are supported:
* - form: Used for Form API element tests.
* - page: Used for theme function tests.
*
* For example, given an include file:
* @code
* ./page/list-operations.inc
* @endcode
* A menu router item with the path 'design_test/page/list-operations' will be
* auto-generated. Upon access, the function design_test_page_list_operations()
* will be called.
*
* The 'form' category behaves identically; e.g., for an include file
* './form/details.inc' a menu item for the path 'design_test/form/details' is
* created and the form constructor function design_test_form_details() will be
* called.
*
* Each resulting test page is enhanced with local actions that allow to quickly
* switch between enabled themes for verifying the expected output.
*/
function design_test_menu() {
// Turn each include file in the module directory into a local task.
$categories = array();
$module_path = drupal_get_path('module', 'design_test');
$tests = file_scan_directory($module_path, '/\\.inc$/', array(
'key' => 'name',
'recurse' => TRUE,
));
foreach ($tests as $name => $file) {
// Build include file path and category.
$filepath = strtr($file->uri, array(
$module_path . '/' => '',
));
list($category) = explode('/', $filepath, 2);
$categories[$category] = $category;
// Build router item path.
$path = preg_replace('@[^a-zA-Z0-9-]@', '-', $name);
// Build page callback function name.
$callback = "design_test_{$category}_" . strtr($path, '-', '_');
// Build router item callback.
if ($category == 'form') {
$page_callback = 'drupal_get_form';
}
else {
$page_callback = $callback;
}
$items["design_test/{$category}/{$path}"] = array(
'title' => drupal_ucfirst($name),
'theme callback' => 'design_test_menu_theme_callback',
'page callback' => $page_callback,
'page arguments' => array(
$callback,
),
'file' => $filepath,
'access callback' => TRUE,
'type' => MENU_LOCAL_TASK | MENU_VISIBLE_IN_TREE,
);
}
$items['design_test'] = array(
'title' => 'Design test',
'page callback' => 'design_test_category_page',
'page arguments' => array(
1,
),
'access callback' => TRUE,
);
$items['design_test/list'] = array(
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
// Lastly, add the category containers.
foreach ($categories as $category) {
$items["design_test/{$category}"] = array(
'title' => drupal_ucfirst($category),
'page callback' => 'design_test_category_page',
'page arguments' => array(
1,
),
'access callback' => TRUE,
'type' => MENU_LOCAL_TASK | MENU_VISIBLE_IN_TREE,
);
}
return $items;
}
/**
* Implements hook_menu_local_tasks_alter().
*/
function design_test_menu_local_tasks_alter(&$data, $router_item, $root_path) {
if ($router_item['number_parts'] > 2 && strpos($root_path, 'design_test/') === 0) {
$actions =& $data['actions']['output'];
// Determine the currently selected theme, if any.
$selected_theme = drupal_container()
->get('request')->query
->get('theme');
$default_theme = variable_get('theme_default', 'stark');
// Expand all enabled themes into action links.
$themes = list_themes();
foreach ($themes as $name => $theme) {
$action = array(
'#theme' => 'menu_local_action',
'#link' => array(
'title' => $theme->info['name'],
'href' => $router_item['href'],
'localized_options' => array(
'html' => FALSE,
),
),
'#active' => $selected_theme == $name,
);
// Only add the theme-switcher query parameter for all non-default themes.
if ($name != $default_theme) {
$action['#link']['localized_options']['query']['theme'] = $name;
}
$actions[] = $action;
}
if ($themes > 1) {
$data['actions']['count']++;
}
}
}
/**
* Menu theme callback for design_test pages.
*
* Returns whichever theme name that has been passed via the 'theme' request
* query parameter. The returned value is validated by the menu system already.
*/
function design_test_menu_theme_callback() {
return drupal_container()
->get('request')->query
->get('theme');
}
/**
* Menu page callback for a category listing page.
*
* This is a specialized version of system_admin_menu_block_page(), which
* retrieves all direct child menu links of the current page, regardless of
* their type, skips default local tasks, and outputs them as a simple menu
* tree as the main page content.
*
* @param string $category
* The design test category being currently accessed. Maps to the subdirectory
* names of this module.
*
* @return array
* A render array containing a menu link tree.
*/
function design_test_category_page($category) {
$link = menu_link_get_preferred();
$tree = menu_build_tree($link['menu_name'], array(
'expanded' => array(
$link['mlid'],
),
'min_depth' => $link['depth'] + 1,
'max_depth' => $link['depth'] + 2,
));
// Local tasks are hidden = -1, so normally not rendered in menu trees.
foreach ($tree as &$data) {
// Exclude default local tasks.
if (!($data['link']['type'] & MENU_LINKS_TO_PARENT)) {
$data['link']['hidden'] = 0;
}
}
$build = menu_tree_output($tree);
return $build;
}
Name | Description |
---|---|
design_test_category_page | Menu page callback for a category listing page. |
design_test_menu | Implements hook_menu(). |
design_test_menu_local_tasks_alter | Implements hook_menu_local_tasks_alter(). |
design_test_menu_theme_callback | Menu theme callback for design_test pages. |