foldershare-8.x-1.2/src/Entity/FolderShare.php

src/Entity/FolderShare.php
<?php
 
namespace Drupal\foldershare\Entity;
 
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityChangedTrait;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Session\AccountInterface;
 
use Drupal\foldershare\Settings;
use Drupal\foldershare\FolderShareInterface;
use Drupal\foldershare\ManageFilenameExtensions;
use Drupal\foldershare\ManageSearch;
 
/**
 * Manages a virtual file system hierarchy of folders, subfolders, and files.
 *
 * FolderShare entities represent entries in a virtual file system that
 * includes folders, subfolders, and files in an arbitrarily deep hierarchy.
 *
 * Every folder or file entity has a set of common fields, including:
 * - Entity ID.
 * - UUID.
 * - Name.
 * - Size.
 * - Visible.
 * - Creation and changed dates.
 * - Owner.
 * - Description.
 * - Kind.
 * - MIME type.
 * - Language code.
 * - Parent item, if any.
 * - Root item, if any.
 *
 * The 'kind' field has one of these values:
 * - folder.
 * - file.
 * - image.
 * - media.
 *
 * The parent folder field is an entity reference to the parent folder
 * containing an item. If this field is NULL, the item has no parent and
 * it exists at the "root" or top-level of the folder hierarchy.
 *
 * The root field is an entity reference to the highest ancestor
 * folder of an item. If this field is NULL, the item has no ancestor root
 * and it exists at the "root" itself.
 *
 * Root-level items have access control fields:
 * - Access grants for viewing.
 * - Access grants for authoring.
 * - Access grants for users known, but currently without viewing or authoring.
 *
 * Non-root level items adopt the access controls of their ancestor root
 * folder.
 *
 * When 'kind' is 'file', the entity has an additional field containing the
 * entity ID of a File object:
 * - File entity ID.
 *
 * When 'kind' is 'image', the entity has an additional field containing the
 * entity ID of a File object containing an image, plus attributes of that
 * image filled in by the Image module:
 * - Image entity ID and attributes.
 *
 * When 'kind' is 'media', the entity has an additional field containing the
 * entity ID of a Media object describing an arbitrary media item, plus
 * attributes of that item:
 * - Media entity ID and attributes.
 *
 * File and Image fields refer to local files managed by Drupal core and
 * the File module. The FolderShare entity handles creating, deleting,
 * and altering File entities and the local files they refer to.
 *
 * Media fields refer to media entities that may point to local files or
 * remote files, such as images or videos on a social media site. The
 * FolderShare entity handles creating, deleting, and altering Media
 * entities, but it has no control over any external media these entities
 * refer to.
 *
 * Operations on FolderShare entities include creating, deleting, moving,
 * copying, duplicating, and renaming objects. Fields on these objects may
 * be adjusted individually and, in some cases, in recursive operations
 * (such as to change ownership of an entire folder tree).
 *
 * Root-level items manage access control for their descendants. Access
 * checks on anything in a descendant tree redirect up to the root. Being able
 * to do this quickly is why every item includes a root reference up
 * to the root high above it.
 *
 * <B>Access control</B>
 * This class's methods do not do access control. The caller should check
 * access as needed by their situation.
 *
 * @internal
 * The FolderShare entity disables the static and render caches, while
 * retaining the persistent cache.
 *
 * Benchmarking found that entity views were so basic that the render cache
 * had negligible benefits. Additionally, view operations on FolderShare
 * entities rarely loaded the same entity more than once, so the static
 * cache had negligible benefits. Disabling the render cache saves on database
 * storage, and disabling the static cache saves on process memory use. The
 * latter can be important during long folder tree operations, such as copy,
 * move, and delete on a big tree. Disabling these caches also reduced the
 * overhead required to clear cache entries after a FolderShare entity is
 * saved or deleted.
 *
 * Benchmarking found that the persistent cache had benefits because the
 * same entities are often loaded repeatedly as users move up and down
 * through a folder tree.
 *
 * Benchmarking also tested enabling and disabling the views cache used
 * for folder lists on an entity view page. The cache saves query results
 * for lists of entities in the rows of a view and benchmarking found this
 * had a significant impact. This module's views therefore enable this cache.
 *
 * @ingroup foldershare
 *
 * @ContentEntityType(
 *   id             = "foldershare",
 *   label          = @Translation("FolderShare file or folder "),
 *   label_singular = @Translation("FolderShare file or folder"),
 *   label_plural   = @Translation("FolderShare files or folders"),
 *   label_count    = @PluralTranslation(
 *     singular     = "@count FolderShare file or folder",
 *     plural       = "@count FolderShare files or folders"
 *  ),
 *   handlers = {
 *     "access"       = "Drupal\foldershare\Entity\FolderShareAccessControlHandler",
 *     "view_builder" = "Drupal\foldershare\Entity\Builder\FolderShareViewBuilder",
 *     "views_data"   = "Drupal\foldershare\Entity\FolderShareViewsData",
 *     "list_builder" = "Drupal\Core\Entity\EntityListBuilder",
 *     "form" = {
 *       "default" = "Drupal\foldershare\Form\EditFolderShare",
 *       "edit"    = "Drupal\foldershare\Form\EditFolderShare",
 *     },
 *   },
 *   list_cache_contexts     = { "user" },
 *   static_cache            = FALSE,
 *   persistent_cache        = TRUE,
 *   render_cache            = FALSE,
 *   admin_permission        = "administer foldershare",
 *   permission_granularity  = "entity_type",
 *   translatable            = FALSE,
 *   base_table              = "foldershare",
 *   fieldable               = TRUE,
 *   common_reference_target = TRUE,
 *   field_ui_base_route     = "entity.foldershare.settings",
 *   entity_keys = {
 *     "id"       = "id",
 *     "uuid"     = "uuid",
 *     "uid"      = "uid",
 *     "label"    = "name",
 *     "langcode" = "langcode",
 *   },
 *   links = {
 *     "canonical" = "/foldershare/{foldershare}",
 *   }
 * )
 */
