association-1.0.0-alpha2/modules/association_menu/src/Form/MenuItemEditForm.php

modules/association_menu/src/Form/MenuItemEditForm.php
<?php

namespace Drupal\association_menu\Form;

use Drupal\association\Entity\AssociationInterface;
use Drupal\association_menu\AssociatedEntityMenuItem;
use Drupal\association_menu\AssociationMenuStorageInterface;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Path\PathValidatorInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Form for editing and adding items to an association menu.
 */
class MenuItemEditForm extends FormBase {

  /**
   * Menu item being edited by this form.
   *
   * @var \Drupal\association_menu\MenuItemInterface
   */
  protected $item;

  /**
   * The association which this menu item belongs to.
   *
   * @var \Drupal\association\Entity\AssociationInterface
   */
  protected $association;

  /**
   * Provides path resolution and validation services.
   *
   * @var \Drupal\Core\Path\PathValidatorInterface
   */
  protected $pathValidator;

  /**
   * Association menu item storage manager.
   *
   * @var \Drupal\association_menu\AssociationMenuStorageInterface
   */
  protected $menuStorage;

  /**
   * Create a new instance of the association menu item edit form.
   *
   * @param \Drupal\Core\Path\PathValidatorInterface $path_validator
   *   Provides path resolution and validation services.
   * @param \Drupal\association_menu\AssociationMenuStorageInterface $association_menu_storage
   *   Association navigation storage manager.
   */
  public function __construct(PathValidatorInterface $path_validator, AssociationMenuStorageInterface $association_menu_storage) {
    $this->pathValidator = $path_validator;
    $this->menuStorage = $association_menu_storage;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('path.validator'),
      $container->get('association_menu.storage')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'association_menu_edit_item_form';
  }

  /**
   * Builds the form elements for the association menu item edit form.
   *
   * @param array $form
   *   Current form structure and elements.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state, values and build information.
   * @param \Drupal\association\Entity\AssociationInterface $association
   *   The entity association which this menu item is being built for.
   * @param int|null $menu_item_id
   *   The ID of the menu item to edit, or NULL if creating a new menu item.
   *
   * @return array
   *   The add or edit menu item form elements.
   */
  public function buildForm(array $form, FormStateInterface $form_state, AssociationInterface $association = NULL, $menu_item_id = NULL) {
    if (!$association) {
      throw new NotFoundHttpException();
    }

    // Set the association and the menu item this form is working with for
    // use in the validate and submit form callbacks.
    $this->association = $association;

    try {
      if ($menu_item_id) {
        /** @var \Drupal\association_menu\MenuItemBase */
        $item = $this->menuStorage->getMenuItem($association, $menu_item_id);
        $this->item = $item;

        $values = [
          'title' => $this->item->title,
          'enabled' => $this->item->isEnabled(),
          'expanded' => $this->item->isExpanded(),
          'options' => $this->item->getOptions(),
        ];
      }
      else {
        $values = [
          'title' => '',
          'enabled' => TRUE,
          'expanded' => TRUE,
          'options' => [],
        ];
      }
    }
    catch (\Exception $e) {
      throw new NotFoundHttpException();
    }

    // Build the form elements.
    $form['title'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Menu link title'),
      '#default_value' => $values['title'],
      '#description' => $this->t('Text to be used for the menu link title.'),
    ];

    $form['actions'] = [
      '#type' => 'actions',

      'save' => [
        '#type' => 'submit',
        '#value' => $this->t('Save'),
      ],
    ];

    if ($this->item instanceof AssociatedEntityMenuItem) {
      $entity = $this->item->getEntity();
      $entityLabel = $entity->label();
      $assocTypeLabel = $association->getType()->label();

      $form['title']['#placeholder'] = $entityLabel;
      $form['title']['#description'] = $this->t('Text to be used for the menu link title. If left blank the @bundle_label content title will be used.', [
        '@bundle_label' => $assocTypeLabel,
      ]);

      $form['url'] = [
        '#theme_wrappers' => ['form_element'],
        '#title' => $this->t('Link URL'),
        '#description' => $this->t('This link is autogenerated from @bundle_label content, and cannot be changed. Disable if you do not want this link to appear in the menu', [
          '@bundle_label' => $assocTypeLabel,
        ]),

        'value' => [
          '#type' => 'link',
          '#title' => $entityLabel,
          '#url' => $this->item->getUrl(),
        ],
      ];

    }
    else {
      // For custom URL links, a title is required.
      $form['title']['#required'] = TRUE;
      $form['url'] = [
        '#type' => 'textfield',
        '#title' => $this->t('Link URL'),
        '#required' => TRUE,
        '#default_value' => '',
        '#description' => $this->t('Enter the location this menu link points to. Enter internal paths starting with "/" like "/node" or "<nolink>" if the menu item does not link anywhere. External URLs should start with "https://".'),
      ];

      if ($this->item) {
        if ($url = $this->item->getUrl()) {
          $form['url']['#default_value'] = $url->toString();
        }

        $form['actions']['delete'] = [
          '#type' => 'link',
          '#title' => $this->t('Delete'),
          '#url' => Url::fromRoute('association_menu.delete_item_confirm', [
            'association' => $association->id(),
            'menu_item_id' => $this->item->id(),
          ]),
          '#attributes' => [
            'class' => ['button', 'button--danger'],
          ],
        ];
      }
    }

    $form['enabled'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enabled'),
      '#default_value' => $values['enabled'],
    ];

    $form['expanded'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Show sub-menu items'),
      '#default_value' => $values['expanded'],
    ];

    $attrs = $values['options']['attributes'] ?? [];
    $form['attributes'] = [
      '#type' => 'details',
      '#title' => $this->t('Link attributes'),
      '#open' => FALSE,
      '#tree' => TRUE,

      'target' => [
        '#type' => 'select',
        '#title' => $this->t('Link target'),
        '#options' => [
          '' => $this->t('- None -'),
          '_self' => $this->t('Same window (_self)'),
          '_blank' => $this->t('New windown (_blank)'),
        ],
        '#default_value' => $attrs['target'] ?? NULL,
      ],
      'rel' => [
        '#type' => 'textfield',
        '#title' => $this->t('Rel'),
        '#pattern' => '[a-zA-Z\-\s]+',
        '#default_value' => $attrs['rel'] ?? '',
      ],
      'class' => [
        '#type' => 'css_class',
        '#title' => $this->t('Class'),
        '#default_value' => $attrs['class'] ?? [],
      ],
    ];

    return $form;
  }

