navigation_plus-1.0.5/src/Plugin/Mode/Edit.php

src/Plugin/Mode/Edit.php
<?php

declare(strict_types=1);

namespace Drupal\navigation_plus\Plugin\Mode;

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\navigation_plus\ModeInterface;
use Drupal\navigation_plus\ModePluginBase;
use Drupal\navigation_plus\Attribute\Mode;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\navigation_plus\NavigationPlusUi;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\navigation_plus\ToolPluginManager;
use Drupal\Core\Extension\ModuleExtensionList;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\navigation_plus\Event\SettingsSidebarEvent;
use Drupal\navigation_plus\Event\ShouldNotEditModeEvent;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

/**
 * Edit mode plugin.
 */
#[Mode(
  id: 'edit',
  label: new TranslatableMarkup('Edit Mode'),
  weight: 100,
)]
final class Edit extends ModePluginBase implements PluginFormInterface {

  use StringTranslationTrait;

  public EntityInterface $entity;

  public function __construct(
    ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition,
    protected ModuleExtensionList $extensionList,
    protected ToolPluginManager $toolManager,
    protected RouteMatchInterface $routeMatch,
    protected NavigationPlusUi $ui,
    protected EventDispatcherInterface $eventDispatcher,
    private readonly RequestStack $requestStack,
  ) {
    parent::__construct($container, $configuration, $plugin_id, $plugin_definition, $this->extensionList, $ui);
  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static (
      $container,
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('extension.list.module'),
      $container->get('plugin.manager.tools'),
      $container->get('current_route_match'),
      $container->get('navigation_plus.ui'),
      $container->get('event_dispatcher'),
      $container->get('request_stack'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function applies(): bool {
    $entity = $this->ui->deriveEntityFromRoute();
    $event = $this->eventDispatcher->dispatch(new ShouldNotEditModeEvent($entity), ShouldNotEditModeEvent::class);
    return !$event->shouldNotEdit();
  }

  /**
   * {@inheritdoc}
   */
  public function addAttachments(array &$attachments): void {
    $attachments['library'][] = 'navigation_plus/edit_mode';
  }

  /**
   * {@inheritdoc}
   */
  public function getIconPath(): string {
    $path = $this->extensionList->getPath('navigation_plus');
    return "/$path/assets/code.svg";
  }

  /**
   * {@inheritdoc}
   */
  public function buildToolbar(array &$variables): array {
    $tools = $this->getToolPlugins();
    if (empty($tools)) {
      return [];
    }
    $tool_indicators = [];

    // Add tool buttons.
    foreach ($tools as $id => $tool) {
      $tool->addAttachments($variables['#attached']);

      // Add styles for the plugin buttons and cursors.
      $icons = $tool->getIconsPath();
      $style = "<style>";
      if (!empty($icons['mouse_icon'])) {
        $style .= ".$id,\n.$id a {\n  cursor: {$icons['mouse_icon']}, auto;\n}\n";
      }
      if (!empty($icons['toolbar_button_icons'])) {
        foreach ($icons['toolbar_button_icons'] as $name => $path) {
          $style .= ".toolbar-button--icon--$name {\n  --icon: url('$path');\n}\n";
        }
      }
      $style .= "</style>";

      // Collect tool indicator settings.
      if (!empty($icons['tool_indicator_icons'])) {
        foreach ($icons['tool_indicator_icons'] as $name => $path) {
          $tool_indicators[$id][$name] = file_get_contents(\Drupal::root() . $path);
        }
      }

      // Add a button for the tool.
      $tools[$id] = [
        '#wrapper_attributes' => [
          'class' => ['toolbar-block__list-item'],
        ],
        '#type' => 'inline_template',
        '#template' => "<a href='javascript:void(0)' title='{{title}}' data-tool='{{id}}' data-icon-text='{{icon_text}}' class='toolbar-button toolbar-button--collapsible navigation-plus-button toolbar-button--icon--{{id}}'><span class='toolbar-button__label'>{{label}}</span></a>$style",
        '#context' => [
          'id' => $id,
          'label' => $tool->label(),
          'title' => $tool->label() . ' ' . strtoupper($tool->hotKey()),
          'icon_text' => substr($tool->label(), 0, 2),
        ],
      ];
    }

    // Set the initial mode and active tool when visiting a page for the first time.
    $entity = $this->ui->deriveEntityFromRoute();

    if ($bundle_entity_type = $entity->getEntityType()->getBundleEntityType()) {
      $entity_type = \Drupal::entityTypeManager()->getStorage($bundle_entity_type)->load($entity->bundle());
      $initial_mode = $entity_type->getThirdPartySetting('navigation_plus', 'initial_mode', 'none');
      if ($initial_mode !== 'none') {
        $variables['content']['content']['navigation_plus']['#attached']['drupalSettings']['navigationPlus']['initialMode'] = $initial_mode;
      }
      if ($initial_mode === 'edit') {
        $configured_modes = $entity_type->getThirdPartySetting('navigation_plus', 'modes', []);
        $mode_settings = $configured_modes[$initial_mode] ?? $this->getConfiguration();
        if (!empty($mode_settings['default_tool'])) {
          $variables['content']['content']['navigation_plus']['#attached']['drupalSettings']['navigationPlus']['defaultTool'] = $mode_settings['default_tool'];
        }
      }
    }

    // Pass hot key settings.
    $variables['content']['content']['navigation_plus']['#attached']['drupalSettings']['navigationPlus']['toolIndicators']['icons'] = $tool_indicators;

    return [
      'title' => [
        '#type' => 'html_tag',
        '#tag' => 'h4',
        '#value' => t('Editing Tools'),
        '#attributes' => [
          'class' => ['toolbar-label'],
        ],
      ],
      'tools' => [
        '#theme' => 'item_list',
        '#attributes' => [
          'class' => ['toolbar-block__list'],
        ],
        '#items' => $tools,
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildBars(array &$page_top, ModeInterface $mode): void {
    $this->buildTopBar($page_top, $mode);
    $this->buildSideBars($page_top, $mode);

    $page_top['#markup'] = '<div id="plus-suite-root"></div>';
  }

  /**
   * Build top bar.
   *
   * @param array $page_top
   *   The page top render array.
   * @param \Drupal\navigation_plus\ModeInterface $mode
   *   The mode plugin.
   *
   * @return void
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   */
  public function buildTopBar(array &$page_top, ModeInterface $mode): void {
    $top_bar = [];

    // Add a global area on the right side of the page for buttons that work with all tools.
    $top_bar['global'] = [
      '#type' => 'container',
      '#attributes' => [
        'id' => 'navigation_plus-top-bar',
        'class' => ['top-bar__content', 'top-bar__right'],
      ],
      'refresh' => [
        '#type' => 'container',
        '#attributes' => [
          'id' => 'navigation-plus-refresh',
          'title' => t('Refresh the editing UI'),
          'class' => ['toolbar-button', 'toolbar-button--collapsible', 'toolbar-button--icon--refresh'],
          'data-icon-text' => 'Re',
        ],
        'label' => [
          '#type' => 'html_tag',
          '#tag' => 'span',
          '#value' => $this->t('Refresh'),
          '#attributes' => [
            'class' => ['toolbar-button__label'],
          ],
        ],
      ],
      'save' => [
        '#type' => 'container',
        '#attributes' => [
          'id' => 'navigation-plus-save',
          'title' => t('Commit the tempstore changes'),
          'class' => ['toolbar-button', 'toolbar-button--collapsible', 'toolbar-button--icon--save'],
          'data-icon-text' => 'Sa',
        ],
        'label' => [
          '#type' => 'html_tag',
          '#tag' => 'span',
          '#value' => $this->t('Save'),
          '#attributes' => [
            'class' => ['toolbar-button__label'],
          ],
        ],
      ],
      'discard-changes' => [
        '#type' => 'container',
        '#attributes' => [
          'id' => 'navigation-plus-discard-changes',
          'title' => t('Discard the tempstore changes'),
          'class' => ['toolbar-button', 'toolbar-button--collapsible', 'toolbar-button--icon--discard-changes'],
          'data-icon-text' => 'Dc',
        ],
        'label' => [
          '#type' => 'html_tag',
          '#tag' => 'span',
          '#value' => $this->t('Discard changes'),
          '#attributes' => [
            'class' => ['toolbar-button__label'],
          ],
        ],
      ],
      'edit_mode_settings' => [
        '#type' => 'container',
        '#attributes' => [
          'id' => 'navigation-plus-settings',
          'title' => t('Configure Edit Mode'),
          'class' => ['toolbar-button', 'toolbar-button--collapsible', 'toolbar-button--icon--settings'],
          'data-icon-text' => 'Em',
          'data-right-sidebar-button-for' => '#edit-mode-settings',
        ],
        '#cache' => ['contexts' => ['user.permissions', 'cookies:settings_sidebar']],
        'label' => [
          '#type' => 'html_tag',
          '#tag' => 'span',
          '#value' => $this->t('Settings'),
          '#attributes' => [
            'class' => ['toolbar-button__label'],
          ],
        ],
      ],
    ];

    $settings_state = $this->requestStack->getCurrentRequest()->cookies->get('edit_mode_settings_sidebar');
    if ($settings_state === 'open') {
      $top_bar['global']['edit_mode_settings']['#attributes']['class'][] = 'active';
    }

    // Add tool specific buttons.
    foreach ($this->getToolPlugins() as $id => $tool) {
      $tool->buildGlobalTopBarButtons($top_bar['global']);
      $tool_top_bar = $tool->buildToolTopBarButtons();
      if (!empty($tool_top_bar)) {
        $top_bar[$id] = [
          '#type' => 'container',
          '#attributes' => [
            'id' => "$id-top-bar",
            'class' => ['top-bar__content', 'top-bar__left'],
          ],
          'top_bar' => $tool_top_bar,
        ];
        if ($this->getActiveTool() !== $id) {
          $top_bar[$id]['#attributes']['class'][] = 'navigation-plus-hidden';
        }
      }
    }

    // Add the top bar.
    $page_top['navigation_plus_top_bar'] = [
      '#type' => 'container',
      '#attributes' => [
        'id' => 'edit-mode-top-bar',
        'class' => ['top-bar', 'navigation-plus-top-bar'],
        'data-drupal-admin-styles' => '',
      ],
      '#cache' => ['contexts' => ['user.permissions', 'cookies:navigationMode']],
      'tools' => $top_bar,
    ];

    // Hide the top bar when not in Editing mode.
    if ($this->ui->getMode() !== 'edit') {
      $page_top['navigation_plus_top_bar']['#attributes']['class'][] = 'navigation-plus-hidden';
    }
  }

  /**
   * Build side bars.
   *
   * @param array $page_top
   *   The page top render array.
   *
   * @return void
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   */
  public function buildSideBars(array &$page_top): void {
    // Let tool plugins build their sidebars.
    $left_sidebars = [];
    $right_sidebars = [
      'edit_mode_settings' => [
        '#type' => 'container',
        '#attributes' => [
          'id' => 'edit-mode-settings',
          'class' => ['navigation-plus-sidebar', 'right-sidebar'],
          'data-sidebar-button' => '#navigation-plus-settings',
          'data-sidebar-type' => 'default',
        ],
        'contents' => [
          '#type' => 'markup',
          '#markup' => $this->t('<h3>Edit mode settings</h3>'),
        ],
      ],
    ];

    foreach ($this->getToolPlugins() as $id => $tool) {

      $left_side_bar = $tool->buildLeftSideBar();
      if (!empty($left_side_bar)) {
        $left_sidebars[$id] = [
          '#type' => 'container',
          '#attributes' => [
            'id' => "$id-left-sidebar",
            'class' => [
              'navigation-plus-sidebar',
              'left-sidebar',
            ],
          ],
          '#cache' => ['contexts' => ['user.permissions', 'cookies:settings_sidebar']],
          'left_side_bar' => $left_side_bar,
        ];
        if (!empty($left_side_bar['#wrapper_attributes'])) {
          $left_sidebars[$id]['#attributes'] = array_merge($left_sidebars[$id]['#attributes'], $left_side_bar['#wrapper_attributes']);
        }

        if ($this->getActiveTool() !== $id) {
          $left_sidebars[$id]['#attributes']['class'][] = 'navigation-plus-hidden';
        }
      }

      $right_side_bar = $tool->buildRightSideBar();
      if (!empty($right_side_bar)) {
        $right_sidebars[$id] = [
          '#type' => 'container',
          '#attributes' => [
            'id' => "$id-right-sidebar",
            'class' => [
              'navigation-plus-sidebar',
              'right-sidebar',
            ],
          ],
          'right_side_bar' => $right_side_bar,
        ];
        if (!empty($right_side_bar['#wrapper_attributes'])) {
          $right_sidebars[$id]['#attributes'] = array_merge($right_sidebars[$id]['#attributes'], $right_side_bar['#wrapper_attributes']);
        }
        if ($this->getActiveTool() !== $id) {
          $right_sidebars[$id]['#attributes']['class'][] = 'navigation-plus-hidden';
        }
      }

     $settings = $tool->buildSettings();
      if (!empty($settings)) {
        $right_sidebars['edit_mode_settings']['contents'][$id] = $settings;
      }
    }
    $event = $this->eventDispatcher->dispatch(new SettingsSidebarEvent(), SettingsSidebarEvent::class);
    $non_tool_settings = $event->getSettings();
    if (!empty($non_tool_settings)) {
      $right_sidebars['edit_mode_settings']['contents'] = array_merge($right_sidebars['edit_mode_settings']['contents'], $non_tool_settings);
    }

    $this->setSidebarsVisibility($left_sidebars, $right_sidebars);

    // Add the sidebars wrapper.
    $page_top['navigation_plus_left_sidebar'] = [
      '#type' => 'html_tag',
      '#tag' => 'aside',
      '#attributes' => [
        'id' => 'navigation-plus-left-sidebar',
        'class' => ['navigation-plus-sidebar-wrapper'],
      ],
      '#cache' => ['contexts' => ['user.permissions', 'cookies:navigationMode']],
      'left_sidebars' => $left_sidebars,
    ];
    $page_top['navigation_plus_right_sidebar'] = [
      '#type' => 'html_tag',
      '#tag' => 'aside',
      '#attributes' => [
        'id' => 'navigation-plus-right-sidebar',
        'class' => ['navigation-plus-sidebar-wrapper'],
      ],
      '#cache' => ['contexts' => ['user.permissions', 'cookies:navigationMode']],
      'right_sidebars' => $right_sidebars,
    ];

    // Hide the sidebar when not in Editing mode.
    if ($this->ui->getMode() !== 'edit') {
      $page_top['navigation_plus_sidebar']['#attributes']['class'][] = 'navigation-plus-hidden';
    }
  }


  /**
   * Get tool plugins.
   *
   * @return \Drupal\navigation_plus\ToolInterface[]
   *   An array of tool plugins.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   */
  public function getToolPlugins(): array {
    $tool_definitions = $this->toolManager->getDefinitions();
    $tools = [];
    if (!empty($tool_definitions)) {
      $entity = $this->ui->deriveEntityFromRoute();
      foreach ($tool_definitions as $tool_definition) {
        $tool = $this->toolManager->createInstance($tool_definition['id']);
        if ($entity && $tool->applies($entity)) {
          $tools[$tool_definition['id']] = $tool;
        }
      }
    }
    return $tools;
  }

  /**
   * Get active tool.
   *
   * @return string
   *   The active tool.
   */
  public function getActiveTool(): string {
    return $this->requestStack->getCurrentRequest()->cookies->get('activeTool') ?? 'pointer';
  }

  /**
   * {@inheritdoc}
   */
  public function getSummary(): string|TranslatableMarkup {
    $config = $this->getConfiguration();
    $tool = $this->toolManager->getDefinition($config['default_tool'], FALSE);
    if ($tool) {
      $label = $tool['label'];
    }
    else {
      $label = $config['default_tool'];
    }
    return new TranslatableMarkup('Default to tool: @tool', ['@tool' => $label]);
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    if (\Drupal::moduleHandler()->moduleExists('edit_plus')) {
      $default_tool_default_value = 'edit_plus';
    } else {
      $default_tool_default_value = 'last';
    }
    return ['default_tool' => $default_tool_default_value];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state, string $entity_type_id = NULL, string $entity_bundle_id = NULL) {
    $bundled_entity = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
    $bundle_entity_type = $bundled_entity->getBundleEntityType();
    if ($bundle_entity_type) {
      /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $bundle_entity */
      $bundle_entity = \Drupal::entityTypeManager()
        ->getStorage($bundle_entity_type)
        ->load($entity_bundle_id);
      if (!$bundle_entity) {
        return [];
      }
    }

    $options = [
      'last' => $this->t('The last tool used or Preview'),
    ];
    foreach ($this->toolManager->getDefinitions() as $tool => $definition) {
      $options[$tool] = $definition['label'];
    }

    $configured_modes = $bundle_entity->getThirdPartySetting('navigation_plus', 'modes', []);
    $values = $configured_modes[$this->getPluginId()] ?? $this->getConfiguration();
    $form['default_tool'] = [
      '#title' => $this->t('Default tool'),
      '#type' => 'radios',
      '#options' => $options,
      '#default_value' => $values['default_tool'],
      '#description' => $this->t('Choose the tool that will be activated when @type\'s are initially edited. Subsequent edits of the same page will reactivate the last tool that was used.', ['@type' => $bundle_entity->label()]),
    ];
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {}

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $this->setConfiguration([
      'default_tool' => $form_state->getValue('default_tool')
    ]);
  }

  /**
   * @param array $left_sidebars
   * @param array $right_sidebars
   *
   * @return void
   */
  public function setSidebarsVisibility(array &$left_sidebars, array &$right_sidebars): void {
    $apply_visibility = function(array &$sidebars, string $id, string $direction) {
      $sidebar_state = $this->requestStack->getCurrentRequest()->cookies->get("{$id}_sidebar") ?? 'closed';
      if ($this->ui->getMode() !== 'edit' || $sidebar_state === 'closed') {
        $sidebars[$id]['#attributes']['class'][] = 'navigation-plus-hidden';
      } else {
        $sidebars[$id]['#attributes']["data-offset-$direction"] = '';
      }
    };
    foreach (array_keys($left_sidebars) as $id) {
      $apply_visibility($left_sidebars, $id, 'left');
    }
    foreach (array_keys($right_sidebars) as $id) {
      $apply_visibility($right_sidebars, $id, 'right');
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc