first import
This commit is contained in:
195
sites/all/modules/rules/ui/rules.autocomplete.js
Normal file
195
sites/all/modules/rules/ui/rules.autocomplete.js
Normal file
@@ -0,0 +1,195 @@
|
||||
|
||||
// Registers the rules namespace.
|
||||
Drupal.rules = Drupal.rules || {};
|
||||
|
||||
(function($) {
|
||||
Drupal.behaviors.rules_autocomplete = {
|
||||
attach: function(context) {
|
||||
var autocomplete_settings = Drupal.settings.rules_autocomplete;
|
||||
|
||||
$('input.rules-autocomplete').once(function() {
|
||||
var input = this;
|
||||
new Drupal.rules.autocomplete(input, autocomplete_settings[$(input).attr('id')]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Rules autocomplete object.
|
||||
*/
|
||||
Drupal.rules.autocomplete = function(input, settings) {
|
||||
this.id = settings.inputId;
|
||||
this.uri = settings.source;
|
||||
this.jqObject = $('#' + this.id);
|
||||
this.cache = new Array();
|
||||
this.jqObject.addClass('ui-corner-left');
|
||||
|
||||
this.opendByFocus = false;
|
||||
this.focusOpens = true;
|
||||
this.groupSelected = false;
|
||||
|
||||
this.button = $('<span> </span>');
|
||||
this.button.attr( {
|
||||
'tabIndex': -1,
|
||||
'title': 'Show all items'
|
||||
});
|
||||
this.button.insertAfter(this.jqObject);
|
||||
|
||||
this.button.button( {
|
||||
icons: {
|
||||
primary: 'ui-icon-triangle-1-s'
|
||||
},
|
||||
text: false
|
||||
});
|
||||
|
||||
// Don't round the left corners.
|
||||
this.button.removeClass('ui-corner-all');
|
||||
this.button.addClass('ui-corner-right ui-button-icon rules-autocomplete-button');
|
||||
|
||||
this.jqObject.autocomplete();
|
||||
this.jqObject.autocomplete("option", "minLength", 0);
|
||||
// Add a custom class, so we can style the autocomplete box without
|
||||
// interfering with other jquery autocomplete widgets.
|
||||
this.jqObject.autocomplete("widget").addClass('rules-autocomplete');
|
||||
|
||||
// Save the current rules_autocomplete object, so it can be used in
|
||||
// handlers.
|
||||
var instance = this;
|
||||
|
||||
// Event handlers
|
||||
this.jqObject.focus(function() {
|
||||
if (instance.focusOpens) {
|
||||
instance.toggle();
|
||||
instance.opendByFocus = true;
|
||||
}
|
||||
else {
|
||||
instance.focusOpens = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Needed when the window is closed but the textfield has the focus.
|
||||
this.jqObject.click(function() {
|
||||
// Since the focus event happens earlier then the focus event, we need to
|
||||
// check here, if the window should be opened.
|
||||
if (!instance.opendByFocus) {
|
||||
instance.toggle();
|
||||
}
|
||||
else {
|
||||
instance.opendByFocus = false;
|
||||
}
|
||||
});
|
||||
|
||||
this.jqObject.bind("autocompleteselect", function(event, ui) {
|
||||
// If a group was selected then set the groupSelected to true for the
|
||||
// overriden close function from jquery autocomplete.
|
||||
if (ui.item.value.substring(ui.item.value.length - 1, ui.item.value.length) == ":") {
|
||||
instance.groupSelected = true;
|
||||
}
|
||||
instance.focusOpens = false;
|
||||
instance.opendByFocus = false;
|
||||
});
|
||||
|
||||
this.jqObject.autocomplete("option", "source", function(request, response) {
|
||||
if (request.term in instance.cache) {
|
||||
response(instance.cache[request.term]);
|
||||
return;
|
||||
}
|
||||
$.ajax( {
|
||||
url: instance.uri + '/' + request.term,
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
instance.success(data, request, response);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Since jquery autocomplete by default strips html text by using .text()
|
||||
// we need our own _renderItem function to display html content.
|
||||
this.jqObject.data("autocomplete")._renderItem = function(ul, item) {
|
||||
return $("<li></li>").data("item.autocomplete", item).append("<a>" + item.label + "</a>").appendTo(ul);
|
||||
};
|
||||
|
||||
// Override close function
|
||||
this.jqObject.data("autocomplete").close = function (event) {
|
||||
var value = this.element.val();
|
||||
// If the selector is not a group, then trigger the close event an and
|
||||
// hide the menu.
|
||||
if (value === undefined || instance.groupSelected === false) {
|
||||
clearTimeout(this.closing);
|
||||
if (this.menu.element.is(":visible")) {
|
||||
this._trigger("close", event);
|
||||
this.menu.element.hide();
|
||||
this.menu.deactivate();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Else keep all open and trigger a search for the group.
|
||||
instance.jqObject.autocomplete("search", instance.jqObject.val());
|
||||
// After the suggestion box was opened again, we want to be able to
|
||||
// close it.
|
||||
instance.groupSelected = false;
|
||||
}
|
||||
};
|
||||
|
||||
this.button.click(function() {
|
||||
instance.toggle();
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Success function for Rules autocomplete object.
|
||||
*/
|
||||
Drupal.rules.autocomplete.prototype.success = function(data, request, response) {
|
||||
var list = new Array();
|
||||
jQuery.each(data, function(index, value) {
|
||||
list.push( {
|
||||
label: value,
|
||||
value: index
|
||||
});
|
||||
});
|
||||
|
||||
this.cache[request.term] = list;
|
||||
response(list);
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the autocomplete window.
|
||||
* @param searchFor The term for will be searched for. If undefined then the
|
||||
* entered input text will be used.
|
||||
*/
|
||||
Drupal.rules.autocomplete.prototype.open = function(searchFor) {
|
||||
// If searchFor is undefined, we want to search for the passed argument.
|
||||
this.jqObject.autocomplete("search", ((searchFor === undefined) ? this.jqObject.val() : searchFor));
|
||||
this.button.addClass("ui-state-focus");
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the autocomplete window.
|
||||
*/
|
||||
Drupal.rules.autocomplete.prototype.close = function() {
|
||||
this.jqObject.autocomplete("close");
|
||||
this.button.removeClass("ui-state-focus");
|
||||
};
|
||||
|
||||
/**
|
||||
* Toogle the autcomplete window.
|
||||
*/
|
||||
Drupal.rules.autocomplete.prototype.toggle = function() {
|
||||
if (this.jqObject.autocomplete("widget").is(":visible")) {
|
||||
this.close();
|
||||
this.focusOpens = true;
|
||||
}
|
||||
else {
|
||||
var groups = this.jqObject.val().split(":");
|
||||
var selector = "";
|
||||
for (var i=0; i<groups.length-1; i++) {
|
||||
selector = selector.concat(groups[i]) + ":";
|
||||
}
|
||||
this.focusOpens = false;
|
||||
this.jqObject.focus();
|
||||
this.open(selector);
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
68
sites/all/modules/rules/ui/rules.debug.js
Normal file
68
sites/all/modules/rules/ui/rules.debug.js
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @file
|
||||
* Adds the collapsible functionality to the rules debug log.
|
||||
*/
|
||||
|
||||
// Registers the rules namespace.
|
||||
Drupal.rules = Drupal.rules || {};
|
||||
|
||||
(function($) {
|
||||
Drupal.behaviors.rules_debug_log = {
|
||||
attach: function(context) {
|
||||
$('.rules-debug-open').click(function () {
|
||||
var icon = $(this).children('span.ui-icon');
|
||||
if ($(this).next().is(':hidden')) {
|
||||
Drupal.rules.changeDebugIcon(icon, true);
|
||||
}
|
||||
else {
|
||||
Drupal.rules.changeDebugIcon(icon, false);
|
||||
}
|
||||
$(this).next().toggle();
|
||||
}).next().hide();
|
||||
|
||||
$('.rules-debug-open-main').click(function () {
|
||||
var icon = $(this).children('span.ui-icon');
|
||||
if ($(this).parent().next().is(':hidden')) {
|
||||
Drupal.rules.changeDebugIcon(icon, true);
|
||||
$(this).parent().children('.rules-debug-open-all').text(Drupal.t('-Close all-'));
|
||||
}
|
||||
else {
|
||||
Drupal.rules.changeDebugIcon(icon, false);
|
||||
$(this).parent().children('.rules-debug-open-all').text(Drupal.t('-Open all-'));
|
||||
}
|
||||
$(this).parent().next().toggle();
|
||||
}).parent().next().hide();
|
||||
|
||||
$('.rules-debug-open-all').click(function() {
|
||||
if ($('.rules-debug-open-main').parent().next().is(':hidden')) {
|
||||
$('.rules-debug-open').next().show();
|
||||
Drupal.rules.changeDebugIcon($('.rules-debug-open').children('span.ui-icon'), true);
|
||||
$('.rules-debug-open-main').parent().next().show();
|
||||
Drupal.rules.changeDebugIcon($(this).prev().children('span.ui-icon'), true);
|
||||
$(this).text(Drupal.t('-Close all-'));
|
||||
}
|
||||
else {
|
||||
$('.rules-debug-open-main').parent().next().hide();
|
||||
Drupal.rules.changeDebugIcon($('.rules-debug-open-main').children('span.ui-icon'), false);
|
||||
$(this).text(Drupal.t('-Open all-'));
|
||||
$('.rules-debug-open').next().hide();
|
||||
Drupal.rules.changeDebugIcon($(this).prev().children('span.ui-icon'), false);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the icon of a collapsible div.
|
||||
*/
|
||||
Drupal.rules.changeDebugIcon = function(item, open) {
|
||||
if (open == true) {
|
||||
item.removeClass('ui-icon-triangle-1-e');
|
||||
item.addClass('ui-icon-triangle-1-s');
|
||||
}
|
||||
else {
|
||||
item.removeClass('ui-icon-triangle-1-s');
|
||||
item.addClass('ui-icon-triangle-1-e');
|
||||
}
|
||||
}
|
||||
})(jQuery);
|
196
sites/all/modules/rules/ui/rules.ui.css
Normal file
196
sites/all/modules/rules/ui/rules.ui.css
Normal file
@@ -0,0 +1,196 @@
|
||||
@CHARSET "UTF-8";
|
||||
|
||||
.rules-show-js, html.js .rules-hide-js {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.rules-hide-js, html.js .rules-show-js {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.rules-elements-table ul.action-links {
|
||||
margin: 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.rules-elements-table ul.rules-operations li {
|
||||
list-style: none;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.rules-elements-table ul.rules-operations a {
|
||||
background: none;
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
table tr.rules-elements-add {
|
||||
background-color: #e5eff4;
|
||||
}
|
||||
|
||||
.rules-elements-table ul.rules-operations-add a {
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
|
||||
tr.rules-elements-add td {
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
ul.rules-operations-add li {
|
||||
float: left;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
.rules-elements-table {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
/* We cannot set a positive margin-top for rules tables as the table drag link
|
||||
should be positioned directly on top of the table. Thus we use a large bottom
|
||||
margin and fix the upper most margin: */
|
||||
#rules-form-wrapper:first-child {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
/* Fix table drag weights to don't take extra space */
|
||||
.rules-elements-table .tabledrag-toggle-weight-wrapper {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.rules-elements-table caption, .rules-overview-table caption {
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
padding-bottom: 0.5em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.rules-overview-table {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.rules-content-group-integrity-error {
|
||||
color: #df0101;
|
||||
}
|
||||
|
||||
.rules-debug-log {
|
||||
font: 81.3% "Lucida Grande","Lucida Sans Unicode",sans-serif;
|
||||
background-color: #eeeeee;
|
||||
border: 1px solid #cccccc;
|
||||
color: #333333;
|
||||
padding: 5px;
|
||||
margin: 1.5em 0em;
|
||||
}
|
||||
|
||||
.rules-debug-collapsible-link {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
/* The span element with the icon which opens the log, has a whitepsace.
|
||||
Since we don't want the user to mark this white space, we prevent this
|
||||
using the this code.*/
|
||||
-moz-user-select: -moz-none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.rules-debug-log-head {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.rules-debug-log-head {
|
||||
margin: 0.5em 0em;
|
||||
}
|
||||
|
||||
.rules-debug-icon-open {
|
||||
position: relative;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.rules-debug-open-all {
|
||||
position: relative;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.rules-debug-log ul {
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
.rules-debug-log .rules-debug-warn {
|
||||
color: #df0101;
|
||||
}
|
||||
|
||||
.rules-debug-log .rules-debug-error {
|
||||
font-weight: bold;
|
||||
color: #df0101;
|
||||
}
|
||||
|
||||
#rules-filter-form {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.rules-parameter-label {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#rules-plugin-add-help {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.rules-element-content {
|
||||
float: left;
|
||||
}
|
||||
|
||||
form input.rules-switch-button {
|
||||
-moz-border-radius: 5px 5px 5px 5px;
|
||||
cursor: pointer;
|
||||
font-size: 0.8em;
|
||||
font-weight: normal;
|
||||
margin-bottom: 1em;
|
||||
padding: 2px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.rules-form-heading {
|
||||
margin-top: 3em;
|
||||
}
|
||||
|
||||
.rules-autocomplete-button {
|
||||
top: 3px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
ul.rules-autocomplete {
|
||||
max-height: 23em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
ul.rules-autocomplete div {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
ul.rules-autocomplete a.ui-corner-all {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
ul.rules-autocomplete .rules-dsac-group {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
ul.rules-autocomplete .ui-corner-all {
|
||||
-moz-border-radius: 0px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not display the hide/show descriptions link above the permissions matrix.
|
||||
*/
|
||||
#rules-form-wrapper #edit-settings-access-permissions .compact-link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* IE 6 hack for max-height. */
|
||||
* html ul.rule-autocomplete{
|
||||
height: 23em;
|
||||
}
|
95
sites/all/modules/rules/ui/rules.ui.seven.css
Normal file
95
sites/all/modules/rules/ui/rules.ui.seven.css
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* JQuery UI style sheet fix for the seven theme.
|
||||
*/
|
||||
|
||||
.ui-button {
|
||||
border: 1px solid #cccccc;
|
||||
background: #e6e6e6;
|
||||
}
|
||||
|
||||
.ui-state-hover,
|
||||
.ui-state-focus {
|
||||
border: 1px solid #bbbbbb;
|
||||
}
|
||||
|
||||
.ui-button.ui-state-active {
|
||||
border: 1px solid #777777;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Corner radius
|
||||
*/
|
||||
.ui-corner-tl {
|
||||
-moz-border-radius-topleft: 4px;
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
|
||||
.ui-corner-tr {
|
||||
-moz-border-radius-topright: 4px;
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
|
||||
.ui-corner-bl {
|
||||
-moz-border-radius-bottomleft: 4px;
|
||||
-webkit-border-bottom-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
.ui-corner-br {
|
||||
-moz-border-radius-bottomright: 4px;
|
||||
-webkit-border-bottom-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
.ui-corner-top {
|
||||
-moz-border-radius-topleft: 4px;
|
||||
-moz-border-radius-topright: 4px;
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
|
||||
.ui-corner-bottom {
|
||||
-moz-border-radius-bottomleft: 4px;
|
||||
-moz-border-radius-bottomright: 4px;
|
||||
-webkit-border-bottom-left-radius: 4px;
|
||||
-webkit-border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
.ui-corner-right {
|
||||
-moz-border-radius-bottomright: 4px;
|
||||
-moz-border-radius-topright: 4px;
|
||||
-webkit-border-bottom-right-radius: 4px;
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
|
||||
.ui-corner-left {
|
||||
-moz-border-radius-bottomleft: 4px;
|
||||
-moz-border-radius-topleft: 4px;
|
||||
-webkit-border-bottom-left-radius: 4px;
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
|
||||
.ui-corner-all {
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the position of the core-autocomplete popup when shown in the settings
|
||||
* fieldset.
|
||||
*/
|
||||
.form-item-settings-tags {
|
||||
position: relative;
|
||||
}
|
316
sites/all/modules/rules/ui/ui.controller.inc
Normal file
316
sites/all/modules/rules/ui/ui.controller.inc
Normal file
@@ -0,0 +1,316 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file Contains the UI controller for Rules.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Controller class for the Rules UI.
|
||||
*
|
||||
* The Rules UI controller defines the methods other modules may use in order
|
||||
* to easily re-use the UI, regardless whether the rules admin module is
|
||||
* enabled.
|
||||
*/
|
||||
class RulesUIController {
|
||||
|
||||
/**
|
||||
* Generates menu items to manipulate rules configurations.
|
||||
*
|
||||
* @param $base_path
|
||||
* The path to the overview page from where the configurations are edited.
|
||||
*/
|
||||
public function config_menu($base_path) {
|
||||
$items = array();
|
||||
$base_count = count(explode('/', $base_path));
|
||||
$items[$base_path . '/manage/%rules_config'] = array(
|
||||
'title callback' => 'rules_get_title',
|
||||
'title arguments' => array('Editing !plugin "!label"', $base_count + 1),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('rules_ui_form_edit_rules_config', $base_count + 1, $base_path),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('update', $base_count + 1),
|
||||
'type' => MENU_VISIBLE_IN_BREADCRUMB,
|
||||
'file' => 'ui/ui.forms.inc',
|
||||
'file path' => drupal_get_path('module', 'rules'),
|
||||
);
|
||||
$items[$base_path . '/manage/%rules_config/add/%rules_element'] = array(
|
||||
// Adding another part to the path would hit the menu path-part-limit
|
||||
// for base paths like admin/config/workflow/rules. Therefor we have to
|
||||
// use this fugly way for setting the title.
|
||||
'title callback' => 'rules_menu_add_element_title',
|
||||
// Wrap the integer in an array, so it is passed as is.
|
||||
'title arguments' => array(array($base_count + 4)),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('rules_ui_add_element', $base_count + 1, $base_count + 4, $base_count + 3, $base_path),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('update', $base_count + 1),
|
||||
'load arguments' => array($base_count + 1),
|
||||
'file' => 'ui/ui.forms.inc',
|
||||
'file path' => drupal_get_path('module', 'rules'),
|
||||
);
|
||||
$items[$base_path . '/manage/%rules_config/add/event'] = array(
|
||||
'title callback' => 'rules_get_title',
|
||||
'title arguments' => array('Adding event to !plugin "!label"', $base_count + 1),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('rules_ui_add_event', $base_count + 1, $base_path),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('update', $base_count + 1),
|
||||
'load arguments' => array($base_count + 1),
|
||||
'file' => 'ui/ui.forms.inc',
|
||||
'file path' => drupal_get_path('module', 'rules'),
|
||||
);
|
||||
$items[$base_path . '/manage/%rules_config/delete/event'] = array(
|
||||
//@todo: improve title.
|
||||
'title' => 'Remove event',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('rules_ui_remove_event', $base_count + 1, $base_count + 4, $base_path),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('update', $base_count + 1),
|
||||
'description' => 'Remove an event from a reaction rule.',
|
||||
'file' => 'ui/ui.forms.inc',
|
||||
'file path' => drupal_get_path('module', 'rules'),
|
||||
);
|
||||
$items[$base_path . '/manage/%rules_config/edit/%rules_element'] = array(
|
||||
'title callback' => 'rules_get_title',
|
||||
'title arguments' => array('Editing !plugin "!label"', $base_count + 3),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('rules_ui_edit_element', $base_count + 1, $base_count + 3, $base_path),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('update', $base_count + 1),
|
||||
'load arguments' => array($base_count + 1),
|
||||
'file' => 'ui/ui.forms.inc',
|
||||
'file path' => drupal_get_path('module', 'rules'),
|
||||
);
|
||||
$items[$base_path . '/manage/%rules_config/autocomplete'] = array(
|
||||
'page callback' => 'rules_ui_form_data_selection_auto_completion',
|
||||
'page arguments' => array($base_count + 3, $base_count + 4, $base_count + 5),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('update', $base_count + 1),
|
||||
'type' => MENU_CALLBACK,
|
||||
'file' => 'ui/ui.forms.inc',
|
||||
'file path' => drupal_get_path('module', 'rules'),
|
||||
);
|
||||
$items[$base_path . '/manage/%rules_config/delete/%rules_element'] = array(
|
||||
'title callback' => 'rules_get_title',
|
||||
'title arguments' => array('Editing !plugin "!label"', $base_count + 3),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('rules_ui_delete_element', $base_count + 1, $base_count + 3, $base_path),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('update', $base_count + 1),
|
||||
'load arguments' => array($base_count + 1),
|
||||
'file' => 'ui/ui.forms.inc',
|
||||
'file path' => drupal_get_path('module', 'rules'),
|
||||
);
|
||||
$items[$base_path . '/manage/%rules_config/%'] = array(
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('rules_ui_form_rules_config_confirm_op', $base_count + 1, $base_count + 2, $base_path),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('update', $base_count + 1),
|
||||
'file' => 'ui/ui.forms.inc',
|
||||
'file path' => drupal_get_path('module', 'rules'),
|
||||
);
|
||||
$items[$base_path . '/manage/%rules_config/clone'] = array(
|
||||
'title callback' => 'rules_get_title',
|
||||
'title arguments' => array('Cloning !plugin "!label"', $base_count + 1),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('rules_ui_form_clone_rules_config', $base_count + 1, $base_path),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('update', $base_count + 1),
|
||||
'file' => 'ui/ui.forms.inc',
|
||||
'file path' => drupal_get_path('module', 'rules'),
|
||||
);
|
||||
$items[$base_path . '/manage/%rules_config/export'] = array(
|
||||
'title callback' => 'rules_get_title',
|
||||
'title arguments' => array('Export of !plugin "!label"', $base_count + 1),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('rules_ui_form_export_rules_config', $base_count + 1, $base_path),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('view', $base_count + 1),
|
||||
'file' => 'ui/ui.forms.inc',
|
||||
'file path' => drupal_get_path('module', 'rules'),
|
||||
);
|
||||
$items[$base_path . '/manage/%rules_config/execute'] = array(
|
||||
'title callback' => 'rules_get_title',
|
||||
'title arguments' => array('Executing !plugin "!label"', $base_count + 1),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('rules_ui_form_execute_rules_config', $base_count + 1, $base_path),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('update', $base_count + 1),
|
||||
'file' => 'ui/ui.forms.inc',
|
||||
'file path' => drupal_get_path('module', 'rules'),
|
||||
);
|
||||
drupal_alter('rules_ui_menu', $items, $base_path, $base_count);
|
||||
|
||||
if (module_exists('rules_scheduler')) {
|
||||
$items[$base_path . '/manage/%rules_config/schedule'] = array(
|
||||
'title callback' => 'rules_get_title',
|
||||
'title arguments' => array('Schedule !plugin "!label"', $base_count + 1),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('rules_scheduler_schedule_form', $base_count + 1, $base_path),
|
||||
'access callback' => 'rules_config_access',
|
||||
'access arguments' => array('update', $base_count + 1),
|
||||
'file' => 'rules_scheduler.admin.inc',
|
||||
'file path' => drupal_get_path('module', 'rules_scheduler'),
|
||||
);
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the render array for a overview configuration table for arbitrary
|
||||
* rule configs that match the given conditions.
|
||||
*
|
||||
* Note: The generated overview table contains multiple links for editing the
|
||||
* rule configurations. For the links to properly work use
|
||||
* RulesUIController::config_menu($base_path) to generate appropriate menu
|
||||
* items for the path at which the overview table is displayed.
|
||||
*
|
||||
* @param $conditions
|
||||
* An array of conditions as needed by rules_config_load_multiple().
|
||||
* @param $options
|
||||
* An array with optional options. Known keys are:
|
||||
* - 'hide status op': If set to TRUE, enable/disable links are not added.
|
||||
* Defaults to FALSE.
|
||||
* - 'show plugin': If set to FALSE, the plugin is not shown. Defaults to
|
||||
* TRUE.
|
||||
* - 'show events': If set to TRUE, the event column is shown. Defaults to
|
||||
* TRUE if only reaction rules are listed.
|
||||
* - 'show execution op': If set to TRUE an operation for execution a
|
||||
* component is shown for components, as well as a link to schedule a
|
||||
* component if the rules scheduler module is enabled.
|
||||
* - 'base path': Optionally, a different base path to use instead of the
|
||||
* currently set RulesPluginUI::$basePath. If no base path has been set
|
||||
* yet, the current path is used by default.
|
||||
*
|
||||
* @return Array
|
||||
* A renderable array.
|
||||
*/
|
||||
public function overviewTable($conditions = array(), $options = array()) {
|
||||
$options += array(
|
||||
'hide status op' => FALSE,
|
||||
'show plugin' => TRUE,
|
||||
'show events' => isset($conditions['plugin']) && $conditions['plugin'] == 'reaction rule',
|
||||
'show execution op' => !(isset($conditions['plugin']) && $conditions['plugin'] == 'reaction rule'),
|
||||
);
|
||||
if (!empty($options['base path'])) {
|
||||
RulesPluginUI::$basePath = $options['base path'];
|
||||
}
|
||||
else if (!isset(RulesPluginUI::$basePath)) {
|
||||
// Default to the current path, only if no path has been set yet.
|
||||
RulesPluginUI::$basePath = current_path();
|
||||
}
|
||||
|
||||
$entities = entity_load('rules_config', FALSE, $conditions);
|
||||
ksort($entities);
|
||||
|
||||
// Prepare some variables used by overviewTableRow().
|
||||
$this->event_info = rules_fetch_data('event_info');
|
||||
$this->cache = rules_get_cache();
|
||||
|
||||
$rows = array();
|
||||
foreach ($entities as $id => $entity) {
|
||||
if (user_access('bypass rules access') || $entity->access()) {
|
||||
$rows[] = $this->overviewTableRow($conditions, $id, $entity, $options);
|
||||
}
|
||||
}
|
||||
// Assemble the right table header.
|
||||
$header = array(t('Name'), t('Event'), t('Plugin'), t('Status'), array('data' => t('Operations')));
|
||||
if (!$options['show events']) {
|
||||
// Remove the event heading as there is no such column.
|
||||
unset($header[1]);
|
||||
}
|
||||
if (!$options['show plugin']) {
|
||||
unset($header[2]);
|
||||
}
|
||||
// Fix the header operation column colspan.
|
||||
$num_cols = isset($rows[0]) ? count($rows[0]) : 0;
|
||||
if (($addition = $num_cols - count($header)) > 0) {
|
||||
$header[4]['colspan'] = $addition + 1;
|
||||
}
|
||||
|
||||
$table = array(
|
||||
'#theme' => 'table',
|
||||
'#header' => $header,
|
||||
'#rows' => $rows,
|
||||
'#empty' => t('None.'),
|
||||
);
|
||||
$table['#attributes']['class'][] = 'rules-overview-table';
|
||||
$table['#attached']['css'][] = drupal_get_path('module', 'rules') . '/ui/rules.ui.css';
|
||||
|
||||
// TODO: hide configs where access() is FALSE.
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the row for a single rules config.
|
||||
*
|
||||
* @param $additional_cols
|
||||
* Additional columns to be added after the entity label column.
|
||||
*/
|
||||
protected function overviewTableRow($conditions, $name, $config, $options) {
|
||||
// Build content includes the label, as well as a short overview including
|
||||
// the machine name.
|
||||
$row[] = array('data' => $config->buildContent());
|
||||
|
||||
// Add events if the configs are assigned to events.
|
||||
if ($options['show events']) {
|
||||
$events = array();
|
||||
if ($config instanceof RulesTriggerableInterface) {
|
||||
foreach ($config->events() as $event_name) {
|
||||
$this->event_info += array($event_name => array('label' => t('Unknown event "!event_name"', array('!event_name' => $event_name))));
|
||||
$events[] = check_plain($this->event_info[$event_name]['label']);
|
||||
}
|
||||
}
|
||||
$row[] = implode(", ", $events);
|
||||
}
|
||||
if ($options['show plugin']) {
|
||||
$plugin = $config->plugin();
|
||||
$row[] = isset($this->cache['plugin_info'][$plugin]['label']) ? $this->cache['plugin_info'][$plugin]['label'] : $plugin;
|
||||
}
|
||||
|
||||
$row[] = array('data' => array(
|
||||
'#theme' => 'entity_status',
|
||||
'#status' => $config->status,
|
||||
));
|
||||
|
||||
// Add operations depending on the options and the exportable status.
|
||||
if (!$config->hasStatus(ENTITY_FIXED)) {
|
||||
$row[] = l(t('edit'), RulesPluginUI::path($name), array('attributes' => array('class' => array('edit', 'action'))));
|
||||
$row[] = l(t('translate'), RulesPluginUI::path($name, 'translate'), array('attributes' => array('class' => array('translate', 'action'))));
|
||||
}
|
||||
else {
|
||||
$row[] = '';
|
||||
$row[] = '';
|
||||
}
|
||||
|
||||
if (!$options['hide status op']) {
|
||||
// Add either an enable or disable link.
|
||||
$text = $config->active ? t('disable') : t('enable');
|
||||
$active_class = $config->active ? 'disable' : 'enable';
|
||||
$link_path = RulesPluginUI::path($name, $active_class);
|
||||
$row[] = $config->hasStatus(ENTITY_FIXED) ? '' : l($text, $link_path, array('attributes' => array('class' => array($active_class, 'action')), 'query' => drupal_get_destination()));
|
||||
}
|
||||
$row[] = l(t('clone'), RulesPluginUI::path($name, 'clone'), array('attributes' => array('class' => array('clone', 'action'))));
|
||||
|
||||
// Add execute link for for components.
|
||||
if ($options['show execution op']) {
|
||||
$row[] = ($config instanceof RulesTriggerableInterface) ? '' : l(t('execute'), RulesPluginUI::path($name, 'execute'), array('attributes' => array('class' => array('execute', 'action')), 'query' => drupal_get_destination()));
|
||||
if (module_exists('rules_scheduler')) {
|
||||
// Add schedule link for action components only.
|
||||
$row[] = $config instanceof RulesActionInterface ? l(t('schedule'), RulesPluginUI::path($name, 'schedule'), array('attributes' => array('class' => array('schedule', 'action')), 'query' => drupal_get_destination())) : '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$config->hasStatus(ENTITY_IN_CODE) && !$config->hasStatus(ENTITY_FIXED)) {
|
||||
$row[] = l(t('delete'), RulesPluginUI::path($name, 'delete'), array('attributes' => array('class' => array('delete', 'action')), 'query' => drupal_get_destination()));
|
||||
}
|
||||
elseif ($config->hasStatus(ENTITY_OVERRIDDEN) && !$config->hasStatus(ENTITY_FIXED)) {
|
||||
$row[] = l(t('revert'), RulesPluginUI::path($name, 'revert'), array('attributes' => array('class' => array('revert', 'action')), 'query' => drupal_get_destination()));
|
||||
}
|
||||
else {
|
||||
$row[] = '';
|
||||
}
|
||||
$row[] = l(t('export'), RulesPluginUI::path($name, 'export'), array('attributes' => array('class' => array('export', 'action'))));
|
||||
return $row;
|
||||
}
|
||||
}
|
1171
sites/all/modules/rules/ui/ui.core.inc
Normal file
1171
sites/all/modules/rules/ui/ui.core.inc
Normal file
File diff suppressed because it is too large
Load Diff
521
sites/all/modules/rules/ui/ui.data.inc
Normal file
521
sites/all/modules/rules/ui/ui.data.inc
Normal file
@@ -0,0 +1,521 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file Contains data type related forms.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Interface for data types providing a direct input form.
|
||||
*/
|
||||
interface RulesDataDirectInputFormInterface {
|
||||
|
||||
/**
|
||||
* Constructs the direct input form.
|
||||
*
|
||||
* @return Array
|
||||
* The direct input form.
|
||||
*/
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element);
|
||||
|
||||
/**
|
||||
* Render the configured value.
|
||||
*
|
||||
* @return Array
|
||||
* A renderable array.
|
||||
*/
|
||||
public static function render($value);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Default UI related class for data types.
|
||||
*/
|
||||
class RulesDataUI {
|
||||
|
||||
/**
|
||||
* Specifies the default input mode per data type.
|
||||
*/
|
||||
public static function getDefaultMode() {
|
||||
return 'selector';
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the selection form for a parameter.
|
||||
*/
|
||||
public static function selectionForm($name, $info, $settings, RulesPlugin $element) {
|
||||
if (!isset($settings[$name . ':select'])) {
|
||||
$settings[$name . ':select'] = '';
|
||||
$vars = $element->availableVariables();
|
||||
// Default to variables with the same name as the parameter.
|
||||
if (isset($vars[$name])) {
|
||||
$settings[$name . ':select'] = $name;
|
||||
}
|
||||
// If there is only one match, use it by default.
|
||||
elseif (count($matches = RulesData::matchingDataSelector($vars, $info, '', 1, FALSE)) == 1) {
|
||||
$settings[$name . ':select'] = rules_array_key($matches);
|
||||
}
|
||||
}
|
||||
$form[$name . ':select'] = array(
|
||||
'#type' => 'rules_data_selection',
|
||||
'#title' => t('Data selector'),
|
||||
'#default_value' => $settings[$name . ':select'],
|
||||
'#required' => empty($info['optional']),
|
||||
'#autocomplete_path' => RulesPluginUI::path($element->root()->name, 'autocomplete' . '/' . $name),
|
||||
// Make the autocomplete textfield big enough so that it can display
|
||||
// descriptions without word wraps.
|
||||
'#size' => 75,
|
||||
'#description' => t("The data selector helps you drill down into the data available to Rules. <em>To make entity fields appear in the data selector, you may have to use the condition 'entity has field' (or 'content is of type').</em> More useful tips about data selection is available in <a href='@url'>the online documentation</a>.",
|
||||
array('@url' => rules_external_help('data-selection'))),
|
||||
);
|
||||
|
||||
$cache = rules_get_cache();
|
||||
$form['types_help'] = array(
|
||||
'#theme' => 'rules_settings_help',
|
||||
'#heading' => t('Data types'),
|
||||
);
|
||||
if ($info['type'] == '*') {
|
||||
$type_labels[] = t('any');
|
||||
}
|
||||
else {
|
||||
$types = is_array($info['type']) ? $info['type'] : array($info['type']);
|
||||
$type_labels = array();
|
||||
foreach ($types as $type) {
|
||||
$type_labels[] = drupal_ucfirst(isset($cache['data_info'][$type]['label']) ? $cache['data_info'][$type]['label'] : $type);
|
||||
}
|
||||
}
|
||||
$form['types_help']['#text'] = format_plural(count($type_labels), 'Select data of the type %types.', 'Select data of the types %types.', array('%types' => implode(', ', $type_labels)));
|
||||
|
||||
if (!empty($info['translatable'])) {
|
||||
if (empty($info['custom translation language'])) {
|
||||
$text = t('If a multilingual data source (i.e. a translatable field) is given, the argument is translated to the current interface language.');
|
||||
}
|
||||
else {
|
||||
$text = t('If a multilingual data source (i.e. a translatable field) is given, the argument is translated to the configured language.');
|
||||
}
|
||||
$form['translation'] = array(
|
||||
'#theme' => 'rules_settings_help',
|
||||
'#text' => $text,
|
||||
'#heading' => t('Translation'),
|
||||
);
|
||||
}
|
||||
$form['help'] = array(
|
||||
'#theme' => 'rules_data_selector_help',
|
||||
'#variables' => $element->availableVariables(),
|
||||
'#parameter' => $info,
|
||||
);
|
||||
|
||||
// Add data processor.
|
||||
$settings += array($name . ':process' => array());
|
||||
$form[$name . ':process'] = array();
|
||||
RulesDataProcessor::attachForm($form[$name . ':process'], $settings[$name . ':process'], $info, $element->availableVariables());
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the value by making use of the label if an options list is available.
|
||||
*
|
||||
* Used for data UI classes implementing the
|
||||
* RulesDataDirectInputFormInterface.
|
||||
*
|
||||
* In case an options list is available, the the usual render() method won't
|
||||
* be invoked, instead the selected entry is rendered via this method.
|
||||
*
|
||||
* @todo for Drupal 8: Refactor to avoid implementations have to care about
|
||||
* option lists when generating the form, but not when rendering values.
|
||||
*/
|
||||
public static function renderOptionsLabel($value, $name, $info, RulesPlugin $element) {
|
||||
if (!empty($info['options list'])) {
|
||||
$element->call('loadBasicInclude');
|
||||
$options = entity_property_options_flatten($info['options list']($element, $name));
|
||||
if (!is_array($value) && isset($options[$value])) {
|
||||
$value = $options[$value];
|
||||
}
|
||||
elseif (is_array($value)) {
|
||||
foreach ($value as $key => $single_value) {
|
||||
if (isset($options[$single_value])) {
|
||||
$value[$key] = $options[$single_value];
|
||||
}
|
||||
}
|
||||
$value = implode(', ', $value);
|
||||
}
|
||||
return array(
|
||||
'content' => array('#markup' => check_plain($value)),
|
||||
'#attributes' => array('class' => array('rules-parameter-options-entry')),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for textual data.
|
||||
*/
|
||||
class RulesDataUIText extends RulesDataUI implements RulesDataDirectInputFormInterface {
|
||||
|
||||
public static function getDefaultMode() {
|
||||
return 'input';
|
||||
}
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
if (!empty($info['options list'])) {
|
||||
// Make sure the .rules.inc of the providing module is included as the
|
||||
// options list callback may reside there.
|
||||
$element->call('loadBasicInclude');
|
||||
$form[$name] = array(
|
||||
'#type' => 'select',
|
||||
'#options' => call_user_func($info['options list'], $element, $name),
|
||||
);
|
||||
}
|
||||
else {
|
||||
$form[$name] = array(
|
||||
'#type' => 'textarea',
|
||||
);
|
||||
RulesDataInputEvaluator::attachForm($form, $settings, $info, $element->availableVariables());
|
||||
}
|
||||
$settings += array($name => isset($info['default value']) ? $info['default value'] : NULL);
|
||||
$form[$name] += array(
|
||||
'#title' => t('Value'),
|
||||
'#default_value' => $settings[$name],
|
||||
'#required' => empty($info['optional']),
|
||||
'#after_build' => array('rules_ui_element_fix_empty_after_build'),
|
||||
'#rows' => 3,
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
public static function render($value) {
|
||||
return array(
|
||||
'content' => array('#markup' => check_plain($value)),
|
||||
'#attributes' => array('class' => array('rules-parameter-text')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for text tokens.
|
||||
*/
|
||||
class RulesDataUITextToken extends RulesDataUIText {
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
if ($form[$name]['#type'] == 'textarea') {
|
||||
$form[$name]['#element_validate'][] = 'rules_ui_element_token_validate';
|
||||
$form[$name]['#description'] = t('May only contain lowercase letters, numbers, and underscores and has to start with a letter.');
|
||||
$form[$name]['#rows'] = 1;
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for formatted text.
|
||||
*/
|
||||
class RulesDataUITextFormatted extends RulesDataUIText {
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
$settings += array($name => isset($info['default value']) ? $info['default value'] : array('value' => NULL, 'format' => NULL));
|
||||
|
||||
$form[$name]['#type'] = 'text_format';
|
||||
$form[$name]['#base_type'] = 'textarea';
|
||||
$form[$name]['#default_value'] = $settings[$name]['value'];
|
||||
$form[$name]['#format'] = $settings[$name]['format'];
|
||||
return $form;
|
||||
}
|
||||
|
||||
public static function render($value) {
|
||||
return array(
|
||||
'content' => array('#markup' => check_plain($value['value'])),
|
||||
'#attributes' => array('class' => array('rules-parameter-text-formatted')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* UI for decimal data.
|
||||
*/
|
||||
class RulesDataUIDecimal extends RulesDataUIText {
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
if (empty($info['options list'])) {
|
||||
$form[$name]['#type'] = 'textfield';
|
||||
}
|
||||
$form[$name]['#element_validate'][] = 'rules_ui_element_decimal_validate';
|
||||
$form[$name]['#rows'] = 1;
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for integers.
|
||||
*/
|
||||
class RulesDataUIInteger extends RulesDataUIText {
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
if (empty($info['options list'])) {
|
||||
$form[$name]['#type'] = 'textfield';
|
||||
}
|
||||
$form[$name]['#element_validate'][] = 'rules_ui_element_integer_validate';
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for boolean data.
|
||||
*/
|
||||
class RulesDataUIBoolean extends RulesDataUI implements RulesDataDirectInputFormInterface {
|
||||
|
||||
public static function getDefaultMode() {
|
||||
return 'input';
|
||||
}
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$settings += array($name => isset($info['default value']) ? $info['default value'] : NULL);
|
||||
// Note: Due to the checkbox even optional parameter always receive a value.
|
||||
$form[$name] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => check_plain($info['label']),
|
||||
'#default_value' => $settings[$name],
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
public static function render($value) {
|
||||
return array(
|
||||
'content' => array('#markup' => !empty($value) ? t('true') : t('false')),
|
||||
'#attributes' => array('class' => array('rules-parameter-boolean')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for dates.
|
||||
*/
|
||||
class RulesDataUIDate extends RulesDataUIText {
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$settings += array($name => isset($info['default value']) ? $info['default value'] : (empty($info['optional']) ? gmdate('Y-m-d H:i:s', time()) : NULL));
|
||||
|
||||
// Convert any configured timestamp into a readable format.
|
||||
if (is_numeric($settings[$name])) {
|
||||
$settings[$name] = gmdate('Y-m-d H:i:s', $settings[$name]);
|
||||
}
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
$form[$name]['#type'] = 'textfield';
|
||||
$form[$name]['#element_validate'][] = 'rules_ui_element_date_validate';
|
||||
// Note that the date input evaluator takes care for parsing dates using
|
||||
// strtotime() into a timestamp, which is the internal date format.
|
||||
$form[$name]['#description'] = t('The date in GMT. You may enter a fixed time (like %format) or any other values in GMT known by the PHP !strtotime function (like "+1 day"). Relative dates like "+1 day" or "now" relate to the evaluation time.',
|
||||
array('%format' => gmdate('Y-m-d H:i:s', time() + 86400),
|
||||
'!strtotime' => l('strtotime()', 'http://php.net/strtotime')));
|
||||
|
||||
//TODO: Leverage the jquery datepicker+timepicker once a module providing
|
||||
//the timpeicker is available.
|
||||
return $form;
|
||||
}
|
||||
|
||||
public static function render($value) {
|
||||
$value = is_numeric($value) ? format_date($value, 'short') : check_plain($value);
|
||||
return array(
|
||||
'content' => array('#markup' => $value),
|
||||
'#attributes' => array('class' => array('rules-parameter-date')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for duration type parameter.
|
||||
*/
|
||||
class RulesDataUIDuration extends RulesDataUIText {
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
$form[$name]['#type'] = 'rules_duration';
|
||||
$form[$name]['#after_build'][] = 'rules_ui_element_duration_after_build';
|
||||
return $form;
|
||||
}
|
||||
|
||||
public static function render($value) {
|
||||
$value = is_numeric($value) ? format_interval($value) : check_plain($value);
|
||||
return array(
|
||||
'content' => array('#markup' => $value),
|
||||
'#attributes' => array('class' => array('rules-parameter-duration')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for the URI type parameter.
|
||||
*/
|
||||
class RulesDataUIURI extends RulesDataUIText {
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
$form[$name]['#rows'] = 1;
|
||||
$form[$name]['#description'] = t('You may enter relative URLs like %url as well as absolute URLs like %absolute-url.', array('%url' => 'user/login?destination=node', '%absolute-url' => 'http://drupal.org'));
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for lists of textual data.
|
||||
*/
|
||||
class RulesDataUIListText extends RulesDataUIText {
|
||||
|
||||
public static function getDefaultMode() {
|
||||
return 'input';
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo This does not work for inputting textual values including "\n".
|
||||
*/
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$settings += array($name => isset($info['default value']) ? $info['default value'] : NULL);
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
|
||||
if ($form[$name]['#type'] == 'textarea') {
|
||||
// Fix up the value to be an array during after build.
|
||||
$form[$name]['#delimiter'] = "\n";
|
||||
$form[$name]['#after_build'][] = 'rules_ui_list_textarea_after_build';
|
||||
$form[$name]['#pre_render'][] = 'rules_ui_list_textarea_pre_render';
|
||||
$form[$name]['#default_value'] = !empty($settings[$name]) ? implode("\n", $settings[$name]) : NULL;
|
||||
$form[$name]['#description'] = t('A list of values, one on each line.');
|
||||
}
|
||||
else {
|
||||
$form[$name]['#multiple'] = TRUE;
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
public static function render($value) {
|
||||
return array(
|
||||
'content' => array('#markup' => check_plain(implode(', ', $value))),
|
||||
'#attributes' => array('class' => array('rules-parameter-list')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for lists of integers.
|
||||
*/
|
||||
class RulesDataUIListInteger extends RulesDataUIListText {
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$settings += array($name => isset($info['default value']) ? $info['default value'] : NULL);
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
|
||||
if ($form[$name]['#type'] == 'textarea') {
|
||||
$form[$name]['#description'] = t('A list of integers, separated by commas. E.g. enter "1, 2, 3".');
|
||||
$form[$name]['#delimiter'] = ',';
|
||||
$form[$name]['#default_value'] = !empty($settings[$name]) ? implode(", ", $settings[$name]) : NULL;
|
||||
$form[$name]['#element_validate'][] = 'rules_ui_element_integer_list_validate';
|
||||
$form[$name]['#rows'] = 1;
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for lists of tokens.
|
||||
*/
|
||||
class RulesDataUIListToken extends RulesDataUIListInteger {
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
|
||||
if ($form[$name]['#type'] == 'textarea') {
|
||||
$form[$name]['#description'] = t('A list of text tokens, separated by commas. E.g. enter "one, two, three".');
|
||||
$form[$name]['#element_validate'] = array('rules_ui_element_token_list_validate');
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for entity-based data types.
|
||||
*/
|
||||
class RulesDataUIEntity extends RulesDataUIText {
|
||||
|
||||
public static function getDefaultMode() {
|
||||
return 'selector';
|
||||
}
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
if (empty($info['options list'])) {
|
||||
$form[$name]['#type'] = 'textfield';
|
||||
|
||||
$entity_info = entity_get_info($info['type']);
|
||||
if (empty($entity_info['entity keys']['name'])) {
|
||||
$form[$name]['#element_validate'][] = 'rules_ui_element_integer_validate';
|
||||
}
|
||||
$form[$name]['#title'] = t('@entity identifier', array('@entity' => $entity_info['label']));
|
||||
$entity_label = strtolower($entity_info['label'][0]) . substr($entity_info['label'], 1);
|
||||
$form[$name]['#description'] = t('Specify an identifier of a @entity.', array('@entity' => $entity_label));
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for exportable entity-based data types.
|
||||
*/
|
||||
class RulesDataUIEntityExportable extends RulesDataUIEntity {
|
||||
|
||||
public static function getDefaultMode() {
|
||||
return 'input';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for taxonomy vocabularies.
|
||||
*
|
||||
* @see RulesTaxonomyVocabularyWrapper
|
||||
*/
|
||||
class RulesDataUITaxonomyVocabulary extends RulesDataUIEntity {
|
||||
|
||||
public static function getDefaultMode() {
|
||||
return 'input';
|
||||
}
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
// Add an options list of all vocabularies if there is none yet.
|
||||
if (!isset($info['options list'])) {
|
||||
$info['options list'] = array('RulesDataUITaxonomyVocabulary', 'optionsList');
|
||||
}
|
||||
return parent::inputForm($name, $info, $settings, $element);
|
||||
}
|
||||
|
||||
public static function optionsList() {
|
||||
$options = array();
|
||||
foreach (taxonomy_vocabulary_get_names() as $machine_name => $vocab) {
|
||||
$options[$machine_name] = $vocab->name;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for lists of entity-based data types.
|
||||
*/
|
||||
class RulesDataUIListEntity extends RulesDataUIListInteger {
|
||||
|
||||
public static function inputForm($name, $info, $settings, RulesPlugin $element) {
|
||||
$form = parent::inputForm($name, $info, $settings, $element);
|
||||
if (empty($info['options list'])) {
|
||||
|
||||
$entity_info = entity_get_info(entity_property_list_extract_type($info['type']));
|
||||
if (!empty($entity_info['entity keys']['name'])) {
|
||||
$form[$name]['#element_validate'] = array('rules_ui_element_token_list_validate');
|
||||
}
|
||||
$form[$name]['#title'] = t('@entity identifiers', array('@entity' => $entity_info['label']));
|
||||
$entity_label = strtolower($entity_info['label'][0]) . substr($entity_info['label'], 1);
|
||||
$form[$name]['#description'] = t('Specify a comma-separated list of identifiers of @entity entities.', array('@entity' => $entity_label));
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
}
|
920
sites/all/modules/rules/ui/ui.forms.inc
Normal file
920
sites/all/modules/rules/ui/ui.forms.inc
Normal file
@@ -0,0 +1,920 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file Rules UI forms
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ajax callback for reloading the whole form.
|
||||
*/
|
||||
function rules_ui_form_ajax_reload_form($form, $form_state) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines #ajax properties.
|
||||
*/
|
||||
function rules_ui_form_default_ajax($effect = 'slide') {
|
||||
return array(
|
||||
'callback' => 'rules_ui_form_ajax_reload_form',
|
||||
'wrapper' => 'rules-form-wrapper',
|
||||
'effect' => $effect,
|
||||
'speed' => 'fast',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit handler for switching the parameter input mode.
|
||||
*/
|
||||
function rules_ui_parameter_replace_submit($form, &$form_state) {
|
||||
if (isset($form_state['triggering_element'])) {
|
||||
$name = $form_state['triggering_element']['#parameter'];
|
||||
$form_state['parameter_mode'][$name] = $form_state['parameter_mode'][$name] == 'selector' ? 'input' : 'selector';
|
||||
}
|
||||
$form_state['rebuild'] = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* General form submit handler, that rebuilds the form
|
||||
*/
|
||||
function rules_form_submit_rebuild($form, &$form_state) {
|
||||
$form_state['rebuild'] = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a rules configuration.
|
||||
*/
|
||||
function rules_ui_form_edit_rules_config($form, &$form_state, $rules_config, $base_path) {
|
||||
RulesPluginUI::$basePath = $base_path;
|
||||
$form_state += array('rules_element' => $rules_config);
|
||||
// Add the rule configuration's form.
|
||||
$rules_config->form($form, $form_state, array('show settings' => TRUE, 'button' => TRUE));
|
||||
$form['#validate'] = array('rules_ui_form_rules_config_validate');
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* General rules configuration form validation callback. Also populates the
|
||||
* rules configuration with the form values.
|
||||
*/
|
||||
function rules_ui_form_rules_config_validate($form, &$form_state) {
|
||||
$form_state['rules_element']->form_validate($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a rules configuration form submit callback.
|
||||
*/
|
||||
function rules_ui_form_edit_rules_config_submit($form, &$form_state) {
|
||||
$form_state['rules_element']->form_submit($form, $form_state);
|
||||
drupal_set_message(t('Your changes have been saved.'));
|
||||
if (empty($form_state['redirect'])) {
|
||||
$form_state['redirect'] = RulesPluginUI::defaultRedirect($form_state['rules_element']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a rules configuration form.
|
||||
*/
|
||||
function rules_ui_form_clone_rules_config($form, &$form_state, $rules_config, $base_path) {
|
||||
RulesPluginUI::$basePath = $base_path;
|
||||
$rules_config = clone $rules_config;
|
||||
$rules_config->module = 'rules';
|
||||
$rules_config->id = NULL;
|
||||
$rules_config->name = '';
|
||||
$rules_config->label .= ' (' . t('cloned') . ')';
|
||||
$rules_config->status = ENTITY_CUSTOM;
|
||||
|
||||
$form['#validate'][] = 'rules_ui_form_rules_config_validate';
|
||||
$form['#submit'][] = 'rules_ui_form_edit_rules_config_submit';
|
||||
$form_state += array('rules_element' => $rules_config, 'op' => 'clone');
|
||||
|
||||
// Add the rule configuration's form.
|
||||
$rules_config->form($form, $form_state, array('show settings' => TRUE, 'button' => TRUE, 'init' => TRUE));
|
||||
|
||||
// Open the settings fieldset so altering the name is easier.
|
||||
$form['settings']['#collapsed'] = FALSE;
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple form just showing a textarea with the export.
|
||||
*/
|
||||
function rules_ui_form_export_rules_config($form, &$form_state, $rules_config, $base_path) {
|
||||
$form['export'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => t('Export'),
|
||||
'#description' => t('For importing copy the content of the text area and paste it into the import page.'),
|
||||
'#rows' => 25,
|
||||
'#default_value' => $rules_config->export(),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration form to directly execute a rules configuration.
|
||||
*/
|
||||
function rules_ui_form_execute_rules_config($form, &$form_state, $rules_config, $base_path) {
|
||||
// Only components can be executed.
|
||||
if (!($rules_config instanceof RulesTriggerableInterface)) {
|
||||
RulesPluginUI::$basePath = $base_path;
|
||||
// Create either the appropriate action or condition element.
|
||||
$element = rules_plugin_factory($rules_config instanceof RulesActionInterface ? 'action' : 'condition', 'component_' . $rules_config->name);
|
||||
$form['exec_help'] = array(
|
||||
'#prefix' => '<p>',
|
||||
'#markup' => t('This form allows you to manually trigger the execution of the @plugin "%label". If this component requires any parameters, input the suiting execution arguments below.', array('@plugin' => $rules_config->plugin(), '%label' => $rules_config->label())),
|
||||
'#suffix' => '</p>',
|
||||
);
|
||||
$element->form($form, $form_state);
|
||||
|
||||
// For conditions hide the option to negate them.
|
||||
if (isset($form['negate'])) {
|
||||
$form['negate']['#access'] = FALSE;
|
||||
}
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Execute'),
|
||||
'#weight' => 20,
|
||||
);
|
||||
// Re-use the validation callback, which will also populate the action with
|
||||
// the configuration settings in the form.
|
||||
$form['#validate'] = array('rules_ui_form_rules_config_validate');
|
||||
return $form;
|
||||
}
|
||||
drupal_not_found();
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit callback for directly executing a component.
|
||||
*/
|
||||
function rules_ui_form_execute_rules_config_submit($form, &$form_state) {
|
||||
$element = $form_state['rules_element'];
|
||||
$result = $element->execute();
|
||||
if ($element instanceof RulesActionInterface) {
|
||||
drupal_set_message(t('Component %label has been executed.', array('%label' => $element->label())));
|
||||
}
|
||||
else {
|
||||
drupal_set_message(t('Component %label evaluated to %result.', array('%label' => $element->label(), '%result' => $result ? 'true' : 'false')));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the confirmation question for valid operations, or else FALSE.
|
||||
*/
|
||||
function rules_ui_confirm_operations($op, $rules_config) {
|
||||
$vars = array('%plugin' => $rules_config->plugin(), '%label' => $rules_config->label());
|
||||
|
||||
switch ($op) {
|
||||
case 'enable':
|
||||
return array(t('Are you sure you want to enable the %plugin %label?', $vars), '');
|
||||
case 'disable':
|
||||
return array(t('Are you sure you want to disable the %plugin %label?', $vars), '');
|
||||
case 'revert':
|
||||
return array(t('Are you sure you want to revert the %plugin %label?', $vars), t('This action cannot be undone.'));
|
||||
case 'delete':
|
||||
return array(t('Are you sure you want to delete the %plugin %label?', $vars), t('This action cannot be undone.'));
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirmation form for applying the operation to the config.
|
||||
*/
|
||||
function rules_ui_form_rules_config_confirm_op($form, &$form_state, $rules_config, $op, $base_path) {
|
||||
if (list($confirm_question, $description) = rules_ui_confirm_operations($op, $rules_config)) {
|
||||
RulesPluginUI::$basePath = $base_path;
|
||||
$form_state += array('rules_config' => $rules_config, 'op' => $op);
|
||||
return confirm_form($form, $confirm_question, $base_path, $description, t('Confirm'), t('Cancel'));
|
||||
}
|
||||
else {
|
||||
drupal_not_found();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the operation and returns the message to show to the user. Also the
|
||||
* operation is logged to the watchdog. Note that the string is defined two
|
||||
* times so that the translation extractor can find it.
|
||||
*/
|
||||
function rules_ui_confirm_operation_apply($op, $rules_config) {
|
||||
$vars = array('%plugin' => $rules_config->plugin(), '%label' => $rules_config->label());
|
||||
$edit_link = l(t('edit'), RulesPluginUI::path($rules_config->name));
|
||||
|
||||
switch ($op) {
|
||||
case 'enable':
|
||||
$rules_config->active = TRUE;
|
||||
$rules_config->save();
|
||||
watchdog('rules', 'Enabled %plugin %label.', $vars, WATCHDOG_NOTICE, $edit_link);
|
||||
return t('Enabled %plugin %label.', $vars);
|
||||
|
||||
case 'disable':
|
||||
$rules_config->active = FALSE;
|
||||
$rules_config->save();
|
||||
watchdog('rules', 'Disabled %plugin %label.', $vars, WATCHDOG_NOTICE, $edit_link);
|
||||
return t('Disabled %plugin %label.', $vars);
|
||||
|
||||
case 'revert':
|
||||
$rules_config->delete();
|
||||
watchdog('rules', 'Reverted %plugin %label to the defaults.', $vars, WATCHDOG_NOTICE, $edit_link);
|
||||
return t('Reverted %plugin %label to the defaults.', $vars);
|
||||
|
||||
case 'delete':
|
||||
$rules_config->delete();
|
||||
watchdog('rules', 'Deleted %plugin %label.', $vars);
|
||||
return t('Deleted %plugin %label.', $vars);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rule config deletion form submit callback.
|
||||
*/
|
||||
function rules_ui_form_rules_config_confirm_op_submit($form, &$form_state) {
|
||||
if ($form_state['values']['confirm']) {
|
||||
$msg = rules_ui_confirm_operation_apply($form_state['op'], $form_state['rules_config']);
|
||||
drupal_set_message($msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new element a rules configuration.
|
||||
*/
|
||||
function rules_ui_add_element($form, &$form_state, $rules_config, $plugin_name, RulesContainerPlugin $parent, $base_path) {
|
||||
$cache = rules_get_cache();
|
||||
if (!isset($cache['plugin_info'][$plugin_name]['class'])) {
|
||||
drupal_not_found();
|
||||
exit;
|
||||
}
|
||||
RulesPluginUI::$basePath = $base_path;
|
||||
$plugin_is_abstract = in_array('RulesAbstractPlugin', class_parents($cache['plugin_info'][$plugin_name]['class']));
|
||||
// In the first step create the element and in the second step show its edit
|
||||
// form.
|
||||
if ($plugin_is_abstract && !isset($form_state['rules_element'])) {
|
||||
RulesPluginUI::formDefaults($form, $form_state);
|
||||
$form_state += array('parent_element' => $parent, 'plugin' => $plugin_name);
|
||||
|
||||
$form['element_name'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Select the %element to add', array('%element' => $plugin_name)),
|
||||
'#options' => RulesPluginUI::getOptions($plugin_name),
|
||||
'#ajax' => rules_ui_form_default_ajax() + array(
|
||||
'trigger_as' => array('name' => 'continue'),
|
||||
),
|
||||
);
|
||||
$form['continue'] = array(
|
||||
'#type' => 'submit',
|
||||
'#name' => 'continue',
|
||||
'#value' => t('Continue'),
|
||||
'#ajax' => rules_ui_form_default_ajax(),
|
||||
);
|
||||
}
|
||||
elseif (!$plugin_is_abstract) {
|
||||
// Create the initial, empty element.
|
||||
$element = rules_plugin_factory($plugin_name);
|
||||
// Always add the new element at the bottom, thus set an appropriate weight.
|
||||
$iterator = $parent->getIterator();
|
||||
if ($sibling = end($iterator)) {
|
||||
$element->weight = $sibling->weight + 1;
|
||||
}
|
||||
$element->setParent($parent);
|
||||
$form_state['rules_element'] = $element;
|
||||
}
|
||||
|
||||
if (isset($form_state['rules_element'])) {
|
||||
$form_state['rules_element']->form($form, $form_state, array('button' => TRUE, 'init' => TRUE));
|
||||
$form['#validate'][] = 'rules_ui_edit_element_validate';
|
||||
$form['#submit'][] = 'rules_ui_edit_element_submit';
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add element submit callback.
|
||||
* Used for "abstract plugins" to create the initial element object with the
|
||||
* given implemenation name and rebuild the form.
|
||||
*/
|
||||
function rules_ui_add_element_submit($form, &$form_state) {
|
||||
$element = rules_plugin_factory($form_state['plugin'], $form_state['values']['element_name']);
|
||||
|
||||
// Always add the new element at the bottom, thus set an appropriate weight.
|
||||
$iterator = $form_state['parent_element']->getIterator();
|
||||
if ($sibling = end($iterator)) {
|
||||
$element->weight = $sibling->weight + 1;
|
||||
}
|
||||
// Clear the element settings so they won't be processed on serialization as
|
||||
// there is nothing to be processed yet.
|
||||
$element->settings = array();
|
||||
$element->setParent($form_state['parent_element']);
|
||||
|
||||
$form_state['rules_element'] = $element;
|
||||
$form_state['rebuild'] = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete elements.
|
||||
*/
|
||||
function rules_ui_delete_element($form, &$form_state, $rules_config, $rules_element, $base_path) {
|
||||
RulesPluginUI::$basePath = $base_path;
|
||||
|
||||
if (empty($form_state['rules_config'])) {
|
||||
// Before modifying the rules config we have to clone it, so any
|
||||
// modifications won't appear in the static cache of the loading controller.
|
||||
$rules_config = clone $rules_config;
|
||||
// Also get the element from the cloned config.
|
||||
$rules_element = $rules_config->elementMap()->lookup($rules_element->elementId());
|
||||
|
||||
$form_state['rules_config'] = $rules_config;
|
||||
$form_state['rules_element'] = $rules_element;
|
||||
$form_state['element_parent'] = $rules_element->parentElement();
|
||||
}
|
||||
|
||||
// Try deleting the element and warn the user if something breaks, but
|
||||
// save the parent for determining the right redirect target on submit.
|
||||
$removed_plugin = $form_state['rules_element']->plugin();
|
||||
$rules_element->delete();
|
||||
|
||||
if (empty($rules_config->dirty) && empty($form_state['input'])) {
|
||||
try {
|
||||
$rules_config->integrityCheck();
|
||||
}
|
||||
catch (RulesIntegrityException $e) {
|
||||
$args = array(
|
||||
'@plugin' => $e->element->plugin(),
|
||||
'%label' => $e->element->label(),
|
||||
'@removed-plugin' => $removed_plugin,
|
||||
'!url' => url(RulesPluginUI::path($form_state['rules_config']->name, 'edit', $e->element)),
|
||||
);
|
||||
drupal_set_message(t('Deleting this @removed-plugin would break your configuration as some of its provided variables are utilized by the @plugin <a href="!url">%label</a>.', $args), 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
$confirm_question = t('Are you sure you want to delete the %element_plugin %element_name?', array('%element_plugin' => $rules_element->plugin(), '%element_name' => $rules_element->label(), '%plugin' => $rules_config->plugin(), '%label' => $rules_config->label()));
|
||||
return confirm_form($form, $confirm_question, RulesPluginUI::path($rules_config->name), t('This action cannot be undone.'), t('Delete'), t('Cancel'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rule config deletion form submit callback.
|
||||
*/
|
||||
function rules_ui_delete_element_submit($form, &$form_state) {
|
||||
$rules_config = $form_state['rules_config'];
|
||||
$rules_config->save();
|
||||
if (empty($form_state['redirect'])) {
|
||||
$form_state['redirect'] = RulesPluginUI::defaultRedirect($form_state['element_parent']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure a rule element.
|
||||
*/
|
||||
function rules_ui_edit_element($form, &$form_state, $rules_config, $element, $base_path) {
|
||||
RulesPluginUI::$basePath = $base_path;
|
||||
$form_state += array('rules_element' => $element);
|
||||
$form_state['rules_element']->form($form, $form_state, array('button' => TRUE));
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the element configuration.
|
||||
*/
|
||||
function rules_ui_edit_element_validate($form, &$form_state) {
|
||||
$form_state['rules_element']->form_validate($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit the element configuration.
|
||||
*/
|
||||
function rules_ui_edit_element_submit($form, &$form_state) {
|
||||
$form_state['rules_element']->form_submit($form, $form_state);
|
||||
drupal_set_message(t('Your changes have been saved.'));
|
||||
if (empty($form_state['redirect'])) {
|
||||
$form_state['redirect'] = RulesPluginUI::defaultRedirect($form_state['rules_element']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new event.
|
||||
*/
|
||||
function rules_ui_add_event($form, &$form_state, RulesReactionRule $rules_config, $base_path) {
|
||||
RulesPluginUI::$basePath = $base_path;
|
||||
$form_state += array('rules_config' => $rules_config);
|
||||
$events = array_diff_key(rules_fetch_data('event_info'), array_flip($rules_config->events()));
|
||||
|
||||
$form['help'] = array(
|
||||
'#markup' => t('Select the event to add. However note that all added events need to provide all variables that should be available to your rule.'),
|
||||
);
|
||||
$form['event'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('React on event'),
|
||||
'#options' => RulesPluginUI::getOptions('event', $events),
|
||||
'#description' => t('Whenever the event occurs, rule evaluation is triggered.'),
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Add'),
|
||||
);
|
||||
$form_state['redirect'] = RulesPluginUI::path($rules_config->name);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit callback that just adds the selected event.
|
||||
*
|
||||
* @see rules_admin_add_reaction_rule()
|
||||
*/
|
||||
function rules_ui_add_event_apply($form, &$form_state) {
|
||||
$form_state['rules_config']->event($form_state['values']['event']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit the event configuration.
|
||||
*/
|
||||
function rules_ui_add_event_submit($form, &$form_state) {
|
||||
rules_ui_add_event_apply($form, $form_state);
|
||||
$rules_config = $form_state['rules_config'];
|
||||
|
||||
// Tell the user if this breaks something, but let him proceed.
|
||||
if (empty($rules_config->dirty)) {
|
||||
try {
|
||||
$rules_config->integrityCheck();
|
||||
}
|
||||
catch (RulesIntegrityException $e) {
|
||||
$warning = TRUE;
|
||||
drupal_set_message(t('Added the event, but it does not provide all variables utilized.'), 'warning');
|
||||
}
|
||||
}
|
||||
$rules_config->save();
|
||||
if (!isset($warning)) {
|
||||
$events = rules_fetch_data('event_info');
|
||||
$label = $events[$form_state['values']['event']]['label'];
|
||||
drupal_set_message(t('Added event %event.', array('%event' => $label)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Form to remove a event from a rule.
|
||||
*/
|
||||
function rules_ui_remove_event($form, &$form_state, $rules_config, $event, $base_path) {
|
||||
RulesPluginUI::$basePath = $base_path;
|
||||
$form_state += array('rules_config' => $rules_config, 'rules_event' => $event);
|
||||
$events = rules_fetch_data('event_info');
|
||||
$form_state['event_label'] = $events[$event]['label'];
|
||||
$confirm_question = t('Are you sure you want to remove the event?');
|
||||
return confirm_form($form, $confirm_question, RulesPluginUI::path($rules_config->name), t('You are about to remove the event %event.', array('%event' => $form_state['event_label'])), t('Remove'), t('Cancel'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit the event configuration.
|
||||
*/
|
||||
function rules_ui_remove_event_submit($form, &$form_state) {
|
||||
$rules_config = $form_state['rules_config'];
|
||||
$rules_config->removeEvent($form_state['rules_event']);
|
||||
// Tell the user if this breaks something, but let him proceed.
|
||||
if (empty($rules_config->dirty)) {
|
||||
try {
|
||||
$rules_config->integrityCheck();
|
||||
}
|
||||
catch (RulesIntegrityException $e) {
|
||||
$warning = TRUE;
|
||||
drupal_set_message(t('Removed the event, but it had provided some variables which are now missing.'), 'warning');
|
||||
}
|
||||
}
|
||||
$rules_config->save();
|
||||
if (!isset($warning)) {
|
||||
drupal_set_message(t('Event %event has been removed.', array('%event' => $form_state['event_label'])));
|
||||
}
|
||||
$form_state['redirect'] = RulesPluginUI::path($rules_config->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import form for rule configurations.
|
||||
*/
|
||||
function rules_ui_import_form($form, &$form_state, $base_path) {
|
||||
RulesPluginUI::$basePath = $base_path;
|
||||
RulesPluginUI::formDefaults($form, $form_state);
|
||||
$form['import'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => t('Import'),
|
||||
'#description' => t('Paste an exported Rules configuration here.'),
|
||||
'#rows' => 20,
|
||||
);
|
||||
$form['overwrite'] = array(
|
||||
'#title' => t('Overwrite'),
|
||||
'#type' => 'checkbox',
|
||||
'#description' => t('If checked, any existing configuration with the same identifier will be replaced by the import.'),
|
||||
'#default_value' => FALSE,
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Import'),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation callback for the import form.
|
||||
*/
|
||||
function rules_ui_import_form_validate($form, &$form_state) {
|
||||
if ($rules_config = rules_import($form_state['values']['import'], $error_msg)) {
|
||||
// Store the successfully imported entity in $form_state.
|
||||
$form_state['rules_config'] = $rules_config;
|
||||
if (!$form_state['values']['overwrite']) {
|
||||
// Check for existing entities with the same identifier.
|
||||
if (rules_config_load($rules_config->name)) {
|
||||
$vars = array('@entity' => t('Rules configuration'), '%label' => $rules_config->label());
|
||||
form_set_error('import', t('Import of @entity %label failed, a @entity with the same machine name already exists. Check the overwrite option to replace it.', $vars));
|
||||
}
|
||||
}
|
||||
try {
|
||||
$rules_config->integrityCheck();
|
||||
}
|
||||
catch (RulesIntegrityException $e) {
|
||||
form_set_error('import', t('Integrity check for the imported configuration failed. Error message: %message.', array('%message' => $e->getMessage())));
|
||||
}
|
||||
if (!user_access('bypass rules access') && !$rules_config->access()) {
|
||||
form_set_error('import', t('You have insufficient access permissions for importing this Rules configuration.'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
form_set_error('import', t('Import failed.'));
|
||||
if ($error_msg) {
|
||||
drupal_set_message($error_msg, 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit callback for the import form.
|
||||
*/
|
||||
function rules_ui_import_form_submit($form, &$form_state) {
|
||||
$rules_config = $form_state['rules_config'];
|
||||
|
||||
if ($existing_config = rules_config_load($rules_config->name)) {
|
||||
// Copy DB id and remove the new indicator to overwrite the existing record.
|
||||
$rules_config->id = $existing_config->id;
|
||||
unset($rules_config->is_new);
|
||||
}
|
||||
$rules_config->save();
|
||||
$vars = array('@entity' => t('Rules configuration'), '%label' => $rules_config->label());
|
||||
watchdog('rules_config', 'Imported @entity %label.', $vars);
|
||||
drupal_set_message(t('Imported @entity %label.', $vars));
|
||||
$form_state['redirect'] = RulesPluginUI::$basePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI process callback for the data selection widget.
|
||||
* This finalises the auto completion callback path by appending the form build
|
||||
* id.
|
||||
*/
|
||||
function rules_data_selection_process($element, &$form_state, $form) {
|
||||
$element['#autocomplete_path'] .= '/' . $form['#build_id'];
|
||||
$form_state['cache'] = TRUE;
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Autocomplete data selection results.
|
||||
*/
|
||||
function rules_ui_form_data_selection_auto_completion($parameter, $form_build_id, $string = '') {
|
||||
// Get the form and its state from the cache to get the currently edited
|
||||
// or created element.
|
||||
$form_state = form_state_defaults();
|
||||
$form = form_get_cache($form_build_id, $form_state);
|
||||
if (!isset($form_state['rules_element'])) {
|
||||
return;
|
||||
}
|
||||
$element = $form_state['rules_element'];
|
||||
|
||||
$params = $element->pluginParameterInfo();
|
||||
$matches = array();
|
||||
if (isset($params[$parameter])) {
|
||||
$parts = explode(':', $string);
|
||||
// Remove the last part as it might be unfinished.
|
||||
$last_part = array_pop($parts);
|
||||
$selector = implode(':', $parts);
|
||||
|
||||
// Start with the partly given selector or from scratch.
|
||||
$result = array();
|
||||
if ($selector && $wrapper = $element->applyDataSelector($selector)) {
|
||||
$result = RulesData::matchingDataSelector($wrapper, $params[$parameter], $selector . ':', 0);
|
||||
}
|
||||
elseif (!$selector) {
|
||||
$result = RulesData::matchingDataSelector($element->availableVariables(), $params[$parameter], '', 0);
|
||||
}
|
||||
|
||||
foreach ($result as $selector => $info) {
|
||||
// If we have an uncomplete last part, take it into account now.
|
||||
$attributes = array();
|
||||
if (!$last_part || strpos($selector, $string) === 0) {
|
||||
$attributes['class'][] = 'rules-dsac-item';
|
||||
$attributes['title'] = isset($info['description']) ? strip_tags($info['description']) : '';
|
||||
if ($selector[strlen($selector) - 1] == ':') {
|
||||
$attributes['class'][] = 'rules-dsac-group';
|
||||
$text = check_plain($selector) . '... (' . check_plain($info['label']) . ')';
|
||||
}
|
||||
else {
|
||||
$text = check_plain($selector) . ' (' . check_plain($info['label']) . ')';
|
||||
}
|
||||
$matches[$selector] = "<div" . drupal_attributes($attributes) . ">$text</div";
|
||||
}
|
||||
}
|
||||
}
|
||||
drupal_json_output($matches);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* FAPI validation of an integer element. Copy of the private function
|
||||
* _element_validate_integer().
|
||||
*/
|
||||
function rules_ui_element_integer_validate($element, &$form_state) {;
|
||||
$value = $element['#value'];
|
||||
if (isset($value) && $value !== '' && (!is_numeric($value) || intval($value) != $value)) {
|
||||
form_error($element, t('%name must be an integer value.', array('%name' => isset($element['#title']) ? $element['#title'] : t('Element'))));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI validation of a decimal element. Improved version of the private
|
||||
* function _element_validate_number().
|
||||
*/
|
||||
function rules_ui_element_decimal_validate($element, &$form_state) {
|
||||
// Substitute the decimal separator ",".
|
||||
$value = strtr($element['#value'], ',', '.');
|
||||
if ($value != '' && !is_numeric($value)) {
|
||||
form_error($element, t('%name must be a number.', array('%name' => $element['#title'])));
|
||||
}
|
||||
elseif ($value != $element['#value']) {
|
||||
form_set_value($element, $value, $form_state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI validation of a date element. Makes sure the specified date format is
|
||||
* correct and converts date values specifiy a fixed (= non relative) date to
|
||||
* a timestamp. Relative dates are handled by the date input evaluator.
|
||||
*/
|
||||
function rules_ui_element_date_validate($element, &$form_state) {
|
||||
$value = $element['#value'];
|
||||
if ($value == '' || (is_numeric($value) && intval($value) == $value)) {
|
||||
// The value is a timestamp.
|
||||
return;
|
||||
}
|
||||
elseif (is_string($value) && RulesDateInputEvaluator::gmstrtotime($value) === FALSE) {
|
||||
form_error($element, t('Wrong date format. Specify the date in the format %format.', array('%format' => gmdate('Y-m-d H:i:s', time() + 86400))));
|
||||
}
|
||||
elseif (is_string($value) && RulesDateInputEvaluator::isFixedDateString($value)) {
|
||||
// As the date string specifies a fixed format, we can convert it now.
|
||||
$value = RulesDateInputEvaluator::gmstrtotime($value);
|
||||
form_set_value($element, $value, $form_state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI process callback for the duration element type.
|
||||
*/
|
||||
function rules_ui_element_duration_process($element, &$form_state) {
|
||||
$element['value'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#size' => 8,
|
||||
'#element_validate' => array('rules_ui_element_integer_validate'),
|
||||
'#default_value' => $element['#default_value'],
|
||||
'#required' => !empty($element['#required']),
|
||||
);
|
||||
$element['multiplier'] = array(
|
||||
'#type' => 'select',
|
||||
'#options' => rules_ui_element_duration_multipliers(),
|
||||
'#default_value' => 1,
|
||||
);
|
||||
|
||||
// Put the child elements in a container-inline div.
|
||||
$element['value']['#prefix'] = '<div class="rules-duration container-inline">';
|
||||
$element['multiplier']['#suffix'] = '</div>';
|
||||
|
||||
// Set an appropriate multiplier.
|
||||
if (!empty($element['value']['#default_value'])) {
|
||||
foreach (array_keys(rules_ui_element_duration_multipliers()) as $m) {
|
||||
if ($element['value']['#default_value'] % $m == 0) {
|
||||
$element['multiplier']['#default_value'] = $m;
|
||||
}
|
||||
}
|
||||
// Divide value by the multiplier, so the display is correct.
|
||||
$element['value']['#default_value'] /= $element['multiplier']['#default_value'];
|
||||
}
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines possible duration multiplier.
|
||||
*/
|
||||
function rules_ui_element_duration_multipliers() {
|
||||
return array(
|
||||
1 => t('seconds'),
|
||||
60 => t('minutes'),
|
||||
3600 => t('hours'),
|
||||
// Just use approximate numbers for days (might last 23h on DST change),
|
||||
// months and years.
|
||||
86400 => t('days'),
|
||||
86400 * 30 => t('months'),
|
||||
86400 * 30 * 12 => t('years'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to determine the value for a rules duration form
|
||||
* element.
|
||||
*/
|
||||
function rules_ui_element_duration_value($element, $input = FALSE) {
|
||||
// This runs before child elements are processed, so we cannot calculate the
|
||||
// value here. But we have to make sure the value is an array, so the form
|
||||
// API is able to process the children to set their values in the array. Thus
|
||||
// once the form API has finished processing the element, the value is an
|
||||
// array containing the child element values. Then finally the after build
|
||||
// callback converts it back to the numeric value and sets that.
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI after build callback for the duration parameter type form.
|
||||
* Fixes up the form value by applying the multiplier.
|
||||
*/
|
||||
function rules_ui_element_duration_after_build($element, &$form_state) {
|
||||
if ($element['value']['#value'] !== '') {
|
||||
$element['#value'] = $element['value']['#value'] * $element['multiplier']['#value'];
|
||||
form_set_value($element, $element['#value'], $form_state);
|
||||
}
|
||||
else {
|
||||
$element['#value'] = NULL;
|
||||
form_set_value($element, NULL, $form_state);
|
||||
}
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI after build callback to ensure empty form elements result in no value.
|
||||
*/
|
||||
function rules_ui_element_fix_empty_after_build($element, &$form_state) {
|
||||
if (isset($element['#value']) && $element['#value'] === '') {
|
||||
$element['#value'] = NULL;
|
||||
form_set_value($element, NULL, $form_state);
|
||||
}
|
||||
// Work-a-round for the text_format element.
|
||||
elseif ($element['#type'] == 'text_format' && !isset($element['value']['#value'])) {
|
||||
form_set_value($element, NULL, $form_state);
|
||||
}
|
||||
return $element;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* FAPI after build callback for specifying a list of values.
|
||||
*
|
||||
* Turns the textual value in an array by splitting the text in chunks using the
|
||||
* delimiter set at $element['#delimiter'].
|
||||
*/
|
||||
function rules_ui_list_textarea_after_build($element, &$form_state) {
|
||||
$element['#value'] = $element['#value'] ? explode($element['#delimiter'], $element['#value']) : array();
|
||||
$element['#value'] = array_map('trim', $element['#value']);
|
||||
form_set_value($element, $element['#value'], $form_state);
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI pre render callback. Turns the value back to a string for rendering.
|
||||
*
|
||||
* @see rules_ui_list_textarea_after_build()
|
||||
*/
|
||||
function rules_ui_list_textarea_pre_render($element) {
|
||||
$element['#value'] = implode($element['#delimiter'], $element['#value']);
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI callback to validate a list of integers.
|
||||
*/
|
||||
function rules_ui_element_integer_list_validate($element, &$form_state) {
|
||||
foreach ($element['#value'] as $value) {
|
||||
if ($value !== '' && (!is_numeric($value) || intval($value) != $value)) {
|
||||
form_error($element, t('Each value must be an integer.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI callback to validate a token.
|
||||
*/
|
||||
function rules_ui_element_token_validate($element) {
|
||||
$value = $element['#value'];
|
||||
if (isset($value) && $value !== '' && !entity_property_verify_data_type($value, 'token')) {
|
||||
form_error($element, t('%name may only contain lowercase letters, numbers, and underscores and has to start with a letter.', array('%name' => isset($element['#title']) ? $element['#title'] : t('Element'))));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI callback to validate a list of tokens.
|
||||
*/
|
||||
function rules_ui_element_token_list_validate($element, &$form_state) {
|
||||
foreach ($element['#value'] as $value) {
|
||||
if ($value !== '' && !entity_property_verify_data_type($value, 'token')) {
|
||||
form_error($element, t('Each value may only contain lowercase letters, numbers, and underscores and has to start with a letter.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI callback to validate a machine readable name.
|
||||
*/
|
||||
function rules_ui_element_machine_name_validate($element, &$form_state) {
|
||||
if ($element['#value'] && !preg_match('!^[a-z0-9_]+$!', $element['#value'])) {
|
||||
form_error($element, t('Machine-readable names must contain only lowercase letters, numbers, and underscores.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FAPI callback to validate the form for editing variable info.
|
||||
* @see RulesPluginUI::getVariableForm()
|
||||
*/
|
||||
function rules_ui_element_variable_form_validate($elements, &$form_state) {
|
||||
$names = array();
|
||||
foreach (element_children($elements['items']) as $item_key) {
|
||||
$element = &$elements['items'][$item_key];
|
||||
if ($element['name']['#value'] || $element['type']['#value'] || $element['label']['#value']) {
|
||||
foreach (array('name' => t('Machine name'), 'label' => t('Label'), 'type' => t('Data type')) as $key => $title) {
|
||||
if (!$element[$key]['#value']) {
|
||||
form_error($element[$key], t('!name field is required.', array('!name' => $title)));
|
||||
}
|
||||
}
|
||||
if (isset($names[$element['name']['#value']])) {
|
||||
form_error($element['name'], t('The machine-readable name %name is already taken.', array('%name' => $element['name']['#value'])));
|
||||
}
|
||||
$names[$element['name']['#value']] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to sort elements by their 'weight' key.
|
||||
*/
|
||||
function rules_element_sort_helper($a, $b) {
|
||||
$a += array('weight' => 0);
|
||||
$b += array('weight' => 0);
|
||||
if ($a['weight'] == $b['weight']) {
|
||||
return 0;
|
||||
}
|
||||
return ($a['weight'] < $b['weight']) ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form after build handler to set the static base path.
|
||||
*
|
||||
* @see RulesPluginUI::formDefaults()
|
||||
*/
|
||||
function rules_form_after_build_restore_base_path($form, &$form_state) {
|
||||
if (isset($form_state['_rules_base_path'])) {
|
||||
RulesPluginUI::$basePath = $form_state['_rules_base_path'];
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX page callback to load tag suggestions.
|
||||
*
|
||||
* Largely copied from taxonomy_autocomplete().
|
||||
*/
|
||||
function rules_autocomplete_tags($tags_typed = '') {
|
||||
// The user enters a comma-separated list of tags. We only autocomplete the
|
||||
// last tag.
|
||||
$tags_typed = drupal_explode_tags($tags_typed);
|
||||
$tag_last = drupal_strtolower(array_pop($tags_typed));
|
||||
|
||||
$tag_matches = array();
|
||||
if ($tag_last != '') {
|
||||
$query = db_select('rules_tags', 'rt');
|
||||
// Do not select already entered terms.
|
||||
if (!empty($tags_typed)) {
|
||||
$query->condition('rt.tag', $tags_typed, 'NOT IN');
|
||||
}
|
||||
// Select rows that match by tag name.
|
||||
$tags_return = $query
|
||||
->distinct()
|
||||
->fields('rt', array('tag'))
|
||||
->condition('rt.tag', '%' . db_like($tag_last) . '%', 'LIKE')
|
||||
->groupBy('rt.tag')
|
||||
->range(0, 10)
|
||||
->execute()
|
||||
->fetchCol('rt.tag');
|
||||
|
||||
$prefix = count($tags_typed) ? drupal_implode_tags($tags_typed) . ', ' : '';
|
||||
|
||||
foreach ($tags_return as $name) {
|
||||
$n = $name;
|
||||
// Tag names containing commas or quotes must be wrapped in quotes.
|
||||
if (strpos($name, ',') !== FALSE || strpos($name, '"') !== FALSE) {
|
||||
$n = '"' . str_replace('"', '""', $name) . '"';
|
||||
}
|
||||
$tag_matches[$prefix . $n] = check_plain($name);
|
||||
}
|
||||
}
|
||||
drupal_json_output($tag_matches);
|
||||
}
|
234
sites/all/modules/rules/ui/ui.plugins.inc
Normal file
234
sites/all/modules/rules/ui/ui.plugins.inc
Normal file
@@ -0,0 +1,234 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file Contains UI for diverse plugins provided by Rules.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Rule specific UI.
|
||||
*/
|
||||
class RulesRuleUI extends RulesActionContainerUI {
|
||||
|
||||
protected $rule, $conditions;
|
||||
|
||||
public function __construct(FacesExtendable $object) {
|
||||
parent::__construct($object);
|
||||
$this->rule = $object;
|
||||
$this->conditions = $this->rule->conditionContainer();
|
||||
}
|
||||
|
||||
public function form(&$form, &$form_state, $options = array()) {
|
||||
$form_state['rules_element'] = $this->rule;
|
||||
$label = $this->element->label();
|
||||
// Automatically add a counter to unlabelled rules.
|
||||
if ($label == t('unlabeled') && !$this->element->isRoot() && !empty($options['init'])) {
|
||||
$parent = $this->element->parentElement();
|
||||
$label .= ' ' . count($parent->getIterator());
|
||||
}
|
||||
// Components have already a label. If used inside a rule-set add a label
|
||||
// though. It's called 'Name' in the UI though.
|
||||
if (!$this->element->isRoot()) {
|
||||
$form['label'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Name'),
|
||||
'#default_value' => empty($options['init']) ? $label : '',
|
||||
'#required' => TRUE,
|
||||
'#weight' => 5,
|
||||
'#description' => t('A human-readable name shortly describing the rule.'),
|
||||
);
|
||||
}
|
||||
|
||||
$form += array('conditions' => array('#weight' => -5, '#tree' => TRUE));
|
||||
$this->conditions->form($form['conditions'], $form_state);
|
||||
unset($form['conditions']['negate']);
|
||||
|
||||
// Add actions form.
|
||||
$iterator = new RecursiveIteratorIterator($this->rule->actions(), RecursiveIteratorIterator::SELF_FIRST);
|
||||
parent::form($form, $form_state, $options, $iterator);
|
||||
// Hide nested elements during creation.
|
||||
$form['elements']['#access'] = empty($options['init']);
|
||||
$form['conditions']['elements']['#access'] = empty($options['init']);
|
||||
|
||||
$form_state['redirect'] = RulesPluginUI::path($this->element->root()->name, 'edit', $this->element);
|
||||
if (!empty($options['button'])) {
|
||||
$form['submit']['#value'] = t('Save changes');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the values of the form to the rule configuration.
|
||||
*/
|
||||
function form_extract_values($form, &$form_state) {
|
||||
$form_values = RulesPluginUI::getFormStateValues($form, $form_state);
|
||||
// Run condition and action container value extraction.
|
||||
if (isset($form['conditions'])) {
|
||||
$this->conditions->extender('RulesConditionContainerUI')->form_extract_values($form['conditions'], $form_state);
|
||||
}
|
||||
if (!empty($form_values['label'])) {
|
||||
$this->element->label = $form_values['label'];
|
||||
}
|
||||
parent::form_extract_values($form, $form_state);
|
||||
}
|
||||
|
||||
|
||||
public function operations() {
|
||||
// When rules are listed only show the edit and delete operations.
|
||||
$ops = parent::operations();
|
||||
$ops['#links'] = array_intersect_key($ops['#links'], array_flip(array('edit', 'delete')));
|
||||
return $ops;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reaction rule specific UI.
|
||||
*/
|
||||
class RulesReactionRuleUI extends RulesRuleUI {
|
||||
|
||||
public function form(&$form, &$form_state, $options = array()) {
|
||||
$form['events'] = array(
|
||||
'#type' => 'container',
|
||||
'#weight' => -10,
|
||||
'#access' => empty($options['init']),
|
||||
);
|
||||
|
||||
$event_info = rules_fetch_data('event_info');
|
||||
$form['events']['table'] = array(
|
||||
'#theme' => 'table',
|
||||
'#caption' => 'Events',
|
||||
'#header' => array('Event', 'Operations'),
|
||||
'#empty' => t('None'),
|
||||
);
|
||||
$form['events']['table']['#attributes']['class'][] = 'rules-elements-table';
|
||||
foreach ($this->rule->events() as $event_name) {
|
||||
$event_info += array($event_name => array('label' => t('Unknown event "!event_name"', array('!event_name' => $event_name))));
|
||||
$form['events']['table']['#rows'][$event_name] = array(
|
||||
check_plain($event_info[$event_name]['label']),
|
||||
'<span class="rules_rule_event">' . l(t('delete'), RulesPluginUI::path($this->rule->name, 'delete/event/' . $event_name)) . '</span>',
|
||||
);
|
||||
}
|
||||
|
||||
// Add the "add event" row.
|
||||
$cell['colspan'] = 3;
|
||||
$cell['data']['#theme'] = 'links__rules';
|
||||
$cell['data']['#attributes']['class'][] = 'rules-operations-add';
|
||||
$cell['data']['#attributes']['class'][] = 'action-links';
|
||||
$cell['data']['#links']['add_event'] = array(
|
||||
'title' => t('Add event'),
|
||||
'href' => RulesPluginUI::path($this->rule->name, 'add/event'),
|
||||
'query' => drupal_get_destination(),
|
||||
);
|
||||
$form['events']['table']['#rows'][] = array('data' => array($cell), 'class' => array('rules-elements-add'));
|
||||
|
||||
parent::form($form, $form_state, $options);
|
||||
unset($form['label']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the configuration settings form (label, tags, description, ..).
|
||||
*/
|
||||
public function settingsForm(&$form, &$form_state) {
|
||||
parent::settingsForm($form, $form_state);
|
||||
$form['settings']['active'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Active'),
|
||||
'#default_value' => !isset($this->rule->active) || $this->rule->active,
|
||||
);
|
||||
$form['settings']['weight'] = array(
|
||||
'#type' => 'weight',
|
||||
'#title' => t('Weight'),
|
||||
'#default_value' => $this->element->weight,
|
||||
'#weight' => 5,
|
||||
'#delta' => 10,
|
||||
'#description' => t('Order rules that react on the same event. Rules with a higher weight are evaluated after rules with less weight.'),
|
||||
);
|
||||
unset($form['settings']['component_provides']);
|
||||
}
|
||||
|
||||
public function settingsFormExtractValues($form, &$form_state) {
|
||||
$form_values = RulesPluginUI::getFormStateValues($form['settings'], $form_state);
|
||||
parent::settingsFormExtractValues($form, $form_state);
|
||||
$this->rule->active = $form_values['active'];
|
||||
$this->rule->weight = $form_values['weight'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rule set specific UI.
|
||||
*/
|
||||
class RulesRuleSetUI extends RulesActionContainerUI {
|
||||
|
||||
public function form(&$form, &$form_state, $options = array(), $iterator = NULL) {
|
||||
// Pass an iterator just iterating over the rules, thus no further child
|
||||
// elements will be displayed.
|
||||
parent::form($form, $form_state, $options, $this->element->getIterator());
|
||||
// Only show the add rule link.
|
||||
$form['elements']['#add']['#links'] = array_intersect_key($form['elements']['#add']['#links'], array('add_rule' => 1));
|
||||
$form['elements']['#attributes']['class'][] = 'rules-rule-set';
|
||||
$form['elements']['#caption'] = t('Rules');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI for Rules loops.
|
||||
*/
|
||||
class RulesLoopUI extends RulesActionContainerUI {
|
||||
|
||||
public function form(&$form, &$form_state, $options = array()) {
|
||||
parent::form($form, $form_state, $options);
|
||||
$settings = $this->element->settings;
|
||||
|
||||
$form['item'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Current list item'),
|
||||
'#description' => t('The variable used for holding each list item in the loop. This variable will be available inside the loop only.'),
|
||||
'#tree' => TRUE,
|
||||
);
|
||||
$form['item']['label'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Variable label'),
|
||||
'#default_value' => $settings['item:label'],
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['item']['var'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Variable name'),
|
||||
'#default_value' => $settings['item:var'],
|
||||
'#description' => t('The variable name must contain only lowercase letters, numbers, and underscores and must be unique in the current scope.'),
|
||||
'#element_validate' => array('rules_ui_element_machine_name_validate'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
}
|
||||
|
||||
function form_extract_values($form, &$form_state) {
|
||||
parent::form_extract_values($form, $form_state);
|
||||
$form_values = RulesPluginUI::getFormStateValues($form, $form_state);
|
||||
|
||||
$this->element->settings['item:var'] = $form_values['item']['var'];
|
||||
$this->element->settings['item:label'] = $form_values['item']['label'];
|
||||
}
|
||||
|
||||
public function form_validate($form, &$form_state) {
|
||||
parent::form_validate($form, $form_state);
|
||||
|
||||
$vars = $this->element->availableVariables();
|
||||
$name = $this->element->settings['item:var'];
|
||||
if (isset($vars[$name])) {
|
||||
form_error($form['item']['var'], t('The variable name %name is already taken.', array('%name' => $name)));
|
||||
}
|
||||
}
|
||||
|
||||
public function buildContent() {
|
||||
$content = parent::buildContent();
|
||||
|
||||
$content['description']['item'] = array(
|
||||
'#caption' => t('List item'),
|
||||
'#theme' => 'rules_content_group',
|
||||
);
|
||||
$content['description']['item']['var'] = array(
|
||||
'#theme' => 'rules_variable_view',
|
||||
'#info' => $this->element->listItemInfo(),
|
||||
'#name' => $this->element->settings['item:var'],
|
||||
);
|
||||
return $content;
|
||||
}
|
||||
}
|
287
sites/all/modules/rules/ui/ui.theme.inc
Normal file
287
sites/all/modules/rules/ui/ui.theme.inc
Normal file
@@ -0,0 +1,287 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file Rules theme functions
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Themes a tree of rule elements in a draggable table.
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_rules_elements($variables) {
|
||||
$form = $variables['element'];
|
||||
$form['#theme'] = 'table';
|
||||
$form['#header'] = array(t('Elements'), t('Weight'), t('Operations'));
|
||||
$form['#attributes']['id'] = 'rules-' . drupal_html_id($form['#caption']) . '-id';
|
||||
|
||||
foreach (element_children($form) as $element_id) {
|
||||
$element = &$form[$element_id];
|
||||
|
||||
// Add special classes to be used for tabledrag.js.
|
||||
$element['parent_id']['#attributes']['class'] = array('rules-parent-id');
|
||||
$element['element_id']['#attributes']['class'] = array('rules-element-id');
|
||||
$element['weight']['#attributes']['class'] = array('rules-element-weight');
|
||||
|
||||
$row = array();
|
||||
$row[] = theme('indentation', array('size' => $element['#depth'])) . drupal_render($element['label']);
|
||||
|
||||
$row[] = drupal_render($element['weight']) . drupal_render($element['parent_id']) . drupal_render($element['element_id']);
|
||||
$row[] = array('class' => 'rules-operations', 'data' => $element['operations']);
|
||||
|
||||
$row = array('data' => $row) + $element['#attributes'];
|
||||
$row['class'][] = 'draggable';
|
||||
if (!$element['#container']) {
|
||||
$row['class'][] = 'tabledrag-leaf';
|
||||
}
|
||||
$form['#rows'][] = $row;
|
||||
}
|
||||
if (!empty($form['#rows'])) {
|
||||
drupal_add_tabledrag($form['#attributes']['id'], 'match', 'parent', 'rules-parent-id', 'rules-parent-id', 'rules-element-id', TRUE, 10);
|
||||
drupal_add_tabledrag($form['#attributes']['id'], 'order', 'sibling', 'rules-element-weight');
|
||||
}
|
||||
else {
|
||||
$form['#rows'][] = array(array('data' => t('None'), 'colspan' => 3));
|
||||
}
|
||||
if (!empty($form['#add'])) {
|
||||
$row = array();
|
||||
$row[] = array('data' => $form['#add'], 'colspan' => 3);
|
||||
$form['#rows'][] = array('data' => $row, 'class' => array('rules-elements-add'));
|
||||
}
|
||||
|
||||
// Add a wrapping div.
|
||||
return '<div class="rules-elements-table">' . drupal_render($form) . '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Themes the rules form for editing the used variables.
|
||||
*
|
||||
* @see RulesPluginUI::getVariableForm()
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_rules_ui_variable_form($variables) {
|
||||
$elements = $variables['element'];
|
||||
|
||||
$table['#theme'] = 'table';
|
||||
$table['#header'] = array(t('Data type'), t('Label'), t('Machine name'), t('Usage'), array('data' => t('Weight'), 'class' => array('tabledrag-hide')));
|
||||
$table['#attributes']['id'] = 'rules-' . drupal_html_id($elements['#title']) . '-id';
|
||||
|
||||
foreach (element_children($elements['items']) as $key) {
|
||||
$element = &$elements['items'][$key];
|
||||
// Add special classes to be used for tabledrag.js.
|
||||
$element['weight']['#attributes']['class'] = array('rules-element-weight');
|
||||
|
||||
$row = array();
|
||||
$row[] = array('data' => $element['type']);
|
||||
$row[] = array('data' => $element['label']);
|
||||
$row[] = array('data' => $element['name']);
|
||||
$row[] = array('data' => $element['usage']);
|
||||
$row[] = array('data' => $element['weight']);
|
||||
$row = array('data' => $row) + $element['#attributes'];
|
||||
$row['class'][] = 'draggable';
|
||||
$table['#rows'][] = $row;
|
||||
}
|
||||
$elements['items']['#printed'] = TRUE;
|
||||
if (!empty($table['#rows'])) {
|
||||
drupal_add_tabledrag($table['#attributes']['id'], 'order', 'sibling', 'rules-element-weight');
|
||||
}
|
||||
|
||||
// Theme it like a form item, but with the description above the content.
|
||||
$attributes['class'][] = 'form-item';
|
||||
$attributes['class'][] = 'rules-variables-form';
|
||||
|
||||
$output = '<div' . drupal_attributes($attributes) . '>' . "\n";
|
||||
$output .= theme('form_element_label', $variables);
|
||||
if (!empty($elements['#description'])) {
|
||||
$output .= ' <div class="description">' . $elements['#description'] . "</div>\n";
|
||||
}
|
||||
$output .= ' ' . drupal_render($table) . "\n";
|
||||
// Add in any further children elements.
|
||||
foreach (element_children($elements, TRUE) as $key) {
|
||||
$output .= drupal_render($elements[$key]);
|
||||
}
|
||||
$output .= "</div>\n";
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Themes a view of multiple configuration items.
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_rules_content_group($variables) {
|
||||
$element = $variables['element'];
|
||||
$output = array();
|
||||
foreach (element_children($element) as $key) {
|
||||
$output[] = drupal_render($element[$key]);
|
||||
}
|
||||
$output = array_filter($output);
|
||||
$heading = !empty($element['#caption']) ? "<span class='rules-content-heading'>" . $element['#caption'] . ': </span>' : '';
|
||||
if (!empty($output)) {
|
||||
$element['#attributes']['class'][] = 'rules-element-content-group';
|
||||
return '<div' . drupal_attributes($element['#attributes']) . '>' . $heading . implode(', ', $output) . '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Themes the view of a single parameter configuration.
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_rules_parameter_configuration($variables) {
|
||||
$element = $variables['element'];
|
||||
$content = drupal_render_children($element);
|
||||
// Add the full content to the span's title, but don't use drupal_attributes
|
||||
// for that as this would invoke check_plain() again.
|
||||
$title = strip_tags($content);
|
||||
$element['#attributes']['class'][] = 'rules-parameter-configuration';
|
||||
$attributes = drupal_attributes($element['#attributes']) . " title='$title'";
|
||||
|
||||
$label_attributes['class'][] = 'rules-parameter-label';
|
||||
if (!empty($element['#info']['description'])) {
|
||||
$label_attributes['title'] = $element['#info']['description'];
|
||||
}
|
||||
$label_attributes = drupal_attributes($label_attributes);
|
||||
|
||||
$output = "<span $label_attributes>" . check_plain($element['#info']['label']) . ': </span>';
|
||||
$output .= "<span $attributes>" . truncate_utf8($content, 30, TRUE, TRUE) . "</span>";
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Themes info about variables.
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_rules_variable_view($variables) {
|
||||
$element = $variables['element'];
|
||||
|
||||
$label_attributes['class'][] = 'rules-variable-label';
|
||||
$label_attributes['title'] = '';
|
||||
if (!empty($element['#info']['description'])) {
|
||||
$label_attributes['title'] = $element['#info']['description'] . ' ';
|
||||
}
|
||||
$label_attributes['title'] .= t('Data type: !type', array('!type' => $element['#info']['type']));
|
||||
$label_attributes = drupal_attributes($label_attributes);
|
||||
|
||||
$output = check_plain($element['#info']['label']);
|
||||
$output .= ' (' . check_plain($element['#name']) . ')';
|
||||
return "<span $label_attributes>" . $output . '</span>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Themes help for using the data selector.
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_rules_data_selector_help($variables) {
|
||||
$variables_info = $variables['variables'];
|
||||
$param_info = $variables['parameter'];
|
||||
|
||||
$render = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Data selectors'),
|
||||
'#pre_render' => array(),
|
||||
'#attributes' => array(),
|
||||
);
|
||||
// Make it manually collapsible as we cannot use #collapsible without the
|
||||
// FAPI element processor.
|
||||
$render['#attached']['js'][] = 'misc/collapse.js';
|
||||
$render['#attributes']['class'][] = 'collapsible';
|
||||
$render['#attributes']['class'][] = 'collapsed';
|
||||
|
||||
$render['table'] = array(
|
||||
'#theme' => 'table',
|
||||
'#header' => array(t('Selector'), t('Label'), t('Description')),
|
||||
);
|
||||
foreach (RulesData::matchingDataSelector($variables_info, $param_info) as $selector => $info) {
|
||||
$info += array('label' => '', 'description' => '');
|
||||
$render['table']['#rows'][] = array(check_plain($selector), check_plain(drupal_ucfirst($info['label'])), check_plain($info['description']));
|
||||
}
|
||||
return drupal_render($render);
|
||||
}
|
||||
|
||||
/**
|
||||
* Themes the rules log debug output.
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_rules_log($variables) {
|
||||
$element = $variables['element'];
|
||||
drupal_add_css(drupal_get_path('module', 'rules') . '/ui/rules.ui.css');
|
||||
// Add jquery ui core css and functions, which are needed for the icons.
|
||||
drupal_add_library('system', 'ui');
|
||||
drupal_add_js(drupal_get_path('module', 'rules') . '/ui/rules.debug.js');
|
||||
|
||||
$output = '<div class="rules-debug-log">';
|
||||
|
||||
$output .= '<h3 class="rules-debug-log-head">';
|
||||
$output .= '<span class="rules-debug-open-main rules-debug-collapsible-link">';
|
||||
$output .= '<span unselectable="on" class="ui-icon ui-icon-triangle-1-e rules-debug-icon-open"> </span>';
|
||||
$output .= t('Rules evaluation log');
|
||||
$output .= '</span>';
|
||||
$output .= '</span>';
|
||||
$output .= '<span class="rules-debug-open-all rules-debug-collapsible-link">-' . t('Open all') . '-<span>';
|
||||
$output .= '</h3>';
|
||||
|
||||
$output .= '<div>';
|
||||
$output .= $element['#children'];
|
||||
$output .= '</div>';
|
||||
$output .= '</div>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme rules debug log elements.
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_rules_debug_element($variables) {
|
||||
$output = '<div class="rules-debug-block">';
|
||||
$output .= '<div class="rules-debug-log-head rules-debug-open rules-debug-collapsible-link">"';
|
||||
$output .= '<span unselectable="on" class="ui-icon ui-icon-triangle-1-e rules-debug-icon-open"> </span>';
|
||||
$output .= $variables['head'];
|
||||
if (isset($variables['link'])) {
|
||||
$output .= ' ' . $variables['link'];
|
||||
}
|
||||
$output .= '</div>';
|
||||
$output .= $variables['log'];
|
||||
$output .= '</div>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Themes rules autocomplete forms.
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_rules_autocomplete($variables) {
|
||||
$element = $variables['element'];
|
||||
drupal_add_js(drupal_get_path('module', 'rules') . '/ui/rules.autocomplete.js');
|
||||
drupal_add_library('system', 'ui.autocomplete');
|
||||
drupal_add_library('system', 'ui.button');
|
||||
|
||||
$element['#attributes']['type'] = 'text';
|
||||
element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength'));
|
||||
_form_set_class($element, array('form-text', 'rules-autocomplete'));
|
||||
|
||||
$id = $element['#attributes']['id'];
|
||||
$id_button = drupal_html_id($id . '-button');
|
||||
|
||||
$js_vars['rules_autocomplete'][$id] = array(
|
||||
'inputId' => $id,
|
||||
'source' => url($element['#autocomplete_path'], array('absolute' => TRUE)),
|
||||
);
|
||||
drupal_add_js($js_vars, 'setting');
|
||||
|
||||
$output = '<div class="rules-autocomplete">';
|
||||
$output .= '<input' . drupal_attributes($element['#attributes']) . ' />';
|
||||
$output .= '</div>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* General theme function for displaying settings related help.
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_rules_settings_help($variables) {
|
||||
$text = $variables['text'];
|
||||
$heading = $variables['heading'];
|
||||
return "<p class=\"rules-settings-help\"><strong>$heading:</strong> $text</p>";
|
||||
}
|
Reference in New Issue
Block a user