non security modules update

This commit is contained in:
Bachir Soussi Chiadmi
2015-04-20 16:32:07 +02:00
parent 6a8d30db08
commit 37fbabab56
466 changed files with 32690 additions and 9652 deletions

View File

@@ -22,9 +22,8 @@ Also a dpr() function is provided, which pretty prints arrays and strings.
Useful during development. Many other nice functions like dpm(), dvm().
AJAX developers in particular ought to install FirePHP Core from
http://www.firephp.org/ and put it in the devel directory.
This happens automatically when you enable via drush. You may also
use a drush command to download the library. If downloading by hand,
http://www.firephp.org/ and put it in the devel directory. You may
use the devel-download drush command to download the library. If downloading by hand,
your path to fb.php should look like devel/FirePHPCore/lib/FirePHPCore/fb.php.
You can use svn checkout http://firephp.googlecode.com/svn/trunk/trunk/Libraries/FirePHPCore.
Then you can log php variables to the Firebug console. Is quite useful.

View File

@@ -60,7 +60,7 @@ function devel_admin_settings() {
$form['xhprof']['settings']['devel_xhprof_directory'] = array(
'#type' => 'textfield',
'#title' => 'xhprof directory',
'#description' => t('Location of the xhprof source code on your system, usually somewhere in /usr/local/share or /usr/share, include the leading forward slash.'),
'#description' => t('Location of the xhprof source code on your system, where the directory "xhprof_lib" can be found, usually somewhere in /usr/local/share or /usr/share, include the leading forward slash.'),
'#default_value' => variable_get('devel_xhprof_directory', ''),
'#states' => array(
'invisible' => array(
@@ -90,9 +90,9 @@ function devel_admin_settings() {
'#description' => t('Display page execution time in the query log box.'),
);
$form['dev_mem'] = array('#type' => 'checkbox',
$form['devel_memory'] = array('#type' => 'checkbox',
'#title' => t('Display memory usage'),
'#default_value' => variable_get('dev_mem', 0),
'#default_value' => variable_get('devel_memory', 0),
'#description' => t('Display how much memory is used to generate the current page. This will show memory usage when devel_init() is called and when devel_exit() is called.'),
);
$form['devel_redirect_page'] = array('#type' => 'checkbox',

View File

@@ -12,21 +12,29 @@ function devel_drush_command() {
$items['devel-download'] = array(
'description' => dt('Downloads the FirePHP library from http://firephp.org/.'),
'arguments' => array(
'path' => dt('Optional. A path to the download folder. If omitted Drush will use the default location (sites/all/libraries/firephp).'),
'path' => dt('Path to the download folder. This path is relative to the Drupal root. If omitted Drush will use the default location (sites/all/libraries/FirePHPCore).'),
),
);
$items['devel-reinstall'] = array(
'description' => dt('Disable, Uninstall, and Install a list of projects.'),
'drush dependencies' => array('pm'),
'arguments' => array(
'projects' => dt('A space-separated list of project names.'),
),
'allow-additional-options' => array('pm-disable', 'pm-uninstall', 'pm-enable'),
'required-arguments' => 1,
'aliases' => array('dre'),
);
$items['fn-hook'] = array(
'description' => 'List implementations of a given hook and explore source of specified one.',
'description' => 'List implementations of a given hook and explore the source of the selected one.',
'arguments' => array(
'hook' => 'The name of the hook to explore.'
'hook' => 'The name of the hook to explore (e.g. "menu" for hook_menu()).'
),
'examples' => array(
'fn-hook cron' => 'List implementations of hook_cron().',
),
'allow-additional-options' => array('fn-view'),
'required-arguments' => 1,
'aliases' => array('fnh', 'hook'),
);
$items['fn-view'] = array(
@@ -44,11 +52,13 @@ function devel_drush_command() {
'fn-view NodeController::load' => 'View the source code for method load in the class NodeController'
),
'aliases' => array('fnv'),
'required-arguments' => 1,
);
$items['devel-token'] = array(
'description' => dt('List available tokens'),
'aliases' => array('token'),
'core' => array(7), // Remove once 3.0 is released.
//@todo support --format option for json, csv, etc.
);
return $items;
}
@@ -72,25 +82,28 @@ function drush_devel_reinstall() {
/**
* A command callback.
*/
function drush_devel_download() {
$args = func_get_args();
if (isset($args[0])) {
$path = $args[0];
function drush_devel_download($path = NULL) {
// If no path is provided by the user, set our default path.
if (is_null($path)) {
// We use devel folder for legacy reason.
$path = drupal_get_path('module', 'devel') . '/FirePHPCore';
}
else {
$path = drush_get_context('DRUSH_DRUPAL_ROOT');
// If FirePHP is not installed and libraries module is enabled,
// try to find FirePHP by its own means.
if (!is_dir($path)) {
if (module_exists('libraries')) {
$path .= '/' . libraries_get_path('FirePHPCore') . '/FirePHPCore';
}
else {
$path .= '/' . drupal_get_path('module', 'devel') . '/FirePHPCore';
// Libraries 1.x will return a path even if it doesn't exist
// while 2.x will return FALSE.
$path = libraries_get_path('FirePHPCore');
if (!$path) {
$path = 'sites/all/libraries/FirePHPCore';
}
}
}
if (is_dir($path)) {
drush_log('FirePHP already present. No download required.', 'ok');
drush_log(dt('FirePHP already present at @path. No download required.', array('@path' => $path)), 'ok');
}
elseif (drush_shell_exec('svn export http://firephp.googlecode.com/svn/branches/Library-FirePHPCore-0.3 ' . $path)) {
elseif (drush_shell_exec('svn export http://firephp.googlecode.com/svn/branches/Library-FirePHPCore-0.3 %s', $path)) {
drush_log(dt('FirePHP has been exported via svn to @path.', array('@path' => $path)), 'success');
}
else {
@@ -98,21 +111,6 @@ function drush_devel_download() {
}
}
/**
* Implements drush_MODULE_post_COMMAND().
*/
function drush_devel_post_pm_enable() {
$extensions = func_get_args();
// Deal with comma delimited extension list.
if (strpos($extensions[0], ',') !== FALSE) {
$extensions = explode(',', $extensions[0]);
}
if (in_array('devel', $extensions) && !drush_get_option('skip')) {
drush_devel_download();
}
}
/**
* Command handler. Show hook implementations.
*/

View File

@@ -7,9 +7,9 @@ tags[] = developer
files[] = devel.test
files[] = devel.mail.inc
; Information added by drupal.org packaging script on 2012-06-05
version = "7.x-1.3"
; Information added by Drupal.org packaging script on 2014-05-01
version = "7.x-1.5"
core = "7.x"
project = "devel"
datestamp = "1338940281"
datestamp = "1398963366"

View File

@@ -31,18 +31,27 @@ function devel_enable() {
* Implements hook_uninstall().
*/
function devel_uninstall() {
variable_del('devel_form_weights');
variable_del('devel_execution');
variable_del('dev_timer');
variable_del('devel_query_display');
variable_del('devel_redirect_page');
variable_del('devel_api_url');
variable_del('dev_mem');
variable_del('devel_memory');
variable_del('devel_error_handlers');
variable_del('devel_raw_names');
variable_del('devel_switch_user_list_size');
variable_del('devel_switch_user_include_anon');
variable_del('devel_switch_user_show_form');
variable_del('devel_krumo_skin');
variable_del('devel_page_alter');
variable_del('devel_query_sort');
variable_del('devel_rebuild_theme_registry');
variable_del('devel_use_uncompressed_jquery');
variable_del('devel_xhprof_directory');
variable_del('devel_xhprof_enabled');
variable_del('devel_xhprof_url');
variable_del('devel_debug_mail_file_format');
variable_del('devel_debug_mail_directory');
// Delete the development menu.
if (module_exists('menu')) {
@@ -106,3 +115,21 @@ function devel_update_7004() {
variable_set('devel_error_handlers', drupal_map_assoc($error_handlers));
}
}
/**
* Delete variable 'devel_form_weights' from database as it was removed from code.
*/
function devel_update_7005() {
variable_del('devel_form_weights');
}
/**
* Change variable 'dev_mem' to 'devel_memory'.
*/
function devel_update_7006() {
if (variable_get('dev_mem', NULL) !== NULL) {
variable_set('devel_memory', variable_get('dev_mem'));
}
variable_del('dev_mem');
}

View File

@@ -2,11 +2,11 @@
// Explain link in query log
Drupal.behaviors.devel_explain = {
attach: function() {
attach: function(context, settings) {
$('a.dev-explain').click(function () {
qid = $(this).attr("qid");
cell = $('#devel-query-' + qid);
$('.dev-explain', cell).load(Drupal.settings.basePath + '?q=devel/explain/' + Drupal.settings.devel.request_id + '/' + qid).show();
$('.dev-explain', cell).load(settings.basePath + '?q=devel/explain/' + settings.devel.request_id + '/' + qid).show();
$('.dev-placeholders', cell).hide();
$('.dev-arguments', cell).hide();
return false;
@@ -16,11 +16,11 @@ Drupal.behaviors.devel_explain = {
// Arguments link in query log
Drupal.behaviors.devel_arguments = {
attach: function() {
attach: function(context, settings) {
$('a.dev-arguments').click(function () {
qid = $(this).attr("qid");
cell = $('#devel-query-' + qid);
$('.dev-arguments', cell).load(Drupal.settings.basePath + '?q=devel/arguments/' + Drupal.settings.devel.request_id + '/' + qid).show();
$('.dev-arguments', cell).load(settings.basePath + '?q=devel/arguments/' + settings.devel.request_id + '/' + qid).show();
$('.dev-placeholders', cell).hide();
$('.dev-explain', cell).hide();
return false;
@@ -30,7 +30,7 @@ Drupal.behaviors.devel_arguments = {
// Placeholders link in query log
Drupal.behaviors.devel_placeholders = {
attach: function() {
attach: function(context, settings) {
$('a.dev-placeholders').click(function () {
qid = $(this).attr("qid");
cell = $('#devel-query-' + qid);

View File

@@ -27,7 +27,10 @@ class DevelMailLog extends DefaultMailSystem {
$line_endings = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
$output = join($line_endings, $mimeheaders) . $line_endings;
$output .= $message['subject'] . $line_endings;
// 'Subject:' is a mail header and should not be translated.
$output .= 'Subject: ' . $message['subject'] . $line_endings;
// Blank line to separate headers from body.
$output .= $line_endings;
$output .= preg_replace('@\r?\n@', $line_endings, $message['body']);
return $output;
}

File diff suppressed because it is too large Load Diff

View File

@@ -145,20 +145,17 @@ function devel_field_info_page() {
$output .= kprint_r($info, TRUE, t('Instances'));
$info = field_info_bundles();
$output .= kprint_r($info, TRUE, t('Bundles'));
$info = field_info_field_types();
$output .= kprint_r($info, TRUE, t('Field types'));
$info = field_info_formatter_types();
$output .= kprint_r($info, TRUE, t('Formatter types'));
$info = field_info_storage_types();
$output .= kprint_r($info, TRUE, t('Storage types'));
$info = field_info_widget_types();
$output .= kprint_r($info, TRUE, t('Widget types'));
return $output;
}
/**
* Menu callback; display all variables.
*/
function devel_variable_page() {
// We return our own $page so as to avoid blocks.
$output = drupal_get_form('devel_variable_form');
drupal_set_page_content($output);
$page = element_info('page');
return $page;
}
function devel_variable_form() {
$header = array(
'name' => array('data' => t('Name'), 'field' => 'name', 'sort' => 'asc'),

View File

@@ -45,7 +45,8 @@ class DevelMailTest extends DrupalWebTestCase {
$this->assertEqual($content, 'From: postmaster@example.com
X-stupid: dumb
To: drupal@example.com
Test mail
Subject: Test mail
I am the body of this message');
}

View File

@@ -10,6 +10,7 @@
*/
function devel_generate_drush_command() {
$items['generate-users'] = array(
'callback' => 'drush_devel_generate_users',
'description' => 'Create users.',
'arguments' => array(
'number_users' => 'Number of users to generate.',
@@ -17,10 +18,12 @@ function devel_generate_drush_command() {
'options' => array(
'kill' => 'Delete all users before generating new ones.',
'roles' => 'A comma delimited list of role IDs which should be granted to the new users. No need to specify authenticated user role.',
'pass' => 'Specify a password to be set for all generated users.',
),
'aliases' => array('genu'),
);
$items['generate-terms'] = array(
'callback' => 'drush_devel_generate_terms',
'description' => 'Create terms in specified vocabulary.',
'arguments' => array(
'machine_name' => 'Vocabulary machine name into which new terms will be inserted.',
@@ -28,12 +31,13 @@ function devel_generate_drush_command() {
),
'options' => array(
'kill' => 'Delete all terms in specified vocabulary before generating.',
'feedback' => 'An integer representing interval for insertion rate logging. Defaults to 500',
'feedback' => 'An integer representing interval for insertion rate logging. Defaults to 1000',
),
'aliases' => array('gent'),
);
$items['generate-vocabs'] = array(
'callback' => 'drush_devel_generate_vocabs',
'description' => 'Create vocabularies.',
'arguments' => array(
'num_vocabs' => 'Number of vocabularies to create. Defaults to 1.',
@@ -44,6 +48,7 @@ function devel_generate_drush_command() {
'aliases' => array('genv'),
);
$items['generate-content'] = array(
'callback' => 'drush_devel_generate_content',
'description' => 'Create content.',
'drupal dependencies' => array('devel_generate'),
'arguments' => array(
@@ -53,13 +58,14 @@ function devel_generate_drush_command() {
'options' => array(
'kill' => 'Delete all content before generating new content.',
'types' => 'A comma delimited list of content types to create. Defaults to page,article.',
'feedback' => 'An integer representing interval for insertion rate logging. Defaults to 500',
'feedback' => 'An integer representing interval for insertion rate logging. Defaults to 1000',
'skip-fields' => 'A comma delimited list of fields to omit when generating random values',
'languages' => 'A comma-separated list of language codes',
),
'aliases' => array('genc'),
);
$items['generate-menus'] = array(
'callback' => 'drush_devel_generate_menus',
'description' => 'Create menus and menu items.',
'drupal dependencies' => array('devel_generate'), // Remove these once devel.module is moved down a directory. http://drupal.org/node/925246
'arguments' => array(
@@ -86,7 +92,8 @@ function drush_devel_generate_users($num_users = NULL) {
}
drush_generate_include_devel();
$roles = drush_get_option('roles') ? explode(',', drush_get_option('roles')) : array();
devel_create_users($num_users, drush_get_option('kill'), 0, $roles);
$pass = drush_get_option('pass', NULL);
devel_create_users($num_users, drush_get_option('kill'), 0, $roles, $pass);
drush_log(t('Generated @number users.', array('@number' => $num_users)), 'success');
}
@@ -103,9 +110,14 @@ function drush_devel_generate_terms($vname = NULL, $num_terms = 10) {
}
drush_generate_include_devel();
$vocabs[$vocab->vid] = $vocab;
devel_generate_term_data($vocabs, $num_terms, '12', drush_get_option('kill'));
drush_log(dt('Generated @num_terms terms.', array('@num_terms' => $num_terms)), 'success');
if (drush_get_option('kill')) {
devel_generate_delete_vocabulary_terms($vocab->vid);
drush_log(dt('Deleted existing terms.'), 'success');
}
$new_terms = devel_generate_terms($num_terms, array($vocab->vid => $vocab), '12');
if (!empty($new_terms)) {
drush_log(dt("Created the following new terms:\n!terms", array('!terms' => implode("\n", $new_terms))), 'success');
}
}
/**
@@ -116,8 +128,14 @@ function drush_devel_generate_vocabs($num_vocab = 1) {
return drush_set_error('DEVEL_GENERATE_INVALID_INPUT', dt('Invalid number of vocabularies: !num.', array('!num' => $num_vocab)));
}
drush_generate_include_devel();
devel_generate_vocab_data($num_vocab, '12', drush_get_option('kill'));
drush_log(dt('Generated @num_vocab vocabularies.', array('@num_vocab' => $num_vocab)), 'success');
if (drush_get_option('kill')) {
devel_generate_delete_vocabularies();
drush_log(dt('Deleted existing vocabularies.'), 'success');
}
$new_vocs = devel_generate_vocabs($num_vocab, '12');
if (!empty($new_vocs)) {
drush_log(dt("Created the following new vocabularies:\n!vocs", array('!vocs' => implode("\n", $new_vocs))), 'success');
}
}
/**
@@ -152,6 +170,10 @@ function drush_devel_generate_content($num_nodes = NULL, $max_comments = NULL) {
$values['values']['num_nodes'] = $num_nodes;
$values['values']['max_comments'] = $max_comments;
$values['values']['node_types'] = drupal_map_assoc(explode(',', drush_get_option('types', 'page,article')));
$node_types = array_filter($values['values']['node_types']);
if (!empty($values['values']['kill_content']) && empty($node_types)) {
return drush_set_error('DEVEL_GENERATE_INVALID_INPUT', dt('Please provide content type (--types) in which you want to delete the content.'));
}
drush_generate_include_devel();
devel_generate_content($values);
drush_log(t('Generated @num_nodes nodes, @max_comments comments (or less) per node.', array('@num_nodes' => (int)$num_nodes, '@max_comments' => (int)$max_comments)), 'success');
@@ -179,12 +201,26 @@ function drush_devel_generate_menus($number_menus = 2, $number_links = 50, $max_
$user = $user_one;
drupal_save_session(FALSE);
$kill = drush_get_option('kill');
drush_generate_include_devel();
// Delete custom menus.
if (drush_get_option('kill')) {
devel_generate_delete_menus();
drush_log(dt('Deleted existing menus and links.'), 'success');
}
// Generate new menus.
$new_menus = devel_generate_menus($number_menus, '12');
if (!empty($new_menus)) {
drush_log(dt("Created the following new menus:\n!menus", array('!menus' => implode("\n", $new_menus))), 'success');
}
// Generate new menu links.
$link_types = drupal_map_assoc(array('node', 'front', 'external'));
devel_generate_menu_data($number_menus, array(), $number_links, 12, $link_types, $max_depth, $max_width, $kill);
drush_log(t('Generated @number_menus menus, @number_links links.', array('@number_menus' => (int)$number_menus, '@number_links' => (int)$number_links)), 'success');
$new_links = devel_generate_links($number_links, $new_menus, '12', $link_types, $max_depth, $max_width);
drush_log(dt('Created !count new menu links.', array('!count' => count($new_links))), 'success');
}
//////////////////////////////////////////////////////////////////////////////
// Helper functions

View File

@@ -11,8 +11,10 @@
* The max age of each randomly-generated user, in seconds.
* @param $roles
* An array of role IDs that the users should receive.
* @param $pass
* A string to be used as common password for all generated users.
*/
function devel_create_users($num, $kill, $age = 0, $roles = array()) {
function devel_create_users($num, $kill, $age = 0, $roles = array(), $pass = NULL) {
$url = parse_url($GLOBALS['base_url']);
if ($kill) {
$uids = db_select('users', 'u')
@@ -45,8 +47,8 @@ function devel_create_users($num, $kill, $age = 0, $roles = array()) {
$edit = array(
'uid' => NULL,
'name' => $name,
'pass' => NULL, // No password avoids user_hash_password() which is expensive.
'mail' => $name . '@' . $url['host'],
'pass' => $pass,
'mail' => $name . '@' . $url['host'].'.invalid',
'status' => 1,
'created' => REQUEST_TIME - mt_rand(0, $age),
'roles' => drupal_map_assoc($roles),
@@ -103,6 +105,7 @@ function devel_create_users($num, $kill, $age = 0, $roles = array()) {
// Save the user record with the new picture.
$edit = (array) $account;
$edit['picture'] = $file;
$edit['pass'] = $pass; // Reassign password as it is replaced with the hashed version in $account
user_save($account, $edit);
}
}
@@ -114,8 +117,11 @@ function devel_create_users($num, $kill, $age = 0, $roles = array()) {
/**
* The main API function for creating content.
*
* See devel_generate_content_form() for the supported keys in $form_state['values'].
* Other modules may participate by form_alter() on that form and then handling their data during hook_nodeapi('pre_save') or in own submit handler for the form.
* See devel_generate_content_form() for the supported keys in
* $form_state['values'].
* Other modules may participate by form_alter() on that form and then handling
* their data during hook_node_insert() or in their own submit handler for the
* form.
*
* @param string $form_state
* @return void
@@ -205,6 +211,18 @@ function devel_generate_vocabs($records, $maxlength = 12, $types = array('page',
return $vocs;
}
/**
* Generates taxonomy terms for a list of given vocabularies.
*
* @param $records
* int number of terms to create in total.
* @param $vocabs
* array list of vocabs to populate.
* @param $maxlength
* int maximum length per term.
* @return
* array the list of names of the created terms.
*/
function devel_generate_terms($records, $vocabs, $maxlength = 12) {
$terms = array();
@@ -255,7 +273,7 @@ function devel_generate_terms($records, $vocabs, $maxlength = 12) {
// Populate all core fields on behalf of field.module
module_load_include('inc', 'devel_generate', 'devel_generate.fields');
devel_generate_fields($term, 'term', $term->vocabulary_machine_name);
devel_generate_fields($term, 'taxonomy_term', $term->vocabulary_machine_name);
if ($status = taxonomy_term_save($term)) {
$max += 1;
@@ -289,69 +307,49 @@ function devel_generate_get_terms($vids) {
->fetchCol('tid');
}
function devel_generate_term_data($vocabs, $num_terms, $title_length, $kill) {
if ($kill) {
foreach (devel_generate_get_terms(array_keys($vocabs)) as $tid) {
taxonomy_term_delete($tid);
}
drupal_set_message(t('Deleted existing terms.'));
}
$new_terms = devel_generate_terms($num_terms, $vocabs, $title_length);
if (!empty($new_terms)) {
drupal_set_message(t('Created the following new terms: !terms', array('!terms' => theme('item_list', array('items' => $new_terms)))));
/**
* Deletes all terms of a vocabulary.
*
* @param $vid
* int a vocabulary vid.
*/
function devel_generate_delete_vocabulary_terms($vid) {
foreach (taxonomy_get_tree($vid) as $term) {
taxonomy_term_delete($term->tid);
}
}
function devel_generate_vocab_data($num_vocab, $title_length, $kill) {
if ($kill) {
foreach (taxonomy_get_vocabularies() as $vid => $vocab) {
taxonomy_vocabulary_delete($vid);
}
drupal_set_message(t('Deleted existing vocabularies.'));
}
$new_vocs = devel_generate_vocabs($num_vocab, $title_length);
if (!empty($new_vocs)) {
drupal_set_message(t('Created the following new vocabularies: !vocs', array('!vocs' => theme('item_list', array('items' => $new_vocs)))));
/**
* Deletes all vocabularies.
*/
function devel_generate_delete_vocabularies() {
foreach (taxonomy_vocabulary_load_multiple(FALSE) as $vid => $vocab) {
taxonomy_vocabulary_delete($vid);
}
}
function devel_generate_menu_data($num_menus, $existing_menus, $num_links, $title_length, $link_types, $max_depth, $max_width, $kill) {
// Delete menus and menu links.
if ($kill) {
if (module_exists('menu')) {
foreach (menu_get_menus(FALSE) as $menu => $menu_title) {
if (strpos($menu, 'devel-') === 0) {
$menu = menu_load($menu);
menu_delete($menu);
}
/**
* Deletes custom generated menus
*/
function devel_generate_delete_menus() {
if (module_exists('menu')) {
foreach (menu_get_menus(FALSE) as $menu => $menu_title) {
if (strpos($menu, 'devel-') === 0) {
$menu = menu_load($menu);
menu_delete($menu);
}
}
// Delete menu links generated by devel.
$result = db_select('menu_links', 'm')
->fields('m', array('mlid'))
->condition('m.menu_name', 'devel', '<>')
// Look for the serialized version of 'devel' => TRUE.
->condition('m.options', '%' . db_like('s:5:"devel";b:1') . '%', 'LIKE')
->execute();
foreach ($result as $link) {
menu_link_delete($link->mlid);
}
drupal_set_message(t('Deleted existing menus and links.'));
}
// Generate new menus.
$new_menus = devel_generate_menus($num_menus, $title_length);
if (!empty($new_menus)) {
drupal_set_message(t('Created the following new menus: !menus', array('!menus' => theme('item_list', array('items' => $new_menus)))));
// Delete menu links generated by devel.
$result = db_select('menu_links', 'm')
->fields('m', array('mlid'))
->condition('m.menu_name', 'devel', '<>')
// Look for the serialized version of 'devel' => TRUE.
->condition('m.options', '%' . db_like('s:5:"devel";b:1') . '%', 'LIKE')
->execute();
foreach ($result as $link) {
menu_link_delete($link->mlid);
}
// Generate new menu links.
$menus = $new_menus + $existing_menus;
$new_links = devel_generate_links($num_links, $menus, $title_length, $link_types, $max_depth, $max_width);
drupal_set_message(t('Created @count new menu links.', array('@count' => count($new_links))));
}
/**
@@ -366,7 +364,7 @@ function devel_generate_menus($num_menus, $title_length = 12) {
for ($i = 1; $i <= $num_menus; $i++) {
$menu = array();
$menu['title'] = devel_generate_word(mt_rand(2, $title_length));
$menu['title'] = devel_generate_word(mt_rand(2, max(2, $title_length)));
$menu['menu_name'] = 'devel-' . drupal_strtolower($menu['title']);
$menu['description'] = t('Description of @name', array('@name' => $menu['title']));
menu_save($menu);
@@ -394,7 +392,7 @@ function devel_generate_links($num_links, $menus, $title_length, $link_types, $m
'options' => array('devel' => TRUE),
'weight' => mt_rand(-50, 50),
'mlid' => 0,
'link_title' => devel_generate_word(mt_rand(2, $title_length)),
'link_title' => devel_generate_word(mt_rand(2, max(2, $title_length))),
);
$link['options']['attributes']['title'] = t('Description of @title.', array('@title' => $link['link_title']));
@@ -404,7 +402,7 @@ function devel_generate_links($num_links, $menus, $title_length, $link_types, $m
}
else {
// Otherwise, get a random parent menu depth.
$depth = mt_rand(1, $max_depth - 1);
$depth = mt_rand(1, max(1, $max_depth - 1));
}
// Get a random parent link from the proper depth.
do {
@@ -674,9 +672,19 @@ function devel_generate_content_add_node(&$results) {
$users = $results['users'];
$node->uid = $users[array_rand($users)];
$type = node_type_get_type($node);
$node->title = $type->has_title ? devel_create_greeking(mt_rand(2, $results['title_length']), TRUE) : '';
$node->revision = mt_rand(0,1);
$node->promote = mt_rand(0, 1);
if ($type->has_title) {
// We should not use the random function if the value is not random
if ($results['title_length'] < 2) {
$node->title = devel_create_greeking(1, TRUE);
}
else {
$node->title = devel_create_greeking(mt_rand(1, $results['title_length']), TRUE);
}
}
// Avoid NOTICE.
if (!isset($results['time_range'])) {
$results['time_range'] = 0;
@@ -686,14 +694,16 @@ function devel_generate_content_add_node(&$results) {
$node->created = REQUEST_TIME - mt_rand(0, $results['time_range']);
// A flag to let hook_nodeapi() implementations know that this is a generated node.
// A flag to let hook_node_insert() implementations know that this is a
// generated node.
$node->devel_generate = $results;
// Populate all core fields on behalf of field.module
module_load_include('inc', 'devel_generate', 'devel_generate.fields');
devel_generate_fields($node, 'node', $node->type);
// See devel_generate_nodeapi() for actions that happen before and after this save.
// See devel_generate_node_insert() for actions that happen before and after
// this save.
node_save($node);
}

View File

@@ -2,13 +2,13 @@ name = Devel generate
description = Generate dummy users, nodes, and taxonomy terms.
package = Development
core = 7.x
dependencies[] = devel
tags[] = developer
configure = admin/config/development/generate
files[] = devel_generate.test
; Information added by drupal.org packaging script on 2012-06-05
version = "7.x-1.3"
; Information added by Drupal.org packaging script on 2014-05-01
version = "7.x-1.5"
core = "7.x"
project = "devel"
datestamp = "1338940281"
datestamp = "1398963366"

View File

@@ -71,6 +71,14 @@ function devel_generate_users_form() {
'#options' => $options,
);
$form['pass'] = array(
'#type' => 'textfield',
'#title' => t('Password to be set'),
'#default_value' => NULL,
'#size' => 32,
'#description' => t('Leave this field empty if you do not need to set a password.'),
);
$options = array(1 => t('Now'));
foreach (array(3600, 86400, 604800, 2592000, 31536000) as $interval) {
$options[$interval] = format_interval($interval, 1) . ' ' . t('ago');
@@ -93,10 +101,10 @@ function devel_generate_users_form() {
/**
* FormAPI submission to generate users.
*/
function devel_generate_users_form_submit($form_id, &$form_state) {
function devel_generate_users_form_submit($form, &$form_state) {
module_load_include('inc', 'devel_generate');
$values = $form_state['values'];
devel_create_users($values['num'], $values['kill_users'], $values['time_range'], $values['roles']);
devel_create_users($values['num'], $values['kill_users'], $values['time_range'], $values['roles'], $values['pass']);
}
/**
@@ -117,14 +125,15 @@ function devel_generate_content_form() {
}
else {
$types = node_type_get_types();
$suffix = '';
foreach ($types as $type) {
$options[$type->type] = array(
'type' => t($type->name),
);
if (module_exists('comment')) {
$default = variable_get('comment_' . $type->type, COMMENT_NODE_OPEN);
$map = array(t('Hidden'), t('Closed'), t('Open'));
$suffix = '<small>. ' . t('Comments: ') . $map[$default]. '</small>';
$options[$type->type]['comments'] = '<small>'. $map[$default]. '</small>';
}
$options[$type->type] = t($type->name) . $suffix;
}
}
// we cannot currently generate valid polls.
@@ -135,11 +144,18 @@ function devel_generate_content_form() {
return;
}
$header = array(
'type' => t('Content type'),
);
if (module_exists('comment')) {
$header['comments'] = t('Comments');
}
$form['node_types'] = array(
'#type' => 'checkboxes',
'#title' => t('Content types'),
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options,
'#default_value' => array_keys($options),
'#required' => TRUE,
);
if (module_exists('checkall')) $form['node_types']['#checkall'] = TRUE;
$form['kill_content'] = array(
@@ -218,12 +234,21 @@ function devel_generate_content_form() {
return $form;
}
/**
* FormAPI validation before generate nodes.
*/
function devel_generate_content_form_validate($form, &$form_state) {
form_set_value($form['node_types'], array_filter($form_state['values']['node_types']) , $form_state);
if (!empty($form_state['values']['kill_content']) && empty($form_state['values']['node_types'])) {
form_set_error('', t('Please select at least one content type to delete the content.'));
}
}
/**
* FormAPI submission to generate nodes.
*/
function devel_generate_content_form_submit($form_id, &$form_state) {
function devel_generate_content_form_submit($form, &$form_state) {
module_load_include('inc', 'devel_generate', 'devel_generate');
$form_state['values']['node_types'] = array_filter($form_state['values']['node_types']);
if ($form_state['values']['num_nodes'] <= 50 && $form_state['values']['max_comments'] <= 10) {
module_load_include('inc', 'devel_generate');
devel_generate_content($form_state);
@@ -305,18 +330,36 @@ function devel_generate_vocab_form() {
/**
* FormAPI submission to generate taxonomy terms.
*/
function devel_generate_term_form_submit($form_id, &$form_state) {
function devel_generate_term_form_submit($form, &$form_state) {
$values = $form_state['values'];
module_load_include('inc', 'devel_generate');
$vocabs = taxonomy_vocabulary_load_multiple($form_state['values']['vids']);
devel_generate_term_data($vocabs, $form_state['values']['num_terms'], $form_state['values']['title_length'], $form_state['values']['kill_taxonomy']);
if ($values['kill_taxonomy']) {
foreach ($values['vids'] as $vid) {
devel_generate_delete_vocabulary_terms($vid);
}
drupal_set_message(t('Deleted existing terms.'));
}
$vocabs = taxonomy_vocabulary_load_multiple($values['vids']);
$new_terms = devel_generate_terms($values['num_terms'], $vocabs, $values['title_length']);
if (!empty($new_terms)) {
drupal_set_message(t('Created the following new terms: !terms', array('!terms' => implode(', ', $new_terms))));
}
}
/**
* FormAPI submission to generate taxonomy vocabularies.
*/
function devel_generate_vocab_form_submit($form_id, &$form_state) {
function devel_generate_vocab_form_submit($form, &$form_state) {
$values = $form_state['values'];
module_load_include('inc', 'devel_generate');
devel_generate_vocab_data($form_state['values']['num_vocabs'], $form_state['values']['title_length'], $form_state['values']['kill_taxonomy']);
if ($values['kill_taxonomy']) {
devel_generate_delete_vocabularies();
drupal_set_message(t('Deleted existing vocabularies.'));
}
$new_vocs = devel_generate_vocabs($values['num_vocabs'], $values['title_length']);
if (!empty($new_vocs)) {
drupal_set_message(t('Created the following new vocabularies: !vocs', array('!vocs' => implode(', ', $new_vocs))));
}
}
/**
@@ -407,6 +450,7 @@ function devel_generate_menu_form() {
$form['title_length'] = array(
'#type' => 'textfield',
'#title' => t('Maximum number of characters in menu and menu link names'),
'#description' => t("The minimum length is 2."),
'#default_value' => 12,
'#size' => 10,
'#required' => TRUE,
@@ -453,11 +497,26 @@ function devel_generate_menu_form() {
/**
* FormAPI submission to generate menus.
*/
function devel_generate_menu_form_submit($form_id, &$form_state) {
function devel_generate_menu_form_submit($form, &$form_state) {
// If the create new menus checkbox is off, set the number of new menus to 0.
if (!isset($form_state['values']['existing_menus']['__new-menu__']) || !$form_state['values']['existing_menus']['__new-menu__']) {
$form_state['values']['num_menus'] = 0;
}
module_load_include('inc', 'devel_generate');
devel_generate_menu_data($form_state['values']['num_menus'], $form_state['values']['existing_menus'], $form_state['values']['num_links'], $form_state['values']['title_length'], $form_state['values']['link_types'], $form_state['values']['max_depth'], $form_state['values']['max_width'], $form_state['values']['kill']);
// Delete custom menus.
if ($form_state['values']['kill']) {
devel_generate_delete_menus();
drupal_set_message(t('Deleted existing menus and links.'));
}
// Generate new menus.
$new_menus = devel_generate_menus($form_state['values']['num_menus'], $form_state['values']['title_length']);
if (!empty($new_menus)) {
drupal_set_message(t('Created the following new menus: !menus', array('!menus' => implode(', ', $new_menus))));
}
// Generate new menu links.
$menus = $new_menus + $form_state['values']['existing_menus'];
$new_links = devel_generate_links($form_state['values']['num_links'], $menus, $form_state['values']['title_length'], $form_state['values']['link_types'], $form_state['values']['max_depth'], $form_state['values']['max_width']);
drupal_set_message(t('Created @count new menu links.', array('@count' => count($new_links))));
}

View File

@@ -0,0 +1,108 @@
<?php
/**
* @file
* Implements tests for devel_generate submodule.
*/
/**
* class DevelGenerateTest
*/
class DevelGenerateTest extends DrupalWebTestCase {
/*
* The getInfo() method provides information about the test.
* In order for the test to be run, the getInfo() method needs
* to be implemented.
*/
public static function getInfo() {
return array(
'name' => t('Devel Generate'),
'description' => t('Tests the logic to generate data.'),
'group' => t('Devel'),
);
}
/**
* Prepares the testing environment
*/
function setUp() {
parent::setUp(array('devel', 'devel_generate', 'taxonomy', 'menu', 'comment'));
// Create Basic page and Article node types.
if ($this->profile != 'standard') {
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic Page'));
}
}
/**
* Tests generate commands
*/
public function testGenerate() {
$user = $this->drupalCreateUser(array(
'administer taxonomy',
'administer menu',
'administer nodes',
));
$this->drupalLogin($user);
// Generate taxonomy vocabularies.
$edit = array(
'num_vocabs' => 5,
'title_length' => 12,
'kill_taxonomy' => 1,
);
$this->drupalPost('admin/config/development/generate/vocabs',
$edit, t('Generate'));
$this->assertText(t('Deleted existing vocabularies.'));
$this->assertText(t('Created the following new vocabularies:'));
// Generate taxonomy terms.
$form = devel_generate_term_form();
$vids = array_keys($form['vids']['#options']);
$edit = array(
'vids[]' => $vids,
'num_terms' => 5,
'title_length' => 12,
'kill_taxonomy' => 1,
);
$this->drupalPost('admin/config/development/generate/taxonomy',
$edit, t('Generate'));
$this->assertText(t('Deleted existing terms.'));
$this->assertText(t('Created the following new terms: '));
// Generate menus.
$edit = array(
'existing_menus[__new-menu__]' => 1,
'num_menus' => 2,
'num_links' => 50,
'title_length' => 12,
'link_types[node]' => 1,
'link_types[front]' => 1,
'link_types[external]' => 1,
'max_depth' => 4,
'max_width' => 6,
'kill' => 1,
);
$this->drupalPost('admin/config/development/generate/menu',
$edit, t('Generate'));
$this->assertText(t('Deleted existing menus and links.'));
$this->assertText(t('Created the following new menus:'));
$this->assertText(t('Created 50 new menu links.'));
// Generate content.
// First we create a node in order to test the Delete content checkbox.
$this->drupalCreateNode(array());
// Now submit the generate content form.
$edit = array(
'node_types[page]' => 1,
'kill_content' => 1,
'num_nodes' => 2,
'time_range' => 604800,
'max_comments' => 3,
'title_length' => 4,
);
$this->drupalPost('admin/config/development/generate/content', $edit, t('Generate'));
$this->assertText(t('Deleted 1 nodes.'));
$this->assertText(t('Finished creating 2 nodes'));
}
}

View File

@@ -18,7 +18,7 @@ function _file_devel_generate($object, $field, $instance, $bundle) {
$source->uri = $path;
$source->uid = 1; // TODO: randomize? use case specific.
$source->filemime = 'text/plain';
$source->filename = array_pop(explode("//", $path));
$source->filename = basename($path);
$destination_dir = $field['settings']['uri_scheme'] . '://' . $instance['settings']['file_directory'];
file_prepare_directory($destination_dir, FILE_CREATE_DIRECTORY);
$destination = $destination_dir . '/' . basename($path);

View File

@@ -23,7 +23,7 @@ function _image_devel_generate($object, $field, $instance, $bundle) {
$min_resolution = empty($instance['settings']['min_resolution']) ? '100x100' : $instance['settings']['min_resolution'];
$max_resolution = empty($instance['settings']['max_resolution']) ? '600x600' : $instance['settings']['max_resolution'];
$extensions = array_intersect(explode(' ', $instance['settings']['file_extensions']), array('png', 'jpg'));
$extensions = array_intersect(explode(' ', $instance['settings']['file_extensions']), array('png', 'gif', 'jpg', 'jpeg'));
$extension = array_rand(drupal_map_assoc($extensions));
// Generate a max of 5 different images.
@@ -33,7 +33,7 @@ function _image_devel_generate($object, $field, $instance, $bundle) {
$source->uri = $path;
$source->uid = 1; // TODO: randomize? Use case specific.
$source->filemime = 'image/' . pathinfo($path, PATHINFO_EXTENSION);
$source->filename = array_pop(explode("//", $path));
$source->filename = basename($path);
$destination_dir = $field['settings']['uri_scheme'] . '://' . $instance['settings']['file_directory'];
file_prepare_directory($destination_dir, FILE_CREATE_DIRECTORY);
$destination = $destination_dir . '/' . basename($path);
@@ -89,8 +89,6 @@ function devel_generate_image($extension = 'png', $min_resolution, $max_resoluti
$save_function = 'image'. ($extension == 'jpg' ? 'jpeg' : $extension);
$save_function($im, drupal_realpath($destination));
$images[$extension][$min_resolution][$max_resolution][$destination] = $destination;
}
return $destination;
}

View File

@@ -19,7 +19,7 @@ function _text_devel_generate($object, $field, $instance, $bundle) {
$format = filter_fallback_format();
}
if ($instance['widget']['type'] != 'text_textfield') {
if (empty($field['settings']['max_length'])) {
// Textarea handling
$object_field['value'] = devel_create_content($format);
if ($instance['widget']['type'] == 'text_textarea_with_summary' && !empty($instance['display_summary'])) {
@@ -28,11 +28,7 @@ function _text_devel_generate($object, $field, $instance, $bundle) {
}
else {
// Textfield handling.
// Generate a value that respects max_length.
if (empty($field['settings']['max_length'])) {
$field['settings']['max_length'] = 12;
}
$object_field['value'] = user_password($field['settings']['max_length']);
$object_field['value'] = substr(devel_create_greeking(mt_rand(1, $field['settings']['max_length'] / 6), FALSE), 0, $field['settings']['max_length']);
}
$object_field['format'] = $format;
return $object_field;

View File

@@ -7,7 +7,7 @@ Drupal.behaviors.devel = {
attach: function (context, settings) {
// Add hint to footnote
$('.krumo-footnote .krumo-call').before('<img style="vertical-align: middle;" title="Click to expand. Double-click to show path." src="' + Drupal.settings.basePath + 'misc/help.png"/>');
$('.krumo-footnote .krumo-call').once().before('<img style="vertical-align: middle;" title="Click to expand. Double-click to show path." src="' + settings.basePath + 'misc/help.png"/>');
var krumo_name = [];
var krumo_type = [];

View File

@@ -6,9 +6,9 @@ core = 7.x
configure = admin/config/development/devel
tags[] = developer
; Information added by drupal.org packaging script on 2012-06-05
version = "7.x-1.3"
; Information added by Drupal.org packaging script on 2014-05-01
version = "7.x-1.5"
core = "7.x"
project = "devel"
datestamp = "1338940281"
datestamp = "1398963366"

View File

@@ -7,7 +7,7 @@
/**
* Perform the access by user ajax request.
*/
function devel_node_access_user_ajax(context) {
function devel_node_access_user_ajax(context, settings) {
// Get the cell ID for the first .dna-permission that isn't processed.
var cell = $('td.dna-permission', context)
.not('.ajax-processed', context)
@@ -15,7 +15,7 @@
if (cell !== undefined) {
// Generate the URI from the basePath, path, data type, cell ID, and a
// random token to bypass caching.
var url = Drupal.settings.basePath
var url = settings.basePath
+ "?q="
+ 'devel/node_access/by_user/json/'
+ cell
@@ -25,7 +25,7 @@
$.getJSON(url, function(data) {
$('#' + cell, context).html(data).addClass('ajax-processed');
// Call this function again.
devel_node_access_user_ajax(context);
devel_node_access_user_ajax(context, settings);
});
// Ajax fails silently on error, mark bad requests with an error message.
// If the request is just slow this will update when the request succeeds.
@@ -42,7 +42,7 @@
)
.addClass('ajax-processed');
// Call this function again.
devel_node_access_user_ajax(context);
devel_node_access_user_ajax(context, settings);
}
},
3000
@@ -55,10 +55,10 @@
* Attach the access by user behavior which initiates ajax.
*/
Drupal.behaviors.develNodeAccessUserAjax = {
attach: function(context) {
attach: function(context, settings) {
// Start the ajax.
devel_node_access_user_ajax(context);
devel_node_access_user_ajax(context, settings);
}
};
})(jQuery);
})(jQuery);

View File

@@ -226,9 +226,13 @@ function dna_visible_nodes($nid = NULL) {
if ($nid) {
$nids[$nid] = $nid;
}
elseif (empty($nids) && arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == NULL) {
// show DNA information on node/NID even if access is denied (IF the user has the 'view devel_node_access information' permission)!
return array(arg(1));
elseif (empty($nids)) {
$menu_item = menu_get_item();
$map = $menu_item['original_map'];
if ($map[0] == 'node' && isset($map[1]) && is_numeric($map[1]) && !isset($map[2])) {
// show DNA information on node/NID even if access is denied (IF the user has the 'view devel_node_access information' permission)!
return array($map[1]);
}
}
return $nids;
}
@@ -368,6 +372,7 @@ function _devel_node_access_nar_alter(&$grants, $node) {
}
else {
// it's an existing grant, check for changes
$view = $update = $delete = FALSE;
foreach (array('view', 'update', 'delete') as $op) {
$$op = $grant["grant_$op"] - $data[$grant['realm']][$grant['gid']]['current']["grant_$op"];
}
@@ -496,6 +501,7 @@ function devel_node_access_block_info() {
$blocks['dna_user'] = array(
'info' => t('Devel Node Access by User'),
'region' => 'footer',
'status' => 0,
'cache' => DRUPAL_NO_CACHE,
);
return $blocks;
@@ -645,7 +651,7 @@ function devel_node_access_block_view($delta) {
foreach (array('view', 'update', 'delete') as $op) {
$grants = _devel_node_access_module_invoke_all('node_grants', $user, $op);
// call all hook_node_grants_alter() implementations
$ng_alter_data = _devel_node_access_ng_alter($grants, $user, $op);
$ng_alter_datas[$op] = _devel_node_access_ng_alter($grants, $user, $op);
$checked_grants[$nid][$op] = array_merge(array('all' => array(0)), $grants);
}
}
@@ -788,7 +794,15 @@ function devel_node_access_block_view($delta) {
'data' => '<a href="#node-' . $grant['nid'] . '">' . $row['nid'] . '</a>',
'title' => $grant['#title'],
);
$row['realm'] = (empty($grant['#module']) || strpos($grant['realm'], $grant['#module']) === 0 ? '' : $grant['#module'] . ':<br />') . $grant['realm'];
if (empty($grant['#module']) || strpos($grant['realm'], $grant['#module']) === 0) {
$row['realm'] = $grant['realm'];
}
else {
$row['realm'] = array(
'data' => $grant['#module'] . ':<br />' . $grant['realm'],
'title' => t("The '@module' module fails to adhere to the best practice of naming its realm(s) after itself.", array('@module' => $grant['#module'])),
);
}
// prepend information from the D7 hook_node_access_records_alter()
$next_style = array();
@@ -906,7 +920,7 @@ function devel_node_access_block_view($delta) {
);
}
else {
$variables['!list'] = '<div style="margin-left: 2em">' . _devel_node_access_get_grant_list($nid, $ng_alter_data) . '</div>';
$variables['!list'] = '<div style="margin-left: 2em">' . _devel_node_access_get_grant_list($nid, $ng_alter_datas['view']) . '</div>';
$variables['%access'] = 'view';
$output[] = array(
'#prefix' => "\n<div style='text-align: left' title='" . t('These are the grants returned by hook_node_grants() for this user.') . "'>",
@@ -915,7 +929,10 @@ function devel_node_access_block_view($delta) {
);
$accounts[] = $user;
}
if (arg(0) == 'node' && is_numeric(arg(1)) && !$block1_visible) { // only for single nodes
$menu_item = menu_get_item();
$map = $menu_item['original_map'];
if ($map[0] == 'node' && isset($map[1]) && is_numeric($map[1]) && !isset($map[2]) && !$block1_visible) {
// only for single nodes
if (user_is_logged_in()) {
$accounts[] = user_load(0); // Anonymous, too
}
@@ -948,10 +965,11 @@ function devel_node_access_block_view($delta) {
'#suffix' => '</div>',
);
}
$variables['!username'] = theme('username', array('account' => $account));
$variables['!username'] = '<em class="placeholder">' . theme('username', array('account' => $account)) . '</em>';
$output[] = array(
'#prefix' => "\n<div style='text-align: left'>",
'#markup' => t("!username has the following access", $variables),
'#type' => 'item',
'lead-in' => array('#markup' => t("!username has the following access", $variables) . ' '),
'items' => $account_items,
'#suffix' => "\n</div>\n",
);
@@ -971,9 +989,28 @@ function devel_node_access_block_view($delta) {
case 'dna_user':
// show which users can access this node
if (arg(0) == 'node' && is_numeric($nid = arg(1)) && arg(2) == NULL && $node = node_load($nid)) {
$menu_item = menu_get_item();
$map = $menu_item['original_map'];
if ($map[0] != 'node' || !isset($map[1]) || !is_numeric($map[1]) || isset($map[2])) {
// Ignore anything but node/%.
return;
}
if (isset($menu_item['map'][1]) && is_object($node = $menu_item['map'][1])) {
// We have the node.
}
elseif (is_numeric($menu_item['original_map'][1])) {
$node = node_load($menu_item['original_map'][1]);
}
if (isset($node)) {
$nid = $node->nid;
$node_type = node_type_get_type($node);
$headers = array(t('username'), '<span title="' . t("Create nodes of the '@Node_type' type.", array('@Node_type' => $node_type->name)) . '">' . t('create') . '</span>', t('view'), t('update'), t('delete'));
$variables = array('@Node_type' => ($node_type ? $node_type->name : $node->type));
$create_header = '<span title="' . t("Create nodes of the '@Node_type' type.", $variables) . '">' . t('create') . '</span>';
if (!$node_type) {
$create_header .= '<br /><span class="error">' . t("(missing type: '@Node_type')", $variables) . '</span>';
}
$headers = array(t('username'), $create_header, t('view'), t('update'), t('delete'));
$rows = array();
// Determine whether to use Ajax or prepopulate the tables.
if ($ajax = variable_get('devel_node_access_user_ajax', FALSE)) {

View File

@@ -604,7 +604,8 @@ This is a list of all the values from the <code><b><?php echo realpath($ini_file
$_recursion_marker = krumo::_marker();
if ($hive =& krumo::_hive($dummy)) {
foreach($hive as $i=>$bee){
if (is_object($bee)) {
// skip closures set as properties
if (is_object($bee) && !($bee instanceof Closure)) {
unset($hive[$i]->$_recursion_marker);
// DEVEL: changed 'else' to 'elseif' below
} elseif (is_array($bee)) {

View File

@@ -0,0 +1,22 @@
#!/usr/bin/env sh
# This script will run phpunit-based test classes using Drush's
# test framework. First, the Drush executable is located, and
# then phpunit is invoked, passing in drush_testcase.inc as
# the bootstrap file.
#
# Any parameters that may be passed to phpunit may also be used
# with runtests.sh.
DRUSH_PATH="`which drush`"
DRUSH_DIRNAME="`dirname -- "$DRUSH_PATH"`"
# if [ $# = 0 ] ; then
# phpunit --bootstrap="$DRUSH_DIRNAME/tests/drush_testcase.inc" .
# else
# phpunit --bootstrap="$DRUSH_DIRNAME/tests/drush_testcase.inc" "$@"
# fi
#Instead, hard code target file so we don't find a simpletest file at
# /lib/Drupal/devel_generate/Tests/DevelGenerateTest.php.
phpunit --bootstrap="$DRUSH_DIRNAME/tests/drush_testcase.inc" develDrushTest.php

View File

@@ -1,4 +1,22 @@
Libraries 7.x-2.2, 2014-02-09
-----------------------------
#2046919 by tstoeckler: Clarify 'version' docs.
#1946110 by munroe_richard: Allow uppercase letters as library machine names.
#1953260 by tstoeckler: Improve documentation of libraries_get_version().
#1855918 by tstoeckler: Make integration file loading backwards-compatible.
#1876124 by tstoeckler: Fix integration files for themes.
#1876124 by tstoeckler: Add tests for theme-provided library information.
#1876124 by tstoeckler: Prepare for adding a test theme.
#1876124 by tstoeckler | whastings, fubhy: Fix hook_libraries_info() for themes.
#2015721 by tstoeckler, CaptainHook: Protect against files overriding local variables.
#2046919 by tstoeckler: Improve documentation around 'version callback'.
#1844272 by tstoeckler, jweowu: Fix typos in libraries.api.php.
#1938638 by tstoeckler: Prevent weird PHP notice on update.
#1329388 by RobLoach, tstoeckler: Clear static caches in libraries_flush_caches().
#1855918 by rbayliss: Load integration files after library files.
#1938638 by Pol: Fix typo in libraries.api.php.
Libraries 7.x-2.1, 2013-03-09
-----------------------------
#1937446 by Pol, tstoeckler: Add a 'pre-dependencies-load' callback group.
@@ -13,7 +31,6 @@ Libraries 7.x-2.0, 2012-07-29
#1578618 by iamEAP: Fixed Fatal cache flush failure on major version upgrades.
#1449346 by tstoeckler, sun: Clean-up libraries.test
Libraries 7.x-2.0-alpha2, 2011-12-15
------------------------------------
#1299076 by tstoeckler: Improve testing of JS, CSS, and PHP files.
@@ -23,7 +40,6 @@ Libraries 7.x-2.0-alpha2, 2011-12-15
#1321372 by Rob Loach: Provide a 'post-load' callback group.
#1205854 by tstoeckler, sun: Test library caching.
Libraries 7.x-2.0-alpha1, 2011-10-01
------------------------------------
#1268342 by tstoeckler: Clean up drush libraries-list command.
@@ -65,20 +81,20 @@ by sun: Fixed testbot breaks upon .info file without .module file.
Libraries 7.x-1.x, xxxx-xx-xx
-----------------------------
Libraries 7.x-1.0, 2010-01-27
-----------------------------
#743522 by sun: Ported to D7.
Libraries 6.x-1.x, xxxx-xx-xx
-----------------------------
Libraries 6.x-1.0, 2010-01-27
-----------------------------
#1028744 by tstoeckler: Code clean-up.
#496732 by tstoeckler, robphillips: Allow placing libraries in root directory.
Libraries 6.x-1.0-ALPHA1, 2009-12-30
Libraries 6.x-1.0-alpha1, 2009-12-30
------------------------------------
#480440 by markus_petrux: Fixed base_path() not applied to default library path.
#320562 by sun: Added basic functions.

View File

@@ -30,7 +30,9 @@
* changes of implementing modules and to support different versions of a
* library simultaneously (though only one version can be installed per
* site). A valid use-case is an external library whose version cannot be
* determined programatically.
* determined programmatically. Either 'version' or 'version callback' (or
* 'version arguments' in case libraries_get_version() is being used as a
* version callback) must be declared.
* - version callback: (optional) The name of a function that detects and
* returns the full version string of the library. The first argument is
* always $library, an array containing all library information as described
@@ -38,18 +40,22 @@
* arguments, either as a single $options parameter or as multiple
* parameters, which correspond to the two ways to specify the argument
* values (see 'version arguments'). Defaults to libraries_get_version().
* - version arguments: A list of arguments to pass to the version callback.
* Version arguments can be declared either as an associative array whose
* keys are the argument names or as an indexed array without specifying
* keys. If declared as an associative array, the arguments get passed to
* the version callback as a single $options parameter whose keys are the
* argument names (i.e. $options is identical to the specified array). If
* declared as an indexed array, the array values get passed to the version
* callback as seperate arguments in the order they were declared. The
* default version callback libraries_get_version() expects a single,
* associative array with named keys:
* - file: The filename to parse for the version, relative to the library
* path. For example: 'docs/changelog.txt'.
* Unless 'version' is declared or libraries_get_version() is being used as
* a version callback, 'version callback' must be declared. In the latter
* case, however, 'version arguments' must be declared in the specified way.
* - version arguments: (optional) A list of arguments to pass to the version
* callback. Version arguments can be declared either as an associative
* array whose keys are the argument names or as an indexed array without
* specifying keys. If declared as an associative array, the arguments get
* passed to the version callback as a single $options parameter whose keys
* are the argument names (i.e. $options is identical to the specified
* array). If declared as an indexed array, the array values get passed to
* the version callback as separate arguments in the order they were
* declared. The default version callback libraries_get_version() expects a
* single, associative array with named keys:
* - file: The filename to parse for the version, relative to the path
* speficied as the 'library path' property (see above). For example:
* 'docs/changelog.txt'.
* - pattern: A string containing a regular expression (PCRE) to match the
* library version. For example: '@version\s+([0-9a-zA-Z\.-]+)@'. Note
* that the returned version is not the match of the entire pattern (i.e.
@@ -60,6 +66,10 @@
* - cols: (optional) The maximum number of characters per line to take into
* account. Defaults to 200. In case of minified or compressed files, this
* prevents reading the entire file into memory.
* Defaults to an empty array. 'version arguments' must be specified unless
* 'version' is declared or the specified 'version callback' does not
* require any arguments. The latter might be the case with a
* library-specific version callback, for example.
* - files: An associative array of library files to load. Supported keys are:
* - js: A list of JavaScript files to load, using the same syntax as Drupal
* core's hook_library().
@@ -100,10 +110,10 @@
* available or not. The first argument is always $library, an array
* containing all library information as described here. The second
* argument is always a string containing the variant name. There are two
* ways to declare the variant callback's additinal arguments, either as a
* ways to declare the variant callback's additional arguments, either as a
* single $options parameter or as multiple parameters, which correspond
* to the two ways to specify the argument values (see 'variant
* arguments'). If ommitted, the variant is expected to always be
* arguments'). If omitted, the variant is expected to always be
* available.
* - variant arguments: A list of arguments to pass to the variant callback.
* Variant arguments can be declared either as an associative array whose
@@ -112,7 +122,7 @@
* the variant callback as a single $options parameter whose keys are the
* argument names (i.e. $options is identical to the specified array). If
* declared as an indexed array, the array values get passed to the
* variant callback as seperate arguments in the order they were declared.
* variant callback as separate arguments in the order they were declared.
* Variants can be version-specific (see 'versions').
* - versions: (optional) An associative array of supported library versions.
* Naturally, libraries evolve over time and so do their APIs. In case a
@@ -146,9 +156,23 @@
* Valid callback groups are:
* - info: Callbacks registered in this group are applied after the library
* information has been retrieved via hook_libraries_info() or info files.
* At this point the following additional information is available:
* - $library['info type']: How the library information was obtained. Can
* be 'info file', 'module', or 'theme', depending on whether the
* library information was obtained from an info file, an enabled module
* or an enabled theme, respectively.
* Additionally, one of the following three keys is available, depending
* on the value of $library['info type'].
* - $library['info file']: In case the library information was obtained
* from an info file, the URI of the info file.
* - $library['module']: In case the library was obtained from an enabled
* module, the name of the providing module.
* - $library['theme']: In case the library was obtained from an enabled
* theme, the name of the providing theme.
* - pre-detect: Callbacks registered in this group are applied after the
* library path has been determined and before the version callback is
* invoked. At this point the following additional information is available:
* invoked. At this point the following additional information is
* available:
* - $library['library path']: The path on the file system to the library.
* - post-detect: Callbacks registered in this group are applied after the
* library has been successfully detected. At this point the library
@@ -299,7 +323,7 @@ function hook_libraries_info() {
'mymodule_example_libraries_postdetect_callback',
),
// Called before the library's dependencies are loaded.
'pre-dependencie-load' => array(
'pre-dependencies-load' => array(
'mymodule_example_libraries_pre_dependencies_load_callback',
),
// Called before the library is loaded.

View File

@@ -1,11 +1,13 @@
name = Libraries
description = Allows version-dependent and shared usage of external libraries.
core = 7.x
; We use hook_system_theme_info() which was added in Drupal 7.11
dependencies[] = system (>=7.11)
files[] = tests/libraries.test
; Information added by drupal.org packaging script on 2013-03-09
version = "7.x-2.1"
; Information added by Drupal.org packaging script on 2014-02-09
version = "7.x-2.2"
core = "7.x"
project = "libraries"
datestamp = "1362848412"
datestamp = "1391965716"

View File

@@ -9,6 +9,14 @@
* Implements hook_flush_caches().
*/
function libraries_flush_caches() {
// Clear static caches.
// We don't clear the 'libraries_load' static cache, because that could result
// in libraries that had been loaded before the cache flushing to be loaded
// again afterwards.
foreach (array('libraries_get_path', 'libraries_info') as $name) {
drupal_static_reset($name);
}
// @todo When upgrading from 1.x, update.php attempts to flush caches before
// the cache table has been created.
// @see http://drupal.org/node/1477932
@@ -133,7 +141,7 @@ function libraries_scan_info_files() {
$files = array();
foreach ($directories as $dir) {
if (file_exists($dir)) {
$files = array_merge($files, file_scan_directory($dir, '@^[a-z0-9._-]+\.libraries\.info$@', array(
$files = array_merge($files, file_scan_directory($dir, '@^[A-Za-z0-9._-]+\.libraries\.info$@', array(
'key' => 'name',
'recurse' => FALSE,
)));
@@ -158,6 +166,13 @@ function libraries_scan_info_files() {
* An array of library information, passed by reference.
*/
function libraries_invoke($group, &$library) {
// When introducing new callback groups in newer versions, stale cached
// library information somehow reaches this point during the database update
// before clearing the library cache.
if (empty($library['callbacks'][$group])) {
return;
}
foreach ($library['callbacks'][$group] as $callback) {
libraries_traverse_library($library, $callback);
}
@@ -333,27 +348,31 @@ function &libraries_info($name = NULL) {
if (!isset($libraries)) {
$libraries = array();
// Gather information from hook_libraries_info().
// Gather information from hook_libraries_info() in enabled modules.
foreach (module_implements('libraries_info') as $module) {
foreach (module_invoke($module, 'libraries_info') as $machine_name => $properties) {
$properties['info type'] = 'module';
$properties['module'] = $module;
$libraries[$machine_name] = $properties;
}
}
// Gather information from hook_libraries_info() in enabled themes.
// @see drupal_alter()
global $theme, $base_theme_info;
if (isset($theme)) {
$theme_keys = array();
foreach ($base_theme_info as $base) {
$theme_keys[] = $base->name;
}
$theme_keys[] = $theme;
foreach ($theme_keys as $theme_key) {
$function = $theme_key . '_' . 'libraries_info';
$themes = array();
foreach (list_themes() as $theme_name => $theme_info) {
if ($theme_info->status && file_exists(drupal_get_path('theme', $theme_name) . '/template.php')) {
// Collect a list of viable themes for re-use when calling the alter
// hook.
$themes[] = $theme_name;
include_once drupal_get_path('theme', $theme_name) . '/template.php';
$function = $theme_name . '_libraries_info';
if (function_exists($function)) {
foreach ($function() as $machine_name => $properties) {
$properties['theme'] = $theme_key;
$properties['info type'] = 'theme';
$properties['theme'] = $theme_name;
$libraries[$machine_name] = $properties;
}
}
@@ -364,6 +383,7 @@ function &libraries_info($name = NULL) {
// .info files override module definitions.
foreach (libraries_scan_info_files() as $machine_name => $file) {
$properties = drupal_parse_info_file($file->uri);
$properties['info type'] = 'info file';
$properties['info file'] = $file->uri;
$libraries[$machine_name] = $properties;
}
@@ -373,8 +393,20 @@ function &libraries_info($name = NULL) {
libraries_info_defaults($properties, $machine_name);
}
// Allow modules to alter the registered libraries.
drupal_alter('libraries_info', $libraries);
// Allow enabled modules and themes to alter the registered libraries.
// drupal_alter() only takes the currently active theme into account, not
// all enabled themes.
foreach (module_implements('libraries_info_alter') as $module) {
$function = $module . '_libraries_info_alter';
$function($libraries);
}
foreach ($themes as $theme) {
$function = $theme . '_libraries_info_alter';
// The template.php file was included above.
if (function_exists($function)) {
$function($libraries);
}
}
// Invoke callbacks in the 'info' group.
foreach ($libraries as &$properties) {
@@ -418,6 +450,8 @@ function libraries_info_defaults(&$library, $name) {
'versions' => array(),
'integration files' => array(),
'callbacks' => array(),
// @todo Remove in 7.x-3.x
'post-load integration files' => FALSE,
);
$library['callbacks'] += array(
'info' => array(),
@@ -461,9 +495,11 @@ function libraries_detect($name) {
// Re-use the statically cached value of libraries_info() to save memory.
$library = &libraries_info($name);
// Exit early if the library was not found.
if ($library === FALSE) {
return $library;
}
// If 'installed' is set, library detection ran already.
if (isset($library['installed'])) {
return $library;
@@ -600,6 +636,12 @@ function libraries_load($name, $variant = NULL) {
cache_set($name, $library, 'cache_libraries');
}
// Exit early if the library was not found.
if ($library === FALSE) {
$loaded[$name] = $library;
return $loaded[$name];
}
// If a variant was specified, override the top-level properties with the
// variant properties.
if (isset($variant)) {
@@ -652,13 +694,30 @@ function libraries_load($name, $variant = NULL) {
*/
function libraries_load_files($library) {
// Load integration files.
if (!empty($library['integration files'])) {
foreach ($library['integration files'] as $module => $files) {
libraries_load_files(array(
'files' => $files,
'path' => '',
'library path' => drupal_get_path('module', $module),
));
if (!$library['post-load integration files'] && !empty($library['integration files'])) {
$enabled_themes = array();
foreach (list_themes() as $theme_name => $theme) {
if ($theme->status) {
$enabled_themes[] = $theme_name;
}
}
foreach ($library['integration files'] as $provider => $files) {
if (module_exists($provider)) {
libraries_load_files(array(
'files' => $files,
'path' => '',
'library path' => drupal_get_path('module', $provider),
'post-load integration files' => FALSE,
));
}
elseif (in_array($provider, $enabled_themes)) {
libraries_load_files(array(
'files' => $files,
'path' => '',
'library path' => drupal_get_path('theme', $provider),
'post-load integration files' => FALSE,
));
}
}
}
@@ -706,15 +765,60 @@ function libraries_load_files($library) {
foreach ($library['files']['php'] as $file => $array) {
$file_path = DRUPAL_ROOT . '/' . $path . '/' . $file;
if (file_exists($file_path)) {
require_once $file_path;
_libraries_require_once($file_path);
$count++;
}
}
}
// Load integration files.
if ($library['post-load integration files'] && !empty($library['integration files'])) {
$enabled_themes = array();
foreach (list_themes() as $theme_name => $theme) {
if ($theme->status) {
$enabled_themes[] = $theme_name;
}
}
foreach ($library['integration files'] as $provider => $files) {
if (module_exists($provider)) {
libraries_load_files(array(
'files' => $files,
'path' => '',
'library path' => drupal_get_path('module', $provider),
'post-load integration files' => FALSE,
));
}
elseif (in_array($provider, $enabled_themes)) {
libraries_load_files(array(
'files' => $files,
'path' => '',
'library path' => drupal_get_path('theme', $provider),
'post-load integration files' => FALSE,
));
}
}
}
return $count;
}
/**
* Wrapper function for require_once.
*
* A library file could set a $path variable in file scope. Requiring such a
* file directly in libraries_load_files() would lead to the local $path
* variable being overridden after the require_once statement. This would
* break loading further files. Therefore we use this trivial wrapper which has
* no local state that can be tampered with.
*
* @param $file_path
* The file path of the file to require.
*/
function _libraries_require_once($file_path) {
require_once $file_path;
}
/**
* Gets the version information from an arbitrary library.
*

View File

@@ -1,11 +0,0 @@
/**
* @file
* Test CSS file for Libraries loading.
*
* Color the 'libraries-test-css' div red. See README.txt for more information.
*/
.libraries-test-css {
color: red;
}

View File

@@ -1,11 +0,0 @@
/**
* @file
* Test CSS file for Libraries loading.
*
* Color the 'libraries-test-css' div green. See README.txt for more information.
*/
.libraries-test-css {
color: green;
}

View File

@@ -1,11 +0,0 @@
/**
* @file
* Test CSS file for Libraries loading.
*
* Color the 'libraries-test-css' div orange. See README.txt for more information.
*/
.libraries-test-css {
color: orange;
}

View File

@@ -1,11 +0,0 @@
/**
* @file
* Test CSS file for Libraries loading.
*
* Color the 'libraries-test-css' div blue. See README.txt for more information.
*/
.libraries-test-css {
color: blue;
}

View File

@@ -72,7 +72,8 @@ class LibrariesTestCase extends DrupalWebTestCase {
}
function setUp() {
parent::setUp('libraries', 'libraries_test');
parent::setUp('libraries', 'libraries_test_module');
theme_enable(array('libraries_test_theme'));
}
/**
@@ -131,6 +132,7 @@ class LibrariesTestCase extends DrupalWebTestCase {
// FALSE for missing or incompatible dependencies.
$library['installed'] = TRUE;
libraries_detect_dependencies($library);
$this->verbose('Library:<pre>' . var_export($library, TRUE) . '</pre>');
$this->assertTrue($library['installed'], "libraries_detect_dependencies() detects compatible version string: '$version_string' is compatible with '$version'");
}
foreach ($incompatible as $version_string) {
@@ -138,6 +140,7 @@ class LibrariesTestCase extends DrupalWebTestCase {
$library['installed'] = TRUE;
unset($library['error'], $library['error message']);
libraries_detect_dependencies($library);
$this->verbose('Library:<pre>' . var_export($library, TRUE) . '</pre>');
$this->assertEqual($library['error'], 'incompatible dependency', "libraries_detect_dependencies() detects incompatible version strings: '$version_string' is incompatible with '$version'");
}
// Instead of repeating this assertion for each version string, we just
@@ -157,7 +160,7 @@ class LibrariesTestCase extends DrupalWebTestCase {
*/
function testLibrariesScanInfoFiles() {
$expected = array('example_info_file' => (object) array(
'uri' => drupal_get_path('module', 'libraries') . '/tests/example/example_info_file.libraries.info',
'uri' => drupal_get_path('module', 'libraries') . '/tests/libraries/example_info_file.libraries.info',
'filename' => 'example_info_file.libraries.info',
'name' => 'example_info_file.libraries',
));
@@ -169,17 +172,33 @@ class LibrariesTestCase extends DrupalWebTestCase {
* Tests libraries_info().
*/
function testLibrariesInfo() {
// Test that modules can provide and alter library information.
$info = libraries_info();
$this->assertTrue(isset($info['example_module']));
$this->verbose('Library:<pre>' . var_export($info['example_module'], TRUE) . '</pre>');
$this->assertEqual($info['example_module']['info type'], 'module');
$this->assertEqual($info['example_module']['module'], 'libraries_test_module');
$this->assertTrue($info['example_module']['module_altered']);
// Test that themes can provide and alter library information.
$this->assertTrue(isset($info['example_theme']));
$this->verbose('Library:<pre>' . var_export($info['example_theme'], TRUE) . '</pre>');
$this->assertEqual($info['example_theme']['info type'], 'theme');
$this->assertEqual($info['example_theme']['theme'], 'libraries_test_theme');
$this->assertTrue($info['example_theme']['theme_altered']);
// Test that library information is found correctly.
$expected = array(
'name' => 'Example files',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'files' => array(
'js' => array('example_1.js' => array()),
'css' => array('example_1.css' => array()),
'php' => array('example_1.php' => array()),
),
'module' => 'libraries_test',
'info type' => 'module',
'module' => 'libraries_test_module',
);
libraries_info_defaults($expected, 'example_files');
$library = libraries_info('example_files');
@@ -190,7 +209,8 @@ class LibrariesTestCase extends DrupalWebTestCase {
// Test a library specified with an .info file gets detected.
$expected = array(
'name' => 'Example info file',
'info file' => drupal_get_path('module', 'libraries_test') . '/example/example_info_file.libraries.info',
'info type' => 'info file',
'info file' => drupal_get_path('module', 'libraries') . '/tests/libraries/example_info_file.libraries.info',
);
libraries_info_defaults($expected, 'example_info_file');
$library = libraries_info('example_info_file');
@@ -303,6 +323,12 @@ class LibrariesTestCase extends DrupalWebTestCase {
$loaded = &drupal_static('libraries_load');
$this->verbose('<pre>' . var_export($loaded, TRUE) . '</pre>');
$this->assertEqual($loaded['example_dependency']['loaded'], 1, 'Dependency library is also loaded');
// Test that PHP files that have a local $path variable do not break library
// loading.
// @see _libraries_require_once()
$library = libraries_load('example_path_variable_override');
$this->assertEqual($library['loaded'], 2, 'PHP files cannot break library loading.');
}
/**
@@ -311,7 +337,7 @@ class LibrariesTestCase extends DrupalWebTestCase {
function testCallbacks() {
$expected = array(
'name' => 'Example callback',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'versions' => array(
'1' => array(
@@ -344,12 +370,12 @@ class LibrariesTestCase extends DrupalWebTestCase {
),
),
'callbacks' => array(
'info' => array('_libraries_test_info_callback'),
'pre-detect' => array('_libraries_test_pre_detect_callback'),
'post-detect' => array('_libraries_test_post_detect_callback'),
'pre-dependencies-load' => array('_libraries_test_pre_dependencies_load_callback'),
'pre-load' => array('_libraries_test_pre_load_callback'),
'post-load' => array('_libraries_test_post_load_callback'),
'info' => array('_libraries_test_module_info_callback'),
'pre-detect' => array('_libraries_test_module_pre_detect_callback'),
'post-detect' => array('_libraries_test_module_post_detect_callback'),
'pre-dependencies-load' => array('_libraries_test_module_pre_dependencies_load_callback'),
'pre-load' => array('_libraries_test_module_pre_load_callback'),
'post-load' => array('_libraries_test_module_post_load_callback'),
),
'info callback' => 'not applied',
'pre-detect callback' => 'not applied',
@@ -357,7 +383,8 @@ class LibrariesTestCase extends DrupalWebTestCase {
'pre-dependencies-load callback' => 'not applied',
'pre-load callback' => 'not applied',
'post-load callback' => 'not applied',
'module' => 'libraries_test',
'info type' => 'module',
'module' => 'libraries_test_module',
);
libraries_info_defaults($expected, 'example_callback');
@@ -424,37 +451,46 @@ class LibrariesTestCase extends DrupalWebTestCase {
* We check for JavaScript and CSS files directly in the DOM and add a list of
* included PHP files manually to the page output.
*
* @see _libraries_test_load()
* @see _libraries_test_module_load()
*/
function testLibrariesOutput() {
// Test loading of a simple library with a top-level files property.
$this->drupalGet('libraries_test/files');
$this->drupalGet('libraries-test-module/files');
$this->assertLibraryFiles('example_1', 'File loading');
// Test loading of integration files.
$this->drupalGet('libraries_test/integration_files');
$this->assertRaw('libraries_test.js', 'Integration file loading: libraries_test.js found');
$this->assertRaw('libraries_test.css', 'Integration file loading: libraries_test.css found');
$this->assertRaw('libraries_test.inc', 'Integration file loading: libraries_test.inc found');
$this->drupalGet('libraries-test-module/module-integration-files');
$this->assertRaw('libraries_test_module.js', 'Integration file loading: libraries_test_module.js found');
$this->assertRaw('libraries_test_module.css', 'Integration file loading: libraries_test_module.css found');
$this->assertRaw('libraries_test_module.inc', 'Integration file loading: libraries_test_module.inc found');
$this->drupalGet('libraries-test-module/theme-integration-files');
$this->assertRaw('libraries_test_theme.js', 'Integration file loading: libraries_test_theme.js found');
$this->assertRaw('libraries_test_theme.css', 'Integration file loading: libraries_test_theme.css found');
$this->assertRaw('libraries_test_theme.inc', 'Integration file loading: libraries_test_theme.inc found');
// Test loading of post-load integration files.
$this->drupalGet('libraries-test-module/module-integration-files-post-load');
// If the files were not loaded correctly, a fatal error occurs.
$this->assertResponse(200, 'Post-load integration files are loaded correctly.');
// Test version overloading.
$this->drupalGet('libraries_test/versions');
$this->drupalGet('libraries-test-module/versions');
$this->assertLibraryFiles('example_2', 'Version overloading');
// Test variant loading.
$this->drupalGet('libraries_test/variant');
$this->drupalGet('libraries-test-module/variant');
$this->assertLibraryFiles('example_3', 'Variant loading');
// Test version overloading and variant loading.
$this->drupalGet('libraries_test/versions_and_variants');
$this->drupalGet('libraries-test-module/versions-and-variants');
$this->assertLibraryFiles('example_4', 'Concurrent version and variant overloading');
// Test caching.
variable_set('libraries_test_cache', TRUE);
variable_set('libraries_test_module_cache', TRUE);
cache_clear_all('example_callback', 'cache_libraries');
// When the library information is not cached, all callback groups should be
// invoked.
$this->drupalGet('libraries_test/cache');
$this->drupalGet('libraries-test-module/cache');
$this->assertRaw('The <em>info</em> callback group was invoked.', 'Info callback invoked for uncached libraries.');
$this->assertRaw('The <em>pre-detect</em> callback group was invoked.', 'Pre-detect callback invoked for uncached libraries.');
$this->assertRaw('The <em>post-detect</em> callback group was invoked.', 'Post-detect callback invoked for uncached libraries.');
@@ -462,13 +498,13 @@ class LibrariesTestCase extends DrupalWebTestCase {
$this->assertRaw('The <em>post-load</em> callback group was invoked.', 'Post-load callback invoked for uncached libraries.');
// When the library information is cached only the 'pre-load' and
// 'post-load' callback groups should be invoked.
$this->drupalGet('libraries_test/cache');
$this->drupalGet('libraries-test-module/cache');
$this->assertNoRaw('The <em>info</em> callback group was not invoked.', 'Info callback not invoked for cached libraries.');
$this->assertNoRaw('The <em>pre-detect</em> callback group was not invoked.', 'Pre-detect callback not invoked for cached libraries.');
$this->assertNoRaw('The <em>post-detect</em> callback group was not invoked.', 'Post-detect callback not invoked for cached libraries.');
$this->assertRaw('The <em>pre-load</em> callback group was invoked.', 'Pre-load callback invoked for cached libraries.');
$this->assertRaw('The <em>post-load</em> callback group was invoked.', 'Post-load callback invoked for cached libraries.');
variable_set('libraries_test_cache', FALSE);
variable_set('libraries_test_module_cache', FALSE);
}
/**
@@ -516,7 +552,7 @@ class LibrariesTestCase extends DrupalWebTestCase {
foreach ($names as $name => $expected) {
foreach ($extensions as $extension) {
$filepath = drupal_get_path('module', 'libraries_test') . "/example/$name.$extension";
$filepath = drupal_get_path('module', 'libraries') . "/tests/libraries/example/$name.$extension";
// JavaScript and CSS files appear as full URLs and with an appended
// query string.
if (in_array($extension, array('js', 'css'))) {

View File

@@ -14,11 +14,11 @@ CSS and PHP files.
place the following text on the page:
"If this text shows up, no JavaScript test file was loaded."
This text is replaced via JavaScript by a text of the form:
"If this text shows up, [[file] was loaded successfully."
"If this text shows up, [file] was loaded successfully."
[file] is either 'example_1.js', 'example_2.js', 'example_3.js',
'example_4.js' or 'libraries_test.js'. If you have SimpleTest's verbose mode
enabled and see the above text in one of the debug pages, the noted JavaScript
file was loaded successfully.
'example_4.js' or 'libraries_test_module.js'. If you have SimpleTest's verbose
mode enabled and see the above text in one of the debug pages, the noted
JavaScript file was loaded successfully.
- CSS: The filenames of the CSS files are asserted to be in the raw HTML via
SimpleTest. Since the filename could appear, for instance, in an error
message, this is not very robust. Explicit testing of CSS, though, is not yet
@@ -29,7 +29,7 @@ CSS and PHP files.
- example_2: green
- example_3: orange
- example_4: blue
- libraries_test: purple"
- libraries_test_module: purple"
If you have SimpleTest's verbose mode enabled, and see the above text in a
certain color (i.e. not in black), a CSS file was loaded successfully. Which
file depends on the color as referenced in the text above.
@@ -37,6 +37,7 @@ CSS and PHP files.
PHP files and then checking whether this function was defined using
function_exists(). This can be checked programatically with SimpleTest.
The loading of integration files is tested with the same method. The integration
files are libraries_test.js, libraries_test.css, libraries_test.inc and are
located in the tests directory alongside libraries_test.module (i.e. they are
not in the same directory as this file).
files are libraries_test_module.js, libraries_test_module.css,
libraries_test_module.inc and are located in the test module's directory
alongside libraries_test_module.info (i.e. they are not in the same directory as
this file).

View File

@@ -0,0 +1,12 @@
/**
* @file
* Test CSS file for Libraries loading.
*
* Color the 'libraries-test-module-css' div red. See README.txt for more
* information.
*/
.libraries-test-module-css {
color: red;
}

View File

@@ -3,7 +3,7 @@
* @file
* Test JavaScript file for Libraries loading.
*
* Replace the text in the 'libraries-test-javascript' div. See README.txt for
* Replace the text in the 'libraries-test-module-js' div. See README.txt for
* more information.
*/
@@ -11,7 +11,7 @@
Drupal.behaviors.librariesTest = {
attach: function(context, settings) {
$('.libraries-test-javascript').text('If this text shows up, example_1.js was loaded successfully.')
$('.libraries-test-module-js').text('If this text shows up, example_1.js was loaded successfully.')
}
};

View File

@@ -0,0 +1,15 @@
<?php
/**
* @file
* Test PHP file for Libraries loading.
*/
// @see _libraries_require_once()
$path = 'abc';
/**
* Dummy function to see if this file was loaded.
*/
function _libraries_test_module_example_1() {
}

View File

@@ -0,0 +1,12 @@
/**
* @file
* Test CSS file for Libraries loading.
*
* Color the 'libraries-test-module-css' div green. See README.txt for more
* information.
*/
.libraries-test-module-css {
color: green;
}

View File

@@ -3,7 +3,7 @@
* @file
* Test JavaScript file for Libraries loading.
*
* Replace the text in the 'libraries-test-javascript' div. See README.txt for
* Replace the text in the 'libraries-test-module-js' div. See README.txt for
* more information.
*/
@@ -11,7 +11,7 @@
Drupal.behaviors.librariesTest = {
attach: function(context, settings) {
$('.libraries-test-javascript').text('If this text shows up, example_2.js was loaded successfully.')
$('.libraries-test-module-js').text('If this text shows up, example_2.js was loaded successfully.')
}
};

View File

@@ -0,0 +1,15 @@
<?php
/**
* @file
* Test PHP file for Libraries loading.
*/
// @see _libraries_require_once()
$path = 'abc';
/**
* Dummy function to see if this file was loaded.
*/
function _libraries_test_module_example_2() {
}

View File

@@ -0,0 +1,12 @@
/**
* @file
* Test CSS file for Libraries loading.
*
* Color the 'libraries-test-module-css' div orange. See README.txt for more
* information.
*/
.libraries-test-module-css {
color: orange;
}

View File

@@ -3,7 +3,7 @@
* @file
* Test JavaScript file for Libraries loading.
*
* Replace the text in the 'libraries-test-javascript' div. See README.txt for
* Replace the text in the 'libraries-test-module-js' div. See README.txt for
* more information.
*/
@@ -11,7 +11,7 @@
Drupal.behaviors.librariesTest = {
attach: function(context, settings) {
$('.libraries-test-javascript').text('If this text shows up, example_3.js was loaded successfully.')
$('.libraries-test-module-js').text('If this text shows up, example_3.js was loaded successfully.')
}
};

View File

@@ -8,5 +8,5 @@
/**
* Dummy function to see if this file was loaded.
*/
function _libraries_test_example_3() {
function _libraries_test_module_example_3() {
}

View File

@@ -0,0 +1,12 @@
/**
* @file
* Test CSS file for Libraries loading.
*
* Color the 'libraries-test-module-css' div blue. See README.txt for more
* information.
*/
.libraries-test-module-css {
color: blue;
}

View File

@@ -3,7 +3,7 @@
* @file
* Test JavaScript file for Libraries loading.
*
* Replace the text in the 'libraries-test-javascript' div. See README.txt for
* Replace the text in the 'libraries-test-module-js' div. See README.txt for
* more information.
*/
@@ -11,7 +11,7 @@
Drupal.behaviors.librariesTest = {
attach: function(context, settings) {
$('.libraries-test-javascript').text('If this text shows up, example_4.js was loaded successfully.')
$('.libraries-test-module-js').text('If this text shows up, example_4.js was loaded successfully.')
}
};

View File

@@ -8,5 +8,5 @@
/**
* Dummy function to see if this file was loaded.
*/
function _libraries_test_example_4() {
function _libraries_test_module_example_4() {
}

View File

@@ -1,11 +1,10 @@
; This is an example info file of a library used for testing purposes.
name = Example info file
; Information added by drupal.org packaging script on 2013-03-09
version = "7.x-2.1"
; Information added by Drupal.org packaging script on 2014-02-09
version = "7.x-2.2"
core = "7.x"
project = "libraries"
datestamp = "1362848412"
datestamp = "1391965716"

View File

@@ -1,12 +0,0 @@
/**
* @file
* Test CSS file for Libraries loading.
*
* Color the 'libraries-test-css' div purple. See README.txt for more
* information.
*/
.libraries-test-css {
color: purple;
}

View File

@@ -1,11 +0,0 @@
<?php
/**
* @file
* Test PHP file for Libraries loading.
/**
* Dummy function to see if this file was loaded.
*/
function _libraries_test_integration_file() {
}

View File

@@ -1,18 +0,0 @@
/**
* @file
* Test JavaScript file for Libraries loading.
*
* Replace the text in the 'libraries-test-javascript' div. See README.txt for
* more information.
*/
(function ($) {
Drupal.behaviors.librariesTest = {
attach: function(context, settings) {
$('.libraries-test-javascript').text('If this text shows up, libraries_test.js was loaded successfully.')
}
};
})(jQuery);

View File

@@ -0,0 +1,12 @@
/**
* @file
* Test CSS file for Libraries loading.
*
* Color the 'libraries-test-module-css' div purple. See README.txt for more
* information.
*/
.libraries-test-module-css {
color: purple;
}

View File

@@ -3,10 +3,9 @@
/**
* @file
* Test PHP file for Libraries loading.
*/
/**
* Dummy function to see if this file was loaded.
*/
function _libraries_test_example_1() {
function _libraries_test_module_integration_file() {
}

View File

@@ -1,12 +1,13 @@
name = Libraries test module
description = Tests library detection and loading.
core = 7.x
package = Testing
dependencies[] = libraries
hidden = TRUE
; Information added by drupal.org packaging script on 2013-03-09
version = "7.x-2.1"
; Information added by Drupal.org packaging script on 2014-02-09
version = "7.x-2.2"
core = "7.x"
project = "libraries"
datestamp = "1362848412"
datestamp = "1391965716"

View File

@@ -0,0 +1,18 @@
/**
* @file
* Test JavaScript file for Libraries loading.
*
* Replace the text in the 'libraries-test-module-js' div. See README.txt for
* more information.
*/
(function ($) {
Drupal.behaviors.librariesTest = {
attach: function(context, settings) {
$('.libraries-test-module-js').text('If this text shows up, libraries_test_module.js was loaded successfully.')
}
};
})(jQuery);

View File

@@ -8,32 +8,37 @@
/**
* Implements hook_libraries_info().
*/
function libraries_test_libraries_info() {
function libraries_test_module_libraries_info() {
// Test library information gathering.
$libraries['example_module'] = array(
'name' => 'Example module',
'module_altered' => FALSE,
);
// Test library detection.
$libraries['example_missing'] = array(
'name' => 'Example missing',
'library path' => drupal_get_path('module', 'libraries') . '/tests/missing',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/missing',
);
$libraries['example_undetected_version'] = array(
'name' => 'Example undetected version',
'library path' => drupal_get_path('module', 'libraries') . '/tests',
'version callback' => '_libraries_test_return_version',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version callback' => '_libraries_test_module_return_version',
'version arguments' => array(FALSE),
);
$libraries['example_unsupported_version'] = array(
'name' => 'Example unsupported version',
'library path' => drupal_get_path('module', 'libraries') . '/tests',
'version callback' => '_libraries_test_return_version',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version callback' => '_libraries_test_module_return_version',
'version arguments' => array('1'),
'versions' => array(
'2' => array(),
),
);
$libraries['example_supported_version'] = array(
'name' => 'Example supported version',
'library path' => drupal_get_path('module', 'libraries') . '/tests',
'version callback' => '_libraries_test_return_version',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version callback' => '_libraries_test_module_return_version',
'version arguments' => array('1'),
'versions' => array(
'1' => array(),
@@ -43,7 +48,7 @@ function libraries_test_libraries_info() {
// Test the default version callback.
$libraries['example_default_version_callback'] = array(
'name' => 'Example default version callback',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version arguments' => array(
'file' => 'README.txt',
// Version 1
@@ -55,16 +60,16 @@ function libraries_test_libraries_info() {
// Test a multiple-parameter version callback.
$libraries['example_multiple_parameter_version_callback'] = array(
'name' => 'Example multiple parameter version callback',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
// Version 1
'version callback' => '_libraries_test_get_version',
'version callback' => '_libraries_test_module_get_version',
'version arguments' => array('README.txt', '/Version (\d+)/', 5),
);
// Test a top-level files property.
$libraries['example_files'] = array(
'name' => 'Example files',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'files' => array(
'js' => array('example_1.js'),
@@ -76,23 +81,41 @@ function libraries_test_libraries_info() {
// Test loading of integration files.
// Normally added by the corresponding module via hook_libraries_info_alter(),
// these files should be automatically loaded when the library is loaded.
$libraries['example_integration_files'] = array(
'name' => 'Example integration files',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
$libraries['example_module_integration_files'] = array(
'name' => 'Example module integration files',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'integration files' => array(
'libraries_test' => array(
'js' => array('libraries_test.js'),
'css' => array('libraries_test.css'),
'php' => array('libraries_test.inc'),
'libraries_test_module' => array(
'js' => array('libraries_test_module.js'),
'css' => array('libraries_test_module.css'),
'php' => array('libraries_test_module.inc'),
),
),
);
// Test loading of integration files after library files.
// We test the correct loading order by calling a function that is defined in
// example_1.php in libraries_test_module_post_load.inc.
$libraries['example_module_integration_files_post_load'] = array(
'name' => 'Example module post-load integration files',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'files' => array(
'php' => array('example_1.php'),
),
'integration files' => array(
'libraries_test_module' => array(
'php' => array('libraries_test_module_post_load.inc'),
),
),
'post-load integration files' => TRUE,
);
// Test version overloading.
$libraries['example_versions'] = array(
'name' => 'Example versions',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '2',
'versions' => array(
'1' => array(
@@ -115,7 +138,7 @@ function libraries_test_libraries_info() {
// Test variant detection.
$libraries['example_variant_missing'] = array(
'name' => 'Example variant missing',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'variants' => array(
'example_variant' => array(
@@ -124,7 +147,7 @@ function libraries_test_libraries_info() {
'css' => array('example_3.css'),
'php' => array('example_3.php'),
),
'variant callback' => '_libraries_test_return_installed',
'variant callback' => '_libraries_test_module_return_installed',
'variant arguments' => array(FALSE),
),
),
@@ -132,7 +155,7 @@ function libraries_test_libraries_info() {
$libraries['example_variant'] = array(
'name' => 'Example variant',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'variants' => array(
'example_variant' => array(
@@ -141,7 +164,7 @@ function libraries_test_libraries_info() {
'css' => array('example_3.css'),
'php' => array('example_3.php'),
),
'variant callback' => '_libraries_test_return_installed',
'variant callback' => '_libraries_test_module_return_installed',
'variant arguments' => array(TRUE),
),
),
@@ -150,7 +173,7 @@ function libraries_test_libraries_info() {
// Test correct behaviour with multiple versions and multiple variants.
$libraries['example_versions_and_variants'] = array(
'name' => 'Example versions and variants',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '2',
'versions' => array(
'1' => array(
@@ -161,7 +184,7 @@ function libraries_test_libraries_info() {
'css' => array('example_1.css'),
'php' => array('example_1.php'),
),
'variant callback' => '_libraries_test_return_installed',
'variant callback' => '_libraries_test_module_return_installed',
'variant arguments' => array(TRUE),
),
'example_variant_2' => array(
@@ -170,7 +193,7 @@ function libraries_test_libraries_info() {
'css' => array('example_2.css'),
'php' => array('example_2.php'),
),
'variant callback' => '_libraries_test_return_installed',
'variant callback' => '_libraries_test_module_return_installed',
'variant arguments' => array(TRUE),
),
),
@@ -183,7 +206,7 @@ function libraries_test_libraries_info() {
'css' => array('example_3.css'),
'php' => array('example_3.php'),
),
'variant callback' => '_libraries_test_return_installed',
'variant callback' => '_libraries_test_module_return_installed',
'variant arguments' => array(TRUE),
),
'example_variant_2' => array(
@@ -192,7 +215,7 @@ function libraries_test_libraries_info() {
'css' => array('example_4.css'),
'php' => array('example_4.php'),
),
'variant callback' => '_libraries_test_return_installed',
'variant callback' => '_libraries_test_module_return_installed',
'variant arguments' => array(TRUE),
),
),
@@ -206,27 +229,27 @@ function libraries_test_libraries_info() {
// This library acts as a dependency for the libraries below.
$libraries['example_dependency'] = array(
'name' => 'Example dependency',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1.1',
'files' => array('js' => array('example_1.js')),
);
$libraries['example_dependency_missing'] = array(
'name' => 'Example dependency missing',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'dependencies' => array('example_missing'),
'files' => array('js' => array('example_1.js')),
);
$libraries['example_dependency_incompatible'] = array(
'name' => 'Example dependency incompatible',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'dependencies' => array('example_dependency (>1.1)'),
'files' => array('js' => array('example_1.js')),
);
$libraries['example_dependency_compatible'] = array(
'name' => 'Example dependency compatible',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'dependencies' => array('example_dependency (>=1.1)'),
'files' => array('js' => array('example_1.js')),
@@ -235,7 +258,7 @@ function libraries_test_libraries_info() {
// Test the applying of callbacks.
$libraries['example_callback'] = array(
'name' => 'Example callback',
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'versions' => array(
'1' => array(
@@ -271,12 +294,12 @@ function libraries_test_libraries_info() {
),
),
'callbacks' => array(
'info' => array('_libraries_test_info_callback'),
'pre-detect' => array('_libraries_test_pre_detect_callback'),
'post-detect' => array('_libraries_test_post_detect_callback'),
'pre-dependencies-load' => array('_libraries_test_pre_dependencies_load_callback'),
'pre-load' => array('_libraries_test_pre_load_callback'),
'post-load' => array('_libraries_test_post_load_callback'),
'info' => array('_libraries_test_module_info_callback'),
'pre-detect' => array('_libraries_test_module_pre_detect_callback'),
'post-detect' => array('_libraries_test_module_post_detect_callback'),
'pre-dependencies-load' => array('_libraries_test_module_pre_dependencies_load_callback'),
'pre-load' => array('_libraries_test_module_pre_load_callback'),
'post-load' => array('_libraries_test_module_post_load_callback'),
),
// These keys are for testing purposes only.
'info callback' => 'not applied',
@@ -287,24 +310,40 @@ function libraries_test_libraries_info() {
'post-load callback' => 'not applied',
);
$libraries['example_path_variable_override'] = array(
'name' => 'Example path variable override',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'files' => array(
'php' => array('example_1.php', 'example_2.php'),
),
);
return $libraries;
}
/**
* Implements hook_libraries_info_alter().
*/
function libraries_test_module_libraries_info_alter(&$libraries) {
$libraries['example_module']['module_altered'] = TRUE;
}
/**
* Implements hook_libraries_info_file_paths()
*/
function libraries_test_libraries_info_file_paths() {
return array(drupal_get_path('module', 'libraries_test') . '/example');
function libraries_test_module_libraries_info_file_paths() {
return array(drupal_get_path('module', 'libraries') . '/tests/libraries');
}
/**
* Gets the version of an example library.
*
* Returns exactly the version string entered as the $version parameter. This
* function cannot be collapsed with _libraries_test_return_installed(), because
* of the different arguments that are passed automatically.
* function cannot be collapsed with _libraries_test_module_return_installed(),
* because of the different arguments that are passed automatically.
*/
function _libraries_test_return_version($library, $version) {
function _libraries_test_module_return_version($library, $version) {
return $version;
}
@@ -340,7 +379,7 @@ function _libraries_test_return_version($library, $version) {
*
* @see libraries_get_version()
*/
function _libraries_test_get_version($library, $file, $pattern, $lines = 20, $cols = 200) {
function _libraries_test_module_get_version($library, $file, $pattern, $lines = 20, $cols = 200) {
$file = DRUPAL_ROOT . '/' . $library['library path'] . '/' . $file;
if (!file_exists($file)) {
@@ -361,10 +400,10 @@ function _libraries_test_get_version($library, $file, $pattern, $lines = 20, $co
* Detects the variant of an example library.
*
* Returns exactly the value of $installed, either TRUE or FALSE. This function
* cannot be collapsed with _libraries_test_return_version(), because of the
* different arguments that are passed automatically.
* cannot be collapsed with _libraries_test_module_return_version(), because of
* the different arguments that are passed automatically.
*/
function _libraries_test_return_installed($library, $name, $installed) {
function _libraries_test_module_return_installed($library, $name, $installed) {
return $installed;
}
@@ -373,10 +412,10 @@ function _libraries_test_return_installed($library, $name, $installed) {
*
* This function is used as a test callback for the 'info' callback group.
*
* @see _libraries_test_callback()
* @see _libraries_test_module_callback()
*/
function _libraries_test_info_callback(&$library, $version, $variant) {
_libraries_test_callback($library, $version, $variant, 'info');
function _libraries_test_module_info_callback(&$library, $version, $variant) {
_libraries_test_module_callback($library, $version, $variant, 'info');
}
/**
@@ -384,10 +423,10 @@ function _libraries_test_info_callback(&$library, $version, $variant) {
*
* This function is used as a test callback for the 'pre-detect' callback group.
*
* @see _libraries_test_callback()
* @see _libraries_test_module_callback()
*/
function _libraries_test_pre_detect_callback(&$library, $version, $variant) {
_libraries_test_callback($library, $version, $variant, 'pre-detect');
function _libraries_test_module_pre_detect_callback(&$library, $version, $variant) {
_libraries_test_module_callback($library, $version, $variant, 'pre-detect');
}
/**
@@ -395,10 +434,10 @@ function _libraries_test_pre_detect_callback(&$library, $version, $variant) {
*
* This function is used as a test callback for the 'post-detect callback group.
*
* @see _libraries_test_callback()
* @see _libraries_test_module_callback()
*/
function _libraries_test_post_detect_callback(&$library, $version, $variant) {
_libraries_test_callback($library, $version, $variant, 'post-detect');
function _libraries_test_module_post_detect_callback(&$library, $version, $variant) {
_libraries_test_module_callback($library, $version, $variant, 'post-detect');
}
/**
@@ -407,10 +446,10 @@ function _libraries_test_post_detect_callback(&$library, $version, $variant) {
* This function is used as a test callback for the 'pre-dependencies-load'
* callback group.
*
* @see _libraries_test_callback()
* @see _libraries_test_module_callback()
*/
function _libraries_test_pre_dependencies_load_callback(&$library, $version, $variant) {
_libraries_test_callback($library, $version, $variant, 'pre-dependencies-load');
function _libraries_test_module_pre_dependencies_load_callback(&$library, $version, $variant) {
_libraries_test_module_callback($library, $version, $variant, 'pre-dependencies-load');
}
/**
@@ -418,10 +457,10 @@ function _libraries_test_pre_dependencies_load_callback(&$library, $version, $va
*
* This function is used as a test callback for the 'pre-load' callback group.
*
* @see _libraries_test_callback()
* @see _libraries_test_module_callback()
*/
function _libraries_test_pre_load_callback(&$library, $version, $variant) {
_libraries_test_callback($library, $version, $variant, 'pre-load');
function _libraries_test_module_pre_load_callback(&$library, $version, $variant) {
_libraries_test_module_callback($library, $version, $variant, 'pre-load');
}
/**
@@ -429,10 +468,10 @@ function _libraries_test_pre_load_callback(&$library, $version, $variant) {
*
* This function is used as a test callback for the 'post-load' callback group.
*
* @see _libraries_test_callback()
* @see _libraries_test_module_callback()
*/
function _libraries_test_post_load_callback(&$library, $version, $variant) {
_libraries_test_callback($library, $version, $variant, 'post-load');
function _libraries_test_module_post_load_callback(&$library, $version, $variant) {
_libraries_test_module_callback($library, $version, $variant, 'post-load');
}
/**
@@ -456,7 +495,7 @@ function _libraries_test_post_load_callback(&$library, $version, $variant) {
* The variant the library information passed in $library belongs to, or NULL
* if the passed library information is not variant-specific.
*/
function _libraries_test_callback(&$library, $version, $variant, $group) {
function _libraries_test_module_callback(&$library, $version, $variant, $group) {
$string = 'applied';
if (isset($version) && isset($variant)) {
$string .= " (version $version, variant $variant)";
@@ -475,7 +514,7 @@ function _libraries_test_callback(&$library, $version, $variant, $group) {
// The following is used to test caching of library information.
// Only set the message for the top-level library to prevent confusing,
// duplicate messages.
if (!isset($version) && !isset($variant) && variable_get('libraries_test_cache', FALSE)) {
if (!isset($version) && !isset($variant) && variable_get('libraries_test_module_cache', FALSE)) {
drupal_set_message("The <em>$group</em> callback group was invoked.");
}
}
@@ -483,32 +522,40 @@ function _libraries_test_callback(&$library, $version, $variant, $group) {
/**
* Implements hook_menu().
*/
function libraries_test_menu() {
function libraries_test_module_menu() {
$base = array(
'page callback' => '_libraries_test_load',
'page callback' => '_libraries_test_module_load',
'access callback' => TRUE,
);
$items['libraries_test/files'] = $base + array(
$items['libraries-test-module/files'] = $base + array(
'title' => 'Test files',
'page arguments' => array('example_files'),
);
$items['libraries_test/integration_files'] = $base + array(
'title' => 'Test integration files',
'page arguments' => array('example_integration_files'),
$items['libraries-test-module/module-integration-files'] = $base + array(
'title' => 'Test module integration files',
'page arguments' => array('example_module_integration_files'),
);
$items['libraries_test/versions'] = $base + array(
$items['libraries-test-module/module-integration-files-post-load'] = $base + array(
'title' => 'Test module post-load integration files',
'page arguments' => array('example_module_integration_files_post_load'),
);
$items['libraries-test-module/theme-integration-files'] = $base + array(
'title' => 'Test theme integration files',
'page arguments' => array('example_theme_integration_files'),
);
$items['libraries-test-module/versions'] = $base + array(
'title' => 'Test version loading',
'page arguments' => array('example_versions'),
);
$items['libraries_test/variant'] = $base + array(
$items['libraries-test-module/variant'] = $base + array(
'title' => 'Test variant loading',
'page arguments' => array('example_variant', 'example_variant'),
);
$items['libraries_test/versions_and_variants'] = $base + array(
$items['libraries-test-module/versions-and-variants'] = $base + array(
'title' => 'Test concurrent version and variant loading',
'page arguments' => array('example_versions_and_variants', 'example_variant_2'),
);
$items['libraries_test/cache'] = $base + array(
$items['libraries-test-module/cache'] = $base + array(
'title' => 'Test caching of library information',
'page arguments' => array('example_callback'),
);
@@ -523,7 +570,7 @@ function libraries_test_menu() {
* JavaScript and CSS files for easier debugging. See example/README.txt for
* more information.
*/
function _libraries_test_load($library, $variant = NULL) {
function _libraries_test_module_load($library, $variant = NULL) {
libraries_load($library, $variant);
// JavaScript and CSS files can be checked directly by SimpleTest, so we only
// need to manually check for PHP files.
@@ -532,14 +579,14 @@ function _libraries_test_load($library, $variant = NULL) {
// For easer debugging of JS loading, a text is shown that the JavaScript will
// replace.
$output .= '<h2>JavaScript</h2>';
$output .= '<div class="libraries-test-javascript">';
$output .= '<div class="libraries-test-module-js">';
$output .= 'If this text shows up, no JavaScript test file was loaded.';
$output .= '</div>';
// For easier debugging of CSS loading, the loaded CSS files will color the
// following text.
$output .= '<h2>CSS</h2>';
$output .= '<div class="libraries-test-css">';
$output .= '<div class="libraries-test-module-css">';
$output .= 'If one of the CSS test files has been loaded, this text will be colored:';
$output .= '<ul>';
// Do not reference the actual CSS files (i.e. including '.css'), because that
@@ -548,17 +595,18 @@ function _libraries_test_load($library, $variant = NULL) {
$output .= '<li>example_2: green</li>';
$output .= '<li>example_3: orange</li>';
$output .= '<li>example_4: blue</li>';
$output .= '<li>libraries_test: purple</li>';
$output .= '<li>libraries_test_module: purple</li>';
$output .= '<li>libraries_test_theme: turquoise</li>';
$output .= '</ul>';
$output .= '</div>';
$output .= '<h2>PHP</h2>';
$output .= '<div class="libraries-test-php">';
$output .= '<div class="libraries-test-module-php">';
$output .= 'The following is a list of all loaded test PHP files:';
$output .= '<ul>';
$files = get_included_files();
foreach ($files as $file) {
if (strpos($file, 'libraries/test') && !strpos($file, 'libraries_test.module')) {
if (strpos($file, 'libraries/test') && !strpos($file, 'libraries_test_module.module') && !strpos($file, 'template.php')) {
$output .= '<li>' . str_replace(DRUPAL_ROOT . '/', '', $file) . '</li>';
}
}
@@ -567,3 +615,12 @@ function _libraries_test_load($library, $variant = NULL) {
return $output;
}
/**
* Implements hook_system_theme_info().
*/
function libraries_test_module_system_theme_info() {
$themes = array();
$themes['libraries_test_theme'] = drupal_get_path('module', 'libraries') . '/tests/themes/libraries_test_theme/libraries_test_theme.info';
return $themes;
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* @file
* Test PHP file for Libraries loading.
/**
* Dummy function to see if this file was loaded.
*/
function _libraries_test_module_integration_file_post_load() {
}
// Call a function that is defined in the library file, to ensure that was
// loaded prior to this file.
_libraries_test_module_example_1();

View File

@@ -0,0 +1,12 @@
/**
* @file
* Test CSS file for Libraries loading.
*
* Color the 'libraries-test-module-css' div purple. See README.txt for more
* information.
*/
.libraries-test-module-css {
color: turquoise;
}

View File

@@ -3,10 +3,9 @@
/**
* @file
* Test PHP file for Libraries loading.
*/
/**
* Dummy function to see if this file was loaded.
*/
function _libraries_test_example_2() {
function _libraries_test_theme_integration_file() {
}

View File

@@ -0,0 +1,11 @@
name = Libraries test theme
description = Tests that themes can provide and alter library information.
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2014-02-09
version = "7.x-2.2"
core = "7.x"
project = "libraries"
datestamp = "1391965716"

View File

@@ -0,0 +1,18 @@
/**
* @file
* Test JavaScript file for Libraries loading.
*
* Replace the text in the 'libraries-test-module-js' div. See README.txt for
* more information.
*/
(function ($) {
Drupal.behaviors.librariesTest = {
attach: function(context, settings) {
$('.libraries-test-module-js').text('If this text shows up, libraries_test_theme.js was loaded successfully.')
}
};
})(jQuery);

View File

@@ -0,0 +1,36 @@
<?php
/**
* @file
* Libraries test theme.
*/
/**
* Implements hook_libraries_info().
*/
function libraries_test_theme_libraries_info() {
$libraries['example_theme'] = array(
'name' => 'Example theme',
'theme_altered' => FALSE,
);
$libraries['example_theme_integration_files'] = array(
'name' => 'Example theme integration file',
'library path' => drupal_get_path('module', 'libraries') . '/tests/libraries/example',
'version' => '1',
'integration files' => array(
'libraries_test_theme' => array(
'js' => array('libraries_test_theme.js'),
'css' => array('libraries_test_theme.css'),
'php' => array('libraries_test_theme.inc'),
),
),
);
return $libraries;
}
/**
* Implements hook_libraries_info_alter().
*/
function libraries_test_theme_libraries_info_alter(&$libraries) {
$libraries['example_theme']['theme_altered'] = TRUE;
}

View File

@@ -98,6 +98,33 @@ Statistics:
You can view the recorded performance statistics (summary and details) at
/admin/reports/performance-logging
Custom detailed logging implementation
--------------------------------------
As mentioned before, detailed logging is NOT recommended on production environ-
ments. If you, for whatever reason, DO wish detailed logging on production, you
should create a custom detailed logging mechanism that will NOT interfere with
your live site. You can do this by creating your own versions of the following
functions:
- performance_log_details($params)
=> function that is called to store the performance data
- performance_view_details()
=> function that is called to view the stored detail log. This function is
called from hook_menu() and should return content that Drupal can render
as a page.
- performance_clear_details()
=> function that is called to delete the entire detail log
Have a look at includes/performance.details.inc for more details about these
functions.
When you have created those functions, add the location of the file containing
your custom implementation to settings.php like so:
$conf['performance_detail_logging'] = './sites/all/path/to/your/file';
NOTE: there is NO drush support for your custom detail logging implementation!
Drush support
-------------
Drush support has been integrated as well. You can check the summary and detail

View File

@@ -0,0 +1,137 @@
<?php
/**
* @file
* Performance module detail logging related functions. Can be overridden by
* adding $conf['performance_detail_logging'] = 'path/to/your/file' in
* settings.php.
*/
/**
* Helper function to store detailed data in database.
* @param $params
* an array containing the following keys: mem, timer, query_count, query_timer
* anon, path, language, data.
* @return void
*/
function performance_log_details($params) {
$fields = array(
'timestamp' => REQUEST_TIME,
'bytes' => $params['mem'],
'ms' => (int)$params['timer'],
'query_count' => $params['query_count'],
'query_timer' => (int)$params['query_timer'],
'anon' => $params['anon'],
'path' => $params['path'],
'language' => $params['language'],
'data' => $params['data'],
);
try {
db_insert('performance_detail')
->fields($fields)
->execute();
}
catch (Exception $e) {
watchdog_exception('performance', $e, NULL, array(), WATCHDOG_ERROR);
}
}
/**
* Detail page callback.
* @return array
* Drupal render array.
*/
function performance_view_details() {
drupal_set_title(t('Performance logs: Details'));
$header = array(
array('data' => t('#'), 'field' => 'pid', 'sort' => 'desc'),
array('data' => t('Path'), 'field' => 'path'),
array('data' => t('Date'), 'field' => 'timestamp'),
array('data' => t('Memory (MB)'), 'field' => 'bytes'),
array('data' => t('ms (Total)'), 'field' => 'ms'),
array('data' => t('Language'), 'field' => 'language'),
array('data' => t('Anonymous?'), 'field' => 'anon'),
);
if (variable_get(PERFORMANCE_QUERY_VAR, 0)) {
$header[] = array('data' => t('# Queries'), 'field' => 'query_count');
$header[] = array('data' => t('Query ms'), 'field' => 'query_timer');
}
$pager_height = 50;
$result = db_select('performance_detail', 'p')
->fields('p')
->extend('PagerDefault')
->limit($pager_height)
->extend('TableSort')
->orderByHeader($header)
->execute();
$rows = array();
foreach ($result as $data) {
$row_data = array();
$row_data[] = $data->pid;
$row_data[] = l($data->path, $data->path);
$row_data[] = format_date($data->timestamp, 'small');
$row_data[] = number_format($data->bytes / 1024 / 1024, 2);
$row_data[] = $data->ms;
$row_data[] = $data->language;
$row_data[] = ($data->anon) ? t('Yes') : t('No');
if (variable_get(PERFORMANCE_QUERY_VAR, 0)) {
$row_data[] = $data->query_count;
$row_data[] = $data->query_timer;
}
$rows[] = array('data' => $row_data);
}
if (empty($rows) && !variable_get('performance_detail', 0)) {
return array(
'content' => array(
'#markup' => t('Detail performance log is not enabled. Go to the !link to enable it.', array('!link' => l(t('settings page'), PERFORMANCE_SETTINGS, array('query' => drupal_get_destination()))))
),
);
}
elseif (!variable_get('performance_detail', 0)) {
drupal_set_message(t('Detail performance log is not enabled! Showing stored logs.'), 'warning');
}
// Return a renderable array.
return array(
'query_data_detail' => array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#sticky' => TRUE,
'#empty' => t('No log messages available.'),
),
'clear' => array(
'#markup' => l(t('Clear logs'), 'admin/reports/performance-logging/clear/details'),
),
'pager' => array(
'#theme' => 'pager',
'#quantity' => $pager_height,
),
);
}
/**
* Helper function to clear the detail logs.
* @return void
*/
function performance_clear_details() {
db_truncate('performance_detail')->execute();
}
/**
* Helper function to prune detail log on cron.
* @return void
*/
function performance_prune_details() {
db_delete('performance_detail')
->condition('timestamp', REQUEST_TIME - (24 * 60 * 60), '<=')
->execute();
}

View File

@@ -6,9 +6,9 @@ configure = admin/config/development/performance-logging
tags[] = developer
tags[] = monitoring
; Information added by drupal.org packaging script on 2013-01-12
version = "7.x-2.0-beta1"
; Information added by packaging script on 2013-11-09
version = "7.x-2.0"
core = "7.x"
project = "performance"
datestamp = "1358019516"
datestamp = "1384025307"

View File

@@ -23,6 +23,8 @@ define('PERFORMANCE_CACHE', 'cache_default_class');
define('PERFORMANCE_SETTINGS', 'admin/config/development/performance-logging');
include_once variable_get('performance_detail_logging', 'includes/performance.details.inc');
/**
* Implements hook_menu().
*/
@@ -101,9 +103,9 @@ function performance_cron() {
performance_traverse_cache('performance_cron_prune');
// Remove performance_detail rows on a daily basis.
db_delete('performance_detail')
->condition('timestamp', REQUEST_TIME - (24 * 60 * 60), '<=')
->execute();
if (variable_get('performance_detail', 0)) {
performance_prune_details();
}
}
/**
@@ -345,7 +347,7 @@ function performance_log_summary($params) {
}
// Keep records for 1 day.
$expire = $result['last_access'] + (24 * 60 * 60);
$expire = $result['data']['last_access'] + (24 * 60 * 60);
cache_set($key, $result['data'], PERFORMANCE_BIN, $expire);
}
@@ -481,32 +483,6 @@ function performance_get_summary($cache, $timestamp) {
return;
}
/**
* Helper function to store detailed data in database.
*/
function performance_log_details($params = array()) {
$fields = array(
'timestamp' => REQUEST_TIME,
'bytes' => $params['mem'],
'ms' => (int)$params['timer'],
'query_count' => $params['query_count'],
'query_timer' => (int)$params['query_timer'],
'anon' => $params['anon'],
'path' => $params['path'],
'language' => $params['language'],
'data' => $params['data'],
);
try {
db_insert('performance_detail')
->fields($fields)
->execute();
}
catch (Exception $e) {
watchdog_exception('performance', $e, NULL, array(), WATCHDOG_ERROR);
}
}
/**
* Summary page callback.
*/
@@ -688,85 +664,6 @@ function performance_sort_summary($data, $direction, $field) {
return $data;
}
/**
* Detail page callback.
*/
function performance_view_details() {
drupal_set_title(t('Performance logs: Details'));
$header = array(
array('data' => t('#'), 'field' => 'pid', 'sort' => 'desc'),
array('data' => t('Path'), 'field' => 'path'),
array('data' => t('Date'), 'field' => 'timestamp'),
array('data' => t('Memory (MB)'), 'field' => 'bytes'),
array('data' => t('ms (Total)'), 'field' => 'ms'),
array('data' => t('Language'), 'field' => 'language'),
array('data' => t('Anonymous?'), 'field' => 'anon'),
);
if (variable_get(PERFORMANCE_QUERY_VAR, 0)) {
$header[] = array('data' => t('# Queries'), 'field' => 'query_count');
$header[] = array('data' => t('Query ms'), 'field' => 'query_timer');
}
$pager_height = 50;
$result = db_select('performance_detail', 'p')
->fields('p')
->extend('PagerDefault')
->limit($pager_height)
->extend('TableSort')
->orderByHeader($header)
->execute();
$rows = array();
foreach ($result as $data) {
$row_data = array();
$row_data[] = $data->pid;
$row_data[] = l($data->path, $data->path);
$row_data[] = format_date($data->timestamp, 'small');
$row_data[] = number_format($data->bytes / 1024 / 1024, 2);
$row_data[] = $data->ms;
$row_data[] = $data->language;
$row_data[] = ($data->anon) ? t('Yes') : t('No');
if (variable_get(PERFORMANCE_QUERY_VAR, 0)) {
$row_data[] = $data->query_count;
$row_data[] = $data->query_timer;
}
$rows[] = array('data' => $row_data);
}
if (empty($rows) && !variable_get('performance_detail', 0)) {
return array(
'content' => array(
'#markup' => t('Detail performance log is not enabled. Go to the !link to enable it.', array('!link' => l(t('settings page'), PERFORMANCE_SETTINGS, array('query' => drupal_get_destination()))))
),
);
}
elseif (!variable_get('performance_detail', 0)) {
drupal_set_message(t('Detail performance log is not enabled! Showing stored logs.'), 'warning');
}
// Return a renderable array.
return array(
'query_data_detail' => array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#sticky' => TRUE,
'#empty' => t('No log messages available.'),
),
'clear' => array(
'#markup' => l(t('Clear logs'), 'admin/reports/performance-logging/clear/details'),
),
'pager' => array(
'#theme' => 'pager',
'#quantity' => $pager_height,
),
);
}
/**
* Clear logs form.
*/
@@ -812,7 +709,7 @@ function performance_clear_form_submit($form, &$form_state) {
cache_clear_all('*', PERFORMANCE_BIN, TRUE);
break;
case 'details':
db_truncate('performance_detail')->execute();
performance_clear_details();
break;
}