final class FolderShare extends ContentEntityBase implements FolderShareInterface {
  use EntityChangedTrait;
  use FolderShareTraits\ManageHookTrait;
  use FolderShareTraits\ManageLocksTrait;
  use FolderShareTraits\GetSetAccessGrantsTrait;
  use FolderShareTraits\GetSetCreatedTimeTrait;
  use FolderShareTraits\GetSetDescriptionTrait;
  use FolderShareTraits\GetSetFileTrait;
  use FolderShareTraits\GetSetKindTrait;
  use FolderShareTraits\GetSetMimeTrait;
  use FolderShareTraits\GetSetNameTrait;
  use FolderShareTraits\GetSetOwnerTrait;
  use FolderShareTraits\GetSetParentTrait;
  use FolderShareTraits\GetSetRootTrait;
  use FolderShareTraits\GetSetSizeTrait;
  use FolderShareTraits\GetSetSystemDisabledTrait;
  use FolderShareTraits\GetSetSystemHiddenTrait;
  use FolderShareTraits\FindTrait;
  use FolderShareTraits\OperationAddFileTrait;
  use FolderShareTraits\OperationArchiveTrait;
  use FolderShareTraits\OperationChangeOwnerTrait;
  use FolderShareTraits\OperationNewFolderTrait;
  use FolderShareTraits\OperationCopyTrait;
  use FolderShareTraits\OperationDeleteTrait;
  use FolderShareTraits\OperationDuplicateTrait;
  use FolderShareTraits\OperationFsckTrait;
  use FolderShareTraits\OperationMoveTrait;
  use FolderShareTraits\OperationRenameTrait;
  use FolderShareTraits\OperationShareTrait;
  use FolderShareTraits\OperationUnarchiveTrait;
 
  /*---------------------------------------------------------------------
   *
   * Constants - Entity type id.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * The entity type id for the FolderShare entity.
   *
   * This is 'foldershare' and it must match the entity type declaration
   * in this class's comment block.
   *
   * @var string
   */
  const ENTITY_TYPE_ID = 'foldershare';
 
