Drupal: update cTools module

This commit is contained in:
Robert 2020-10-29 11:22:27 +01:00
parent 6297e231bd
commit b73aa3bef0
21 changed files with 1336 additions and 485 deletions

View File

@ -0,0 +1,78 @@
CONTENTS OF THIS FILE
---------------------
* Introduction
* Requirements
* Recommended Modules
* Installation
* Configuration
INTRODUCTION
------------
The Chaos tool suite (ctools) module is primarily a set of APIs and tools to
improve the developer experience. It also contains a module called the Page
Manager whose job is to manage pages. In particular it manages panel pages, but
as it grows it will be able to manage far more than just Panels.
The Chaos Tool Suite (ctools) is a series of tools that makes code readily
available for developers and creates libraries for other modules to use. Modules
that use ctools include Views and Panels.
End users will use ctools as underlying user interface libraries when operating
Views and Panels modules and will not need to explore further (ctools is geared
more toward developer usage). Developers will use the module differently and
work more with the tools provided.
For the moment, it includes the following tools:
* Plugins -- tools to make it easy for modules to let other modules implement
plugins from .inc files.
* Exportables -- tools to make it easier for modules to have objects that live
in database or live in code, such as 'default views'.
* AJAX responder -- tools to make it easier for the server to handle AJAX
requests and tell the client what to do with them.
* Form tools -- tools to make it easier for forms to deal with AJAX.
* Object caching -- tool to make it easier to edit an object across multiple
page requests and cache the editing work.
* Contexts -- the notion of wrapping objects in a unified wrapper and providing
an API to create and accept these contexts as input.
* Modal dialog -- tool to make it simple to put a form in a modal dialog.
* Dependent -- a simple form widget to make form items appear and disappear
based upon the selections in another item.
* Content -- pluggable content types used as panes in Panels and other modules
like Dashboard.
* Form wizard -- an API to make multi-step forms much easier.
* CSS tools -- tools to cache and sanitize CSS easily to make user-input CSS
safe.
* For a full description of the module visit:
https://www.drupal.org/project/ctools
* To submit bug reports and feature suggestions, or to track changes visit:
https://www.drupal.org/project/issues/ctools
REQUIREMENTS
------------
This module requires no modules outside of Drupal core.
RECOMMENDED MODULES
-------------------
The Advanced help module provides extended documentation. Once enabled,
navigate to Administration > Advanced Help and select the Chaos tools link to
view documentation.
* Advanced help - https://www.drupal.org/project/advanced_help
INSTALLATION
------------
* Install the Chaos tool suite module as you would normally install a
contributed Drupal module. Visit https://www.drupal.org/node/895232 for
further information.

View File

@ -5,7 +5,7 @@ dependencies[] = ctools
package = Chaos tool suite
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"

View File

@ -30,6 +30,8 @@ function hook_ctools_plugin_type() {
}
/**
* Tells CTools where to find module-defined plugins.
*
* This hook is used to inform the CTools plugin system about the location of a
* directory that should be searched for files containing plugins of a
* particular type. CTools invokes this same hook for all plugins, using the
@ -104,12 +106,12 @@ function hook_ctools_plugin_directory($owner, $plugin_type) {
* This hook is useful for altering flags or other information that will be
* used or possibly overriden by the process hook if defined.
*
* @param $plugin
* @param array $plugin
* An associative array defining a plugin.
* @param $info
* @param array $info
* An associative array of plugin type info.
*/
function hook_ctools_plugin_pre_alter(&$plugin, &$info) {
function hook_ctools_plugin_pre_alter(array &$plugin, array &$info) {
// Override a function defined by the plugin.
if ($info['type'] == 'my_type') {
$plugin['my_flag'] = 'new_value';
@ -122,12 +124,12 @@ function hook_ctools_plugin_pre_alter(&$plugin, &$info) {
* This hook is useful for overriding the final values for a plugin after it
* has been processed.
*
* @param $plugin
* @param array $plugin
* An associative array defining a plugin.
* @param $info
* @param array $info
* An associative array of plugin type info.
*/
function hook_ctools_plugin_post_alter(&$plugin, &$info) {
function hook_ctools_plugin_post_alter(array &$plugin, array &$info) {
// Override a function defined by the plugin.
if ($info['type'] == 'my_type') {
$plugin['my_function'] = 'new_function';
@ -144,38 +146,63 @@ function hook_ctools_plugin_post_alter(&$plugin, &$info) {
* An array of informations about the implementors of a certain api.
* The key of this array are the module names/theme names.
*/
function hook_ctools_api_hook_alter(&$list) {
function hook_ctools_api_hook_alter(array &$list) {
// Alter the path of the node implementation.
$list['node']['path'] = drupal_get_path('module', 'node');
}
/**
* Alter the available functions to be used in ctools math expression api.
*
* One use case would be to create your own function in your module and
* allow to use it in the math expression api.
*
* @param array $functions
* An array which has the functions as value.
* @param array $context
* An array containing an item 'final' whose value is a reference to the
* definitions for multiple-arg functions. Use this to add in functions that
* require more than one arg.
*/
function hook_ctools_math_expression_functions_alter(array &$functions, array $context) {
// Allow to convert from degrees to radians.
$functions[] = 'deg2rad';
$multiarg = $context['final'];
$multiarg['pow'] = array(
'function' => 'pow',
'arguments' => 2,
);
}
/**
* Alter the available functions to be used in ctools math expression api.
*
* One usecase would be to create your own function in your module and
* allow to use it in the math expression api.
*
* @param $functions
* An array which has the functions as value.
* @param array $constants
* An array of name:value pairs, one for each named constant. Values added
* to this array become read-only variables with the value assigned here.
*/
function hook_ctools_math_expression_functions_alter(&$functions) {
// Allow to convert from degrees to radiant.
$functions[] = 'deg2rad';
function hook_ctools_math_expression_constants_alter(array &$constants) {
// Add the speed of light as constant 'c':
$constants['c'] = 299792458;
}
/**
* Alter everything.
*
* @param $info
* @param array $info
* An associative array containing the following keys:
* - content: The rendered content.
* - title: The content's title.
* - no_blocks: A boolean to decide if blocks should be displayed.
* @param $page
* @param bool $page
* If TRUE then this renderer owns the page and can use theme('page')
* for no blocks; if false, output is returned regardless of any no
* blocks settings.
* @param $context
* @param array $context
* An associative array containing the following keys:
* - args: The raw arguments behind the contexts.
* - contexts: The context objects in use.
@ -183,7 +210,7 @@ function hook_ctools_math_expression_functions_alter(&$functions) {
* - subtask: The subtask object in use.
* - handler: The handler object in use.
*/
function hook_ctools_render_alter(&$info, &$page, &$context) {
function hook_ctools_render_alter(array &$info, &$page, array &$context) {
if ($context['handler']->name == 'my_handler') {
ctools_add_css('my_module.theme', 'my_module');
}
@ -219,7 +246,7 @@ function hook_ctools_content_subtype_alter($subtype, $plugin) {
* @param string $plugin_id
* The plugin ID, in the format NAME:KEY.
*/
function hook_ctools_entity_context_alter(&$plugin, &$entity, $plugin_id) {
function hook_ctools_entity_context_alter(array &$plugin, array &$entity, $plugin_id) {
ctools_include('context');
switch ($plugin_id) {
case 'entity_id:taxonomy_term':
@ -242,13 +269,13 @@ function hook_ctools_entity_context_alter(&$plugin, &$entity, $plugin_id) {
* A string associated with the plugin type, identifying the operation.
* @param string $value
* The value being converted; this is the only return from the function.
* @param $converter_options
* @param array $converter_options
* Array of key-value pairs to pass to a converter function from higher
* levels.
*
* @see ctools_context_convert_context()
*/
function hook_ctools_context_converter_alter($context, $converter, &$value, $converter_options) {
function hook_ctools_context_converter_alter(ctools_context $context, $converter, &$value, array $converter_options) {
if ($converter === 'mystring') {
$value = 'fixed';
}
@ -262,7 +289,7 @@ function hook_ctools_context_converter_alter($context, $converter, &$value, $con
*
* @see hook_ctools_entity_context_alter()
*/
function hook_ctools_entity_contexts_alter(&$plugins) {
function hook_ctools_entity_contexts_alter(array &$plugins) {
$plugins['entity_id:taxonomy_term']['no ui'] = TRUE;
}
@ -274,7 +301,7 @@ function hook_ctools_entity_contexts_alter(&$plugins) {
*
* @see ctools_cleanstring()
*/
function hook_ctools_cleanstring_alter(&$settings) {
function hook_ctools_cleanstring_alter(array &$settings) {
// Convert all strings to lower case.
$settings['lower case'] = TRUE;
}
@ -287,7 +314,7 @@ function hook_ctools_cleanstring_alter(&$settings) {
*
* @see ctools_cleanstring()
*/
function hook_ctools_cleanstring_CLEAN_ID_alter(&$settings) {
function hook_ctools_cleanstring_CLEAN_ID_alter(array &$settings) {
// Convert all strings to lower case.
$settings['lower case'] = TRUE;
}
@ -304,7 +331,7 @@ function hook_ctools_cleanstring_CLEAN_ID_alter(&$settings) {
*
* @see ctools_context_handler_pre_render()
*/
function ctools_context_handler_pre_render($handler, $contexts, $args) {
function ctools_context_handler_pre_render($handler, array $contexts, array $args) {
$handler->conf['css_id'] = 'my-id';
}

View File

@ -20,7 +20,7 @@ files[] = tests/object_cache_unit.test
files[] = tests/page_tokens.test
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"

View File

@ -5,7 +5,7 @@ package = Chaos tool suite
dependencies[] = ctools
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"

View File

@ -5,7 +5,7 @@ dependencies[] = ctools
core = 7.x
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"

View File

@ -5,7 +5,7 @@ package = Chaos tool suite
dependencies[] = ctools
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"

View File

@ -8,7 +8,7 @@ dependencies[] = advanced_help
core = 7.x
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"

File diff suppressed because it is too large Load Diff

View File

@ -98,29 +98,30 @@
};
// Hide these in a ready to ensure that Drupal.ajax is set up first.
$(function() {
Drupal.ajax.prototype.commands.attr = function(ajax, data, status) {
$(data.selector).attr(data.name, data.value);
};
Drupal.behaviors.ctools_add_ajax_responder_commands = {
attach: function () {
Drupal.ajax.prototype.commands.attr = function (ajax, data, status) {
$(data.selector).attr(data.name, data.value);
};
Drupal.ajax.prototype.commands.redirect = function(ajax, data, status) {
if (data.delay > 0) {
setTimeout(function () {
Drupal.ajax.prototype.commands.redirect = function (ajax, data, status) {
if (data.delay > 0) {
setTimeout(function () {
location.href = data.url;
}, data.delay);
}
else {
location.href = data.url;
}, data.delay);
}
else {
location.href = data.url;
}
};
}
};
Drupal.ajax.prototype.commands.reload = function(ajax, data, status) {
location.reload();
};
Drupal.ajax.prototype.commands.reload = function (ajax, data, status) {
location.reload();
};
Drupal.ajax.prototype.commands.submit = function(ajax, data, status) {
$(data.selector).submit();
Drupal.ajax.prototype.commands.submit = function (ajax, data, status) {
$(data.selector).submit();
}
}
});
};
})(jQuery);

View File

@ -299,6 +299,7 @@
// content. This is helpful for allowing users to see error messages at the
// top of a form, etc.
$('#modal-content').html(response.output).scrollTop(0);
$(document).trigger('CToolsAttachBehaviors', $('#modalContent'));
// Attach behaviors within a modal dialog.
var settings = response.settings || ajax.settings || Drupal.settings;

View File

@ -5,7 +5,7 @@
Drupal.CTools.Stylizer.addFarbtastic = function(context) {
// This behavior attaches by ID, so is only valid once on a page.
if ($('#ctools_stylizer_color_scheme_form .color-form.Stylizer-processed').length)) {
if ($('#ctools_stylizer_color_scheme_form .color-form.Stylizer-processed').length) {
return;
}

View File

@ -7,7 +7,7 @@ package = Chaos tool suite
files[] = tests/head_links.test
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"

View File

@ -95,13 +95,28 @@ function page_manager_node_edit($node) {
ctools_include('context-task-handler');
$contexts = ctools_context_handler_get_task_contexts($task, '', array($node));
// Set the default title for the node add/edit form. If the page has a custom
// title it'll override this.
$types = node_type_get_types();
$context = reset($contexts);
if (empty($context->data->nid)) {
drupal_set_title(t('Create @name', array(
'@name' => $types[$context->data->type]->name
)), PASS_THROUGH);
}
else {
drupal_set_title(t('<em>Edit @type</em> @title', array(
'@type' => $types[$context->node_type]->name,
'@title' => $context->data->title
)), PASS_THROUGH);
}
$arg = array(isset($node->nid) ? $node->nid : $node->type);
$output = ctools_context_handler_render($task, '', $contexts, $arg);
if ($output === FALSE) {
// Fall back!
// We've already built the form with the context, so we can't build it again, or
// form_clean_id will mess up our ids. But we don't really need to, either:
$context = reset($contexts);
$output = $context->form;
}

View File

@ -38,7 +38,7 @@ function ctools_term_has_parent_ctools_access_settings($form, &$form_state, $con
'#title' => t('Vocabulary'),
'#type' => 'select',
'#options' => array(),
'#description' => t('Select the vocabulary for this form.'),
'#description' => t('Select the vocabulary your parent term belongs to.'),
'#id' => 'ctools-select-vid',
'#default_value' => $conf['vid'],
'#required' => TRUE,
@ -57,7 +57,7 @@ function ctools_term_has_parent_ctools_access_settings($form, &$form_state, $con
$options[$vid] = $vocabulary->name;
$form['settings']['vid_' . $vid] = array(
'#title' => t('Terms'),
'#description' => t('Select a term or terms from @vocabulary.', array('@vocabulary' => $vocabulary->name)),
'#description' => t('Select a parent term (or terms) from the @vocabulary vocabulary.', array('@vocabulary' => $vocabulary->name)),
'#dependency' => array('ctools-select-vid' => array($vocabulary->vid)),
'#default_value' => !empty($conf['vid_' . $vid]) ? $conf['vid_' . $vid] : '',
'#size' => 10,
@ -77,8 +77,8 @@ function ctools_term_has_parent_ctools_access_settings($form, &$form_state, $con
}
$form['settings']['vid']['#options'] = $options;
$form['settings']['include_self'] = array(
'#title' => t('Include these term(s) as candidates?'),
'#description' => t('When this rule is evaluated, should the term(s) you select be included as candidates for access?'),
'#title' => t('Include these parent term(s)?'),
'#description' => t('Should the term(s) you selected above be included in addition to their children?'),
'#default_value' => !empty($conf['include_self']) ? $conf['include_self'] : FALSE,
'#type' => 'checkbox',
);

View File

@ -6,7 +6,7 @@ dependencies[] = ctools
dependencies[] = color
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"

View File

@ -5,7 +5,7 @@ dependencies[] = ctools
package = Chaos tool suite
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"

View File

@ -8,7 +8,7 @@ hidden = TRUE
files[] = ctools_export.test
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"

View File

@ -6,7 +6,7 @@ dependencies[] = ctools
hidden = TRUE
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"

View File

@ -27,121 +27,308 @@ class CtoolsMathExpressionTestCase extends DrupalWebTestCase {
}
/**
* Returns a random double between 0 and 1.
* Return the sign of the numeric arg $n as an integer -1, 0, 1.
*
* Note: Not defined when $n is Infinity or NaN (or NULL or ...)!
*
* @param int|float $n
* The number to test.
*
* @return int
* -1 if the $n is negative, 0 if $n is zero or 1 if $n is positive.
*
* @see gmp_sign()
*/
protected static function sign($n) {
return ($n > 0) - ($n < 0);
}
/**
* Returns a random number between 0 and 1.
*
* @return float
* A random number between 0 and 1 inclusive.
*/
protected function rand01() {
return rand(0, PHP_INT_MAX) / PHP_INT_MAX;
return mt_rand(0, PHP_INT_MAX) / PHP_INT_MAX;
}
/**
* A custom assertion with checks the values in a certain range.
*
* @param float $first
* A value to check for equality.
* @param float $second
* A value to check for equality.
* @param string $message
* The message describing the correct behaviour, eg. "2/4 equals 1/2". The
* default message is used if this value is empty.
* @param float $delta
* The precision with which values must match. This accounts for rounding
* errors and imprecise representation errors in the floating point format.
* The value passed in should ideally be proportional to the values being
* compared.
* @param string $group
* Which group this assert belongs to.
*
* @return bool
* TRUE if the assertion was correct (that is, $first == $second within the
* given limits), FALSE otherwise.
*/
protected function assertFloat($first, $second, $delta = 0.0000001, $message = '', $group = 'Other') {
return $this->assert(abs($first - $second) <= $delta, $message ? $message : t('Value @first is equal to value @second.', array('@first' => var_export($first, TRUE), '@second' => var_export($second, TRUE))), $group);
protected function assertFloat($first, $second, $message = '', $delta = 0.00000001, $group = 'Other') {
// Check for NaN and Inf because the abs() and sign() code won't like those.
$equal = FALSE
// Equal if both an infinity.
|| (is_infinite($first) && is_infinite($second))
// Equal if both NaN.
|| (is_nan($first) && is_nan($second))
// Equal if same absolute value (within limits) and same sign.
|| ((abs($first - $second) <= $delta) && (self::sign($first) === self::sign($second)));
if (empty($message)) {
$default = t('Value !first is equal to value !second.',
array(
'!first' => var_export($first, TRUE),
'!second' => var_export($second, TRUE),
));
$message = $default;
}
return $this->assert($equal, $message, $group);
}
/**
* Test some arithmetic handling.
*/
public function testArithmetic() {
$math_expression = new ctools_math_expr();
$math_expr = new ctools_math_expr();
// Test constant expressions.
$this->assertEqual($math_expression->e('2'), 2);
$random_number = rand(0, 10);
$this->assertEqual($random_number, $math_expression->e((string) $random_number));
$this->assertEqual($math_expr->evaluate('2'), 2, 'Check Literal 2');
// Test simple arithmetic.
$random_number_a = rand(5, 10);
$random_number_b = rand(5, 10);
$this->assertEqual($random_number_a + $random_number_b, $math_expression->e("$random_number_a + $random_number_b"));
$this->assertEqual($random_number_a - $random_number_b, $math_expression->e("$random_number_a - $random_number_b"));
$this->assertEqual($random_number_a * $random_number_b, $math_expression->e("$random_number_a * $random_number_b"));
$this->assertEqual($random_number_a / $random_number_b, $math_expression->e("$random_number_a / $random_number_b"));
$this->assertEqual($math_expr->e('2+1'), $math_expr->evaluate('2+1'), 'Check that e() and evaluate() are equivalent.');
// Test Associative property.
$random_number_c = rand(5, 10);
$this->assertEqual($math_expression->e("$random_number_a + ($random_number_b + $random_number_c)"), $math_expression->e("($random_number_a + $random_number_b) + $random_number_c"));
$this->assertEqual($math_expression->e("$random_number_a * ($random_number_b * $random_number_c)"), $math_expression->e("($random_number_a * $random_number_b) * $random_number_c"));
foreach (range(1, 4) as $n) {
// Test constant expressions.
$random_number = mt_rand(0, 20);
$this->assertEqual($random_number, $math_expr->evaluate((string) $random_number), "Literal $random_number");
// Test Commutative property.
$this->assertEqual($math_expression->e("$random_number_a + $random_number_b"), $math_expression->e("$random_number_b + $random_number_a"));
$this->assertEqual($math_expression->e("$random_number_a * $random_number_b"), $math_expression->e("$random_number_b * $random_number_a"));
// Test simple arithmetic.
$number_a = mt_rand(-55, 777);
$number_b = mt_rand(-555, 77);
$this->assertEqual(
$number_a + $number_b,
$math_expr->evaluate("$number_a + $number_b"),
"Addition: $number_a + $number_b");
$this->assertEqual(
$number_a - $number_b,
$math_expr->evaluate("$number_a - $number_b"),
"Subtraction: $number_a + $number_b");
$this->assertFloat(
($number_a * $number_b),
$math_expr->evaluate("$number_a * $number_b"),
"Multiplication: $number_a * $number_b = " . ($number_a * $number_b));
$this->assertFloat(
($number_a / $number_b),
$math_expr->evaluate("$number_a / $number_b"),
"Division: $number_a / $number_b = " . ($number_a / $number_b));
// Test Distributive property.
$this->assertEqual($math_expression->e("($random_number_a + $random_number_b) * $random_number_c"), $math_expression->e("($random_number_a * $random_number_c + $random_number_b * $random_number_c)"));
// Test Associative property.
$number_c = mt_rand(-99, 77);
$this->assertEqual(
$math_expr->evaluate("$number_a + ($number_b + $number_c)"),
$math_expr->evaluate("($number_a + $number_b) + $number_c"),
"Associative: $number_a + ($number_b + $number_c)");
$this->assertEqual(
$math_expr->evaluate("$number_a * ($number_b * $number_c)"),
$math_expr->evaluate("($number_a * $number_b) * $number_c"),
"Associative: $number_a * ($number_b * $number_c)");
$this->assertEqual(pow($random_number_a, $random_number_b), $math_expression->e("$random_number_a ^ $random_number_b"));
// Test Commutative property.
$this->assertEqual(
$math_expr->evaluate("$number_a + $number_b"),
$math_expr->evaluate("$number_b + $number_a"),
"Commutative: $number_a + $number_b");
$this->assertEqual(
$math_expr->evaluate("$number_a * $number_b"),
$math_expr->evaluate("$number_b * $number_a"),
"Commutative: $number_a * $number_b");
// Test Distributive property.
$this->assertEqual(
$math_expr->evaluate("($number_a + $number_b) * $number_c"),
$math_expr->evaluate("($number_a * $number_c + $number_b * $number_c)"),
"Distributive: ($number_a + $number_b) * $number_c");
// @todo: Doesn't work with zero or negative powers when number is zero or negative, e.g. 0^0, 0^-2, -2^0, -2^-2.
$random_number = mt_rand(1, 15);
$random_power = mt_rand(-15, 15);
$this->assertFloat(
pow($random_number, $random_power),
$math_expr->evaluate("$random_number ^ $random_power"),
"$random_number ^ $random_power");
$this->assertFloat(
pow($random_number, $random_power),
$math_expr->evaluate("pow($random_number, $random_power)"),
"pow($random_number, $random_power)");
}
}
/**
* Test the basic built-in functions in the math expression library.
* Test various built-in transcendental and extended functions.
*/
public function testBuildInFunctions() {
$math_expression = new ctools_math_expr();
$math_expr = new ctools_math_expr();
// @todo Maybe run this code multiple times to test different values.
$random_double = $this->rand01();
$random_int = rand(5, 10);
$this->assertFloat(sin($random_double), $math_expression->e("sin($random_double)"));
$this->assertFloat(cos($random_double), $math_expression->e("cos($random_double)"));
$this->assertFloat(tan($random_double), $math_expression->e("tan($random_double)"));
$this->assertFloat(exp($random_double), $math_expression->e("exp($random_double)"));
$this->assertFloat(sqrt($random_double), $math_expression->e("sqrt($random_double)"));
$this->assertFloat(log($random_double), $math_expression->e("ln($random_double)"));
$this->assertFloat(round($random_double), $math_expression->e("round($random_double)"));
$this->assertFloat(abs($random_double + $random_int), $math_expression->e('abs(' . ($random_double + $random_int) . ')'));
$this->assertEqual(round($random_double + $random_int), $math_expression->e('round(' . ($random_double + $random_int) . ')'));
$this->assertEqual(ceil($random_double + $random_int), $math_expression->e('ceil(' . ($random_double + $random_int) . ')'));
$this->assertEqual(floor($random_double + $random_int), $math_expression->e('floor(' . ($random_double + $random_int) . ')'));
foreach (range(1, 4) as $n) {
$random_double = $this->rand01();
$random_int = mt_rand(-65535, 65535);
$this->assertFloat(sin($random_double), $math_expr->evaluate("sin($random_double)"), "sin($random_double)");
$this->assertFloat(cos($random_double), $math_expr->evaluate("cos($random_double)"), "cos($random_double)");
$this->assertFloat(tan($random_double), $math_expr->evaluate("tan($random_double)"), "tan($random_double)");
$this->assertFloat(exp($random_double), $math_expr->evaluate("exp($random_double)"), "exp($random_double)");
$this->assertFloat(sqrt($random_double), $math_expr->evaluate("sqrt($random_double)"), "sqrt($random_double)");
$this->assertFloat(log($random_double), $math_expr->evaluate("ln($random_double)"), "ln($random_double)");
$this->assertFloat(round($random_double), $math_expr->evaluate("round($random_double)"), "round($random_double)");
// @fixme: you can't run time without an argument.
$this->assertFloat(time(), $math_expression->e('time(1)'));
$random_real = $random_double + $random_int;
$this->assertFloat(abs($random_real), $math_expr->evaluate('abs(' . $random_real . ')'), "abs($random_real)");
$this->assertEqual(round($random_real), $math_expr->evaluate('round(' . $random_real . ')'), "round($random_real)");
$this->assertEqual(ceil($random_real), $math_expr->evaluate('ceil(' . $random_real . ')'), "ceil($random_real)");
$this->assertEqual(floor($random_real), $math_expr->evaluate('floor(' . $random_real . ')'), "floor($random_real)");
}
$this->assertFloat(time(), $math_expr->evaluate('time()'), "time()");
$random_double_a = $this->rand01();
$random_double_b = $this->rand01();
// @fixme: max/min don't work at the moment.
// $this->assertFloat(max($random_double_a, $random_double_b), $math_expression->e("max($random_double_a, $random_double_b)"));
// $this->assertFloat(min($random_double_a, $random_double_b), $math_expression->e("min($random_double_a, $random_double_b)"));
$this->assertFloat(
max($random_double_a, $random_double_b),
$math_expr->evaluate("max($random_double_a, $random_double_b)"),
"max($random_double_a, $random_double_b)");
$this->assertFloat(
min($random_double_a, $random_double_b),
$math_expr->evaluate("min($random_double_a, $random_double_b)"),
"min($random_double_a, $random_double_b)");
}
/**
* Test variable handling.
*/
public function testVariables() {
$math_expression = new ctools_math_expr();
$math_expr = new ctools_math_expr();
$random_number_a = rand(5, 10);
$random_number_b = rand(5, 10);
// We should have a definition of pi:
$this->assertFloat(pi(), $math_expr->evaluate('pi'));
// Store the first random number and use it on calculations.
$math_expression->e("var = $random_number_a");
$this->assertEqual($random_number_a + $random_number_b, $math_expression->e("var + $random_number_b"));
$this->assertEqual($random_number_a * $random_number_b, $math_expression->e("var * $random_number_b"));
$this->assertEqual($random_number_a - $random_number_b, $math_expression->e("var - $random_number_b"));
$this->assertEqual($random_number_a / $random_number_b, $math_expression->e("var / $random_number_b"));
// And a definition of e:
$this->assertFloat(exp(1), $math_expr->evaluate('e'));
$number_a = 5;
$number_b = 10;
// Store the first number and use it on a calculation.
$math_expr->evaluate("var = $number_a");
$this->assertEqual($number_a + $number_b, $math_expr->evaluate("var + $number_b"));
// Change the value and check the new value is used.
$math_expr->evaluate("var = $number_b");
$this->assertEqual(
$number_b + $number_b,
$math_expr->evaluate("var + $number_b"),
"var + $number_b");
// Store another number and use it on a calculation.
$math_expr->evaluate("var = $number_a");
$math_expr->evaluate("newvar = $number_a");
$this->assertEqual(
$number_a + $number_a,
$math_expr->evaluate('var + newvar'),
'var + newvar');
$this->assertFloat(
$number_a / $number_b,
$math_expr->evaluate("var / $number_b"),
"var / $number_b");
}
/**
* Test custom function handling.
*/
public function testCustomFunctions() {
$math_expression = new ctools_math_expr();
$math_expr = new ctools_math_expr();
$random_number_a = rand(5, 10);
$random_number_b = rand(5, 10);
$number_a = mt_rand(5, 10);
$number_b = mt_rand(5, 10);
// Create a one-argument function.
$math_expression->e("f(x) = 2 * x");
$this->assertEqual($random_number_a * 2, $math_expression->e("f($random_number_a)"));
$this->assertEqual($random_number_b * 2, $math_expression->e("f($random_number_b)"));
$math_expr->evaluate("f(x) = 2 * x");
$this->assertEqual($number_a * 2, $math_expr->evaluate("f($number_a)"));
$this->assertEqual($number_b * 2, $math_expr->evaluate("f($number_b)"));
// Create a two-argument function.
$math_expression->e("g(x, y) = 2 * x + y");
$this->assertEqual($random_number_a * 2 + $random_number_b, $math_expression->e("g($random_number_a, $random_number_b)"));
$math_expr->evaluate("g(x, y) = 2 * x + y");
$this->assertEqual(
$number_a * 2 + $number_b,
$math_expr->evaluate("g($number_a, $number_b)"),
"g($number_a, $number_b)");
// Use a custom function in another function.
$this->assertEqual(($random_number_a * 2 + $random_number_b) * 2, $math_expression->e("f(g($random_number_a, $random_number_b))"));
$this->assertEqual(
($number_a * 2 + $number_b) * 2,
$math_expr->evaluate("f(g($number_a, $number_b))"),
"f(g($number_a, $number_b))");
}
/**
* Test conditional handling.
*/
public function testIf() {
$math_expr = new ctools_math_expr();
$number_a = mt_rand(1, 10);
$number_b = mt_rand(11, 20);
foreach (range(1, 4) as $n) {
// @todo: Doesn't work with negative numbers.
if ($n == 2 || $n == 4) {
//$number_a = -$number_a;
}
if ($n == 3 || $n == 4) {
//$number_b = -$number_b;
}
$this->assertEqual(
$number_a,
$math_expr->evaluate("if(1, $number_a, $number_b)"),
"if(1, $number_a, $number_b)");
$this->assertEqual(
$number_a,
$math_expr->evaluate("if(1, $number_a)",
"if(1, $number_a)"));
$this->assertEqual(
$number_b,
$math_expr->evaluate("if(0, $number_a, $number_b)"),
"if(0, $number_a, $number_b)");
// Also add an expression so ensure it's evaluated.
$this->assertEqual(
$number_b,
$math_expr->evaluate("if($number_a > $number_b, $number_a, $number_b)"),
"if($number_a > $number_b, $number_a, $number_b)");
$this->assertEqual(
$number_b,
$math_expr->evaluate("if($number_a < $number_b, $number_b, $number_a)"),
"if($number_a < $number_b, $number_b, $number_a)");
}
}
}

View File

@ -10,7 +10,7 @@ files[] = plugins/views/views_content_plugin_display_panel_pane.inc
files[] = plugins/views/views_content_plugin_style_ctools_context.inc
; Information added by Drupal.org packaging script on 2020-10-23
version = "7.x-1.16"
version = "7.x-1.17"
core = "7.x"
project = "ctools"
datestamp = "1603430414"
datestamp = "1603490551"