Issue #1812866 by mkadin, effulgentsia: rebuild the server side AJAX API.

8.0.x
Dries 2012-11-16 18:05:11 -08:00
parent 1916c77a34
commit 95feb071fb
20 changed files with 1364 additions and 9 deletions

View File

@ -0,0 +1,53 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\AddCssCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\CommandInterface;
/**
* An AJAX command for adding css to the page via ajax.
*
* This command is implemented by Drupal.ajax.prototype.commands.add_css()
* defined in misc/ajax.js.
*
* @see misc/ajax.js
*/
class AddCssCommand implements CommandInterface {
/**
* A string that contains the styles to be added to the page.
*
* It should include the wrapping style tag.
*
* @var string
*/
protected $styles;
/**
* Constructs an AddCssCommand.
*
* @param string $styles
* A string that contains the styles to be added to the page, including the
* wrapping <style> tag.
*/
public function __construct($styles) {
$this->styles = $styles;
}
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'add_css',
'data' => $this->styles,
);
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\AfterCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\InsertCommand;
/**
* An AJAX command for calling the jQuery after() method.
*
* The 'insert/after' command instructs the client to use jQuery's after()
* method to insert the given HTML content after each element matched by the
* given selector.
*
* This command is implemented by Drupal.ajax.prototype.commands.insert()
* defined in misc/ajax.js.
*
* @see http://docs.jquery.com/Manipulation/after#content
*/
class AfterCommand extends InsertCommand {
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'insert',
'method' => 'after',
'selector' => $this->selector,
'data' => $this->html,
'settings' => $this->settings,
);
}
}

View File

@ -0,0 +1,131 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\AjaxResponse.
*/
namespace Drupal\Core\Ajax;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
/**
* JSON response object for AJAX requests.
*/
class AjaxResponse extends JsonResponse {
/**
* The array of ajax commands.
*
* @var array
*/
protected $commands = array();
/**
* Add an AJAX command to the response.
*
* @param object $command
* An AJAX command object implementing CommandInterface.
*
* @return AjaxResponse
* The current AjaxResponse.
*/
public function addCommand($command) {
$this->commands[] = $command->render();
return $this;
}
/**
* Sets the response's data to be the array of AJAX commands.
*
* @param
* $request A request object.
*
* @return
* Response The current response.
*/
public function prepare(Request $request) {
parent::setData($this->ajaxRender($request));
return parent::prepare($request);
}
/**
* Prepares the AJAX commands for sending back to the client.
*
* @param Request
* The request object that the AJAX is responding to.
*
* @return array
* An array of commands ready to be returned as JSON.
*/
protected function ajaxRender($request) {
// Ajax responses aren't rendered with html.tpl.php, so we have to call
// drupal_get_css() and drupal_get_js() here, in order to have new files
// added during this request to be loaded by the page. We only want to send
// back files that the page hasn't already loaded, so we implement simple
// diffing logic using array_diff_key().
foreach (array('css', 'js') as $type) {
// It is highly suspicious if $_POST['ajax_page_state'][$type] is empty,
// since the base page ought to have at least one JS file and one CSS file
// loaded. It probably indicates an error, and rather than making the page
// reload all of the files, instead we return no new files.
if (empty($request->parameters['ajax_page_state'][$type])) {
$items[$type] = array();
}
else {
$function = 'drupal_add_' . $type;
$items[$type] = $function();
drupal_alter($type, $items[$type]);
// @todo Inline CSS and JS items are indexed numerically. These can't be
// reliably diffed with array_diff_key(), since the number can change
// due to factors unrelated to the inline content, so for now, we
// strip the inline items from Ajax responses, and can add support for
// them when drupal_add_css() and drupal_add_js() are changed to using
// md5() or some other hash of the inline content.
foreach ($items[$type] as $key => $item) {
if (is_numeric($key)) {
unset($items[$type][$key]);
}
}
// Ensure that the page doesn't reload what it already has.
$items[$type] = array_diff_key($items[$type], $request->parameters['ajax_page_state'][$type]);
}
}
// Render the HTML to load these files, and add AJAX commands to insert this
// HTML in the page. We pass TRUE as the $skip_alter argument to prevent the
// data from being altered again, as we already altered it above. Settings
// are handled separately, afterwards.
if (isset($items['js']['settings'])) {
unset($items['js']['settings']);
}
$styles = drupal_get_css($items['css'], TRUE);
$scripts_footer = drupal_get_js('footer', $items['js'], TRUE);
$scripts_header = drupal_get_js('header', $items['js'], TRUE);
if (!empty($styles)) {
$this->addCommand(new AddCssCommand($styles));
}
if (!empty($scripts_header)) {
$this->addCommand(new PrependCommand('head', $scripts_header));
}
if (!empty($scripts_footer)) {
$this->addCommand(new AppendCommand('body', $scripts_footer));
}
// Now add a command to merge changes and additions to Drupal.settings.
$scripts = drupal_add_js();
if (!empty($scripts['settings'])) {
$settings = $scripts['settings'];
$this->addCommand(new SettingsCommand(call_user_func_array('array_merge_recursive', $settings['data']), TRUE));
}
$commands = $this->commands;
drupal_alter('ajax_render', $commands);
return $commands;
}
}

View File

@ -0,0 +1,45 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\AlertCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\CommandInterface;
/**
* AJAX command for a javascript alert box.
*/
class AlertCommand implements CommandInterface {
/**
* The text to be displayed in the alert box.
*
* @var string
*/
protected $text;
/**
* Constructs an AlertCommand object.
*
* @param string $text
* The text to be displayed in the alert box.
*/
public function __construct($text) {
$this->text = $text;
}
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'alert',
'text' => $this->text,
);
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\AppendCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\InsertCommand;
/**
* An AJAX command for calling the jQuery append() method.
*
* The 'insert/append' command instructs the client to use jQuery's append()
* method to append the given HTML content to the inside of each element matched
* by the given selector.
*
* This command is implemented by Drupal.ajax.prototype.commands.insert()
* defined in misc/ajax.js.
*
* @see http://docs.jquery.com/Manipulation/append#content
*/
class AppendCommand extends InsertCommand {
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'insert',
'method' => 'append',
'selector' => $this->selector,
'data' => $this->html,
'settings' => $this->settings,
);
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\InsertCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\InsertCommand;
/**
* An AJAX command for calling the jQuery before() method.
*
* The 'insert/before' command instructs the client to use jQuery's before()
* method to insert the given HTML content before each of elements matched by
* the given selector.
*
* This command is implemented by Drupal.ajax.prototype.commands.insert()
* defined in misc/ajax.js.
*
* @see http://docs.jquery.com/Manipulation/before#content
*/
class BeforeCommand extends InsertCommand {
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'insert',
'method' => 'before',
'selector' => $this->selector,
'data' => $this->html,
'settings' => $this->settings,
);
}
}

View File

@ -0,0 +1,65 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\ChangedCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\CommandInterface;
/**
* An AJAX command for marking HTML elements as changed.
*
* This command instructs the client to mark each of the elements matched by the
* given selector as 'ajax-changed'.
*
* This command is implemented by Drupal.ajax.prototype.commands.changed()
* defined in misc/ajax.js.
*/
class ChangedCommand implements CommandInterface {
/**
* A CSS selector string.
*
* If the command is a response to a request from an #ajax form element then
* this value can be NULL.
*
* @var string
*/
protected $selector;
/**
* An optional CSS selector for elements to which asterisks will be appended.
*
* @var string
*/
protected $asterisk;
/**
* Constructs a ChangedCommand object.
*
* @param string $selector
* CSS selector for elements to be marked as changed.
* @param string $asterisk
* CSS selector for elements to which an asterisk will be appended.
*/
public function __construct($selector, $asterisk = '') {
$this->selector = $selector;
$this->asterisk = $asterisk;
}
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'changed',
'selector' => $this->selector,
'asterisk' => $this->asterisk,
);
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\CommandInterface.
*/
namespace Drupal\Core\Ajax;
/**
* AJAX command interface.
*
* All AJAX commands passed to AjaxResponse objects should implement these
* methods.
*/
interface CommandInterface {
/**
* Return an array to be run through json_encode and sent to the client.
*/
public function render();
}