  /*---------------------------------------------------------------------
   *
   * Constants - Database tables.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * The base table for 'foldershare' entities.
   *
   * This is 'foldershare' and it must match the base table declaration in
   * this class's comment block.
   *
   * @var string
   */
  const BASE_TABLE = 'foldershare';
 
  /*---------------------------------------------------------------------
   *
   * Constants - Lock constants.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * The base name of the process lock for individual content operations.
   *
   * The content lock appends the ID of the entity being locked.
   *
   * @var string
   */
  const CONTENT_LOCK_NAME = 'foldershare_content_lock_';
 
  /**
   * The base name of the process lock for large-scale operations.
   *
   * The operation lock appends the ID of the root entity for the folder tree
   * being locked.
   *
   * @var string
   */
  const OPERATION_LOCK_NAME = 'foldershare_operation_lock_';
 
  /*---------------------------------------------------------------------
   *
   * Constants - Misc.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * The number of operations to complete before checking usage limits.
   *
   * Memory and execution time limits need to be checked periodically
   * during long-running operations, such as copy, delete, and move.
   * Checking them after every item copied, deleted, or moved may be
   * expensive. Instead, checks are performed ever USAGE_CHECK_INTERVAL
   * loads/saves/copies/deletes.
   *
   * @var int
   *
   * @todo This may not be necessary. Benchmarking has found that checking
   * memory use and execution time have negligable cost.
   */
  const USAGE_CHECK_INTERVAL = 100;
 
