foldershare-8.x-1.2/src/Plugin/FolderShareCommand/ChangeOwner.php

src/Plugin/FolderShareCommand/ChangeOwner.php
<?php

namespace Drupal\foldershare\Plugin\FolderShareCommand;

use Drupal\Core\Form\FormStateInterface;
use Drupal\user\Entity\User;

use Drupal\foldershare\Constants;
use Drupal\foldershare\Settings;
use Drupal\foldershare\Utilities\FormatUtilities;
use Drupal\foldershare\Utilities\UserUtilities;
use Drupal\foldershare\Entity\FolderShare;
use Drupal\foldershare\Entity\Exception\RuntimeExceptionWithMarkup;
use Drupal\foldershare\Entity\Exception\ValidationException;

/**
 * Defines a command plugin to change ownership of files or folders.
 *
 * The command sets the UID for the owner of all selected entities.
 * Owenrship changes recurse through all folder content as well.
 *
 * Configuration parameters:
 * - 'parentId': the parent folder, if any.
 * - 'selectionIds': selected entities to change ownership on.
 * - 'uid': the UID of the new owner.
 *
 * @ingroup foldershare
 *
 * @FolderShareCommand(
 *  id              = "foldersharecommand_change_owner",
 *  label           = @Translation("Change Owner"),
 *  menuNameDefault = @Translation("Change Owner..."),
 *  menuName        = @Translation("Change Owner..."),
 *  description     = @Translation("Change the owner of selected files and folders, and optionally for all of a folder's descendants. This command is only available for content administrators."),
 *  category        = "administer",
 *  weight          = 10,
 *  userConstraints = {
 *    "adminpermission",
 *  },
 *  parentConstraints = {
 *    "kinds"   = {
 *      "rootlist",
 *      "any",
 *    },
 *    "access"  = "view",
 *  },
 *  selectionConstraints = {
 *    "types"   = {
 *      "parent",
 *      "one",
 *      "many",
 *    },
 *    "kinds"   = {
 *      "any",
 *    },
 *    "access"  = "chown",
 *  },
 * )
 */
class ChangeOwner extends FolderShareCommandBase {

