diff --git a/src/classes/class-tainacan-capabilities.php b/src/classes/class-tainacan-capabilities.php index 2b2216dc4..b6e499ca7 100644 --- a/src/classes/class-tainacan-capabilities.php +++ b/src/classes/class-tainacan-capabilities.php @@ -277,6 +277,11 @@ class Capabilities { function __construct() { add_action('init', array(&$this, 'init'), 11); add_action('tainacan-insert-tainacan-collections', array(&$this, 'new_collection')); + + add_action('tainacan-add-collection-moderators', array(&$this, 'add_moderators'), 10, 2); + add_action('tainacan-remove-collection-moderators', array(&$this, 'remove_moderators'), 10, 2); + + } /** @@ -353,4 +358,44 @@ class Capabilities { { $this->set_items_capabilities($collection); } + + + public function remove_moderators($collection, $moderators) { + $defaults_caps = apply_filters('tainacan-defaults-capabilities', $this->defaults); + if (is_array($moderators)) { + foreach ($moderators as $moderator) { + $user = get_userdata($moderator); + $cpt_object = get_post_type_object($collection->get_db_identifier()); + + if ($user instanceof \WP_User && $cpt_object instanceof \WP_Post_Type) { + $caps = $defaults_caps['tainacan-items']['editor']; + foreach ($caps as $cap) { + $user->remove_cap($cpt_object->cap->$cap); + } + } + } + } + } + + public function add_moderators($collection, $moderators) { + $defaults_caps = apply_filters('tainacan-defaults-capabilities', $this->defaults); + if (is_array($moderators)) { + foreach ($moderators as $moderator) { + $user = get_userdata($moderator); + $cpt_object = get_post_type_object($collection->get_db_identifier()); + + + + if ($user instanceof \WP_User && $cpt_object instanceof \WP_Post_Type) { + $caps = $defaults_caps['tainacan-items']['editor']; + foreach ($caps as $cap) { + $user->add_cap($cpt_object->cap->$cap); + } + } + } + } + } + + + } diff --git a/src/classes/repositories/class-tainacan-collections.php b/src/classes/repositories/class-tainacan-collections.php index 24ba0738f..a3b36f413 100644 --- a/src/classes/repositories/class-tainacan-collections.php +++ b/src/classes/repositories/class-tainacan-collections.php @@ -13,7 +13,8 @@ class Collections extends Repository { public function __construct() { parent::__construct(); - add_filter('user_has_cap', array($this, 'user_has_cap'), 10, 3); + //add_filter('user_has_cap', array($this, 'user_has_cap'), 10, 3); + add_filter('map_meta_cap', array($this, 'map_meta_cap'), 10, 4); } /** * {@inheritDoc} @@ -171,8 +172,11 @@ class Collections extends Repository { * @see \Tainacan\Repositories\Repository::insert() */ public function insert($collection){ - $new_collection = parent::insert($collection); - $collection->register_collection_item_post_type(); + $this->pre_update_moderators($collection); + $new_collection = parent::insert($collection); + + $collection->register_collection_item_post_type(); + $this->update_moderators($new_collection); return $new_collection; } @@ -242,6 +246,68 @@ class Collections extends Repository { } + function pre_update_moderators($collection) { + $current_moderators = $this->get_mapped_property($collection, 'moderators_ids'); + $this->current_moderators = is_array($current_moderators) ? $current_moderators : []; + + } + + function update_moderators($collection) { + $moderators = $collection->get_moderators_ids(); + + $deleted = array_diff($this->current_moderators, $moderators); + $added = array_diff($moderators, $this->current_moderators); + + do_action('tainacan-add-collection-moderators', $collection, $added); + do_action('tainacan-remove-collection-moderators', $collection, $deleted); + } + + /** + * Filter to handle special permissions + * + * @see https://developer.wordpress.org/reference/hooks/map_meta_cap/ + * + */ + public function map_meta_cap($caps, $cap, $user_id, $args) { + + // Filters meta caps edit_tainacan-collection and check if user is moderator + + if ($cap == 'edit_post') { // edit_tainacan-colletion is mapped to edit_post + + $entity = $args[0]; + + if (is_numeric($entity) || $entity instanceof Entities\Collection) { + + if (is_numeric($entity)) { + $post = get_post($entity); + if ($post instanceof \WP_Post && $post->post_type == Entities\Collection::get_post_type()) { + $entity = new Entities\Collection($post); + } + + } + + if ($entity instanceof Entities\Collection) { + $moderators = $entity->get_moderators_ids(); + if (is_array($moderators) && in_array($user_id, $moderators)) { + + // if user is moderator, we clear the current caps + // (that might fave edit_others_posts) and leave only edit_posts + $collection_cpt = get_post_type_object(Entities\Collection::get_post_type()); + $caps = [$collection_cpt->cap->edit_posts]; + } + } + + + + + } + + } + + return $caps; + + } + /** * Filter to handle special permissions * @@ -256,7 +322,7 @@ class Collections extends Repository { * @param array $args [0] Requested capability * [1] User ID * [2] Associated object ID - */ + public function user_has_cap($allcaps, $cap, $args) { if(count($args) > 2) { $entity = Repository::get_entity_by_post($args[2]); @@ -284,5 +350,5 @@ class Collections extends Repository { return $allcaps; } - + */ } \ No newline at end of file diff --git a/tests/test-collections.php b/tests/test-collections.php index 10c9e923c..2c0da5a12 100644 --- a/tests/test-collections.php +++ b/tests/test-collections.php @@ -75,6 +75,9 @@ class Collections extends TAINACAN_UnitTestCase { true ); $this->assertEquals([$autor2], $collection_test_moderator->get_moderators_ids()); + + wp_set_current_user($autor2); + $this->assertTrue(current_user_can($collection_test_moderator->cap->edit_post, $collection_test_moderator->WP_Post->ID)); $this->assertTrue($collection_test_moderator->can_edit($autor2), 'Moderators cannot edit a collection!'); } diff --git a/tests/test-items.php b/tests/test-items.php index 4c9664208..cef76d9f5 100644 --- a/tests/test-items.php +++ b/tests/test-items.php @@ -47,6 +47,7 @@ class Items extends TAINACAN_UnitTestCase { ), true ); + $itemM = $this->tainacan_entity_factory->create_entity( 'item', array( @@ -56,6 +57,10 @@ class Items extends TAINACAN_UnitTestCase { true ); $this->assertEquals([$sub], $collectionM->get_moderators_ids()); + + wp_set_current_user($sub); + $cpt_obj = get_post_type_object($collectionM->get_db_identifier()); + $this->assertTrue(current_user_can($cpt_obj->cap->edit_post, $itemM->get_id()), 'Moderators cannot edit a item!'); $this->assertTrue($itemM->can_edit($sub), 'Moderators cannot edit a item!'); }