sites_group_overrides-1.x-dev/src/Form/SitesGroupOverridesForm.php
src/Form/SitesGroupOverridesForm.php
<?php
declare(strict_types=1);
namespace Drupal\sites_group_overrides\Form;
use Drupal\Core\Url;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\sites_group\SitesGroupServiceInterface;
use Drupal\group\Entity\GroupRelationshipInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\sites_group_overrides\SitesGroupOverridesServiceInterface;
use Drupal\group\Plugin\Group\Relation\GroupRelationTypeManagerInterface;
/**
* Form controller for the content push.
*/
class SitesGroupOverridesForm extends FormBase {
/**
* The entity from route.
*
* @var \Drupal\Core\Entity\ContentEntityInterface
*/
protected $entity = NULL;
/**
* Static cache for reationships.
*/
protected ?array $relationships = NULL;
/**
* Constructs a SitesGroupEntityContentPushForm object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch
* The route match.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeManagerInterface $groupRelationTypeManager
* The group relation type manager.
* @param \Drupal\sites_group\SitesGroupServiceInterface $sitesGroupService
* The sites_group service.
* @param \Drupal\sites_group_overrides\SitesGroupOverridesServiceInterface $sitesGroupOverridesService
* The sites group overrides service.
*/
public function __construct(
protected readonly EntityTypeManagerInterface $entityTypeManager,
RouteMatchInterface $routeMatch,
protected readonly GroupRelationTypeManagerInterface $groupRelationTypeManager,
protected readonly SitesGroupServiceInterface $sitesGroupService,
protected readonly SitesGroupOverridesServiceInterface $sitesGroupOverridesService,
) {
$this->routeMatch = $routeMatch;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager'),
$container->get('current_route_match'),
$container->get('group_relation_type.manager'),
$container->get('sites_group.service'),
$container->get('sites_group_overrides.service'),
);
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'sites_group_overrides';
}
/**
* The _title_callback for the sites page.
*
* @return string
* The page title.
*/
public function title() {
return $this->t('Overrides')->__toString();
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form = [
'#type' => 'details',
'#title' => t('Overrides'),
'#tree' => TRUE,
'#open' => TRUE,
];
$header = [
'group' => $this->t('Site'),
'operations' => $this->t('Operations'),
];
['options' => $options, 'default_value' => $default_value, 'permitted_to_revert_all' => $permitted_to_revert_all] = $this->getTableSelectOptions();
$form['groups'] = [
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options,
'#default_value' => $default_value,
];
if ($permitted_to_revert_all) {
$form['actions'] = ['#type' => 'action'];
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Revert selected overrides'),
];
}
return $form;
}
/**
* Get relationships with overrides
*
* @return GroupRelationshipInterface[]
* The overrides.
*/
protected function getOverrides(): array {
if (is_null($this->relationships)) {
$this->relationships = [];
if ($entity = $this->getEntity()) {
$this->relationships = $this->sitesGroupOverridesService->getRelationshipsWithOverrides($entity);
}
}
return $this->relationships;
}
/**
* Builds the table select options for the form.
*
* @param \Drupal\group\Entity\GroupTypeInterface $group_type
* The group type config entity.
*/
protected function getTableSelectOptions(): array {
$options = [];
$selected = [];
$permitted_to_revert_all = TRUE;
// Build operations and track which relations exist to set the default value
// for the checkboxes of the tableselect element.
$overrides = $this->getOverrides();
$destination = Url::fromRoute('<current>')->toString();
if (count($overrides) == 1) {
$destination = $this->getSitesTabUrl()->toString();
}
foreach ($overrides as $relationship) {
$selected[$relationship->getGroup()->id()] = $relationship->getGroup()->id();
$options[$relationship->getGroup()->id()] = [
'group' => $relationship->getGroup()->label(),
'operations' => [],
];
$operations = [];
$operations['revert.' . $relationship->id()] = [
'title' => $this->t('Revert override'),
'url' => Url::fromRoute(
'sites_group_overrides.revert_to_defaults', [
'group' => $relationship->getGroupId(),
'group_relationship' => $relationship->id(),
],
['query' => ['destination' => $destination]],
),
'weight' => 10,
];
if ($relationship->getGroup()->hasPermission("revert content overrides", $this->currentUser())) {
$options[$relationship->getGroup()->id()]['operations'] = [
'data' => [
'#type' => 'operations',
'#links' => $operations,
// Allow links to use modals.
'#attached' => [
'library' => ['core/drupal.dialog.ajax'],
],
],
];
}
else {
$permitted_to_revert_all = FALSE;
}
}
return [
'options' => $options,
'default_value' => $selected,
'permitted_to_revert_all' => $permitted_to_revert_all,
];
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$all_overrides_reverted = TRUE;
$selected_grouops = $form_state->getValue('groups');
foreach($this->getOverrides() as $relationship) {
if ($selected_grouops[$relationship->getGroupId()]) {
$this->sitesGroupOverridesService->revertOverride($relationship);
}
else {
$all_overrides_reverted = FALSE;
}
}
if ($all_overrides_reverted) {
$form_state->setRedirectUrl($this->getSitesTabUrl());
}
}
/**
* Get the sites tab URL.
*
* @return Url
* The sites tab URL.
*/
protected function getSitesTabUrl(): Url {
$entity_type = $this->getEntity()->getEntityTypeId();
return Url::fromRoute(
"entity.{$entity_type}.sites",
[$entity_type => $this->getEntity()->id()]
);
}
/**
* Access callback for the route.
*
* @param \Drupal\Core\Session\AccountInterface $account
* The current user.
*
* @return \Drupal\Core\Access\AccessResultInterface
* An access result object.
*/
public function access(AccountInterface $account) {
if (!empty($this->getOverrides())) {
// If a user is allowed to access the sites tab allow overrides tab too.
return $this->getSitesTabUrl()->access($account, TRUE);
}
return AccessResult::neutral();
}
/**
* Loads the entity from route.
*
* Since we don't know on which entity_type this is used, we cannot get the
* entity upcasted by the route for us.
*
* @return \Drupal\Core\Entity\ContentEntityInterface|null
* The entity from Route.
*/
public function getEntity() {
if (!$this->entity) {
foreach ($this->routeMatch->getParameters() as $parameter) {
if ($parameter instanceof ContentEntityInterface) {
$this->entity = $parameter;
continue;
}
}
return $this->entity;
}
return $this->entity;
}
}
