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/system/lib/Drupal/system/Plugin/views/field/BulkFormBase.php b/core/modules/system/lib/Drupal/system/Plugin/views/field/BulkFormBase.php
index fda3479..d662038 100644
--- a/core/modules/system/lib/Drupal/system/Plugin/views/field/BulkFormBase.php
+++ b/core/modules/system/lib/Drupal/system/Plugin/views/field/BulkFormBase.php
@@ -112,4 +112,11 @@ public function views_form(&$form, &$form_state) {
   public function query() {
   }
 
+  /**
+   * Overrides \Drupal\views\Plugin\views\Plugin\field\FieldPluginBase::click_sortable().
+   */
+  public function click_sortable() {
+    return FALSE;
+  }
+
 }
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..abdb048
--- /dev/null
+++ b/core/modules/user/config/views.view.people.yml
@@ -0,0 +1,274 @@
+base_field: uid
+base_table: users
+core: 8.x
+description: 'Find and manage people interacting with your site.'
+status: '1'
+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
+            translation_link: translation_link
+            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
+            translation_link:
+              align: ''
+              separator: ''
+              empty_column: '0'
+              responsive: ''
+            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: 'Bulk update'
+          plugin_id: user_bulk_form
+        name:
+          id: name
+          table: users
+          field: name
+          label: Username
+          link_to_user: '1'
+          format_username: '1'
+          plugin_id: user_name
+        status:
+          id: status
+          table: users
+          field: status
+          label: Status
+          type: active-blocked
+          plugin_id: boolean
+        rid:
+          id: rid
+          table: users_roles
+          field: rid
+          label: Roles
+          type: ul
+          plugin_id: user_roles
+        created:
+          id: created
+          table: users
+          field: created
+          label: 'Member for'
+          date_format: 'raw time ago'
+          plugin_id: date
+        access:
+          id: access
+          table: users
+          field: access
+          label: 'Last access'
+          date_format: 'time ago'
+          plugin_id: date
+        edit_node:
+          id: edit_node
+          table: users
+          field: edit_node
+          exclude: '1'
+          text: Edit
+          plugin_id: user_link_edit
+        translation_link:
+          id: translation_link
+          table: users
+          field: translation_link
+          label: 'Translation link'
+          exclude: '1'
+          alter:
+            alter_text: '0'
+          element_class: ''
+          element_default_classes: '1'
+          empty: ''
+          hide_empty: '0'
+          empty_zero: '0'
+          hide_alter_empty: '1'
+          text: Translate
+          plugin_id: translation_entity_link
+        dropbutton:
+          id: dropbutton
+          table: views
+          field: dropbutton
+          label: Operations
+          fields:
+            edit_node: edit_node
+            translation_link: translation_link
+          destination: '1'
+          plugin_id: dropbutton
+      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
+          plugin_id: user_roles
+        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
+          plugin_id: user_permissions
+        status:
+          id: status
+          table: users
+          field: status
+          operator: '='
+          value: All
+          group: '1'
+          exposed: '1'
+          expose:
+            operator_id: ''
+            label: Active
+            operator: status_op
+            identifier: status
+          plugin_id: boolean
+        uid_raw:
+          id: uid_raw
+          table: users
+          field: uid_raw
+          operator: '!='
+          value:
+            value: '0'
+          group: '1'
+          exposed: '0'
+          plugin_id: numeric
+      sorts:
+        created:
+          id: created
+          table: users
+          field: created
+          order: DESC
+          plugin_id: date
+      title: People
+      empty:
+        area:
+          id: area
+          table: views
+          field: area
+          empty: '1'
+          content: 'No people available.'
+          format: filtered_html
+          plugin_id: area
+  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: default
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 6264824..a41c770 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,7 +51,7 @@ public function buildOptionsForm(&$form, &$form_state) {
 
   // An example of field level access control.
   public function access() {
-    return user_access('access user profiles');
+    return user_access('administer users') || user_access('access user profiles');
   }
 
   public function query() {
diff --git a/core/modules/user/lib/Drupal/user/Plugin/views/field/LinkEdit.php b/core/modules/user/lib/Drupal/user/Plugin/views/field/LinkEdit.php
index b50b0da..615663d 100644
--- a/core/modules/user/lib/Drupal/user/Plugin/views/field/LinkEdit.php
+++ b/core/modules/user/lib/Drupal/user/Plugin/views/field/LinkEdit.php
@@ -26,7 +26,7 @@ class LinkEdit extends Link {
    * Overrides \Drupal\user\Plugin\views\field\Link::render_link().
    */
   public function render_link(EntityInterface $entity, \stdClass $values) {
-    if ($entity && $entity->access('edit')) {
+    if ($entity && $entity->access('update')) {
       $this->options['alter']['make_link'] = TRUE;
 
       $text = !empty($this->options['text']) ? $this->options['text'] : t('Edit');
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..0cea647
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/Plugin/views/field/UserBulkForm.php
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Plugin\views\field\UserBulkForm.
+ */
+
+namespace Drupal\user\Plugin\views\field;
+
+use Drupal\Component\Annotation\Plugin;
+use Drupal\system\Plugin\views\field\BulkFormBase;
+
+/**
+ * Defines a user operations bulk form element.
+ *
+ * @Plugin(
+ *   id = "user_bulk_form",
+ *   module = "user"
+ * )
+ */
+class UserBulkForm extends BulkFormBase {
+
+  /**
+   * Implements \Drupal\system\Plugin\views\field\BulkFormBase::getBulkOptions().
+   */
+  protected function getBulkOptions() {
+    return array_map(function($operation) {
+      return $operation['label'];
+    }, drupal_container()->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) {
+        if ($account = $this->get_entity($result)) {
+          $accounts[$account->id()] = $account;
+        }
+      }
+      // If there are no valid accounts selected, return.
+      if (empty($accounts)) {
+        drupal_set_message(t('No updates to perform.'));
+        return;
+      }
+
+      $operations = drupal_container()->get('module_handler')->invokeAll('user_operations', array($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 3b83b52..ebd627d 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 565e40e..c1c80a6 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 171a976..d12c898 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..51f9b4a
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/Tests/Views/BulkFormTest.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Tests\Views\BulkFormTest.
+ */
+
+namespace Drupal\user\Tests\Views;
+
+/**
+ * Tests the views bulk form test.
+ *
+ * @see \Drupal\user\Plugin\views\field\BulkForm
+ */
+class BulkFormTest extends UserTestBase {
+
+  /**
+   * Views used by this test.
+   *
+   * @var array
+   */
+  public static $testViews = array('test_user_bulk_form');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'User: Bulk form',
+      'description' => 'Tests a user bulk form.',
+      'group' => 'Views module integration',
+    );
+  }
+
+  /**
+   * 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.'));
+
+    // Assign a role to a user.
+    $account = $this->users[0];
+    $roles = user_role_names(TRUE);
+    unset($roles[DRUPAL_AUTHENTICATED_RID]);
+    $role = key($roles);
+
+    $this->assertTrue(!isset($account->roles[$role]), 'The user currently does not have a custom role.');
+    $edit = array(
+      'user_bulk_form[1]' => TRUE,
+      'action' => 'add_role-' . $role,
+    );
+    $this->drupalPost(NULL, $edit, t('Apply'));
+    // Re-load the user and check their roles.
+    $account = entity_load('user', $account->id(), TRUE);
+    $this->assertTrue(isset($account->roles[$role]), 'The user now has the custom role.');
+
+    $edit = array(
+      'user_bulk_form[1]' => TRUE,
+      'action' => 'remove_role-' . $role,
+    );
+    $this->drupalPost(NULL, $edit, t('Apply'));
+    // Re-load the user and check their roles.
+    $account = entity_load('user', $account->id(), TRUE);
+    $this->assertTrue(!isset($account->roles[$role]), 'The user no longer has the custom role.');
+
+    // Block a user using the bulk form.
+    $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(), TRUE);
+    $this->assertFalse($account->status);
+    $this->assertNoRaw($account->label(), 'The user is not found in the table.');
+
+    // Remove the user status filter from the view.
+    $view = views_get_view('test_user_bulk_form');
+    $view->removeItem('default', 'filter', 'status');
+    $view->storage->save();
+
+    // Ensure the anonymous user is found.
+    $this->drupalGet('test-user-bulk-form');
+    $this->assertText(config('user.settings')->get('anonymous'));
+    // Attempt to block the anonymous user.
+    $edit = array(
+      'user_bulk_form[0]' => TRUE,
+      'action' => 'block',
+    );
+    $this->drupalPost(NULL, $edit, t('Apply'));
+    $this->assertText(t('No updates to perform.'));
+  }
+
+}
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..591e807
--- /dev/null
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_bulk_form.yml
@@ -0,0 +1,53 @@
+base_field: uid
+base_table: users
+core: 8.x
+description: ''
+status: '1'
+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
+          plugin_id: user_bulk_form
+        name:
+          id: name
+          table: users
+          field: name
+          plugin_id: user_name
+      sorts:
+        uid:
+          id: uid
+          table: users
+          field: uid
+          order: ASC
+          plugin_id: user
+      filters:
+        status:
+          id: status
+          table: users
+          field: status
+          operator: '='
+          value: '1'
+          plugin_id: boolean
+  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 c3931d8..82d3195 100644
--- a/core/modules/user/user.admin.inc
+++ b/core/modules/user/user.admin.inc
@@ -6,283 +6,11 @@
  */
 
 /**
- * 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()
+ * Page callback: Generates user create administration form.
  */
-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 ? '<div class="additional-filters">' . t('and where') . '</div>' : ''),
-  );
-  $form['filters']['status']['filters'] = array(
-    '#type' => 'container',
-    '#attributes' => array('class' => array('filters')),
-  );
-  foreach ($filters as $key => $filter) {
-    $form['filters']['status']['filters'][$key] = array(
-      '#type' => 'select',
-      '#options' => $filter['options'],
-      '#title' => $filter['title'],
-      '#default_value' => '[any]',
-    );
-  }
-
-  $form['filters']['status']['actions'] = array(
-    '#type' => 'actions',
-    '#attributes' => array('class' => array('container-inline')),
-  );
-  $form['filters']['status']['actions']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => (count($session) ? t('Refine') : t('Filter')),
-  );
-  if (count($session)) {
-    $form['filters']['status']['actions']['undo'] = array(
-      '#type' => 'submit',
-      '#value' => t('Undo'),
-    );
-    $form['filters']['status']['actions']['reset'] = array(
-      '#type' => 'submit',
-      '#value' => t('Reset'),
-    );
-  }
-
-  drupal_add_library('system', 'drupal.form');
-
-  return $form;
-}
-
-/**
- * Process result from user administration filter form.
- */
-function user_filter_form_submit($form, &$form_state) {
-  $op = $form_state['values']['op'];
-  $filters = user_filters();
-  switch ($op) {
-    case t('Filter'):
-    case t('Refine'):
-      // Apply every filter that has a choice selected other than 'any'.
-      foreach ($filters as $filter => $options) {
-        if (isset($form_state['values'][$filter]) && $form_state['values'][$filter] != '[any]') {
-          $_SESSION['user_overview_filter'][] = array($filter, $form_state['values'][$filter]);
-        }
-      }
-      break;
-    case t('Undo'):
-      array_pop($_SESSION['user_overview_filter']);
-      break;
-    case t('Reset'):
-      $_SESSION['user_overview_filter'] = array();
-      break;
-    case t('Update'):
-      return;
-  }
-
-  $form_state['redirect'] = 'admin/people';
-  return;
-}
-
-/**
- * Form builder; User administration page.
- *
- * @ingroup forms
- * @see user_admin_account_validate()
- * @see user_admin_account_submit()
- */
-function user_admin_account() {
-
-  $header = array(
-    'username' => array('data' => t('Username'), 'field' => 'u.name'),
-    'status' => array('data' => t('Status'), 'field' => 'u.status', 'class' => array(RESPONSIVE_PRIORITY_LOW)),
-    'roles' => array('data' => t('Roles'), 'class' => array(RESPONSIVE_PRIORITY_LOW)),
-    'member_for' => array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc', 'class' => array(RESPONSIVE_PRIORITY_LOW)),
-    'access' => array('data' => t('Last access'), 'field' => 'u.access', 'class' => array(RESPONSIVE_PRIORITY_LOW)),
-    'operations' => t('Operations'),
-  );
-
-  $query = db_select('users', 'u');
-  $query->condition('u.uid', 0, '<>');
-  user_build_filter_query($query);
-
-  $count_query = clone $query;
-  $count_query->addExpression('COUNT(u.uid)');
-
-  $query = $query
-    ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
-    ->extend('Drupal\Core\Database\Query\TableSortExtender');
-  $query
-    ->fields('u', array('uid', 'name', 'status', 'created', 'access'))
-    ->limit(50)
-    ->orderByHeader($header)
-    ->setCountQuery($count_query);
-  $result = $query->execute();
-
-  $form['options'] = array(
-    '#type' => 'details',
-    '#title' => t('Update options'),
-    '#attributes' => array('class' => array('container-inline')),
-  );
-  $options = array();
-  foreach (module_invoke_all('user_operations') as $operation => $array) {
-    $options[$operation] = $array['label'];
-  }
-  $form['options']['operation'] = array(
-    '#type' => 'select',
-    '#title' => t('Operation'),
-    '#title_display' => 'invisible',
-    '#options' => $options,
-    '#default_value' => 'unblock',
-  );
-  $options = array();
-  $form['options']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Update'),
-  );
-
-  $destination = drupal_get_destination();
-  $status = array(t('blocked'), t('active'));
-  $roles = array_map('check_plain', user_role_names(TRUE));
-  $accounts = array();
-  foreach ($result as $account) {
-    $account = user_load($account->uid);
-    $users_roles = array();
-    $roles_result = db_query('SELECT rid FROM {users_roles} WHERE uid = :uid', array(':uid' => $account->uid));
-    foreach ($roles_result as $user_role) {
-      $users_roles[] = $roles[$user_role->rid];
-    }
-    asort($users_roles);
-
-    $options[$account->uid] = array(
-      'username' => theme('username', array('account' => $account)),
-      'status' =>  $status[$account->status],
-      'roles' => theme('item_list', array('items' => $users_roles)),
-      'member_for' => format_interval(REQUEST_TIME - $account->created),
-      'access' =>  $account->access ? t('@time ago', array('@time' => format_interval(REQUEST_TIME - $account->access))) : t('never'),
-    );
-    $links = array();
-    $links['edit'] = array(
-      'title' => t('Edit'),
-      'href' => 'user/' . $account->uid . '/edit',
-      'query' => $destination,
-    );
-    if (module_invoke('translation_entity', 'translate_access', $account)) {
-      $links['translate'] = array(
-        'title' => t('Translate'),
-        'href' => 'user/' . $account->uid . '/translations',
-        'query' => $destination,
-      );
-    }
-    $options[$account->uid]['operations']['data'] = array(
-      '#type' => 'operations',
-      '#links' => $links,
-    );
-  }
-
-  $form['accounts'] = array(
-    '#type' => 'tableselect',
-    '#header' => $header,
-    '#options' => $options,
-    '#empty' => t('No people available.'),
-  );
-  $form['pager'] = array('#markup' => theme('pager'));
-
-  return $form;
-}
-
-/**
- * Submit the user administration update form.
- */
-function user_admin_account_submit($form, &$form_state) {
-  $operations = module_invoke_all('user_operations', $form, $form_state);
-  $operation = $operations[$form_state['values']['operation']];
-  // Filter out unchecked accounts.
-  $accounts = array_filter($form_state['values']['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);
-
-    drupal_set_message(t('The update has been performed.'));
-  }
-}
-
-function user_admin_account_validate($form, &$form_state) {
-  $form_state['values']['accounts'] = array_filter($form_state['values']['accounts']);
-  if (count($form_state['values']['accounts']) == 0) {
-    form_set_error('', t('No users selected.'));
-  }
+function user_admin_create() {
+  $account = entity_create('user', array());
+  return entity_get_form($account, 'register');
 }
 
 /**
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index bdf5862..016dd2d 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -929,25 +929,16 @@ function user_menu() {
     'file' => 'user.pages.inc',
   );
 
-  // User listing pages.
   $items['admin/people'] = array(
     'title' => 'People',
     'description' => 'Manage user accounts, roles, and permissions.',
-    'page callback' => 'user_admin',
-    'page arguments' => array('list'),
+    'page callback' => 'system_admin_menu_block_page',
     'access arguments' => array('administer users'),
     'position' => 'left',
     'weight' => -4,
-    'file' => 'user.admin.inc',
-  );
-  $items['admin/people/people'] = array(
-    'title' => 'List',
-    'description' => 'Find and manage people interacting with your site.',
-    'access arguments' => array('administer users'),
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'file' => 'user.admin.inc',
+    'file' => 'system.admin.inc',
+    'file path' => drupal_get_path('module', 'system'),
   );
-
   // Permissions and role forms.
   $items['admin/people/permissions'] = array(
     'title' => 'Permissions',
@@ -983,10 +974,18 @@ function user_menu() {
 
   $items['admin/people/create'] = array(
     'title' => 'Add user',
-    'page arguments' => array('create'),
+    'page callback' => 'user_admin_create',
     'access arguments' => array('administer users'),
+    'file' => 'user.admin.inc',
     'type' => MENU_LOCAL_ACTION,
   );
+  $items['admin/people/cancel'] = array(
+    'title' => 'Add user',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_multiple_cancel_confirm'),
+    'access arguments' => array('administer users'),
+    'file' => 'user.admin.inc',
+  );
 
   // Administration pages.
   $items['admin/config/people'] = array(
@@ -1983,7 +1982,7 @@ function user_role_revoke_permissions($rid, array $permissions = array()) {
 /**
  * Implements hook_user_operations().
  */
-function user_user_operations($form = array(), $form_state = array()) {
+function user_user_operations($selected_operation = FALSE) {
   $operations = array(
     'unblock' => array(
       'label' => t('Unblock the selected users'),
@@ -1995,6 +1994,8 @@ function user_user_operations($form = array(), $form_state = array()) {
     ),
     'cancel' => array(
       'label' => t('Cancel the selected user accounts'),
+      'callback' => 'user_user_operations_cancel',
+      'redirect' => 'admin/people/cancel',
     ),
   );
 
@@ -2028,13 +2029,13 @@ function user_user_operations($form = array(), $form_state = array()) {
 
   // If the form has been posted, we need to insert the proper data for
   // role editing if necessary.
-  if (!empty($form_state['submitted'])) {
-    $operation_rid = explode('-', $form_state['values']['operation']);
+  if ($selected_operation) {
+    $operation_rid = explode('-', $selected_operation);
     $operation = $operation_rid[0];
     if ($operation == 'add_role' || $operation == 'remove_role') {
       $rid = $operation_rid[1];
       if (user_access('administer permissions')) {
-        $operations[$form_state['values']['operation']] = array(
+        $operations[$selected_operation] = array(
           'callback' => 'user_multiple_role_edit',
           'callback arguments' => array($operation, $rid),
         );
@@ -2053,7 +2054,6 @@ function user_user_operations($form = array(), $form_state = array()) {
  * Callback function for admin mass unblocking users.
  */
 function user_user_operations_unblock($accounts) {
-  $accounts = user_load_multiple($accounts);
   foreach ($accounts as $account) {
     // Skip unblocking user if they are already unblocked.
     if ($account !== FALSE && $account->status == 0) {
@@ -2067,7 +2067,6 @@ function user_user_operations_unblock($accounts) {
  * Callback function for admin mass blocking users.
  */
 function user_user_operations_block($accounts) {
-  $accounts = user_load_multiple($accounts);
   foreach ($accounts as $account) {
     // Skip blocking user if they are already blocked.
     if ($account !== FALSE && $account->status == 1) {
@@ -2081,18 +2080,24 @@ function user_user_operations_block($accounts) {
 }
 
 /**
+ * Callback function for admin mass canceling users.
+ */
+function user_user_operations_cancel($accounts) {
+  global $user;
+  // Store the accounts to be canceled in a tempstore.
+  drupal_container()->get('user.tempstore')->get('user_user_operations_cancel')->set($user->uid, $accounts);
+}
+
+/**
  * Callback function for admin mass adding/deleting a user role.
  */
 function user_multiple_role_edit($accounts, $operation, $rid) {
-  $role_name = entity_load('user_role', $rid)->label();
-
   switch ($operation) {
     case 'add_role':
-      $accounts = user_load_multiple($accounts);
       foreach ($accounts as $account) {
         // Skip adding the role to the user if they already have it.
         if ($account !== FALSE && !isset($account->roles[$rid])) {
-          $roles = $account->roles + array($rid => $role_name);
+          $roles = $account->roles + array($rid => $rid);
           // For efficiency manually save the original account before applying
           // any changes.
           $account->original = clone $account;
@@ -2102,11 +2107,10 @@ function user_multiple_role_edit($accounts, $operation, $rid) {
       }
       break;
     case 'remove_role':
-      $accounts = user_load_multiple($accounts);
       foreach ($accounts as $account) {
         // Skip removing the role from the user if they already don't have it.
         if ($account !== FALSE && isset($account->roles[$rid])) {
-          $roles = array_diff($account->roles, array($rid => $role_name));
+          $roles = array_diff($account->roles, array($rid => $rid));
           // For efficiency manually save the original account before applying
           // any changes.
           $account->original = clone $account;
@@ -2119,11 +2123,13 @@ function user_multiple_role_edit($accounts, $operation, $rid) {
 }
 
 function user_multiple_cancel_confirm($form, &$form_state) {
-  $edit = $form_state['input'];
+  global $user;
+  // Retrieve the accounts to be canceled from the temp store.
+  $accounts = drupal_container()->get('user.tempstore')->get('user_user_operations_cancel')->get($user->uid);
 
   $form['accounts'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
-  $accounts = user_load_multiple(array_keys(array_filter($edit['accounts'])));
-  foreach ($accounts as $uid => $account) {
+  foreach ($accounts as $account) {
+    $uid = $account->id();
     // Prevent user 1 from being canceled.
     if ($uid <= 1) {
       continue;
@@ -2186,6 +2192,8 @@ function user_multiple_cancel_confirm($form, &$form_state) {
  */
 function user_multiple_cancel_confirm_submit($form, &$form_state) {
   global $user;
+  // Clear out the accounts from the temp store.
+  drupal_container()->get('user.tempstore')->get('user_user_operations_cancel')->delete($user->uid);
 
   if ($form_state['values']['confirm']) {
     foreach ($form_state['values']['accounts'] as $uid => $value) {
diff --git a/core/modules/user/user.views.inc b/core/modules/user/user.views.inc
index 13b1690..5c68b71 100644
--- a/core/modules/user/user.views.inc
+++ b/core/modules/user/user.views.inc
@@ -316,6 +316,14 @@ function user_views_data() {
     ),
   );
 
+  $data['users']['user_bulk_form'] = array(
+    'title' => t('Bulk update'),
+    'help' => t('Add a form element that lets you run operations on multiple users.'),
+    'field' => array(
+      'id' => 'user_bulk_form',
+    ),
+  );
+
   // Define the base group of this table. Fields that don't have a group defined
   // will go into this field by default.
   $data['users_roles']['table']['group']  = t('User');
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index f1cb911..8173e89 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -926,7 +926,6 @@ function views_get_handler($table, $field, $type, $override = NULL) {
   }
 
   // Finally, use the 'broken' handler.
-  debug(t("Missing handler: @table @field @type", array('@table' => $table, '@field' => $field, '@type' => $type)));
   return $manager->createInstance('broken');
 }
 