View File

@ -0,0 +1,80 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\CssCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\CommandInterface;
/**
* An AJAX command for calling the jQuery css() method.
*
* The 'css' command will instruct the client to use the jQuery css() method to
* apply the CSS arguments to elements matched by the given selector.
*
* This command is implemented by Drupal.ajax.prototype.commands.css() defined
* in misc/ajax.js.
*
* @see http://docs.jquery.com/CSS/css#properties
*/
class CssCommand implements CommandInterface {
/**
* A CSS selector string.
*
* If the command is a response to a request from an #ajax form element then
* this value can be NULL.
*
* @var string
*/
protected $selector;
/**
* An array of property/value pairs to set in the CSS for the selector.
*
* @var array
*/
protected $css = array();
/**
* Constructs a CssCommand object.
*
* @param string $selector
* A CSS selector for elements to which the CSS will be applied.
* @param array $css
* An array of CSS property/value pairs to set.
*/
public function __construct($selector, array $css = array()) {
$this->selector = $selector;
$this->css = $css;
}
/**
* Adds a property/value pair to the CSS to be added to this element.
*
* @param $property
* The CSS property to be changed.
* @param $value
* The new value of the CSS property.
*/
public function setProperty($property, $value) {
$this->css[$property] = $value;
return $this;
}
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'css',
'selector' => $this->selector,
'argument' => $this->css,
);
}
}

View File

