Issue #1828410 by dawehner, damiankloip, tim.plunkett, stevector: Added Provide a bulk_form() element for actions.
parent
597337faae
commit
259b4e2468
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Provides views data and handlers for action.module.
|
||||||
|
*
|
||||||
|
* @ingroup views_module_handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements hook_views_data().
|
||||||
|
*
|
||||||
|
* @todo hook_views_data() is used instead of hook_views_data_alter(), because
|
||||||
|
* the alter hook doesn't load the *.views.inc automatically.
|
||||||
|
*/
|
||||||
|
function action_views_data() {
|
||||||
|
$data['views']['action_bulk_form'] = array(
|
||||||
|
'title' => t('Actions bulk form'),
|
||||||
|
'help' => t('Add a form element that lets you apply actions to multiple items.'),
|
||||||
|
'field' => array(
|
||||||
|
'id' => 'action_bulk_form',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements hook_views_form_substitutions().
|
||||||
|
*/
|
||||||
|
function action_views_form_substitutions() {
|
||||||
|
// Views check_plains the column label, so by doing it matches for the
|
||||||
|
// replacement.
|
||||||
|
$select_all_placeholder = check_plain('<!--action-bulk-form-select-all-->');
|
||||||
|
$select_all = array(
|
||||||
|
'#type' => 'checkbox',
|
||||||
|
'#default_value' => FALSE,
|
||||||
|
'#attributes' => array('class' => array('action-table-select-all')),
|
||||||
|
);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$select_all_placeholder => drupal_render($select_all),
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Contains \Drupal\action\Plugin\views\field\BulkForm.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Drupal\action\Plugin\views\field;
|
||||||
|
|
||||||
|
use Drupal\Core\Annotation\Plugin;
|
||||||
|
use Drupal\views\Plugin\views\field\FieldPluginBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a simple bulk operation form element.
|
||||||
|
*
|
||||||
|
* @Plugin(
|
||||||
|
* id = "action_bulk_form",
|
||||||
|
* module = "action"
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
class BulkForm extends FieldPluginBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides \Drupal\views\Plugin\views\Plugin\field\FieldPluginBase::render().
|
||||||
|
*/
|
||||||
|
public function render($values) {
|
||||||
|
return '<!--form-item-' . $this->options['id'] . '--' . $this->view->row_index . '-->';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides \Drupal\views\Plugin\views\Plugin\field\FieldPluginBase::pre_render().
|
||||||
|
*/
|
||||||
|
public function pre_render(&$values) {
|
||||||
|
parent::pre_render($values);
|
||||||
|
|
||||||
|
// If the view is using a table style, provide a placeholder for a
|
||||||
|
// "select all" checkbox.
|
||||||
|
if (!empty($this->view->style_plugin) && $this->view->style_plugin instanceof \Drupal\views\Plugin\views\style\Table) {
|
||||||
|
// Add the tableselect css classes.
|
||||||
|
$this->options['element_label_class'] .= 'select-all';
|
||||||
|
// Hide the actual label of the field on the table header.
|
||||||
|
$this->options['label'] = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements \Drupal\views\Plugin\views\Plugin\field\FieldPluginBase::views_form().
|
||||||
|
*/
|
||||||
|
public function views_form(&$form, &$form_state) {
|
||||||
|
// Add the tableselect javascript.
|
||||||
|
$form['#attached']['library'][] = array('system', 'drupal.tableselect');
|
||||||
|
|
||||||
|
// Render checkboxes for all rows.
|
||||||
|
foreach ($this->view->result as $row_index => $row) {
|
||||||
|
$entity_id = $this->get_value($row);
|
||||||
|
|
||||||
|
$form[$this->options['id']][$row_index] = array(
|
||||||
|
'#type' => 'checkbox',
|
||||||
|
'#default_value' => FALSE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$form[$this->options['id']]['#tree'] = TRUE;
|
||||||
|
|
||||||
|
// Get all available actions.
|
||||||
|
$actions = action_get_all_actions();
|
||||||
|
$entity_type = $this->getEntityType();
|
||||||
|
// Filter actions by the entity type and build options for the form.
|
||||||
|
$actions = array_filter($actions, function($action) use ($entity_type) {
|
||||||
|
return $action['type'] == $entity_type && empty($action['configurable']);
|
||||||
|
});
|
||||||
|
$options = array_map(function($action) {
|
||||||
|
return $action['label'];
|
||||||
|
}, $actions);
|
||||||
|
|
||||||
|
$form['action'] = array(
|
||||||
|
'#type' => 'select',
|
||||||
|
'#title' => t('Action'),
|
||||||
|
'#options' => $options,
|
||||||
|
'#description' => t('Select the action you want to execute on the content entitites.'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Move the submit button beside the selection.
|
||||||
|
$form['actions']['#weight'] = 1;
|
||||||
|
|
||||||
|
// Replace the text with Update.
|
||||||
|
$form['actions']['submit']['#value'] = t('Update');
|
||||||
|
|
||||||
|
// Put the submit button both at the top and bottom.
|
||||||
|
$form['actions_bottom'] = $form['actions'];
|
||||||
|
$form['actions_bottom']['#weight'] = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements \Drupal\views\Plugin\views\Plugin\field\FieldPluginBase::views_form_submit().
|
||||||
|
*/
|
||||||
|
public function views_form_submit(&$form, &$form_state) {
|
||||||
|
if ($form_state['step'] == 'views_form_views_form') {
|
||||||
|
$action = $form_state['values']['action'];
|
||||||
|
$action = action_load($action);
|
||||||
|
$count = 0;
|
||||||
|
|
||||||
|
// Filter only selected checkboxes.
|
||||||
|
$selected = array_filter($form_state['values'][$this->options['id']]);
|
||||||
|
|
||||||
|
if (!empty($selected)) {
|
||||||
|
foreach (array_keys($selected) as $row_index) {
|
||||||
|
$entity = $this->get_entity($this->view->result[$row_index]);
|
||||||
|
actions_do($action->aid, $entity);
|
||||||
|
$entity->save();
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($count) {
|
||||||
|
drupal_set_message(t('%action action performed on %count item(s).', array('%action' => $action->label, '%count' => $count)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides \Drupal\views\Plugin\views\Plugin\field\FieldPluginBase::query().
|
||||||
|
*/
|
||||||
|
public function query() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Contains \Drupal\action\Tests\BulkFormTest.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Drupal\action\Tests;
|
||||||
|
|
||||||
|
use Drupal\simpletest\WebTestBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the views bulk form test.
|
||||||
|
*
|
||||||
|
* @see \Drupal\action\Plugin\views\field\BulkForm
|
||||||
|
*/
|
||||||
|
class BulkFormTest extends WebTestBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modules to enable.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public static $modules = array('action_bulk_test');
|
||||||
|
|
||||||
|
public static function getInfo() {
|
||||||
|
return array(
|
||||||
|
'name' => 'Bulk form',
|
||||||
|
'description' => 'Tests the views bulk form test.',
|
||||||
|
'group' => 'Action',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the bulk form.
|
||||||
|
*/
|
||||||
|
public function testBulkForm() {
|
||||||
|
$nodes = array();
|
||||||
|
for ($i = 0; $i < 10; $i++) {
|
||||||
|
$nodes[] = $this->drupalCreateNode(array('sticky' => FALSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->drupalGet('test_bulk_form');
|
||||||
|
|
||||||
|
$this->assertFieldById('edit-action', NULL, 'The action select field appears.');
|
||||||
|
|
||||||
|
// Make sure a checkbox appears on all rows.
|
||||||
|
$edit = array();
|
||||||
|
for ($i = 0; $i < 10; $i++) {
|
||||||
|
$this->assertFieldById('edit-bulk-form-' . $i, NULL, format_string('The checkbox on row @row appears.', array('@row' => $i)));
|
||||||
|
$edit["bulk_form[$i]"] = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set all nodes to sticky and check that.
|
||||||
|
$edit += array('action' => 'node_make_sticky_action');
|
||||||
|
$this->drupalPost(NULL, $edit, t('Update'));
|
||||||
|
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
$changed_node = node_load($node->id());
|
||||||
|
$this->assertTrue($changed_node->sticky, format_string('Node @nid got marked as sticky.', array('@nid' => $node->id())));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertText('Make content sticky action performed on 10 item(s).');
|
||||||
|
|
||||||
|
// Unpublish just one node.
|
||||||
|
$node = node_load($nodes[0]->id());
|
||||||
|
$this->assertTrue($node->status, 'The node is published.');
|
||||||
|
|
||||||
|
$edit = array('bulk_form[0]' => TRUE, 'action' => 'node_unpublish_action');
|
||||||
|
$this->drupalPost(NULL, $edit, t('Update'));
|
||||||
|
|
||||||
|
$this->assertText('Unpublish content action performed on 1 item(s).');
|
||||||
|
|
||||||
|
// Load the node again.
|
||||||
|
$node = node_load($node->id(), TRUE);
|
||||||
|
$this->assertFalse($node->status, 'A single node has been unpublished.');
|
||||||
|
|
||||||
|
// The second node should still be published.
|
||||||
|
$node = node_load($nodes[1]->id(), TRUE);
|
||||||
|
$this->assertTrue($node->status, 'An unchecked node is still published.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
name = Action bulk form test
|
||||||
|
description = Support module for action bulk form testing.
|
||||||
|
package = Testing
|
||||||
|
version = VERSION
|
||||||
|
core = 8.x
|
||||||
|
hidden = TRUE
|
||||||
|
dependencies[] = action
|
||||||
|
dependencies[] = views
|
|
@ -0,0 +1 @@
|
||||||
|
<?php
|
|
@ -0,0 +1,149 @@
|
||||||
|
base_table: node
|
||||||
|
name: test_bulk_form
|
||||||
|
description: ''
|
||||||
|
tag: ''
|
||||||
|
human_name: form
|
||||||
|
core: 8.x
|
||||||
|
api_version: '3.0'
|
||||||
|
display:
|
||||||
|
default:
|
||||||
|
display_plugin: default
|
||||||
|
id: default
|
||||||
|
display_title: Master
|
||||||
|
position: ''
|
||||||
|
display_options:
|
||||||
|
access:
|
||||||
|
type: perm
|
||||||
|
cache:
|
||||||
|
type: none
|
||||||
|
query:
|
||||||
|
type: views_query
|
||||||
|
exposed_form:
|
||||||
|
type: basic
|
||||||
|
pager:
|
||||||
|
type: full
|
||||||
|
options:
|
||||||
|
items_per_page: '10'
|
||||||
|
style:
|
||||||
|
type: table
|
||||||
|
options:
|
||||||
|
grouping: { }
|
||||||
|
row_class: ''
|
||||||
|
default_row_class: '1'
|
||||||
|
row_class_special: '1'
|
||||||
|
override: '1'
|
||||||
|
sticky: '0'
|
||||||
|
summary: ''
|
||||||
|
columns:
|
||||||
|
title: title
|
||||||
|
action_bulk_form: action_bulk_form
|
||||||
|
info:
|
||||||
|
title:
|
||||||
|
sortable: '0'
|
||||||
|
default_sort_order: asc
|
||||||
|
align: ''
|
||||||
|
separator: ''
|
||||||
|
empty_column: '0'
|
||||||
|
responsive: ''
|
||||||
|
bulk_form:
|
||||||
|
align: ''
|
||||||
|
separator: ''
|
||||||
|
empty_column: '0'
|
||||||
|
responsive: ''
|
||||||
|
default: '-1'
|
||||||
|
empty_table: '0'
|
||||||
|
row:
|
||||||
|
type: fields
|
||||||
|
fields:
|
||||||
|
title:
|
||||||
|
id: title
|
||||||
|
table: node
|
||||||
|
field: title
|
||||||
|
label: ''
|
||||||
|
alter:
|
||||||
|
alter_text: '0'
|
||||||
|
make_link: '0'
|
||||||
|
absolute: '0'
|
||||||
|
trim: '0'
|
||||||
|
word_boundary: '0'
|
||||||
|
ellipsis: '0'
|
||||||
|
strip_tags: '0'
|
||||||
|
html: '0'
|
||||||
|
hide_empty: '0'
|
||||||
|
empty_zero: '0'
|
||||||
|
link_to_node: '1'
|
||||||
|
bulk_form:
|
||||||
|
id: action_bulk_form
|
||||||
|
table: views
|
||||||
|
field: action_bulk_form
|
||||||
|
relationship: none
|
||||||
|
group_type: group
|
||||||
|
admin_label: ''
|
||||||
|
label: 'Bulk form'
|
||||||
|
exclude: '0'
|
||||||
|
alter:
|
||||||
|
alter_text: '0'
|
||||||
|
text: ''
|
||||||
|
make_link: '0'
|
||||||
|
path: ''
|
||||||
|
absolute: '0'
|
||||||
|
external: '0'
|
||||||
|
replace_spaces: '0'
|
||||||
|
path_case: none
|
||||||
|
trim_whitespace: '0'
|
||||||
|
alt: ''
|
||||||
|
rel: ''
|
||||||
|
link_class: ''
|
||||||
|
prefix: ''
|
||||||
|
suffix: ''
|
||||||
|
target: ''
|
||||||
|
nl2br: '0'
|
||||||
|
max_length: ''
|
||||||
|
word_boundary: '1'
|
||||||
|
ellipsis: '1'
|
||||||
|
more_link: '0'
|
||||||
|
more_link_text: ''
|
||||||
|
more_link_path: ''
|
||||||
|
strip_tags: '0'
|
||||||
|
trim: '0'
|
||||||
|
preserve_tags: ''
|
||||||
|
html: '0'
|
||||||
|
element_type: ''
|
||||||
|
element_class: ''
|
||||||
|
element_label_type: ''
|
||||||
|
element_label_class: ''
|
||||||
|
element_label_colon: '1'
|
||||||
|
element_wrapper_type: ''
|
||||||
|
element_wrapper_class: ''
|
||||||
|
element_default_classes: '1'
|
||||||
|
empty: ''
|
||||||
|
hide_empty: '0'
|
||||||
|
empty_zero: '0'
|
||||||
|
hide_alter_empty: '1'
|
||||||
|
filters:
|
||||||
|
status:
|
||||||
|
value: '1'
|
||||||
|
table: node
|
||||||
|
field: status
|
||||||
|
id: status
|
||||||
|
expose:
|
||||||
|
operator: '0'
|
||||||
|
group: '1'
|
||||||
|
sorts:
|
||||||
|
created:
|
||||||
|
id: created
|
||||||
|
table: node
|
||||||
|
field: created
|
||||||
|
order: DESC
|
||||||
|
title: form
|
||||||
|
page_1:
|
||||||
|
display_plugin: page
|
||||||
|
id: page_1
|
||||||
|
display_title: Page
|
||||||
|
position: ''
|
||||||
|
display_options:
|
||||||
|
path: test_bulk_form
|
||||||
|
base_field: nid
|
||||||
|
disabled: '0'
|
||||||
|
module: views
|
||||||
|
langcode: und
|
|
@ -813,6 +813,33 @@ abstract class HandlerBase extends PluginBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the entity type used by this handler.
|
||||||
|
*
|
||||||
|
* If this handler uses a relationship, the base class of the relationship is
|
||||||
|
* taken into account.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* The machine name of the entity type.
|
||||||
|
*/
|
||||||
|
public function getEntityType() {
|
||||||
|
// If the user has configured a relationship on the handler take that into
|
||||||
|
// account.
|
||||||
|
if (!empty($this->options['relationship']) && $this->options['relationship'] != 'none') {
|
||||||
|
$views_data = views_fetch_data($this->view->relationship->table);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$views_data = views_fetch_data($this->view->storage->get('base_table'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($views_data['table']['entity type'])) {
|
||||||
|
return $views_data['table']['entity type'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new \Exception(format_string('No entity type for field @field on view @view', array('@field' => $this->options['id'], '@view' => $this->view->storage->get('name'))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Breaks x,y,z and x+y+z into an array. Numeric only.
|
* Breaks x,y,z and x+y+z into an array. Numeric only.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1110,9 +1110,15 @@ function views_hook_info() {
|
||||||
$hooks['views_data'] = array(
|
$hooks['views_data'] = array(
|
||||||
'group' => 'views',
|
'group' => 'views',
|
||||||
);
|
);
|
||||||
|
$hooks['views_data_alter'] = array(
|
||||||
|
'group' => 'views',
|
||||||
|
);
|
||||||
$hooks['views_query_substitutions'] = array(
|
$hooks['views_query_substitutions'] = array(
|
||||||
'group' => 'views',
|
'group' => 'views',
|
||||||
);
|
);
|
||||||
|
$hooks['views_form_substitutions'] = array(
|
||||||
|
'group' => 'views',
|
||||||
|
);
|
||||||
|
|
||||||
return $hooks;
|
return $hooks;
|
||||||
}
|
}
|
||||||
|
@ -1641,6 +1647,14 @@ function views_form_views_form($form, &$form_state, ViewExecutable $view, $outpu
|
||||||
'#weight' => 50,
|
'#weight' => 50,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$form['actions'] = array(
|
||||||
|
'#type' => 'actions',
|
||||||
|
);
|
||||||
|
$form['actions']['submit'] = array(
|
||||||
|
'#type' => 'submit',
|
||||||
|
'#value' => t('Save'),
|
||||||
|
);
|
||||||
|
|
||||||
$substitutions = array();
|
$substitutions = array();
|
||||||
foreach ($view->field as $field_name => $field) {
|
foreach ($view->field as $field_name => $field) {
|
||||||
$form_element_name = $field_name;
|
$form_element_name = $field_name;
|
||||||
|
@ -1696,15 +1710,6 @@ function views_form_views_form($form, &$form_state, ViewExecutable $view, $outpu
|
||||||
'#type' => 'value',
|
'#type' => 'value',
|
||||||
'#value' => $substitutions,
|
'#value' => $substitutions,
|
||||||
);
|
);
|
||||||
$form['actions'] = array(
|
|
||||||
'#type' => 'container',
|
|
||||||
'#attributes' => array('class' => array('form-actions')),
|
|
||||||
'#weight' => 100,
|
|
||||||
);
|
|
||||||
$form['actions']['submit'] = array(
|
|
||||||
'#type' => 'submit',
|
|
||||||
'#value' => t('Save'),
|
|
||||||
);
|
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue