diff --git a/bean.info b/bean.info index bfe92cd..d9ff6ee 100644 --- a/bean.info +++ b/bean.info @@ -8,7 +8,9 @@ files[] = plugins/BeanDefault.class.php files[] = includes/translation.handler.bean.inc files[] = includes/bean.inline_entity_form.inc files[] = views/views_handler_filter_bean_type.inc +files[] = views/views_handler_filter_bean_status.inc files[] = views/views_handler_field_bean_type.inc +files[] = views/views_handler_field_bean_status.inc files[] = views/views_handler_field_bean_edit_link.inc files[] = views/views_handler_field_bean_delete_link.inc files[] = views/views_handler_field_bean_operations.inc @@ -22,4 +24,3 @@ version = "7.x-1.11" core = "7.x" project = "bean" datestamp = "1470638340" - diff --git a/bean.install b/bean.install index 837a0d7..d1230ba 100644 --- a/bean.install +++ b/bean.install @@ -85,6 +85,13 @@ function bean_schema() { 'not null' => TRUE, 'default' => 0, ), + 'status' => array( + 'description' => 'Boolean indicating whether the bean is published (visible to non-administrators).', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 1, + ), + ), 'foreign keys' => array( 'type' => array( @@ -477,3 +484,15 @@ function bean_update_7013() { 'not null' => TRUE, )); } + +/** + * Add bean status field + */ +function bean_update_7014() { + db_add_field('bean', 'status', array( + 'description' => 'Boolean indicating whether the bean is published (visible to non-administrators).', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 1, + )); +} diff --git a/bean.module b/bean.module index d75a115..9ea7a7b 100644 --- a/bean.module +++ b/bean.module @@ -5,6 +5,10 @@ * Block Entity */ +define('BEAN_STATUS_PUBLISHED', 1); +define('BEAN_STATUS_UNPUBLISHED', 0); +define('BEAN_STATUS_DEFAULT', BEAN_STATUS_PUBLISHED); + /** * Implements hook_entity_info(). */ @@ -128,7 +132,8 @@ function bean_menu() { 'title' => 'Block', 'page callback' => 'bean_view_page', 'page arguments' => array(1), - 'access arguments' => array('view bean page'), + 'access callback' => 'bean_access', + 'access arguments' => array('view', 1), 'file' => 'includes/bean.pages.inc', ); @@ -648,6 +653,9 @@ function bean_permission() { 'view bean revisions' => array( 'title' => t('View Bean revisions'), ), + 'view unpublished beans' => array( + 'title' => t('View unpublished Beans'), + ), ); // Add a Permission for each entity type. @@ -697,6 +705,12 @@ function bean_type_access($op, $type = NULL, $account = NULL) { function bean_access($op, $bean = NULL, $account = NULL) { $rights = &drupal_static(__FUNCTION__, array()); +// echo '
';
+//  var_dump($op);
+//  krumo($bean);
+//  var_dump($account);
+//  echo '
'; + // Only real permissions are view, delete, create and edit switch ($op) { case 'view': @@ -768,6 +782,38 @@ function bean_access($op, $bean = NULL, $account = NULL) { } /** + * Implements hook_bean_access(). + */ +function bean_bean_access($bean, $op, $account) { + + switch ($op) { + + // For the view operation, we should always have a Bean object rather than a + // bean type as a string. + case 'view': + + // Figure out if this Bean is visible based on it's pubished status and + // user's permission + $bean_published_permission = TRUE; + if ($bean->status != BEAN_STATUS_PUBLISHED && !user_access('view unpublished beans', $account)) { + $bean_published_permission = FALSE; + } + + // Check if we're viewing the bean on it's page, we use a specific + // permission + $uri = entity_uri('bean', $bean); + if (drupal_match_path(current_path(), $uri['path'])) { + return user_access('view bean page', $account) && $bean_published_permission; + } + + return $bean_published_permission; + + break; + + } +} + +/** * Access callback for the general Bean add page (block/add). */ function bean_add_page_access() { diff --git a/bean.test b/bean.test index 1b69332..674258d 100644 --- a/bean.test +++ b/bean.test @@ -253,12 +253,86 @@ class BeanAccess extends DrupalWebTestCase { ); } + function setUp() { + parent::setUp('bean', 'ctools', 'entity', 'bean_test', 'block'); + } + + /** + * Creates a test bean for testing + * + * @param int $published + * THe published status of the bean + * + * @return \Bean + */ + private function createTestBean($published = BEAN_STATUS_PUBLISHED) { + static $delta = 0; + + $values = array( + 'delta' => 'test_bean_' . $delta++, + 'label' => t('Test Bean'), + 'title' => t('Test Bean'), + 'type' => 'test_bean', + 'status' => $published, + 'view_mode' => 'default', + ); + + $bean = bean_create($values); + bean_save($bean); + return $bean; + } + /** * Test */ public function testAccess() { $this->assertTrue(TRUE, t('Not implemented')); } + + /** + * Test that anonymous user can not view a bean on it's entity path by default + * + * This requires that the user has the "view bean page" permission. + */ + function testAnonUserCanNotViewBeanOnEntityPath() { + $published_bean = $this->createTestBean(); + $unpublished_bean = $this->createTestBean(BEAN_STATUS_UNPUBLISHED); + + $this->drupalGet($published_bean->url()); + $this->assertResponse(403, t('Bean Page is not accessible')); + + $this->drupalGet($unpublished_bean->url()); + $this->assertResponse(403, t('Bean Page is not accessible')); + } + + /** + * Test that a user can view a bean on it's entity path with the + * "view bean page" permission. + */ + function testUserCanViewBeanOnEntityPathWithPermission() { + $bean = $this->createTestBean(); + + $user = $this->drupalCreateUser(array('view bean page')); + $this->drupalLogin($user); + + $this->drupalGet($bean->url()); + $this->assertResponse(200, t('Bean Page is accessible')); + } + + /** + * Test that anonymous user can view an unpublished bean on it's entity path + * with the "view bean page" and "view unpublished bean" permission. + */ + function testUserCanViewUnpublishedBeanWithPermission() { + $bean = $this->createTestBean(BEAN_STATUS_UNPUBLISHED); + + $user = $this->drupalCreateUser(array('view bean page', 'view unpublished beans')); + $this->drupalLogin($user); + + $this->drupalGet($bean->url()); + $this->assertResponse(200, t('Bean Page is accessible')); + } + } /** diff --git a/includes/bean.core.inc b/includes/bean.core.inc index f05bd28..aa4c5fd 100644 --- a/includes/bean.core.inc +++ b/includes/bean.core.inc @@ -153,6 +153,7 @@ class Bean extends Entity { public $vid; public $created; public $changed; + public $status; public $log; public $uid; public $default_revision; diff --git a/includes/bean.pages.inc b/includes/bean.pages.inc index c30fa75..380fa1b 100644 --- a/includes/bean.pages.inc +++ b/includes/bean.pages.inc @@ -229,6 +229,13 @@ function bean_form($form, &$form_state, Bean $bean, $type = NULL) { '#weight' => -9, ); + $form['status'] = array( + '#type' => 'checkbox', + '#title' => t('Published'), + '#default_value' => $bean->status, + '#weight' => 5, + ); + $form['revision'] = array( '#weight' => 10, ); diff --git a/views/bean.views.inc b/views/bean.views.inc index 3f23564..9c31340 100644 --- a/views/bean.views.inc +++ b/views/bean.views.inc @@ -20,6 +20,17 @@ function bean_views_data_alter(&$data) { ), ); + $data['bean']['status'] = array( + 'title' => t('Status'), + 'help' => t('The block status'), + 'field' => array( + 'handler' => 'views_handler_field_bean_status', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_bean_status', + ), + ); + $data['bean']['edit_link'] = array( 'title' => t('Edit link'), 'help' => t('Edit link for bean block'), diff --git a/views/bean.views_default.inc b/views/bean.views_default.inc index 64f995a..70bd734 100644 --- a/views/bean.views_default.inc +++ b/views/bean.views_default.inc @@ -42,6 +42,7 @@ function bean_views_default_views() { 'label' => 'label', 'delta' => 'delta', 'type' => 'type', + 'status' => 'status', 'operations' => 'operations', 'delete_block' => 'operations', ); @@ -73,6 +74,11 @@ function bean_views_default_views() { 'separator' => '', 'empty_column' => 0, ), + 'status' => array( + 'align' => '', + 'separator' => '', + 'empty_column' => 0, + ), 'operations' => array( 'align' => 'views-align-right', 'separator' => '', @@ -100,6 +106,10 @@ function bean_views_default_views() { $handler->display->display_options['fields']['type']['id'] = 'type'; $handler->display->display_options['fields']['type']['table'] = 'bean'; $handler->display->display_options['fields']['type']['field'] = 'type'; + /* Field: Block: Status */ + $handler->display->display_options['fields']['status']['id'] = 'status'; + $handler->display->display_options['fields']['status']['table'] = 'bean'; + $handler->display->display_options['fields']['status']['field'] = 'status'; /* Field: Block: Operationslinks */ $handler->display->display_options['fields']['operations']['id'] = 'operations'; $handler->display->display_options['fields']['operations']['table'] = 'bean'; @@ -122,6 +132,15 @@ function bean_views_default_views() { $handler->display->display_options['filters']['type']['expose']['operator'] = 'type_op'; $handler->display->display_options['filters']['type']['expose']['identifier'] = 'type'; $handler->display->display_options['filters']['type']['expose']['multiple'] = TRUE; + /* Filter criterion: Block: Status */ + $handler->display->display_options['filters']['status']['id'] = 'status'; + $handler->display->display_options['filters']['status']['table'] = 'bean'; + $handler->display->display_options['filters']['status']['field'] = 'status'; + $handler->display->display_options['filters']['status']['exposed'] = TRUE; + $handler->display->display_options['filters']['status']['expose']['operator_id'] = 'status_op'; + $handler->display->display_options['filters']['status']['expose']['label'] = 'Type'; + $handler->display->display_options['filters']['status']['expose']['operator'] = 'status_op'; + $handler->display->display_options['filters']['status']['expose']['identifier'] = 'status'; /* Filter criterion: Block: title */ $handler->display->display_options['filters']['title']['id'] = 'title'; $handler->display->display_options['filters']['title']['table'] = 'bean'; diff --git b/views/views_handler_field_bean_status.inc b/views/views_handler_field_bean_status.inc new file mode 100644 index 0000000..16898c0 --- /dev/null +++ b/views/views_handler_field_bean_status.inc @@ -0,0 +1,20 @@ +bean_status)) { + return t('Published'); + } + return t('Un-published'); + } +} diff --git b/views/views_handler_filter_bean_status.inc b/views/views_handler_filter_bean_status.inc new file mode 100644 index 0000000..a423b6d --- /dev/null +++ b/views/views_handler_filter_bean_status.inc @@ -0,0 +1,17 @@ +value_options)) { + $this->value_title = t('Block status'); + $this->value_options = array( + 1 => t('Published'), + 0 => t('Un-published'), + ); + } + } +}