@ -0,0 +1,79 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\DataCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\CommandInterface;
/**
* An AJAX command for implementing jQuery's data() method.
*
* This instructs the client to attach the name=value pair of data to the
* selector via jQuery's data cache.
*
* This command is implemented by Drupal.ajax.prototype.commands.data() defined
* in misc/ajax.js.
*/
class DataCommand implements CommandInterface {
/**
* A CSS selector string for elements to which data will be attached.
*
* If the command is a response to a request from an #ajax form element then
* this value can be NULL.
*
* @var string
*/
protected $selector;
/**
* The key of the data attached to elements matched by the selector.
*
* @var string
*/
protected $name;
/**
* The value of the data to be atached to elements matched by the selector.
*
* The data is not limited to strings; it can be any format.
*
* @var mixed
*/
protected $value;
/**
* Constructs a DataCommand object.
*
* @param string $selector
* A CSS selector for the elements to which the data will be attached.
* @param string $name
* The key of the data to be attached to elements matched by the selector.
* @param type $value
* The value of the data to be attached to elements matched by the selector.
*/
public function __construct($selector, $name, $value) {
$this->selector = $selector;
$this->name = $name;
$this->value = $value;
}
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'data',
'selector' => $this->selector,
'name' => $this->name,
'value' => $this->value,
);
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\HtmlCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\InsertCommand;
/**
* AJAX command for calling the jQuery html() method.
*
* The 'insert/html' command instructs the client to use jQuery's html() method
* to set the HTML content of each element matched by the given selector while
* leaving the outer tags intact.
*
* This command is implemented by Drupal.ajax.prototype.commands.insert()
* defined in misc/ajax.js.
*
* @see http://docs.jquery.com/Attributes/html#val
*/
class HtmlCommand extends InsertCommand {
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'insert',
'method' => 'html',
'selector' => $this->selector,
'data' => $this->html,
'settings' => $this->settings,
);
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\InsertCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\CommandInterface;
/**
* Generic AJAX command for inserting content.
*
* This command instructs the client to insert the given HTML using whichever
* jQuery DOM manipulation method has been specified in the #ajax['method']
* variable of the element that triggered the request.
*
* This command is implemented by Drupal.ajax.prototype.commands.insert()
* defined in misc/ajax.js.
*/
class InsertCommand implements CommandInterface {
/**
* A CSS selector string.
*
* If the command is a response to a request from an #ajax form element then
* this value can be NULL.
*
* @var string
*/
protected $selector;
/**
* The HTML content that will replace the matched element(s).
*
* @var string
*/
protected $html;
/**
* A settings array to be passed to any any attached JavaScript behavior.
*
* @var array
*/
protected $settings;
/**
* Constructs an InsertCommand object.
*
* @param string $selector
* A CSS selector.
* @param string $html
* String of HTML that will replace the matched element(s).
* @param array $settings
* An array of JavaScript settings to be passed to any attached behaviors.
*/
public function __construct($selector, $html, array $settings = NULL) {
$this->selector = $selector;
$this->html = $html;
$this->settings = $settings;
}
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'insert',
'method' => NULL,
'selector' => $this->selector,
'data' => $this->html,
'settings' => $this->settings,
);
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\InvokeCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\CommandInterface;
/**
* AJAX command for invoking an arbitrary jQuery method.
*
* The 'invoke' command will instruct the client to invoke the given jQuery
* method with the supplied arguments on the elements matched by the given
* selector. Intended for simple jQuery commands, such as attr(), addClass(),
* removeClass(), toggleClass(), etc.
*
* This command is implemented by Drupal.ajax.prototype.commands.invoke()
* defined in misc/ajax.js.
*/
class InvokeCommand implements CommandInterface {
/**
* A CSS selector string.
*
* If the command is a response to a request from an #ajax form element then
* this value can be NULL.
*
* @var string
*/
protected $selector;
/**
* A jQuery method to invoke.
*
* @var string
*/
protected $method;
/**
* An optional list of arguments to pass to the method.
*
* @var array
*/
protected $arguments;
/**
* Constructs an InvokeCommand object.
*
* @param string $selector
* A jQuery selector.
* @param string $method
* The name of a jQuery method to invoke.
* @param array $arguments
* An optional array of arguments to pass to the method.
*/
public function __construct($selector, $method, array $arguments = array()) {
$this->selector = $selector;
$this->method = $method;
$this->arguments = $arguments;
}
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'invoke',
'selector' => $this->selector,
'method' => $this->method,
'args' => $this->arguments,
);
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\PrependCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\InsertCommand;
/**
* AJAX command for calling the jQuery insert() method.
*
* The 'insert/prepend' command instructs the client to use jQuery's prepend()
* method to prepend the given HTML content to the inside each element matched
* by the given selector.
*
* This command is implemented by Drupal.ajax.prototype.commands.insert()
* defined in misc/ajax.js.
*
* @see http://docs.jquery.com/Manipulation/prepend#content
*/
class PrependCommand extends InsertCommand {
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'insert',
'method' => 'prepend',
'selector' => $this->selector,
'data' => $this->html,
'settings' => $this->settings,
);
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\RemoveCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\CommandInterface;
/**
* AJAX command for calling the jQuery remove() method.
*
* The 'remove' command instructs the client to use jQuery's remove() method
* to remove each of elements matched by the given selector, and everything
* within them.
*
* This command is implemented by Drupal.ajax.prototype.commands.remove()
* defined in misc/ajax.js.
*
* @see http://docs.jquery.com/Manipulation/remove#expr
*/
class RemoveCommand Implements CommandInterface {
/**
* The CSS selector for the element(s) to be removed.
*
* @var string
*/
protected $selector;
/**
* Constructs a RemoveCommand object.
*
* @param string $selector
*
*/
public function __construct($selector) {
$this->selector = $selector;
}
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'remove',
'selector' => $this->selector,
);
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\ReplaceCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\InsertCommand;
/**
* AJAX command for calling the jQuery replace() method.
*
* The 'insert/replaceWith' command instructs the client to use jQuery's
* replaceWith() method to replace each element matched matched by the given
* selector with the given HTML.
*
* This command is implemented by Drupal.ajax.prototype.commands.insert()
* defined in misc/ajax.js.
*
* See @link http://docs.jquery.com/Manipulation/replaceWith#content jQuery replaceWith command @endlink
*/
class ReplaceCommand extends InsertCommand {
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'insert',
'method' => 'replaceWith',
'selector' => $this->selector,
'data' => $this->html,
'settings' => $this->settings,
);
}
}

View File

