diff --git a/core/lib/Drupal/Core/DependencyInjection/UpdateBundle.php b/core/lib/Drupal/Core/DependencyInjection/UpdateBundle.php index 539affd..06a9522 100644 --- a/core/lib/Drupal/Core/DependencyInjection/UpdateBundle.php +++ b/core/lib/Drupal/Core/DependencyInjection/UpdateBundle.php @@ -7,7 +7,7 @@ namespace Drupal\Core\DependencyInjection; -use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerBuilder as SymfonyContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; /** @@ -22,7 +22,7 @@ class UpdateBundle extends Bundle { /** * Implements \Symfony\Component\HttpKernel\Bundle\BundleInterface::build(). */ - public function build(ContainerBuilder $container) { + public function build(SymfonyContainerBuilder $container) { // Disable the Lock service. $container ->register('lock', 'Drupal\Core\Lock\NullLockBackend'); diff --git a/core/modules/field/lib/Drupal/field/Tests/Views/ApiDataTest.php b/core/modules/field/lib/Drupal/field/Tests/Views/ApiDataTest.php index 00c48d9..53ac126 100644 --- a/core/modules/field/lib/Drupal/field/Tests/Views/ApiDataTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/Views/ApiDataTest.php @@ -79,19 +79,19 @@ function setUp() { * We check data structure for both node and node revision tables. */ function testViewsData() { - $data = drupal_container()->get('views.views_data')->get(); + $views_data = $this->container->get('views.views_data'); // Check the table and the joins of the first field. // Attached to node only. $field = $this->fields[0]; - $current_table = _field_sql_storage_tablename($field); - $revision_table = _field_sql_storage_revision_tablename($field); - $this->assertTrue(isset($data[$current_table])); - $this->assertTrue(isset($data[$revision_table])); + $current_data = $views_data->get(_field_sql_storage_tablename($field)); + $revision_data = $views_data->get(_field_sql_storage_revision_tablename($field)); + $this->assertTrue($current_data); + $this->assertTrue($revision_data); // The node field should join against node. - $this->assertTrue(isset($data[$current_table]['table']['join']['node'])); - $this->assertTrue(isset($data[$revision_table]['table']['join']['node_revision'])); + $this->assertTrue(isset($current_data['table']['join']['node'])); + $this->assertTrue(isset($revision_data['table']['join']['node_revision'])); $expected_join = array( 'left_field' => 'nid', @@ -101,7 +101,7 @@ function testViewsData() { array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE), ), ); - $this->assertEqual($expected_join, $data[$current_table]['table']['join']['node']); + $this->assertEqual($expected_join, $current_data['table']['join']['node']); $expected_join = array( 'left_field' => 'vid', 'field' => 'revision_id', @@ -110,20 +110,20 @@ function testViewsData() { array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE), ), ); - $this->assertEqual($expected_join, $data[$revision_table]['table']['join']['node_revision']); + $this->assertEqual($expected_join, $revision_data['table']['join']['node_revision']); // Check the table and the joins of the second field. // Attached to both node and user. $field_2 = $this->fields[2]; - $current_table_2 = _field_sql_storage_tablename($field_2); - $revision_table_2 = _field_sql_storage_revision_tablename($field_2); + $current_data_2 = $views_data->get(_field_sql_storage_tablename($field_2)); + $revision_data_2 = $views_data->get(_field_sql_storage_revision_tablename($field_2)); - $this->assertTrue(isset($data[$current_table_2])); - $this->assertTrue(isset($data[$revision_table_2])); + $this->assertTrue($current_data_2); + $this->assertTrue($revision_data_2); // The second field should join against both node and users. - $this->assertTrue(isset($data[$current_table_2]['table']['join']['node'])); - $this->assertTrue(isset($data[$revision_table_2]['table']['join']['node_revision'])); - $this->assertTrue(isset($data[$current_table_2]['table']['join']['users'])); + $this->assertTrue(isset($current_data_2['table']['join']['node'])); + $this->assertTrue(isset($revision_data_2['table']['join']['node_revision'])); + $this->assertTrue(isset($current_data_2['table']['join']['users'])); $expected_join = array( 'left_field' => 'nid', @@ -133,7 +133,7 @@ function testViewsData() { array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE), ) ); - $this->assertEqual($expected_join, $data[$current_table_2]['table']['join']['node']); + $this->assertEqual($expected_join, $current_data_2['table']['join']['node']); $expected_join = array( 'left_field' => 'vid', 'field' => 'revision_id', @@ -142,7 +142,7 @@ function testViewsData() { array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE), ) ); - $this->assertEqual($expected_join, $data[$revision_table_2]['table']['join']['node_revision']); + $this->assertEqual($expected_join, $revision_data_2['table']['join']['node_revision']); $expected_join = array( 'left_field' => 'uid', 'field' => 'entity_id', @@ -151,7 +151,7 @@ function testViewsData() { array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE), ) ); - $this->assertEqual($expected_join, $data[$current_table_2]['table']['join']['users']); + $this->assertEqual($expected_join, $current_data_2['table']['join']['users']); } } diff --git a/core/modules/openid/lib/Drupal/openid/Tests/OpenIDFunctionalTest.php b/core/modules/openid/lib/Drupal/openid/Tests/OpenIDFunctionalTest.php index 1715255..d597c3a 100644 --- a/core/modules/openid/lib/Drupal/openid/Tests/OpenIDFunctionalTest.php +++ b/core/modules/openid/lib/Drupal/openid/Tests/OpenIDFunctionalTest.php @@ -253,6 +253,7 @@ function testDelete() { * Test that a blocked user cannot log in. */ function testBlockedUserLogin() { + module_enable(array('views')); // Use a User-supplied Identity that is the URL of an XRDS document. $identity = url('openid-test/yadis/xrds', array('absolute' => TRUE)); @@ -266,10 +267,10 @@ function testBlockedUserLogin() { $this->drupalLogin($admin_user); $this->drupalGet('admin/people'); $edit = array( - 'operation' => 'block', - 'accounts[' . $this->web_user->uid . ']' => TRUE, + 'action' => 'block', + 'user_bulk_form[2]' => TRUE, ); - $this->drupalPost('admin/people', $edit, t('Update')); + $this->drupalPost('admin/people', $edit, t('Apply')); $this->assertRaw('The update has been performed.', 'Account was blocked.'); $this->drupalLogout(); diff --git a/core/modules/user/config/views.view.people.yml b/core/modules/user/config/views.view.people.yml new file mode 100644 index 0000000..a66b53e --- /dev/null +++ b/core/modules/user/config/views.view.people.yml @@ -0,0 +1,237 @@ +base_field: uid +base_table: users +core: 8.x +description: 'Find and manage people interacting with your site.' +disabled: '0' +display: + default: + display_plugin: default + id: default + display_title: Master + position: '' + display_options: + access: + type: perm + options: + perm: 'administer users' + cache: + type: none + query: + type: views_query + exposed_form: + type: basic + options: + submit_button: Filter + reset_button: '1' + reset_button_label: Reset + pager: + type: full + options: + items_per_page: '50' + style: + type: table + options: + columns: + user_bulk_form: user_bulk_form + name: name + status: status + rid: rid + created: created + access: access + edit_node: edit_node + dropbutton: dropbutton + info: + user_bulk_form: + align: '' + separator: '' + empty_column: '0' + responsive: '' + name: + sortable: '1' + default_sort_order: asc + align: '' + separator: '' + empty_column: '0' + responsive: '' + status: + sortable: '1' + default_sort_order: asc + align: '' + separator: '' + empty_column: '0' + responsive: priority-low + rid: + sortable: '0' + default_sort_order: asc + align: '' + separator: '' + empty_column: '0' + responsive: priority-low + created: + sortable: '1' + default_sort_order: desc + align: '' + separator: '' + empty_column: '0' + responsive: priority-low + access: + sortable: '1' + default_sort_order: desc + align: '' + separator: '' + empty_column: '0' + responsive: priority-low + edit_node: + align: '' + separator: '' + empty_column: '0' + responsive: priority-low + dropbutton: + sortable: '0' + default_sort_order: asc + align: '' + separator: '' + empty_column: '0' + responsive: '' + default: created + row: + type: fields + fields: + user_bulk_form: + id: user_bulk_form + table: users + field: user_bulk_form + label: 'User operations bulk form' + name: + id: name + table: users + field: name + label: Username + link_to_user: '1' + format_username: '1' + status: + id: status + table: users + field: status + label: Status + type: active-blocked + rid: + id: rid + table: users_roles + field: rid + label: Roles + type: ul + created: + id: created + table: users + field: created + label: 'Member for' + date_format: 'raw time ago' + access: + id: access + table: users + field: access + label: 'Last access' + date_format: 'time ago' + edit_node: + id: edit_node + table: users + field: edit_node + exclude: '1' + text: edit + dropbutton: + id: dropbutton + table: views + field: dropbutton + label: Operations + fields: + edit_node: edit_node + destination: '1' + filters: + rid: + id: rid + table: users_roles + field: rid + operator: or + value: { } + group: '1' + exposed: '1' + expose: + operator_id: rid_op + label: Roles + operator: rid_op + identifier: role + permission: + id: permission + table: role_permission + field: permission + operator: or + value: { } + group: '1' + exposed: '1' + expose: + operator_id: permission_op + label: Permission + operator: permission_op + identifier: permission + status: + id: status + table: users + field: status + operator: '=' + value: All + group: '1' + exposed: '1' + expose: + operator_id: '' + label: Active + operator: status_op + identifier: status + uid_raw: + id: uid_raw + table: users + field: uid_raw + operator: '!=' + value: + value: '0' + group: '1' + exposed: '0' + sorts: + created: + id: created + table: users + field: created + order: DESC + title: People + empty: + area: + id: area + table: views + field: area + empty: '1' + content: 'No people available.' + format: filtered_html + page_1: + display_plugin: page + id: page_1 + display_title: Page + position: '' + display_options: + path: admin/people/people + menu: + type: 'default tab' + title: List + description: 'Find and manage people interacting with your site.' + name: admin + weight: '0' + context: '0' + tab_options: + type: normal + title: People + description: 'Manage user accounts, roles, and permissions.' + name: admin + weight: '0' +human_name: People +module: views +id: people +tag: '' diff --git a/core/modules/user/lib/Drupal/user/Plugin/views/field/Link.php b/core/modules/user/lib/Drupal/user/Plugin/views/field/Link.php index 8d354c2..655a185 100644 --- a/core/modules/user/lib/Drupal/user/Plugin/views/field/Link.php +++ b/core/modules/user/lib/Drupal/user/Plugin/views/field/Link.php @@ -51,6 +51,10 @@ public function buildOptionsForm(&$form, &$form_state) { // An example of field level access control. public function access() { + if (user_access('administer users')) { + return TRUE; + } + return user_access('access user profiles'); } diff --git a/core/modules/user/lib/Drupal/user/Plugin/views/field/UserBulkForm.php b/core/modules/user/lib/Drupal/user/Plugin/views/field/UserBulkForm.php new file mode 100644 index 0000000..4dd0144 --- /dev/null +++ b/core/modules/user/lib/Drupal/user/Plugin/views/field/UserBulkForm.php @@ -0,0 +1,78 @@ +get('module_handler')->invokeAll('user_operations')); + } + + /** + * Implements \Drupal\views\Plugin\views\field\FieldPluginBase::views_form_validate(). + */ + public function views_form_validate(&$form, &$form_state) { + $selected = array_filter($form_state['values'][$this->options['id']]); + if (count($selected) == 0) { + form_set_error('', t('No users selected.')); + } + } + + /** + * Implements \Drupal\system\Plugin\views\field\BulkFormBase::views_form_submit(). + */ + public function views_form_submit(&$form, &$form_state) { + if ($form_state['step'] == 'views_form_views_form') { + // Filter only selected checkboxes. + $selected = array_filter($form_state['values'][$this->options['id']]); + $accounts = array(); + foreach (array_intersect_key($this->view->result, $selected) as $result) { + $account = $this->get_entity($result); + $accounts[$account->id()] = $account; + } + + $operations = module_invoke_all('user_operations', $form, $form_state['values']['action']); + $operation = $operations[$form_state['values']['action']]; + // Filter out unchecked accounts. + if ($function = $operation['callback']) { + // Add in callback arguments if present. + if (isset($operation['callback arguments'])) { + $args = array_merge(array($accounts), $operation['callback arguments']); + } + else { + $args = array($accounts); + } + call_user_func_array($function, $args); + + if (isset($operation['redirect'])) { + $form_state['redirect'] = $operation['redirect']; + } + else { + drupal_set_message(t('The update has been performed.')); + } + } + } + } + +} diff --git a/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php b/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php index ef3a1d5..8f1f47e 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php @@ -16,7 +16,7 @@ class UserAdminTest extends WebTestBase { * * @var array */ - public static $modules = array('taxonomy'); + public static $modules = array('taxonomy', 'views'); public static function getInfo() { return array( @@ -49,9 +49,7 @@ function testUserAdmin() { $this->assertRaw($link, 'Found user A edit link on admin users page'); // Filter the users by permission 'administer taxonomy'. - $edit = array(); - $edit['permission'] = 'administer taxonomy'; - $this->drupalPost('admin/people', $edit, t('Filter')); + $this->drupalGet('admin/people', array('query' => array('permission' => 'administer taxonomy'))); // Check if the correct users show up. $this->assertNoText($user_a->name, 'User A not on filtered by perm admin users page'); @@ -61,8 +59,7 @@ function testUserAdmin() { // Filter the users by role. Grab the system-generated role name for User C. $roles = $user_c->roles; unset($roles[DRUPAL_AUTHENTICATED_RID]); - $edit['role'] = key($roles); - $this->drupalPost('admin/people', $edit, t('Refine')); + $this->drupalGet('admin/people', array('query' => array('role' => key($roles)))); // Check if the correct users show up when filtered by role. $this->assertNoText($user_a->name, 'User A not on filtered by role on admin users page'); @@ -73,17 +70,17 @@ function testUserAdmin() { $account = user_load($user_c->uid); $this->assertEqual($account->status, 1, 'User C not blocked'); $edit = array(); - $edit['operation'] = 'block'; - $edit['accounts[' . $account->uid . ']'] = TRUE; - $this->drupalPost('admin/people', $edit, t('Update')); + $edit['action'] = 'block'; + $edit['user_bulk_form[1]'] = TRUE; + $this->drupalPost('admin/people', $edit, t('Apply')); $account = user_load($user_c->uid, TRUE); $this->assertEqual($account->status, 0, 'User C blocked'); // Test unblocking of a user from /admin/people page and sending of activation mail $editunblock = array(); - $editunblock['operation'] = 'unblock'; - $editunblock['accounts[' . $account->uid . ']'] = TRUE; - $this->drupalPost('admin/people', $editunblock, t('Update')); + $editunblock['action'] = 'unblock'; + $editunblock['user_bulk_form[1]'] = TRUE; + $this->drupalPost('admin/people', $editunblock, t('Apply')); $account = user_load($user_c->uid, TRUE); $this->assertEqual($account->status, 1, 'User C unblocked'); $this->assertMail("to", $account->mail, "Activation mail sent to user C"); diff --git a/core/modules/user/lib/Drupal/user/Tests/UserCancelTest.php b/core/modules/user/lib/Drupal/user/Tests/UserCancelTest.php index 70623bd..d08172d 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserCancelTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserCancelTest.php @@ -66,6 +66,7 @@ function testUserCancelWithoutPermission() { * administer the site. */ function testUserCancelUid1() { + module_enable(array('views')); // Update uid 1's name and password to we know it. $password = user_password(); $account = array( @@ -87,10 +88,10 @@ function testUserCancelUid1() { $this->admin_user = $this->drupalCreateUser(array('administer users')); $this->drupalLogin($this->admin_user); $edit = array( - 'operation' => 'cancel', - 'accounts[1]' => TRUE, + 'action' => 'cancel', + 'user_bulk_form[0]' => TRUE, ); - $this->drupalPost('admin/people', $edit, t('Update')); + $this->drupalPost('admin/people', $edit, t('Apply')); // Verify that uid 1's account was not cancelled. $user1 = user_load(1, TRUE); @@ -390,6 +391,7 @@ function testUserWithoutEmailCancelByAdmin() { * Create an administrative user and mass-delete other users. */ function testMassUserCancelByAdmin() { + module_enable(array('views')); config('user.settings')->set('cancel_method', 'user_cancel_reassign')->save(); // Enable account cancellation notification. config('user.settings')->set('notify.status_canceled', TRUE)->save(); @@ -407,14 +409,11 @@ function testMassUserCancelByAdmin() { // Cancel user accounts, including own one. $edit = array(); - $edit['operation'] = 'cancel'; - foreach ($users as $uid => $account) { - $edit['accounts[' . $uid . ']'] = TRUE; + $edit['action'] = 'cancel'; + for ($i = 0; $i <= 4; $i++) { + $edit['user_bulk_form[' . $i . ']'] = TRUE; } - $edit['accounts[' . $admin_user->uid . ']'] = TRUE; - // Also try to cancel uid 1. - $edit['accounts[1]'] = TRUE; - $this->drupalPost('admin/people', $edit, t('Update')); + $this->drupalPost('admin/people', $edit, t('Apply')); $this->assertText(t('Are you sure you want to cancel these user accounts?'), 'Confirmation form to cancel accounts displayed.'); $this->assertText(t('When cancelling these accounts'), 'Allows to select account cancellation method.'); $this->assertText(t('Require e-mail confirmation to cancel account.'), 'Allows to send confirmation mail.'); diff --git a/core/modules/user/lib/Drupal/user/Tests/UserCreateTest.php b/core/modules/user/lib/Drupal/user/Tests/UserCreateTest.php index f728123..540c2ec 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserCreateTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserCreateTest.php @@ -14,6 +14,11 @@ */ class UserCreateTest extends WebTestBase { + /** + * Modules to enable. + */ + public static $modules = array('views'); + public static function getInfo() { return array( 'name' => 'User create', diff --git a/core/modules/user/lib/Drupal/user/Tests/UserTranslationUITest.php b/core/modules/user/lib/Drupal/user/Tests/UserTranslationUITest.php index 1b6160a..2a5456b 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserTranslationUITest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserTranslationUITest.php @@ -24,7 +24,7 @@ class UserTranslationUITest extends EntityTranslationUITest { * * @var array */ - public static $modules = array('language', 'translation_entity', 'user'); + public static $modules = array('language', 'translation_entity', 'user', 'views'); public static function getInfo() { return array( diff --git a/core/modules/user/lib/Drupal/user/Tests/Views/BulkFormTest.php b/core/modules/user/lib/Drupal/user/Tests/Views/BulkFormTest.php new file mode 100644 index 0000000..3c0360b --- /dev/null +++ b/core/modules/user/lib/Drupal/user/Tests/Views/BulkFormTest.php @@ -0,0 +1,66 @@ + 'User: Bulk form', + 'description' => 'Tests a user bulk form.', + 'group' => 'Views Modules', + ); + } + + /** + * Tests the user bulk form. + */ + public function testBulkForm() { + $this->drupalLogin($this->drupalCreateUser(array('administer permissions'))); + + $this->drupalGet('test-user-bulk-form'); + $elements = $this->xpath('//select[@id="edit-action"]//option'); + $this->assertIdentical(count($elements), count($this->container->get('module_handler')->invokeAll('user_operations')), 'All user operations are found.'); + + // Test submitting the page with no selection. + $edit = array( + 'action' => 'block', + ); + $this->drupalPost(NULL, $edit, t('Apply')); + // @todo Validation errors are only shown on page refresh. + $this->drupalGet('test-user-bulk-form'); + $this->assertText(t('No users selected.')); + + // Block a user using the bulk form. + $account = $this->users[0]; + $this->assertTrue($account->status); + $this->assertRaw($account->label(), 'The user is found in the table.'); + $edit = array( + 'user_bulk_form[1]' => TRUE, + 'action' => 'block', + ); + $this->drupalPost(NULL, $edit, t('Apply')); + // Re-load the user and check their status. + $account = entity_load('user', $account->id()); + $this->assertFalse($account->status); + $this->assertNoRaw($account->label(), 'The user is not found in the table.'); + } + +} diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_bulk_form.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_bulk_form.yml new file mode 100644 index 0000000..e9df4b4 --- /dev/null +++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_bulk_form.yml @@ -0,0 +1,49 @@ +base_field: uid +base_table: users +core: 8.x +description: '' +disabled: '0' +display: + default: + display_plugin: default + id: default + display_title: Master + position: '' + display_options: + style: + type: table + row: + type: fields + fields: + user_bulk_form: + id: user_bulk_form + table: users + field: user_bulk_form + name: + id: name + table: users + field: name + sorts: + uid: + id: uid + table: users + field: uid + order: ASC + filters: + status: + id: status + table: users + field: status + operator: '=' + value: '1' + page_1: + display_plugin: page + id: page_1 + display_title: Page + position: '' + display_options: + path: test-user-bulk-form +human_name: '' +module: views +id: test_user_bulk_form +tag: '' diff --git a/core/modules/user/user.admin.inc b/core/modules/user/user.admin.inc index 4da13b8..2e1b8d2 100644 --- a/core/modules/user/user.admin.inc +++ b/core/modules/user/user.admin.inc @@ -6,285 +6,12 @@ */ /** - * Page callback: Generates the appropriate user administration form. - * - * This function generates the user registration, multiple user cancellation, - * or filtered user list admin form, depending on the argument and the POST - * form values. - * - * @param string $callback_arg - * (optional) Indicates which form to build. Defaults to '', which will - * trigger the user filter form. If the POST value 'op' is present, this - * function uses that value as the callback argument. - * - * @return string - * A renderable form array for the respective request. - */ -function user_admin($callback_arg = '') { - $op = isset($_POST['op']) ? $_POST['op'] : $callback_arg; - - switch ($op) { - case t('Create new account'): - case 'create': - $account = entity_create('user', array()); - $build['user_register'] = entity_get_form($account, 'register'); - break; - default: - if (!empty($_POST['accounts']) && isset($_POST['operation']) && ($_POST['operation'] == 'cancel')) { - $build['user_multiple_cancel_confirm'] = drupal_get_form('user_multiple_cancel_confirm'); - } - else { - $build['user_filter_form'] = drupal_get_form('user_filter_form'); - $build['user_admin_account'] = drupal_get_form('user_admin_account'); - } - } - return $build; -} - -/** - * Form builder; Return form for user administration filters. - * - * @ingroup forms - * @see user_filter_form_submit() - */ -function user_filter_form() { - $session = isset($_SESSION['user_overview_filter']) ? $_SESSION['user_overview_filter'] : array(); - $filters = user_filters(); - - $i = 0; - $form['filters'] = array( - '#type' => 'details', - '#title' => t('Show only users where'), - '#theme' => 'exposed_filters__user', - ); - foreach ($session as $filter) { - list($type, $value) = $filter; - if ($type == 'permission') { - // Merge arrays of module permissions into one. - // Slice past the first element '[any]' whose value is not an array. - $options = call_user_func_array('array_merge', array_slice($filters[$type]['options'], 1)); - $value = $options[$value]; - } - else { - $value = $filters[$type]['options'][$value]; - } - $t_args = array('%property' => $filters[$type]['title'], '%value' => $value); - if ($i++) { - $form['filters']['current'][] = array('#markup' => t('and where %property is %value', $t_args)); - } - else { - $form['filters']['current'][] = array('#markup' => t('%property is %value', $t_args)); - } - } - - $form['filters']['status'] = array( - '#type' => 'container', - '#attributes' => array('class' => array('clearfix')), - '#prefix' => ($i ? '