  /**
   * Check if the URL string is one of the allowed special routes.
   *
   * This method checks for the following route names:
   *   - <front>
   *   - <nolink>
   *   - <none>
   *   - <button>
   * Which as of this writing are all allowed for URL route names.
   *
   * @param string $url_string
   *   URL string to check for a match to the specially allowed route names.
   *
   * @return bool
   *   TRUE if the string is one of the special Drupal recognized route names.
   */
  protected function isAllowedRouteName($url_string) {
    return (bool) preg_match('/^<(?:nolink|none|front|button>)>$/i', $url_string);
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $urlString = $form_state->getValue('url');

    if ($urlString) {
      $urlString = trim($urlString);

      // First check if for special routes and check if it fits the format of
      // external or internal URLs.
      if (!$this->isAllowedRouteName($urlString) && !UrlHelper::isValid($urlString, TRUE)) {
        if ($urlString[0] != '/' || !UrlHelper::isValid($urlString)) {
          $form_state->setError($form['url'], $this->t('URL specified is not in the correct format. Start your URL with "https://" and use the full address for external links, or start internal links with "/".'));
        }
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $item = $this->item;
    $values = $form_state->getValues();
    $values['attributes'] = array_filter($values['attributes']);

    // Update the common settings for all menu links.
    $data = [
      'title' => $values['title'],
      'enabled' => (bool) $values['enabled'],
      'expanded' => (bool) $values['expanded'],
      // Only populate the attribute changes here if there were any.
      // For custom links, the other URL options such as query and fragment
      // are determined later, but shouldn't retain any previous data.
      'options' => $values['attributes'] ? ['attributes' => $values['attributes']] : [],
    ];

    if ($item) {
      $data['id'] = $item->id();
    }

    // If pointing to an entity, the URL cannot be changed, the title is
    // optional, and only the attributes are allowed for URL options.
    if ($item instanceof AssociatedEntityMenuItem) {
      $data['entity'] = $item->getEntity();

      if (empty($data['title'])) {
        unset($data['title']);
      }
    }
    else {
      $urlStr = trim($values['url']);

      if ($this->isAllowedRouteName($urlStr)) {
        $data['route'] = [
          'route_name' => strtolower($urlStr),
        ];
      }
      else {
        $parsed = UrlHelper::parse($urlStr);

        // Add the query or fragment to the URL options if there were any.
        if ($parsed['query']) {
          $data['options']['query'] = $parsed['query'];
        }
        if ($parsed['fragment']) {
          $data['options']['fragment'] = $parsed['fragment'];
        }

        // Absolute path, use the URI menu field.
        if (UrlHelper::isExternal($parsed['path'])) {
          $data['uri'] = $parsed['path'];
        }
        elseif ($url = $this->pathValidator->getUrlIfValid($parsed['path'])) {
          if ($url->isRouted()) {
            $data['route'] = [
              'route_name' => $url->getRouteName(),
              'route_parameters' => $url->getRouteParameters(),
            ];
          }
          else {
            $data['uri'] = $url->getUri();
          }
        }
        else {
          $this->messenger()->addError($this->t('Unable to save menu link due to an invalid URL.'));
          $form_state->setRebuild();
          return;
        }
      }
    }

    $this->menuStorage->saveMenuItem($this->association, $data);

    // Go back to the association menu tree overview page.
    $form_state->setRedirectUrl(Url::fromRoute(
      'association_menu.entity.menu_form',
      ['association' => $this->association->id()],
    ));
  }

}

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

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