@ -0,0 +1,54 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\RestripeCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\CommandInterface;
/**
* AJAX command for resetting the striping on a table.
*
* The 'restripe' command instructs the client to restripe a table. This is
* usually used after a table has been modified by a replace or append command.
*
* This command is implemented by Drupal.ajax.prototype.commands.restripe()
* defined in misc/ajax.js.
*/
class RestripeCommand implements CommandInterface {
/**
* A CSS selector string.
*
* If the command is a response to a request from an #ajax form element then
* this value can be NULL.
*
* @var string
*/
protected $selector;
/**
* Constructs a RestripeCommand object.
*
* @param string $selector
* A CSS selector for the table to be restriped.
*/
public function __construct($selector) {
$this->selector = $selector;
}
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'restripe',
'selector' => $this->selector,
);
}
}

View File

@ -0,0 +1,69 @@
<?php
/**
* @file
* Definition of Drupal\Core\Ajax\SettingsCommand.
*/
namespace Drupal\Core\Ajax;
use Drupal\Core\Ajax\CommandInterface;
/**
* AJAX command for adjusting Drupal's JavaScript settings.
*
* The 'settings' command instructs the client either to use the given array as
* the settings for ajax-loaded content or to extend Drupal.settings with the
* given array, depending on the value of the $merge parameter.
*
* This command is implemented by Drupal.ajax.prototype.commands.settings()
* defined in misc/ajax.js.
*/
class SettingsCommand implements CommandInterface {
/**
* An array of key/value pairs of JavaScript settings.
*
* This will be utilized for all commands after this if they do not include
* their own settings array.
*
* @var array
*/
protected $settings;
/**
* Whether the settings should be merged into the global Drupal.settings.
*
* By default (FALSE), the settings that are passed to Drupal.attachBehaviors
* will not include the global Drupal.settings.
*
* @var boolean
*/
protected $merge;
/**
* Constructs a SettingsCommand object.
*
* @param array $settings
* An array of key/value pairs of JavaScript settings.
* @param boolean $merge
* Whether the settings should be merged into the global Drupal.settings.
*/
public function __construct(array $settings, $merge = FALSE) {
$this->settings = $settings;
$this->merge = $merge;
}
/**
* Implements Drupal\Core\Ajax\CommandInterface:render().
*/
public function render() {
return array(
'command' => 'settings',
'settings' => $this->settings,
'merge' => $this->merge,
);
}
}

View File