  /*---------------------------------------------------------------------
   *
   * Entity definition.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * Defines the fields used by instances of this class.
   *
   * The following fields are defined, along with their intended
   * public or private access:
   *
   * | Field            | Allow for view | Allow for edit |
   * | ---------------- | -------------- | -------------- |
   * | id               | any user       | no             |
   * | uuid             | no             | no             |
   * | uid              | any user       | no             |
   * | langcode         | no             | no             |
   * | created          | any user       | no             |
   * | changed          | any user       | no             |
   * | size             | any user       | no             |
   * | kind             | any user       | no             |
   * | mime             | any user       | no             |
   * | name             | any user       | any user       |
   * | description      | any user       | any user       |
   * | parentid         | any user       | no             |
   * | rootid           | any user       | no             |
   * | file             | any user       | no             |
   * | image            | any user       | no             |
   * | media            | any user       | no             |
   * | grantauthoruids  | any user       | no             |
   * | grantviewuids    | any user       | no             |
   * | systemdisabled   | no             | no             |
   * | systemhidden     | no             | no             |
   *
   * Some fields are supported by parent class methods:
   *
   * | Field            | Get method                           |
   * | ---------------- | ------------------------------------ |
   * | id               | ContentEntityBase::id()              |
   * | uuid             | ContentEntityBase::uuid()            |
   * | name (label)     | ContentEntityBase::getName()         |
   * | changed          | EntityChangedTrait::getChangedTime() |
   * | langcode         | ContentEntityBase::language()        |
   *
   * Some fields are supported by methods in this class:
   *
   * | Field            | Get method                           |
   * | ---------------- | ------------------------------------ |
   * | uid              | getOwner()                           |
   * | description      | getDescription()                     |
   * | created          | getCreatedTime()                     |
   * | size             | getSize()                            |
   * | kind             | getKind()                            |
   * | mime             | getMimeType()                        |
   * | file             | getFileId()                          |
   * | image            | getImageId()                         |
   * | media            | getMediaId()                         |
   *
   * Some fields have no get/set methods or no set methods because handling
   * them requires special code and context:
   *
   * | Field            | Get method                           |
   * | ---------------- | ------------------------------------ |
   * | parentid         |                                      |
   * | rootid           |                                      |
   * | file             |                                      |
   * | image            |                                      |
   * | media            |                                      |
   *
   * @param \Drupal\Core\Entity\EntityTypeInterface $entityType
   *   The entity type for which we are returning base field
   *   definitions.
   *
   * @return array
   *   An array of field definitions where keys are field names and
   *   values are BaseFieldDefinition objects.
   */
  public static function baseFieldDefinitions(EntityTypeInterface $entityType) {
    //
    // Base class fields
    // -----------------
    // The parent ContentEntityBase class supports several standard
    // entity fields:
    //
    // - id: the entity ID
    // - uuid: the entity unique ID
    // - langcode: the content language
    // - revision: the revision ID
    // - bundle: the entity bundle
    //
    // The parent class ONLY defines these fields if they exist in
    // THIS class's comment block declaring class fields.  Of the
    // above fields, we only define these for this class:
    //
    // - id
    // - uuid
    // - langcode
    //
    // By invoking the parent class, we don't have to define these
    // ourselves below.
    //
    // Node adds a few fields we don't need, including promote, sticky,
    // revision_timestamp, revision_uid, and revision_tralsnation_affected.
    $fields = parent::baseFieldDefinitions($entityType);
 
    // But we do need to adjust display options a bit (see below).
    $weight = 0;
 
    //
    // Entity id.
    // - Integer.
    // - Primary database index.
    // - Read-only (set at creation time)
    // - 'view' shows ID (though usually converted to entity name)
    // - 'form' unsupported since read only.
    //
    // Field editing blocked by FolderShareAccessControlHandler
    // for all users.  The field is read only.
    //
    // Note:  This field was already defined by the parent class.
    // We just need to adjust it a little.
    // - Already has label ("ID").
    // - Already marked read only.
    // - Already marked unsigned.
    $fields[$entityType->getKey('id')]
      ->setDescription(t('The ID of the item.'))
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'hidden',
          'type'   => 'number_integer',
          'weight' => $weight,
        ]);
    $weight += 10;
 
    //
    // Unique id (UUID).
    // - Integer.
    // - Read-only (set at creation time)
    // - 'view' unsupported.
    // - 'form' unsupported.
    //
    // Field editing blocked by FolderShareAccessControlHandler
    // for all users. The field is read only.
    //
    // Note:  This field was already defined by the parent class.
    // We just need to adjust it a little to have a better description
    // and a way to view it.
    // - Already has label ("UUID").
    // - Already marked read only.
    $fields[$entityType->getKey('uuid')]
      ->setDescription(t('The UUID of the item.'))
      ->setDisplayConfigurable('view', FALSE)
      ->setDisplayConfigurable('form', FALSE);
    $weight += 10;
 
    //
    // Language code.
    // - 'view' hidden.
    // - 'form' selects language.
    //
    // Field editing blocked by FolderShareAccessControlHandler
    // for all users.
    //
    // Note: This field is required by the ContentEntityBase base class,
    // which may use it to guide trnaslations.  We do not need to
    // implement anything further.
    //
    // Note:  This field was already defined by the parent class.
    // We just need to adjust it a little.
    // - Already has label ("Language").
    // - Already has view (hidden).
    // - Already has form (language select).
    $f = $fields[$entityType->getKey('langcode')];
    $f->setDescription(t('The original language for the item.'));
    $fa = $f->getDisplayOptions('form');
    if ($fa === NULL) {
      $fa = ['type' => 'language_select'];
    }
 
    $fa['weight'] = $weight;
    $f->setDisplayOptions('form', $fa);
 
    //
    // Common fields
    // -------------
    // Like Drupal nodes, folders have an owner, creation date,
    // changed date, and name (node calls it a title).  We use
    // definitions that are very similar to those for node fields.
    //
    // Name.
    // - String.
    // - Required, no default.
    // - 'view' shows the name.
    // - 'form' unsupported.
    //
    // Note that the 'name' field is specifically excluded from the
    // folder's default edit form. Names are handled separately via a
    // 'Rename' command that does not use the default edit form.
    $fields['name'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Name'))
      ->setDescription(t('The name of the item.'))
      ->setRequired(TRUE)
      ->setSettings([
        'default_value'   => 'Item',
        'max_length'      => self::MAX_NAME_LENGTH,
        'text_processing' => FALSE,
      ])
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'hidden',
          'type'   => 'string',
          'weight' => $weight,
        ])
      ->setDisplayConfigurable('form', FALSE);
    $weight += 10;
 
    //
    // User (owner) id.
    // - Entity reference to user object.
    // - 'view' shows the user's name.
    // - 'form' unsupported.
    //
    // Field editing blocked by FolderShareAccessControlHandler
    // except for admins.
    //
    // Note that even for admins, the 'uid' field is specifically
    // excluded from the item's default edit form. User IDs are
    // handled separately via a 'Chown' (Change owner) command that
    // does not use the default edit form (and must recurse through
    // a folder tree).
    $fields['uid'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Owner'))
      ->setDescription(t("The user ID of the item's owner."))
      ->setRequired(TRUE)
      ->setSetting('target_type', 'user')
      ->setSetting('handler', 'default')
      ->setDefaultValueCallback(
        'Drupal\foldershare\Entity\FolderShare::getCurrentUserId')
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'inline',
          'type'   => 'author',
          'weight' => $weight,
        ])
      ->setDisplayConfigurable('form', FALSE);
    $weight += 10;
 
    //
    // Creation date.
    // - Time stamp.
    // - 'view' shows date/time.
    // - 'form' unsupported.
    //
    // Field editing blocked by FolderShareAccessControlHandler
    // except for admins.
    $fields['created'] = BaseFieldDefinition::create('created')
      ->setLabel(t('Created'))
      ->setDescription(t('The date and time when the item was created.'))
      ->setRequired(TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'inline',
          'type'   => 'timestamp',
          'weight' => $weight,
        ])
      ->setDisplayConfigurable('form', FALSE);
    $weight += 10;
 
    //
    // Changed (modified) date.
    // - Time stamp.
    // - 'view' shows date/time.
    // - 'form' unsupported.
    //
    // Field editing blocked by FolderShareAccessControlHandler.
    //
    // Note: This field is required by the EntityChangedTrait, which
    // implements the EntityChangedInterface.  Because we use the trait,
    // we do not need to implement anything further.
    $fields['changed'] = BaseFieldDefinition::create('changed')
      ->setLabel(t('Modified'))
      ->setDescription(t('The date and time when the item was most recently modified.'))
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'inline',
          'type'   => 'timestamp',
          'weight' => $weight,
        ])
      ->setDisplayConfigurable('form', FALSE);
    $weight += 10;
 
    //
    // Custom fields
    // -------------
    // FolderShare entities have a variety of custom fields.
    //
    // Description.
    // - Long text.
    // - Optional, no default.
    // - 'view' shows the text.
    // - 'form' edits the text as a text area.
    $fields['description'] = BaseFieldDefinition::create('text_long')
      ->setLabel(t('Description'))
      ->setDescription(t('The description of the item. The text may be empty, brief, or long.'))
      ->setRequired(FALSE)
      ->setSettings(['default_value' => ''])
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'hidden',
          'type'   => 'text_default',
          'weight' => $weight,
        ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayOptions(
        'form',
        [
          'type'        => 'text_textfield',
          'description' => 'Enter a description of the item. The description may be empty, brief, or long.',
          'rows'        => 20,
          'weight'      => $weight,
        ]);
    $weight += 10;
 
    //
    // Kind.
    // - String.
    // - Required, no default.
    // - 'view' shows the text.
    // - 'form' unsupported.
    $fields['kind'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Kind'))
      ->setDescription(t('The kind of item, such as a file or folder.'))
      ->setRequired(TRUE)
      ->setSettings(['default_value' => ''])
      ->setSetting('is_ascii', TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'hidden',
          'type'   => 'text_default',
          'weight' => $weight,
        ])
      ->setDisplayConfigurable('form', FALSE);
    $weight += 10;
 
    //
    // MIME.
    // - String.
    // - Required, no default.
    // - 'view' shows the text.
    // - 'form' unsupported.
    $fields['mime'] = BaseFieldDefinition::create('string')
      ->setLabel(t('MIME type'))
      ->setDescription(t("The MIME type characterizing a file's contents, such as a JPEG image or a PDF document."))
      ->setRequired(TRUE)
      ->setSettings(['default_value' => ''])
      ->setSetting('is_ascii', TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'hidden',
          'type'   => 'text_default',
          'weight' => $weight,
        ])
      ->setDisplayConfigurable('form', FALSE);
    $weight += 10;
 
    //
    // Parent ID.
    // - Entity reference to parent Folder, if any.
    // - Optional, no default (empty means folder is in root list)
    // - 'view' shows the parent folder's name.
    // - 'form' unsupported.
    //
    // Field editing blocked by FolderShareAccessControlHandler
    // for all users.
    $fields['parentid'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Parent folder'))
      ->setDescription(t("The item's direct ancestor folder. When an item is at the top-level itself, this field is empty (NULL)."))
      ->setRequired(FALSE)
      ->setSetting('target_type', self::ENTITY_TYPE_ID)
      ->setSetting('handler', 'default')
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'hidden',
          'type'   => 'entity_reference_label',
          'weight' => $weight,
        ]);
    $weight += 10;
 
    //
    // Root ID.
    // - Entity reference to a root item, if any.
    // - Optional, no default (empty means item is at the root).
    // - 'view' shows the root item's name.
    // - 'form' unsupported.
    //
    // Field editing blocked by FolderShareAccessControlHandler
    // for all users.
    $fields['rootid'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Top-level folder'))
      ->setDescription(t("The item's highest folder ancestor. When an item is at the top-level itself, this field points back to the same entity."))
      ->setRequired(FALSE)
      ->setSetting('target_type', self::ENTITY_TYPE_ID)
      ->setSetting('handler', 'default')
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'hidden',
          'type'   => 'entity_reference_label',
          'weight' => $weight,
        ]);
    $weight += 10;
 
    //
    // Size.
    // - Big integer.
    // - Optional, no default (filled in as needed by auto size calc)
    // - 'view' shows the size.
    // - 'form' unsupported.
    //
    // Field editing blocked by FolderShareAccessControlHandler
    // for all users.
    $fields['size'] = BaseFieldDefinition::create('integer')
      ->setLabel(t('Size'))
      ->setDescription(t('The storage space (in bytes) used by the file or folder, and all of its child files and folders.'))
      ->setRequired(FALSE)
      ->setSetting('size', 'big')
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'inline',
          'type'   => 'foldershare_storage_size',
          'weight' => $weight,
        ]);
    $weight += 10;
 
    //
    // System hidden field flag.
    // - Boolean.
    // - Default is FALSE.
    // - 'view' unsupported.
    // - 'form' unsupported.
    //
    // Field editing blocked by FolderShareAccessControlHandler for all users.
    $fields['systemhidden'] = BaseFieldDefinition::create('boolean')
      ->setLabel(t('System hidden'))
      ->setDescription(t('A TRUE/FALSE value indicating if the entity has been hidden by the system during special operations.'))
      ->setRequired(FALSE)
      ->setDefaultValue(FALSE)
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', FALSE);
    $weight += 10;
 
    //
    // System disabled field flag.
    // - Boolean.
    // - Default is FALSE.
    // - 'view' unsupported.
    // - 'form' unsupported.
    //
    // Field editing blocked by FolderShareAccessControlHandler for all users.
    $fields['systemdisabled'] = BaseFieldDefinition::create('boolean')
      ->setLabel(t('System disabled'))
      ->setDescription(t('A TRUE/FALSE value indicating if the entity has been disabled by the system during special operations.'))
      ->setRequired(FALSE)
      ->setDefaultValue(FALSE)
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', FALSE);
    $weight += 10;
 
    //
    // File.
    // - A single File entity for a file item in a folder (i.e. kind == file).
    // - 'view' shows item.
    // - 'form' unsupported (custom code later).
    //
    // Field editing is blocked by FolderShareAccessControlHandler
    // for all users.
    //
    // Because folders are intended to contain any type of file,
    // we would rather not restrict the set of file extensions.
    // Unfortunately, this is currently not possible:
    //
    // Instead, elsewhere we provide our own handling of uploaded
    // files in order to take control over file extension testing.
    //
    // File names are constrained to not be empty, not include :, /, or \,
    // and not collide with an existing file. We check names explicitly
    // durring add/rename operations instead of using a field constraint,
    // which would be less efficient since it would require checking and
    // rechecking the name every time the entity was modified for any
    // reason (such as changing its description).
    //
    // A 'file' field type extends an entity reference field type and
    // adds these stored values with every instance:
    // - display     = true/false for whether the file should be shown.
    // - description = description text for the file.
    //
    // The 'file' field also adds these settings applied to this usage
    // of the field type:
    // - file_extensions   = the allowed extensions list.
    // - file_directory    = a subdirectory in which to store files.
    // - max_filesize      = the maximum uploaded file size allowed.
    // - description_field = whether to include a description per file.
    //
    // FolderShare does not use all of these features of 'file' fields:
    // - description_field is set to FALSE and the description text is
    //   never set or used. The containing FolderShare entity has its
    //   own description field.
    // - file_directory is ignored and FolderShare determines the directory
    //   path on its own (see FolderShareStream).
    $extensions = '';
    if (Settings::getFileRestrictExtensions() === TRUE) {
      $extensions = Settings::getAllowedNameExtensions();
    }
 
    $fields['file'] = BaseFieldDefinition::create('file')
      ->setLabel(t('File'))
      ->setDescription(t('A non-image file within a folder.'))
      ->setRequired(FALSE)
      ->setSetting('target_type', 'file')
      ->setSetting('handler', 'default')
      ->setSetting('file_extensions', $extensions)
      ->setSetting('max_filesize', '')
      ->setSetting('description_field', FALSE)
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'inline',
          'type'   => 'file_default',
          'weight' => $weight,
        ]);
    $weight += 10;
 
    //
    // Image.
    // - A single Image entity for a file item in a folder (i.e. kind == image).
    // - 'view' shows item.
    // - 'form' unsupported (custom code later).
    //
    // See comments above for the file field.
    //
    // An 'image' field type extends the 'file' field type and adds these
    // stored values for every instance:
    // - alt    = alternate text for the image's 'alt' attribute.
    // - title  = title text for the image's 'title' attribute.
    // - width  = the image width.
    // - height = the image height.
    //
    // The 'image' field also adds these settings applied to this usage
    // of the field type:
    // - alt_field            = whether to include an alt value per image.
    // - alt_field_required   = whether alt text is required.
    // - title_field          = whether to include a title value per image.
    // - title_field_required = whether title text is required.
    // - min_resolution       = the minimum accepted image resolution.
    // - max_resolution       = the maximum accepted image resolution.
    // - default_image        = a default image if none is provided.
    //
    // FolderShare does not use all of these features of 'image' fields:
    // - alt_field and title_field are not used and alt_field_required
    //   and title_field_required are set to FALSE.
    // - default_image is not used because the image field is only set if
    //   we have an image file.
    $fields['image'] = BaseFieldDefinition::create('image')
      ->setLabel(t('Image'))
      ->setDescription(t('An image file within a folder.'))
      ->setRequired(FALSE)
      ->setSetting('target_type', 'file')
      ->setSetting('handler', 'default')
      ->setSetting('file_extensions', $extensions)
      ->setSetting('description_field', FALSE)
      ->setSetting('alt_field', FALSE)
      ->setSetting('alt_field_required', FALSE)
      ->setSetting('title_field', FALSE)
      ->setSetting('title_field_required', FALSE)
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'inline',
          'type'   => 'image',
          'weight' => $weight,
        ]);
    $weight += 10;
 
    //
    // Media.
    // - A single Media entity for a media item in a folder (i.e. kind ==media).
    // - 'view' shows item.
    // - 'form' unsupported (custom code later).
    //
    // See comments above for the file field.
    //
    // Media entities do not have a corresponding media field type. Instead
    // we refer to a media entity using an entity_reference.
    $fields['media'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Media'))
      ->setDescription(t('A media item within a folder.'))
      ->setRequired(FALSE)
      ->setSetting('target_type', 'media')
      ->setSetting('handler', 'default')
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'inline',
          'type'   => 'media_thumbnail',
          'weight' => $weight,
        ]);
    $weight += 10;
 
    //
    // Access control for author access.
    // Access control for view access.
    // - List of UIDs.
    // - 'view' shows author names (except disabled field).
    // - 'form' unsupported (custom code required).
    //
    // Field editing blocked by FolderShareAccessControlHandler
    // for all users.
    //
    $fields['grantauthoruids'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Author grants'))
      ->setDescription(t("A list of IDs for users that have been granted author access to the item and all of its descendants. Only top-level items have values. The item's owner is always on this list."))
      ->setRequired(FALSE)
      ->setSetting('target_type', 'user')
      ->setSetting('handler', 'default')
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'inline',
          'type'   => 'author',
          'weight' => $weight,
        ]);
    $weight += 10;
 
    $fields['grantviewuids'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Viewer grants'))
      ->setDescription(t("A list of IDs for users that have been granted view access to the item and all of its descendants. Only top-level items have values. The item's owner is always on this list."))
      ->setRequired(FALSE)
      ->setSetting('target_type', 'user')
      ->setSetting('handler', 'default')
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions(
        'view',
        [
          'label'  => 'inline',
          'type'   => 'author',
          'weight' => $weight,
        ]);
    $weight += 10;
 
    return $fields;
  }
 
  /*---------------------------------------------------------------------
   *
   * Entity management.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * {@inheritdoc}
   *
   * This method is called immediately after an entity has been saved.
   * If the Drupal core Search module is installed, the entity is marked
   * for search re-indexing.
   */
  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
    // Let the parent class do its work.
    parent::postSave($storage, $update);
 
    // If search module is enabled, mark entity as in need of re-indexing.
    if ($update === TRUE) {
      ManageSearch::markForReindex([$this]);
    }
  }
 
  /**
   * {@inheritdoc}
   *
   * This method is called immediately before an entity is deleted.
   * If the core 'search' module is installed, the search index entry
   * for the entity is cleared.
   */
  public static function preDelete(
    EntityStorageInterface $storage,
    array $items) {
    // Let the parent class do its work.
    parent::preDelete($storage, $items);
 
    // Clear entities from the search index.
    ManageSearch::deleteFromIndex($items);
  }
 
  /*---------------------------------------------------------------------
   *
   * General utilities.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * Returns the current user ID.
   *
   * This function provides the deault value callback for the 'uid'
   * base field definition.
   *
   * @return array
   *   An array of default values. In this case, the array only
   *   contains the current user ID.
   *
   * @see ::baseFieldDefinitions()
   */
  public static function getCurrentUserId() {
    return [\Drupal::currentUser()->id()];
  }
 
  /**
   * {@inheritdoc}
   */
  public function getExtension() {
    return ManageFilenameExtensions::getExtensionFromPath($this->getName());
  }
 
  /**
   * {@inheritdoc}
   */
  public function getPath() {
    $names = $this->findAncestorFolderNames();
    if (empty($names) === TRUE) {
      return '/' . $this->getName();
    }
 
    return '/' . implode('/', $names) . '/' . $this->getName();
  }
 
  /*---------------------------------------------------------------------
   *
   * Access control.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * {@inheritdoc}
   */
  public function access(
    $operation,
    AccountInterface $account = NULL,
    $returnAsObject = FALSE) {
 
    // Drupal's Entity class implements this method and splits 'create'
    // operations off from all other operations:
    // - 'create' is sent to the access controller's createAccess() method.
    // - Everything else is sent to the access controller's access() method.
    //
    // This is fine for everything except 'create'. By sending 'create'
    // to the createAccess() method, the context of the current entity is
    // lost. That method does not include an entity argument.
    //
    // Without the context of the current entity, the access controller
    // cannot check access grants based on the folder tree. All it can do
    // is check permissions.
    //
    // Without checking access grants, createAccess() is forced to return a
    // generic and incomplete answer. Drupal automatically caches that answer
    // and uses instead of making further access checks. This will cause a
    // mess when that answer needs to vary based on entity context and access
    // grants, and yet it can't. Inappropriate cached answers will be used
    // over and over again in every context.
    //
    // The fix is to route 'create' operations to the access controller's
    // access() method, along with all other operations. This enables
    // the access controller to check access grants on the entity's folder
    // tree and include a result cache dependency on the entity at hand.
    return $this->entityTypeManager()
      ->getAccessControlHandler($this->entityTypeId)
      ->access($this, $operation, $account, $returnAsObject);
  }
 
}

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

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