diff --git a/tests/uc_addresses.views.test b/tests/uc_addresses.views.test new file mode 100644 index 0000000..bed60de --- /dev/null +++ b/tests/uc_addresses.views.test @@ -0,0 +1,261 @@ + 'Ubercart Addresses Views tests', + 'description' => 'Test the Ubercart Addresses Views integration.', + 'group' => 'Ubercart Addresses', + 'dependencies' => array('ctools', 'token', 'uc_store', 'views'), + ); + } + + /** + * Setup. + */ + public function setUp() { + parent::setUp(); + module_enable(array('views')); + } + + /** + * Tests if the address access filters work as expected. + */ + public function testAccessFilters() { + // Setup View. + $this->createView(); + + // Create some users. + $accounts = array(); + $accounts['extraUser'] = $this->basicUser; + $accounts['customerBasic'] = $this->drupalCreateUser(); + $accounts['customerViewDef'] = $this->drupalCreateUser(array('view own default addresses')); + $accounts['customerView'] = $this->drupalCreateUser(array('view own addresses')); + $accounts['customerEdit'] = $this->drupalCreateUser(array('add/edit own addresses')); + $accounts['customerDelete'] = $this->drupalCreateUser(array('add/edit own addresses', 'delete own addresses')); + $accounts['adminViewDef'] = $this->drupalCreateUser(array('view all default addresses')); + $accounts['adminView'] = $this->drupalCreateUser(array('view all addresses')); + $accounts['adminEdit'] = $this->drupalCreateUser(array('add/edit all addresses')); + $accounts['adminAll'] = $this->adminUser; + + // Create 2 addresses for each type of user: + // - one default address. + // - one other address. + foreach ($accounts as $account) { + $addressBook = UcAddressesAddressBook::get($account->uid); + // Create default address. + $address = $addressBook->addAddress(); + $address->setAsDefault(); + $address->setName($account->name . '_default'); + // Create other address. + $address = $addressBook->addAddress(); + $address->setName($account->name . '_other'); + // Save all addresses. + $addressBook->save(); + } + + $this->doAccessFilterTests($accounts['customerBasic'], FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE); + $this->doAccessFilterTests($accounts['customerViewDef'], TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE); + $this->doAccessFilterTests($accounts['customerView'], TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE); + $this->doAccessFilterTests($accounts['customerEdit'], TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE); + $this->doAccessFilterTests($accounts['customerDelete'], TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE); + $this->doAccessFilterTests($accounts['adminViewDef'], TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE); + $this->doAccessFilterTests($accounts['adminView'], TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE); + $this->doAccessFilterTests($accounts['adminEdit'], TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE); + $this->doAccessFilterTests($accounts['adminAll'], TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE); + } + + /** + * Tests if the address access filters work for one particular + * account. + * + * @param object $account + * The account to check access for. + * @param boolean $view_own_def + * If the user is supposed to see his own default addresses. + * @param boolean $view_own + * If the user is supposed to see all of his own addresses. + * @param boolean $edit_own + * If the user is supposed to edit all of his own addresses. + * @param boolean $delete_own + * If the user is supposed to delete all of his own addresses. + * @param boolean $view_all_def + * If the user is supposed to see his all default addresses. + * @param boolean $view_all + * If the user is supposed to see all addresses. + * @param boolean $edit_all + * If the user is supposed to edit all addresses. + * @param boolean $delete_all + * If the user is supposed to delete all addresses. + * + * @return void + */ + protected function doAccessFilterTests($account, $view_own_def, $view_own, $edit_own, $delete_own, $view_all_def, $view_all, $edit_all, $delete_all) { + $this->drupalLogin($account); + + // Test view access. + $this->drupalGet('uc_addresses/view'); + // View own default addresses. + $text = $account->name . '_default'; + if ($view_own_def) { + $this->assertText($text, 'User sees own default address.'); + } + else { + $this->assertNoText($text); + } + // View own addresses. + $text = $account->name . '_other'; + if ($view_own) { + $this->assertText($text); + } + else { + $this->assertNoText($text); + } + // View all default addresses. + $text = $this->basicUser->name . '_default'; + if ($view_all_def) { + $this->assertText($text); + } + else { + $this->assertNoText($text); + } + // View all addresses. + $text = $this->basicUser->name . '_other'; + if ($view_all) { + $this->assertText($text); + } + else { + $this->assertNoText($text); + } + + // Test edit access. + $this->drupalGet('uc_addresses/edit'); + // Edit own address. + $text = $account->name . '_other'; + if ($edit_own) { + $this->assertText($text); + } + else { + $this->assertNoText($text); + } + // Edit all addresses. + $text = $this->basicUser->name . '_other'; + if ($edit_all) { + $this->assertText($text); + } + else { + $this->assertNoText($text); + } + + // Test delete access. + $this->drupalGet('uc_addresses/delete'); + // Delete own address. + $text = $account->name . '_other'; + if ($delete_own) { + $this->assertText($text); + } + else { + $this->assertNoText($text); + } + // Delete all addresses. + $text = $this->basicUser->name . '_other'; + if ($delete_all) { + $this->assertText($text); + } + else { + $this->assertNoText($text); + } + } + + /** + * Creates a View. + * + * @return object + * The created View. + */ + protected function createView() { + $view = new view(); + $view->name = 'uc_addresses_access_filters'; + $view->description = 'Used to test if address access filters work as expected.'; + $view->tag = 'default'; + $view->base_table = 'uc_addresses'; + $view->human_name = 'uc_addresses_access_filters'; + $view->core = 7; + $view->api_version = '3.0'; + $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ + + /* Display: Master */ + $handler = $view->new_display('default', 'Master', 'default'); + $handler->display->display_options['use_more_always'] = FALSE; + $handler->display->display_options['access']['type'] = 'none'; + $handler->display->display_options['cache']['type'] = 'none'; + $handler->display->display_options['query']['type'] = 'views_query'; + $handler->display->display_options['exposed_form']['type'] = 'basic'; + $handler->display->display_options['pager']['type'] = 'none'; + $handler->display->display_options['pager']['options']['offset'] = '0'; + $handler->display->display_options['style_plugin'] = 'default'; + $handler->display->display_options['row_plugin'] = 'fields'; + /* Field: Ubercart Addresses: Address ID */ + $handler->display->display_options['fields']['aid']['id'] = 'aid'; + $handler->display->display_options['fields']['aid']['table'] = 'uc_addresses'; + $handler->display->display_options['fields']['aid']['field'] = 'aid'; + /* Field: Ubercart Addresses: Address name */ + $handler->display->display_options['fields']['address_name']['id'] = 'address_name'; + $handler->display->display_options['fields']['address_name']['table'] = 'uc_addresses'; + $handler->display->display_options['fields']['address_name']['field'] = 'address_name'; + + /* Display: uc_addresses_view_access */ + $handler = $view->new_display('page', 'uc_addresses_view_access', 'page_1'); + $handler->display->display_options['defaults']['hide_admin_links'] = FALSE; + $handler->display->display_options['defaults']['filter_groups'] = FALSE; + $handler->display->display_options['defaults']['filters'] = FALSE; + /* Filter criterion: Ubercart Addresses: Access */ + $handler->display->display_options['filters']['access_view']['id'] = 'access_view'; + $handler->display->display_options['filters']['access_view']['table'] = 'uc_addresses'; + $handler->display->display_options['filters']['access_view']['field'] = 'access_view'; + $handler->display->display_options['filters']['access_view']['value'] = '1'; + $handler->display->display_options['path'] = 'uc_addresses/view'; + + /* Display: uc_addresses_edit_access */ + $handler = $view->new_display('page', 'uc_addresses_edit_access', 'page_2'); + $handler->display->display_options['defaults']['hide_admin_links'] = FALSE; + $handler->display->display_options['defaults']['filter_groups'] = FALSE; + $handler->display->display_options['defaults']['filters'] = FALSE; + /* Filter criterion: Ubercart Addresses: Edit access */ + $handler->display->display_options['filters']['access_edit']['id'] = 'access_edit'; + $handler->display->display_options['filters']['access_edit']['table'] = 'uc_addresses'; + $handler->display->display_options['filters']['access_edit']['field'] = 'access_edit'; + $handler->display->display_options['filters']['access_edit']['value'] = '1'; + $handler->display->display_options['path'] = 'uc_addresses/edit'; + + /* Display: uc_addresses_delete_access */ + $handler = $view->new_display('page', 'uc_addresses_delete_access', 'page_3'); + $handler->display->display_options['defaults']['hide_admin_links'] = FALSE; + $handler->display->display_options['defaults']['filter_groups'] = FALSE; + $handler->display->display_options['defaults']['filters'] = FALSE; + /* Filter criterion: Ubercart Addresses: Delete access */ + $handler->display->display_options['filters']['access_delete']['id'] = 'access_delete'; + $handler->display->display_options['filters']['access_delete']['table'] = 'uc_addresses'; + $handler->display->display_options['filters']['access_delete']['field'] = 'access_delete'; + $handler->display->display_options['filters']['access_delete']['value'] = '1'; + $handler->display->display_options['path'] = 'uc_addresses/delete'; + + // Save View. + $view->save(); + + return $view; + } +} diff --git a/uc_addresses.info b/uc_addresses.info index c64e90a..71295c2 100644 --- a/uc_addresses.info +++ b/uc_addresses.info @@ -20,6 +20,9 @@ files[] = handlers/UcAddressesFieldHandler.class.php files[] = handlers/ubercart.handlers.inc files[] = handlers/uc_addresses.handlers.inc +; Views handlers +files[] = views/uc_addresses_handler_filter_access.inc + ; Test cases files[] = tests/UcAddressesTestCase.class.php files[] = tests/uc_addresses.addressbook.test @@ -28,6 +31,7 @@ files[] = tests/uc_addresses.checkout.test files[] = tests/uc_addresses.order.test files[] = tests/uc_addresses.register.test files[] = tests/uc_addresses.tokens.test +files[] = tests/uc_addresses.views.test ; Additional files with hook implementations files[] = uc_addresses.ubercart.inc diff --git a/views/uc_addresses.views.inc b/views/uc_addresses.views.inc index ade7466..61f8b2f 100644 --- a/views/uc_addresses.views.inc +++ b/views/uc_addresses.views.inc @@ -301,5 +301,37 @@ function uc_addresses_views_data() { ), ); + // Access filters. + $data['uc_addresses']['access_view'] = array( + 'title' => t('Access'), + 'help' => t('Filter the Views results by address view access.'), + 'real field' => 'aid', + 'filter' => array( + 'help' => t('Filters the result of the view by checking address view access.') . ' ' . t('Note that this filter does not work well with pager.'), + 'handler' => 'uc_addresses_handler_filter_access', + 'uc_addresses_access_type' => 'view', + ), + ); + $data['uc_addresses']['access_edit'] = array( + 'title' => t('Edit access'), + 'help' => t('Filter the Views results by address edit access.'), + 'real field' => 'aid', + 'filter' => array( + 'help' => t('Filters the result of the view by checking address edit access.') . ' ' . t('Note that this filter does not work well with pager.'), + 'handler' => 'uc_addresses_handler_filter_access', + 'uc_addresses_access_type' => 'edit', + ), + ); + $data['uc_addresses']['access_delete'] = array( + 'title' => t('Delete access'), + 'help' => t('Filter the Views results by address delete access.'), + 'real field' => 'aid', + 'filter' => array( + 'help' => t('Filters the result of the view by checking address delete access.') . ' ' . t('Note that this filter does not work well with pager.'), + 'handler' => 'uc_addresses_handler_filter_access', + 'uc_addresses_access_type' => 'delete', + ), + ); + return $data; } diff --git a/views/uc_addresses_handler_filter_access.inc b/views/uc_addresses_handler_filter_access.inc new file mode 100644 index 0000000..ce21670 --- /dev/null +++ b/views/uc_addresses_handler_filter_access.inc @@ -0,0 +1,98 @@ +view->uc_addresses_view_access = TRUE; + } + + /** + * Loads a single address. + * + * @param int $aid + * The ID of the address to load. + * @param int $uid + * (optional) The owner of the address. + * + * @return UcAddressesAddresss + * An address object. + */ + public function loadAddress($aid, $uid = NULL) { + if (empty($uid)) { + $address = UcAddressesAddressBook::loadAddress($aid); + } + else { + $address = UcAddressesAddressBook::get($uid)->getAddressById($aid); + } + return $address; + } + + /** + * Remove the rows the user should have no access to. + * + * @param array $values + * The loaded values. + * + * @todo This doesn't work with pager. + */ + public function post_execute(&$values) { + // Guess the field name of 'aid' in the results. + if (!empty($this->relationship)) { + // Table is assumed to be the relationship. + $table = $this->relationship; + } + else { + $table = 'uc_addresses'; + } + $alias = $this->view->query->field_aliases[$table]['aid']; + + foreach ($values as $index => $row) { + $aid = $row->$alias; + $address = $this->loadAddress($aid); + $uid = $address->getUserId(); + $address_user = user_load($uid); + if ( + ($this->value && !$this->check_access($address_user, $address)) + || (!$this->value && $this->check_access($address_user, $address)) + ) { + unset($values[$index]); + $this->view->total_rows--; + } + } + } + + /** + * Checks address access for the current user. + * + * @param object $address_user + * The user who owns the address. + * @param UcAddressesAddress + * The address to check access for. + * + * @return boolean + * TRUE, if the user should have access. + * FALSE otherwise. + */ + public function check_access($address_user, $address) { + switch ($this->definition['uc_addresses_access_type']) { + case 'view': + return UcAddressesPermissions::canViewAddress($address_user, $address); + case 'edit': + return UcAddressesPermissions::canEditAddress($address_user, $address); + case 'delete': + return UcAddressesPermissions::canDeleteAddress($address_user, $address); + } + } +}