@ -10,6 +10,8 @@ use Drupal\Core\Template\Attribute;
use Symfony\Component\HttpFoundation\JsonResponse;
use Drupal\file\FileUsage\DatabaseFileUsageBackend;
use Drupal\file\FileUsage\FileUsageInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
// Load all Field module hooks for File.
require_once DRUPAL_ROOT . '/core/modules/file/file.field.inc';
@ -750,9 +752,8 @@ function file_ajax_upload() {
if (empty($_POST['form_build_id']) || $form_build_id != $_POST['form_build_id']) {
// Invalid request.
drupal_set_message(t('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (@size) that this server supports.', array('@size' => format_size(file_upload_max_size()))), 'error');
$commands = array();
$commands[] = ajax_command_replace(NULL, theme('status_messages'));
return array('#type' => 'ajax', '#commands' => $commands);
$response = new AjaxResponse();
return $response->addCommand(new ReplaceCommand(NULL, theme('status_messages')));
}
list($form, $form_state) = ajax_get_form();
@ -760,9 +761,8 @@ function file_ajax_upload() {
if (!$form) {
// Invalid form_build_id.
drupal_set_message(t('An unrecoverable error occurred. Use of this form has expired. Try reloading the page and submitting again.'), 'error');
$commands = array();
$commands[] = ajax_command_replace(NULL, theme('status_messages'));
return array('#type' => 'ajax', '#commands' => $commands);
$response = new AjaxResponse();
return $response->addCommand(new ReplaceCommand(NULL, theme('status_messages')));
}
// Get the current element and count the number of files.
@ -793,9 +793,8 @@ function file_ajax_upload() {
$js = drupal_add_js();
$settings = call_user_func_array('array_merge_recursive', $js['settings']['data']);
$commands = array();
$commands[] = ajax_command_replace(NULL, $output, $settings);
return array('#type' => 'ajax', '#commands' => $commands);
$response = new AjaxResponse();
return $response->addCommand(new ReplaceCommand(NULL, $output, $settings));
}
/**

View File

@ -0,0 +1,309 @@
<?php
/**
* @file
* Definition of Drupal\system\Tests\Ajax\AjaxCommandsUnitTest.
*/
namespace Drupal\system\Tests\Ajax;
use Drupal\simpletest\UnitTestBase;
use Drupal\Core\Ajax\AddCssCommand;
use Drupal\Core\Ajax\AfterCommand;
use Drupal\Core\Ajax\AlertCommand;
use Drupal\Core\Ajax\AppendCommand;
use Drupal\Core\Ajax\BeforeCommand;
use Drupal\Core\Ajax\ChangedCommand;
use Drupal\Core\Ajax\CssCommand;
use Drupal\Core\Ajax\DataCommand;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\InsertCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\PrependCommand;
use Drupal\Core\Ajax\RemoveCommand;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Ajax\RestripeCommand;
use Drupal\Core\Ajax\SettingsCommand;
/**
* Tests for all AJAX Commands.
*/
class AjaxCommandsUnitTest extends UnitTestBase {
public static function getInfo() {
return array(
'name' => 'Ajax Command Objects',
'description' => 'Test that each AJAX command object can be created and rendered',
'group' => 'AJAX',
);
}
/**
* Tests that AddCssCommand objects can be constructed and rendered.
*/
function testAddCssCommand() {
$command = new AddCssCommand('p{ text-decoration:blink; }');
$expected = array(
'command' => 'add_css',
'data' => 'p{ text-decoration:blink; }',
);
$this->assertEqual($command->render(), $expected, 'AddCssCommand::render() returns a proper array.');
}
/**
* Tests that AfterCommand objecst can be constructed and rendered.
*/
function testAfterCommand() {
$command = new AfterCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
$expected = array(
'command' => 'insert',
'method' => 'after',
'selector' => '#page-title',
'data' => '<p>New Text!</p>',
'settings' => array('my-setting' => 'setting'),
);
$this->assertEqual($command->render(), $expected, 'AfterCommand::render() returns a proper array.');
}
/**
* Tests that AlertCommand objects can be constructed and rendered.
*/
function testAlertCommand() {
$command = new AlertCommand('Set condition 1 throughout the ship!');
$expected = array(
'command' => 'alert',
'text' => 'Set condition 1 throughout the ship!',
);
$this->assertEqual($command->render(), $expected, 'AlertCommand::render() returns a proper array.');
}
/**
* Tests that AppendCommand objects can be constructed and rendered.
*/
function testAppendCommand() {
// Test AppendCommand.
$command = new AppendCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
$expected = array(
'command' => 'insert',
'method' => 'append',
'selector' => '#page-title',
'data' => '<p>New Text!</p>',
'settings' => array('my-setting' => 'setting'),
);
$this->assertEqual($command->render(), $expected, 'AppendCommand::render() returns a proper array.');
}
/**
* Tests that BeforeCommand objects can be constructed and rendered.
*/
function testBeforeCommand() {
$command = new BeforeCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
$expected = array(
'command' => 'insert',
'method' => 'before',
'selector' => '#page-title',
'data' => '<p>New Text!</p>',
'settings' => array('my-setting' => 'setting'),
);
$this->assertEqual($command->render(), $expected, 'BeforeCommand::render() returns a proper array.');
}
/**
* Tests that ChangedCommand objects can be constructed and rendered.
*/
function testChangedCommand() {
$command = new ChangedCommand('#page-title', '#page-title-changed');
$expected = array(
'command' => 'changed',
'selector' => '#page-title',
'asterisk' => '#page-title-changed',
);
$this->assertEqual($command->render(), $expected, 'ChangedCommand::render() returns a proper array.');
}
/**
* Tests that CssCommand objects can be constructed and rendered.
*/
function testCssCommand() {
$command = new CssCommand('#page-title', array('text-decoration' => 'blink'));
$command->setProperty('font-size', '40px')->setProperty('font-weight', 'bold');
$expected = array(
'command' => 'css',
'selector' => '#page-title',
'argument' => array(
'text-decoration' => 'blink',
'font-size' => '40px',
'font-weight' => 'bold',
),
);
$this->assertEqual($command->render(), $expected, 'CssCommand::render() returns a proper array.');
}
/**
* Tests that DataCommand objects can be constructed and rendered.
*/
function testDataCommand() {
$command = new DataCommand('#page-title', 'my-data', array('key' => 'value'));
$expected = array(
'command' => 'data',
'selector' => '#page-title',
'name' => 'my-data',
'value' => array('key' => 'value'),
);
$this->assertEqual($command->render(), $expected, 'DataCommand::render() returns a proper array.');
}
/**
* Tests that HtmlCommand objects can be constructed and rendered.
*/
function testHtmlCommand() {
$command = new HtmlCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
$expected = array(
'command' => 'insert',
'method' => 'html',
'selector' => '#page-title',
'data' => '<p>New Text!</p>',
'settings' => array('my-setting' => 'setting'),
);
$this->assertEqual($command->render(), $expected, 'HtmlCommand::render() returns a proper array.');
}
/**
* Tests that InsertCommand objects can be constructed and rendered.
*/
function testInsertCommand() {
$command = new InsertCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
$expected = array(
'command' => 'insert',
'method' => NULL,
'selector' => '#page-title',
'data' => '<p>New Text!</p>',
'settings' => array('my-setting' => 'setting'),
);
$this->assertEqual($command->render(), $expected, 'InsertCommand::render() returns a proper array.');
}
/**
* Tests that InvokeCommand objects can be constructed and rendered.
*/
function testInvokeCommand() {
$command = new InvokeCommand('#page-title', 'myMethod', array('var1', 'var2'));
$expected = array(
'command' => 'invoke',
'selector' => '#page-title',
'method' => 'myMethod',
'args' => array('var1', 'var2'),
);
$this->assertEqual($command->render(), $expected, 'InvokeCommand::render() returns a proper array.');
}
/**
* Tests that PrependCommand objects can be constructed and rendered.
*/
function testPrependCommand() {
$command = new PrependCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
$expected = array(
'command' => 'insert',
'method' => 'prepend',
'selector' => '#page-title',
'data' => '<p>New Text!</p>',
'settings' => array('my-setting' => 'setting'),
);
$this->assertEqual($command->render(), $expected, 'PrependCommand::render() returns a proper array.');
}
/**
* Tests that RemoveCommand objects can be constructed and rendered.
*/
function testRemoveCommand() {
$command = new RemoveCommand('#page-title');
$expected = array(
'command' => 'remove',
'selector' => '#page-title',
);
$this->assertEqual($command->render(), $expected, 'RemoveCommand::render() returns a proper array.');
}
/**
* Tests that ReplaceCommand objects can be constructed and rendered.
*/
function testReplaceCommand() {
$command = new ReplaceCommand('#page-title', '<p>New Text!</p>', array('my-setting' => 'setting'));
$expected = array(
'command' => 'insert',
'method' => 'replaceWith',
'selector' => '#page-title',
'data' => '<p>New Text!</p>',
'settings' => array('my-setting' => 'setting'),
);
$this->assertEqual($command->render(), $expected, 'ReplaceCommand::render() returns a proper array.');
}
/**
* Tests that RestripeCommand objects can be constructed and rendered.
*/
function testRestripeCommand() {
$command = new RestripeCommand('#page-title');
$expected = array(
'command' => 'restripe',
'selector' => '#page-title',
);
$this->assertEqual($command->render(), $expected, 'RestripeCommand::render() returns a proper array.');
}
/**
* Tests that SettingsCommand objects can be constructed and rendered.
*/
function testSettingsCommand() {
$command = new SettingsCommand(array('key' => 'value'), TRUE);
$expected = array(
'command' => 'settings',
'settings' => array('key' => 'value'),
'merge' => TRUE,
);
$this->assertEqual($command->render(), $expected, 'SettingsCommand::render() returns a proper array.');
}
}