diff --git a/group.install b/group.install index d398a8e..646d762 100644 --- a/group.install +++ b/group.install @@ -277,3 +277,21 @@ function group_update_8007() { $view->set('display.default.display_options.arguments.gid.title', '{{ arguments.gid|placeholder }} members'); $view->save(TRUE); } + +/** + * Add a request_status column to the group_content_field_data table. + */ +function group_update_8008() { + $database = \Drupal::database(); + $schema = $database->schema(); + + $spec = array( + 'description' => 'Request status code.', + 'type' => 'int', + 'size' => 'small', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 1, + ); + $schema->addField('group_content_field_data', 'request_status', $spec); +} diff --git a/group.links.task.yml b/group.links.task.yml index 0a9d472..1567fc3 100644 --- a/group.links.task.yml +++ b/group.links.task.yml @@ -35,6 +35,12 @@ group.content: route_name: 'entity.group_content.collection' weight: 15 +group.pending_members: + title: 'Pending Members' + base_route: 'entity.group.canonical' + route_name: 'entity.group_content.group_membership.pending_collection' + weight: 15 + group_type.edit_form: title: 'Edit' base_route: 'entity.group_type.edit_form' diff --git a/group.module b/group.module index 906aaca..fb5c226 100644 --- a/group.module +++ b/group.module @@ -15,6 +15,7 @@ use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Access\AccessResult; +use Drupal\Component\Utility\SafeMarkup; /** * Implements hook_help(). @@ -329,6 +330,23 @@ function group_user_predelete(EntityInterface $account) { } /** + * Implements hook_mail(). + */ +function group_mail($key, &$message, $params) { + $options = array( + 'langcode' => $message['langcode'], + ); + switch ($key) { + case 'immediate_notifications': + $message['from'] = \Drupal::config('system.site')->get('mail'); + $message['subject'] = $params['subject']; + $message['body'][] = SafeMarkup::checkPlain($params['message']); + $message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed; delsp=yes'; + break; + } +} + +/** * @defgroup group_access Group access rights * @{ * The group access system determines who can do what in which groups. @@ -358,4 +376,4 @@ function group_user_predelete(EntityInterface $account) { /** * @} End of "defgroup group_access". - */ + */ \ No newline at end of file diff --git a/src/Controller/GroupMembershipController.php b/src/Controller/GroupMembershipController.php index 75ad79f..99235e2 100644 --- a/src/Controller/GroupMembershipController.php +++ b/src/Controller/GroupMembershipController.php @@ -72,6 +72,7 @@ class GroupMembershipController extends ControllerBase { 'type' => $plugin->getContentTypeConfigId(), 'gid' => $group->id(), 'entity_id' => $this->currentUser->id(), + 'request_status' => 1, ]); return $this->entityFormBuilder->getForm($group_content, 'group-join'); @@ -91,6 +92,70 @@ class GroupMembershipController extends ControllerBase { } /** + * Provides the Request membership form for joining a group. + * + * @param \Drupal\group\Entity\GroupInterface $group + * The group to join. + * + * @return array + * A group join form. + */ + public function requestMembership(GroupInterface $group) { + /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */ + $plugin = $group->getGroupType()->getContentPlugin('group_membership'); + + // Pre-populate a group membership with the current user. + $group_content = GroupContent::create([ + 'type' => $plugin->getContentTypeConfigId(), + 'gid' => $group->id(), + 'entity_id' => $this->currentUser->id(), + 'request_status' => 0, + ]); + + return $this->entityFormBuilder()->getForm($group_content, 'group-request'); + } + + /** + * The _title_callback for the request membership form route. + * + * @param \Drupal\group\Entity\GroupInterface $group + * The group to join. + * + * @return string + * The page title. + */ + public function requestMembershipTitle(GroupInterface $group) { + return $this->t('Request membership group %label', ['%label' => $group->label()]); + } + + /** + * The _title_callback for the request membership form route. + * + * @param \Drupal\group\Entity\GroupInterface $group + * The group to join. + * + * @return string + * The page title. + */ + public function cancelMembershipTitle(GroupInterface $group) { + return $this->t('Cancel membership request for group %label', ['%label' => $group->label()]); + } + + /** + * Provides the form cancel membership for a group. + * + * @param \Drupal\group\Entity\GroupInterface $group + * The group to leave. + * + * @return array + * A group leave form. + */ + public function cancelMembership(GroupInterface $group) { + $group_content = $group->getMember($this->currentUser)->getGroupContent(); + return $this->entityFormBuilder()->getForm($group_content, 'group-cancel'); + } + + /** * Provides the form for leaving a group. * * @param \Drupal\group\Entity\GroupInterface $group diff --git a/src/Entity/Controller/GroupContentListBuilder.php b/src/Entity/Controller/GroupContentListBuilder.php index 9c219cb..59b1547 100644 --- a/src/Entity/Controller/GroupContentListBuilder.php +++ b/src/Entity/Controller/GroupContentListBuilder.php @@ -76,6 +76,14 @@ class GroupContentListBuilder extends EntityListBuilder { protected function getEntityIds() { $query = $this->getStorage()->getQuery(); $query->sort($this->entityType->getKey('id')); + $query->condition('gid', $this->group->id()); + $current_path = explode('/', \Drupal::service('path.current')->getPath()); + if ($current_path[3] == 'pending-members') { + $query->condition('request_status', 0, '='); + } + else { + $query->condition('request_status', 1, '='); + } // Only show group content for the group on the route. $query->condition('gid', $this->group->id()); @@ -132,7 +140,27 @@ class GroupContentListBuilder extends EntityListBuilder { */ protected function getDefaultOperations(EntityInterface $entity) { /** @var \Drupal\group\Entity\GroupContentInterface $entity */ - $operations = parent::getDefaultOperations($entity); + $operations = array(); + $current_path = explode('/', \Drupal::service('path.current')->getPath()); + if ($current_path[3] == 'pending-members') { + if ($entity->access('update') && $entity->hasLinkTemplate('edit-form')) { + $operations['approve'] = array( + 'title' => $this->t('Approve'), + 'weight' => 10, + 'url' => $entity->urlInfo('approve-form'), + ); + } + if ($entity->access('delete') && $entity->hasLinkTemplate('delete-form')) { + $operations['reject'] = array( + 'title' => $this->t('Reject'), + 'weight' => 100, + 'url' => $entity->urlInfo('reject-form'), + ); + } + } + else { + $operations = parent::getDefaultOperations($entity); + } // Improve the edit and delete operation labels. if (isset($operations['edit'])) { diff --git a/src/Entity/Form/GroupContentApproveForm.php b/src/Entity/Form/GroupContentApproveForm.php new file mode 100644 index 0000000..de32640 --- /dev/null +++ b/src/Entity/Form/GroupContentApproveForm.php @@ -0,0 +1,69 @@ +getEntity(); + return $group_content->getContentPlugin(); + } + + /** + * {@inheritdoc} + */ + public function getQuestion() { + return $this->t('Are you sure you want to approve %name?', ['%name' => $this->entity->label()]); + } + + /** + * {@inheritdoc} + */ + public function getCancelURL() { + // @todo Read a redirect from the plugin? + return new Url('entity.group.pending_collection'); + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return $this->t('Approve'); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $entity = $this->getEntity(); + $entity->request_status = 1; + $entity->save(); + + \Drupal::logger('group_content')->notice('@type: approved %title.', [ + '@type' => $this->entity->bundle(), + '%title' => $this->entity->label(), + ]); + // @todo Read a redirect from the plugin? + $form_state->setRedirect('entity.group.collection'); + } + +} diff --git a/src/Entity/Form/GroupContentRejectForm.php b/src/Entity/Form/GroupContentRejectForm.php new file mode 100644 index 0000000..91154b8 --- /dev/null +++ b/src/Entity/Form/GroupContentRejectForm.php @@ -0,0 +1,68 @@ +getEntity(); + return $group_content->getContentPlugin(); + } + + /** + * {@inheritdoc} + */ + public function getQuestion() { + return $this->t('Are you sure you want to reject %name?', ['%name' => $this->entity->label()]); + } + + /** + * {@inheritdoc} + */ + public function getCancelURL() { + // @todo Read a redirect from the plugin? + return new Url('entity.group.pending_collection'); + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return $this->t('Reject'); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $entity = $this->getEntity(); + $entity->delete(); + + \Drupal::logger('group_content')->notice('@type: rejected %title.', [ + '@type' => $this->entity->bundle(), + '%title' => $this->entity->label(), + ]); + // @todo Read a redirect from the plugin? + $form_state->setRedirect('entity.group.collection'); + } + +} diff --git a/src/Entity/Group.php b/src/Entity/Group.php index 708e989..5d69390 100644 --- a/src/Entity/Group.php +++ b/src/Entity/Group.php @@ -195,6 +195,7 @@ class Group extends ContentEntityBase implements GroupInterface { */ public function addMember(UserInterface $account, $values = []) { if (!$this->getMember($account)) { + $values['request_status'] = 1; $this->addContent($account, 'group_membership', $values); } } @@ -202,6 +203,15 @@ class Group extends ContentEntityBase implements GroupInterface { /** * {@inheritdoc} */ + public function getMemberRequestStatus(AccountInterface $account) { + $group_content = $this->membershipLoader()->load($this, $account); + $data = $group_content->getGroupContent(); + return $data->values['request_status']['x-default']; + } + + /** + * {@inheritdoc} + */ public function getMember(AccountInterface $account) { return $this->membershipLoader()->load($this, $account); } diff --git a/src/Entity/GroupContent.php b/src/Entity/GroupContent.php index a7d6d6c..553f026 100644 --- a/src/Entity/GroupContent.php +++ b/src/Entity/GroupContent.php @@ -39,6 +39,8 @@ use Drupal\Core\Entity\EntityStorageInterface; * "delete" = "Drupal\group\Entity\Form\GroupContentDeleteForm", * "group-join" = "Drupal\group\Form\GroupJoinForm", * "group-leave" = "Drupal\group\Form\GroupLeaveForm", + * "approve" = "Drupal\group\Entity\Form\GroupContentApproveForm", + * "reject" = "Drupal\group\Entity\Form\GroupContentRejectForm", * }, * "access" = "Drupal\group\Entity\Access\GroupContentAccessControlHandler", * }, @@ -131,6 +133,7 @@ class GroupContent extends ContentEntityBase implements GroupContentInterface { ->loadByProperties([ 'type' => array_keys($group_content_types), 'entity_id' => $entity->id(), + 'request_status' => 0, ]); } @@ -181,6 +184,12 @@ class GroupContent extends ContentEntityBase implements GroupContentInterface { /** * {@inheritdoc} */ + public function getRequestStatus() { + return $this->get('request_status')->value; + } + /** + * {@inheritdoc} + */ public function setOwnerId($uid) { $this->set('uid', $uid); return $this; @@ -197,6 +206,14 @@ class GroupContent extends ContentEntityBase implements GroupContentInterface { /** * {@inheritdoc} */ + public function setRequestStatus($value) { + $this->set('request_status', $value); + return $this; + } + + /** + * {@inheritdoc} + */ public function preSave(EntityStorageInterface $storage) { parent::preSave($storage); @@ -265,6 +282,13 @@ class GroupContent extends ContentEntityBase implements GroupContentInterface { ->setDescription(t('The time that the group content was last edited.')) ->setTranslatable(TRUE); + $fields['request_status'] = BaseFieldDefinition::create('integer') + ->setLabel(t('Request Status')) + ->setDescription(t('Request mebership status.')) + ->setSetting('unsigned', TRUE) + ->setDefaultValue(1) + ->setTranslatable(TRUE); + return $fields; } diff --git a/src/Entity/GroupInterface.php b/src/Entity/GroupInterface.php index 07eeee5..b4fd69a 100644 --- a/src/Entity/GroupInterface.php +++ b/src/Entity/GroupInterface.php @@ -116,6 +116,17 @@ interface GroupInterface extends ContentEntityInterface, EntityOwnerInterface, E public function getMember(AccountInterface $account); /** + * Retrieves a user's membership request status for the group. + * + * @param \Drupal\Core\Session\AccountInterface $account + * The user to load the membership for. + * + * @return \Drupal\group\GroupMembership|false + * The loaded GroupMembership or FALSE if none was found. + */ + public function getMemberRequestStatus(AccountInterface $account); + + /** * Retrieves all group memberships for the group. * * @param string|array $roles diff --git a/src/Form/GroupCancelRequestMembershipForm.php b/src/Form/GroupCancelRequestMembershipForm.php new file mode 100644 index 0000000..4d603bc --- /dev/null +++ b/src/Form/GroupCancelRequestMembershipForm.php @@ -0,0 +1,33 @@ + $this->getEntity()->getGroup()->label()]; + return $this->t($message, $replace); + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return $this->t('Cancel group mebership request'); + } + +} diff --git a/src/Form/GroupRequestMembershipForm.php b/src/Form/GroupRequestMembershipForm.php new file mode 100644 index 0000000..37eff51 --- /dev/null +++ b/src/Form/GroupRequestMembershipForm.php @@ -0,0 +1,65 @@ + 'textarea', + '#title' => $this->t('Message Body'), + '#description' => $this->t('We will attache this message in request membership mail.'), + ]; + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + parent::submitForm($form, $form_state); + $subject = "Requested Membership for a Group"; + $message = $form_state->getValue('message'); + $to = $this->config('system.site')->get('mail'); + $mailManager = \Drupal::service('plugin.manager.mail'); + $module = 'group'; + $key = 'immediate_notifications'; + $params['message'] = $message; + $params['subject'] = $subject; + $langcode = \Drupal::currentUser()->getPreferredLangcode(); + $send = true; + $result = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send); + if ($result['result'] !== true) { + drupal_set_message(t('There was a problem sending your message and it was not sent.'), 'error'); + }else { + drupal_set_message(t('Mail sent.'), 'status'); + } + } + + /** + * {@inheritdoc} + */ + protected function actions(array $form, FormStateInterface $form_state) { + $actions = parent::actions($form, $form_state); + $actions['submit']['#value'] = $this->t('Request Membership group'); + return $actions; + } + +} diff --git a/src/Plugin/GroupContentEnabler/GroupMembership.php b/src/Plugin/GroupContentEnabler/GroupMembership.php index d828e72..1ceb2c2 100644 --- a/src/Plugin/GroupContentEnabler/GroupMembership.php +++ b/src/Plugin/GroupContentEnabler/GroupMembership.php @@ -36,7 +36,14 @@ class GroupMembership extends GroupContentEnablerBase { $operations = []; if ($group->getMember($account)) { - if ($group->hasPermission('leave group', $account)) { + if ($group->getMemberRequestStatus($account) == 0) { + $operations['group-cancel'] = [ + 'title' => $this->t('Cancel requested membership'), + 'url' => new Url($this->getRouteName('cancel-membership-form'), ['group' => $group->id()]), + 'weight' => 99, + ]; + } + elseif ($group->hasPermission('leave group', $account)) { $operations['group-leave'] = [ 'title' => $this->t('Leave group'), 'url' => new Url('entity.group.leave', ['group' => $group->id()]), @@ -51,6 +58,13 @@ class GroupMembership extends GroupContentEnablerBase { 'weight' => 0, ]; } + if ($group->hasPermission('request group membership', $account) && (!$group->getMember($account))) { + $operations['group-request'] = [ + 'title' => $this->t('Request group membership'), + 'url' => new Url($this->getRouteName('request-membership-form'), ['group' => $group->id()]), + 'weight' => 0, + ]; + } return $operations; } @@ -58,6 +72,18 @@ class GroupMembership extends GroupContentEnablerBase { /** * {@inheritdoc} */ + public function getEntityForms() { + return [ + 'group-join' => 'Drupal\group\Form\GroupJoinForm', + 'group-leave' => 'Drupal\group\Form\GroupLeaveForm', + 'group-request' => 'Drupal\group\Form\GroupRequestMembershipForm', + 'group-cancel' => 'Drupal\group\Form\GroupCancelRequestMembershipForm', + ]; + } + + /** + * {@inheritdoc} + */ public function getPermissions() { $permissions['administer members'] = [ 'title' => 'Administer group members', @@ -76,6 +102,11 @@ class GroupMembership extends GroupContentEnablerBase { 'allowed for' => ['member'], ]; + $permissions['request group membership'] = [ + 'title' => 'Request group membership', + 'allowed for' => ['outsider'], + ]; + // Update the labels of the default permissions. $permissions['view group_membership content']['title'] = 'View individual group members'; $permissions['edit own group_membership content'] = [ @@ -96,6 +127,172 @@ class GroupMembership extends GroupContentEnablerBase { /** * {@inheritdoc} */ + public function getPaths() { + return parent::getPaths() + [ + 'join-form' => '/group/{group}/join', + 'leave-form' => '/group/{group}/leave', + 'request-membership-form' => '/group/{group}/requestMembership', + 'cancel-membership-form' => '/group/{group}/cancelMembership', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getCollectionRoute() { + $route = parent::getCollectionRoute(); + + // Reset the default requirements and add our own group permissions. The '+' + // signifies that only one permission needs to be set for the user. We also + // don't set the _group_installed_content requirement again because we know + // this plugin will always be installed. + $route->setRequirements([])->setRequirement('_group_permission', 'administer members+access group_membership overview'); + + // Swap out the GroupContent list controller for our own. + // @todo Implement this after we've completed the above list controller. + + return $route; + } + + /** + * Gets the join form route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getJoinFormRoute() { + if ($path = $this->getPath('join-form')) { + $route = new Route($path); + + $route + ->setDefaults([ + '_controller' => '\Drupal\group\Controller\GroupMembershipController::join', + '_title_callback' => '\Drupal\group\Controller\GroupMembershipController::joinTitle', + 'plugin_id' => $this->getPluginId(), + ]) + ->setRequirement('_group_permission', 'join group') + ->setRequirement('_group_member', 'FALSE') + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group'], + ]); + + return $route; + } + } + + /** + * Gets the leave form route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getLeaveFormRoute() { + if ($path = $this->getPath('leave-form')) { + $route = new Route($path); + + $route + ->setDefaults([ + '_controller' => '\Drupal\group\Controller\GroupMembershipController::leave', + 'plugin_id' => $this->getPluginId(), + ]) + ->setRequirement('_group_permission', 'leave group') + ->setRequirement('_group_member', 'TRUE') + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group'], + ]); + + return $route; + } + } + + /** + * Gets the leave form route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getRequestMembershipFormRoute() { + if ($path = $this->getPath('request-membership-form')) { + $route = new Route($path); + + $route + ->setDefaults([ + '_controller' => '\Drupal\group\Controller\GroupMembershipController::requestMembership', + '_title_callback' => '\Drupal\group\Controller\GroupMembershipController::requestMembershipTitle', + 'plugin_id' => $this->getPluginId(), + ]) + ->setRequirement('_group_permission', 'request group membership') + ->setRequirement('_group_member', 'FALSE') + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group'], + ]); + + return $route; + } + } + + /** + * Gets the cancel membership form route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getCancelMembershipFormRoute() { + if ($path = $this->getPath('cancel-membership-form')) { + $route = new Route($path); + + $route + ->setDefaults([ + '_controller' => '\Drupal\group\Controller\GroupMembershipController::cancelMembership', + '_title_callback' => '\Drupal\group\Controller\GroupMembershipController::cancelMembershipTitle', + 'plugin_id' => $this->getPluginId(), + ]) + ->setRequirement('_group_member', 'TRUE') + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group'], + ]); + + return $route; + } + } + + /** + * {@inheritdoc} + */ + public function getRoutes() { + $routes = parent::getRoutes(); + + if ($route = $this->getJoinFormRoute()) { + $routes[$this->getRouteName('join-form')] = $route; + } + + if ($route = $this->getLeaveFormRoute()) { + $routes[$this->getRouteName('leave-form')] = $route; + } + + if ($route = $this->getRequestMembershipFormRoute()) { + $routes[$this->getRouteName('request-membership-form')] = $route; + } + + if ($route = $this->getCancelMembershipFormRoute()) { + $routes[$this->getRouteName('cancel-membership-form')] = $route; + } + + return $routes; + } + + /** + * {@inheritdoc} + */ + public function getLocalActions() { + $actions = parent::getLocalActions(); + $actions['group_membership.add']['title'] = 'Add member'; + return $actions; + } + + /** + * {@inheritdoc} + */ public function createAccess(GroupInterface $group, AccountInterface $account) { return GroupAccessResult::allowedIfHasGroupPermission($group, $account, 'administer members'); } diff --git a/src/Plugin/GroupContentEnablerBase.php b/src/Plugin/GroupContentEnablerBase.php index 4ad6db8..2f78e62 100644 --- a/src/Plugin/GroupContentEnablerBase.php +++ b/src/Plugin/GroupContentEnablerBase.php @@ -205,6 +205,325 @@ abstract class GroupContentEnablerBase extends PluginBase implements GroupConten /** * {@inheritdoc} */ + public function getPaths() { + $path_key = $this->pluginDefinition['path_key']; + return empty($path_key) ? [] : [ + 'collection' => "/group/{group}/$path_key", + 'pending-collection' => "/group/{group}/pending-$path_key", + 'add-form' => "/group/{group}/$path_key/add", + 'canonical' => "/group/{group}/$path_key/{group_content}", + 'edit-form' => "/group/{group}/$path_key/{group_content}/edit", + 'delete-form' => "/group/{group}/$path_key/{group_content}/delete", + 'approve-form' => "/group/{group}/$path_key/{group_content}/approve", + 'reject-form' => "/group/{group}/$path_key/{group_content}/reject", + ]; + } + + /** + * {@inheritdoc} + */ + public function getPath($name) { + $paths = $this->getPaths(); + return isset($paths[$name]) ? $paths[$name] : FALSE; + } + + /** + * {@inheritdoc} + */ + public function getRouteName($name) { + $route_prefix = 'entity.group_content.' . str_replace(':', '__', $this->getPluginId()); + return $route_prefix . '.' . str_replace(['-', 'drupal:'], ['_', ''], $name); + } + + /** + * Gets the collection route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getCollectionRoute() { + if ($path = $this->getPath('collection')) { + $plugin_id = $this->getPluginId(); + $route = new Route($path); + + $route + ->setDefaults([ + '_entity_list' => 'group_content', + '_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::title', + 'plugin_id' => $plugin_id, + ]) + ->setRequirement('_group_permission', "access $plugin_id overview") + ->setRequirement('_group_installed_content', $plugin_id) + ->setOption('_group_operation_route', TRUE) + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group'], + ]); + + return $route; + } + } + + /** + * Gets the collection route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getPendingCollectionRoute() { + + if ($path = $this->getPath('pending-collection')) { + $plugin_id = $this->getPluginId(); + $route = new Route($path); + + $route + ->setDefaults([ + '_entity_list' => 'group_content', + '_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::title', + 'plugin_id' => $plugin_id, + ]) + ->setRequirement('_group_permission', "access $plugin_id overview") + ->setRequirement('_group_installed_content', $plugin_id) + + ->setOption('_group_operation_route', TRUE) + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group', 'request_status' => '0'], + ]); + + return $route; + } + } + + /** + * Gets the canonical route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getCanonicalRoute() { + if ($path = $this->getPath('canonical')) { + $route = new Route($path); + + $route + ->setDefaults([ + '_entity_view' => 'group_content.full', + '_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::title', + ]) + ->setRequirement('_entity_access', 'group_content.view') + ->setRequirement('_group_owns_content', 'TRUE') + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group'], + 'group_content' => ['type' => 'entity:group_content'], + ]); + + return $route; + } + } + + /** + * Gets the add form route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getAddFormRoute() { + if ($path = $this->getPath('add-form')) { + $route = new Route($path); + + $route + ->setDefaults([ + '_controller' => '\Drupal\group\Entity\Controller\GroupContentController::add', + '_title_callback' => '\Drupal\group\Entity\Controller\GroupContentController::addPageTitle', + 'plugin_id' => $this->getPluginId(), + ]) + ->setRequirement('_group_content_add_access', $this->getPluginId()) + ->setRequirement('_group_installed_content', $this->getPluginId()) + ->setOption('_group_operation_route', TRUE) + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group'], + ]); + + return $route; + } + } + + /** + * Gets the edit form route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getEditFormRoute() { + if ($path = $this->getPath('edit-form')) { + $route = new Route($path); + + $route + ->setDefaults([ + '_entity_form' => 'group_content.edit', + '_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::editTitle', + ]) + ->setRequirement('_entity_access', 'group_content.update') + ->setRequirement('_group_owns_content', 'TRUE') + ->setOption('_group_operation_route', TRUE) + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group'], + 'group_content' => ['type' => 'entity:group_content'], + ]); + + return $route; + } + } + + /** + * Gets the delete form route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getDeleteFormRoute() { + if ($path = $this->getPath('delete-form')) { + $route = new Route($path); + + $route + ->setDefaults([ + '_entity_form' => 'group_content.delete', + '_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::deleteTitle', + ]) + ->setRequirement('_entity_access', 'group_content.delete') + ->setRequirement('_group_owns_content', 'TRUE') + ->setOption('_group_operation_route', TRUE) + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group'], + 'group_content' => ['type' => 'entity:group_content'], + ]); + + return $route; + } + } + + /** + * Gets the delete form route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getApproveFormRoute() { + if ($path = $this->getPath('approve-form')) { + $route = new Route($path); + + $route + ->setDefaults([ + '_entity_form' => 'group_content.approve', + '_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::editTitle', + ]) + ->setRequirement('_entity_access', 'group_content.update') + ->setRequirement('_group_owns_content', 'TRUE') + ->setOption('_group_operation_route', TRUE) + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group'], + 'group_content' => ['type' => 'entity:group_content'], + ]); + + return $route; + } + } + + /** + * Gets the reject form route. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getRejectFormRoute() { + if ($path = $this->getPath('reject-form')) { + $route = new Route($path); + + $route + ->setDefaults([ + '_entity_form' => 'group_content.reject', + '_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::deleteTitle', + ]) + ->setRequirement('_entity_access', 'group_content.delete') + ->setRequirement('_group_owns_content', 'TRUE') + ->setOption('_group_operation_route', TRUE) + ->setOption('parameters', [ + 'group' => ['type' => 'entity:group'], + 'group_content' => ['type' => 'entity:group_content'], + ]); + + return $route; + } + } + + /** + * {@inheritdoc} + */ + public function getRoutes() { + $routes = []; + + if ($route = $this->getCollectionRoute()) { + $routes[$this->getRouteName('collection')] = $route; + } + + if ($route = $this->getPendingCollectionRoute()) { + $routes[$this->getRouteName('pending-collection')] = $route; + } + + if ($route = $this->getCanonicalRoute()) { + $routes[$this->getRouteName('canonical')] = $route; + } + + if ($route = $this->getAddFormRoute()) { + $routes[$this->getRouteName('add-form')] = $route; + } + + if ($route = $this->getEditFormRoute()) { + $routes[$this->getRouteName('edit-form')] = $route; + } + + if ($route = $this->getDeleteFormRoute()) { + $routes[$this->getRouteName('delete-form')] = $route; + } + + if ($route = $this->getApproveFormRoute()) { + $routes[$this->getRouteName('approve-form')] = $route; + } + + if ($route = $this->getRejectFormRoute()) { + $routes[$this->getRouteName('reject-form')] = $route; + } + return $routes; + } + + /** + * {@inheritdoc} + */ + public function getLocalActions() { + $actions = []; + + if (($appears_on = $this->getRouteName('collection')) && ($route_name = $this->getRouteName('add-form'))) { + $prefix = str_replace(':', '-', $this->getPluginId()); + $actions["$prefix.add"] = [ + 'title' => 'Add ' . $this->getLabel(), + 'route_name' => $route_name, + 'appears_on' => [$appears_on], + ]; + } + + if (($appears_on = $this->getRouteName('pending-collection')) && ($route_name = $this->getRouteName('add-form'))) { + $prefix = str_replace(':', '-', $this->getPluginId()); + $actions["$prefix.add"] = [ + 'title' => 'Add ' . $this->getLabel(), + 'route_name' => $route_name, + 'appears_on' => [$appears_on], + ]; + } + + return $actions; + } + + /** + * {@inheritdoc} + */ public function createAccess(GroupInterface $group, AccountInterface $account) { $plugin_id = $this->getPluginId(); return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "create $plugin_id content");