  /*--------------------------------------------------------------------
   *
   * Configuration.
   *
   *--------------------------------------------------------------------*/

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    // Add room for the UID and a recursion flag.
    $config = parent::defaultConfiguration();
    $config['uid'] = '';
    $config['changedescendants'] = 'FALSE';
    return $config;
  }

  /**
   * {@inheritdoc}
   */
  public function validateParameters() {
    if ($this->parametersValidated === TRUE) {
      return;
    }

    // Get the new UID from the configuration and check if it is valid.
    $uid = $this->configuration['uid'];
    if ($uid === NULL) {
      // When there is no UID in the configuration, it is probably because
      // the form auto-complete did not recognize the user name the user
      // typed in, and therefore could not map it to a UID. So make the
      // error message about an unknown user name, not a missing UID.
      throw new ValidationException(FormatUtilities::createFormattedMessage(
        t('The user name does not match any user account at this site.'),
        t('Please check that the name is correct and for an existing account.')));
    }

    $user = User::load($uid);
    if ($user === NULL) {
      throw new ValidationException(FormatUtilities::createFormattedMessage(
        t(
          'The user ID "@uid" does not match any user account at this site.',
          [
            '@uid' => $uid,
          ]),
        t('Please check that the ID is correct and for an existing account.')));
    }

    $this->parametersValidated = TRUE;
  }

  /*--------------------------------------------------------------------
   *
   * Configuration form setup.
   *
   *--------------------------------------------------------------------*/

  /**
   * {@inheritdoc}
   */
  public function hasConfigurationForm() {
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function getDescription(bool $forPage) {
    $selectionIds = $this->getSelectionIds();
    if (empty($selectionIds) === TRUE) {
      $item = $this->getParent();
    }
    else {
      $item = FolderShare::load(reset($selectionIds));
    }

    $isShared = $item->getRootItem()->isAccessShared();
    $isRoot = $item->isRootItem();

    if ($isShared === TRUE && $isRoot === TRUE) {
      return [
        '',
        t('This item is shared. Changing its owner will end shared access and may affect other users.'),
      ];
    }

    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getTitle(bool $forPage) {
    // The title varies for page vs. dialog:
    //
    // - Dialog: "Change owner".
    //
    // - Page: The title is longer and has the form "Change the owner of
    //   OPERAND?". where OPERAND can be the name of the item if one item
    //   is being changed, or the count and kinds if multiple items are
    //   being changed. This follows Drupal convention.
    if ($forPage === FALSE) {
      return t('Change owner');
    }

    $selectionIds = $this->getSelectionIds();
    if (empty($selectionIds) === TRUE) {
      $selectionIds[] = $this->getParentId();
    }

    if (count($selectionIds) === 1) {
      // Page title. There is only one item. Load it.
      $item = FolderShare::load($selectionIds[0]);
      return t(
        'Change owner of "@name"?',
        [
          '@name' => $item->getName(),
        ]);
    }

    // Find the kinds for each of the selection IDs. Then choose an
    // operand based on the selection's single kind, or "items".
    $selectionKinds = FolderShare::findKindsForIds($selectionIds);
    if (count($selectionIds) === 1) {
      $kind = key($selectionKinds);
      $operand = FolderShare::translateKind($kind);
    }
    elseif (count($selectionKinds) === 1) {
      $kind = key($selectionKinds);
      $operand = FolderShare::translateKinds($kind);
    }
    else {
      $operand = FolderShare::translateKinds('items');
    }

    // Page title. Include the count and operand kind. Question mark.
    return t(
      "Change owner of @count @operand?",
      [
        '@count' => count($selectionIds),
        '@operand' => $operand,
      ]);
  }

  /**
   * {@inheritdoc}
   */
  public function getSubmitButtonName() {
    return t('Change');
  }

  /*--------------------------------------------------------------------
   *
   * Configuration form.
   *
   *--------------------------------------------------------------------*/

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(
    array $form,
    FormStateInterface $formState) {

    // Find the kinds for each of the selection IDs.
    $selectionIds = $this->getSelectionIds();
    $selectionKinds = FolderShare::findKindsForIds($selectionIds);
    $hasFolders = (isset($selectionKinds[FolderShare::FOLDER_KIND]) === TRUE);

    // Use the UID of the current user as the default value.
    $account = \Drupal::currentUser();
    $this->configuration['uid'] = $account->id();

    $formInput = $formState->getUserInput();

    // The command wrapper provides form basics:
    // - Attached libraries.
    // - Page title (if not an AJAX dialog).
    // - Description (from ::getDescription()).
    // - Submit buttion (labeled with ::getSubmitButtonName()).
    // - Cancel button (if AJAX dialog).
    //
    // Add a text field for the new owner, and optionally a checkbox for
    // recursing through folder contents.
    $description = '';
    switch (Settings::getUserAutocompleteStyle()) {
      default:
      case 'none':
      case 'name-only':
        $description = t('Enter the account name of a user.');
        break;

      case 'name-email':
      case 'name-masked-email':
        $description = t('Enter the account name or email address of a user.');
        break;
    }

    $defaultUser = '';
    if (isset($formInput['owner']) === TRUE) {
      $defaultUser = $formInput['owner'];
    }

    if (empty($defaultUser) === TRUE) {
      $defaultUser = $account->getAccountName();
    }

    $form['owner'] = [
      '#type'          => 'textfield',
      '#maxlength'     => 256,
      '#default_value' => $defaultUser,
      '#name'          => 'owner',
      '#title'         => t('New owner:'),
      '#weight'        => 10,
      '#required'      => TRUE,
      '#size'          => 30,
      '#attributes'    => [
        'autofocus'    => 'autofocus',
        'spellcheck'   => 'false',
        'class'        => [
          Constants::MODULE . '-changeowneritem-owner',
        ],
      ],
    ];
    $form['ownerdescription'] = [
      '#type'             => 'html_tag',
      '#tag'              => 'p',
      '#value'            => $description,
      '#weight'           => 11,
      '#attributes'       => [
        'class'           => [
          'description',
        ],
      ],
    ];

    // If the site allows user autocomplete, set up the text field.
    if (Settings::getUserAutocompleteStyle() !== 'none') {
      $form['owner']['#autocomplete_route_name'] =
        'entity.foldershare.userautocomplete';

      $form['owner']['#autocomplete_route_parameters'] = [
        'excludeBlocked' => 0,
      ];
    }

    if ($hasFolders === TRUE) {
      $form['changedescendants'] = [
        '#type'          => 'checkbox',
        '#name'          => 'changedescendants',
        '#weight'        => 20,
        '#title'         => t('Apply to enclosed items'),
        '#default_value' => ($this->configuration['changedescendants'] === 'TRUE'),
        '#attributes' => [
          'class'     => [
            Constants::MODULE . '-changeowneritem-changedescendants',
          ],
        ],
      ];
    }

    $form['status'] = [
      '#type'          => 'status_messages',
      '#weight'        => 30,
    ];

    return $form;
  }

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

    // Get the entered text for the new owner.
    $name = $formState->getValue('owner');

    // Remove leading white space.
    $cleanedName = mb_ereg_replace('^\s+', '', $name);
    if ($cleanedName !== FALSE) {
      $name = $cleanedName;
    }

    // Remove trailing white space.
    $cleanedName = mb_ereg_replace('\s+$', '', $name);
    if ($cleanedName !== FALSE) {
      $name = $cleanedName;
    }

    if (empty($name) === TRUE) {
      // Empty user.
      // Since the field is required, Drupal adds a default error message
      // when the field is left empty. Get rid of that so we can provide
      // a more helpful message.
      $formState->clearErrors();

      // And now intentionally use an empty error message. This will
      // highlight the form field but not show a message. Such a message
      // would be redundant and just say "Enter an account name", which
      // is what the description under the field already says.
      $formState->setErrorByName('owner', '');

      // Clear the name field.
      // Since a validation error does not rebuild the form, updating the
      // form's state does not work to insure the form name field is empty.
      $form['owner']['#value'] = '';
      $formState->setRebuild();
      return;
    }

    // Use the given name to find a user then add them to the grants list.
    $uid = UserUtilities::findUser($name);
    if ($uid === (-1)) {
      // User not found.
      $formState->setErrorByName(
        'owner',
        t(
          '"%name" is not a recognized account at this site.',
          [
            '%name' => $name,
          ]));

      // Insure the name field has the cleaned name.
      // Since a validation error does not rebuild the form, updating the
      // form's state does not work to insure the form is showing the cleaned
      // name. Set it into the form directly.
      $form['owner']['#value'] = $name;
      $formState->setRebuild();
      return;
    }

    $this->configuration['uid'] = $uid;

    // Get the descendants flag, if any.
    $this->configuration['changedescendants'] = 'FALSE';
    if ($formState->hasValue('changedescendants') === TRUE &&
        $formState->getValue('changedescendants') === 1) {
      $this->configuration['changedescendants'] = 'TRUE';
    }

    // Validate.
    try {
      $this->validateParameters();
    }
    catch (RuntimeExceptionWithMarkup $e) {
      // Unfortunately, setErrorByName() will not accept complex markup,
      // such as for multi-line error messages. If we pass the markup,
      // the function strips it down to the last line of text. To avoid
      // this, we have to pass the message text instead.
      $formState->setErrorByName('owner', $e->getMessage());
      $formState->setRebuild();
    }
    catch (\Exception $e) {
      $formState->setErrorByName('owner', $e->getMessage());
      $formState->setRebuild();
    }
  }

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

    if ($this->isValidated() === TRUE) {
      $this->execute();
    }
  }

  /*---------------------------------------------------------------------
   *
   * Execution behavior.
   *
   *---------------------------------------------------------------------*/

  /**
   * {@inheritdoc}
   */
  public function getExecuteBehavior() {
    if (empty($this->getSelectionIds()) === TRUE) {
      // When there is no selection, execution falls back to operating
      // on the current parent. After a change, the breadcrumbs or
      // other page decoration may differ. We need to refresh the page.
      return FolderShareCommandInterface::POST_EXECUTE_PAGE_REFRESH;
    }

    // When there is a selection, execution changes that selection on the
    // current page. While columns may change, the page doesn't, so we
    // only need to refresh the view.
    return FolderShareCommandInterface::POST_EXECUTE_VIEW_REFRESH;
  }

  /*--------------------------------------------------------------------
   *
   * Execute.
   *
   *--------------------------------------------------------------------*/

  /**
   * {@inheritdoc}
   */
  public function execute() {
    $ids = $this->getSelectionIds();
    if (empty($ids) === TRUE) {
      $ids[] = $this->getParentId();
    }

    try {
      FolderShare::changeOwnerIdMultiple(
        $ids,
        $this->configuration['uid'],
        ($this->configuration['changedescendants'] === 'TRUE'));
    }
    catch (RuntimeExceptionWithMarkup $e) {
      \Drupal::messenger()->addMessage($e->getMarkup(), 'error', TRUE);
    }
    catch (\Exception $e) {
      \Drupal::messenger()->addMessage($e->getMessage(), 'error');
    }

    if (Settings::getCommandNormalCompletionReportEnable() === TRUE) {
      \Drupal::messenger()->addMessage(
        \Drupal::translation()->formatPlural(
          count($ids),
          "The item has been changed.",
          "@count items have been changed."),
        'status');
    }
  }

}

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

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