You are here

class Pbf in Permissions by field 8

Plugin implementation of the 'pbf' field type.

Plugin annotation


@FieldType(
  id = "pbf",
  label = @Translation("Permissions by field"),
  description = @Translation("Permissions by field"),
  default_widget = "pbf_widget",
  default_formatter = "pbf_formatter_default",
  list_class = "\Drupal\pbf\Plugin\Field\PbfFieldItemList",
)

Hierarchy

Expanded class hierarchy of Pbf

File

src/Plugin/Field/FieldType/Pbf.php, line 26

Namespace

Drupal\pbf\Plugin\Field\FieldType
View source
class Pbf extends EntityReferenceItem {

  /**
   * The access rights operations.
   *
   * @var array
   */
  protected static $operations = [
    'grant_public' => 'Public',
    'grant_view' => 'Grant View',
    'grant_update' => 'Grant Update',
    'grant_delete' => 'Grant Delete',
  ];

  /**
   * The Entity Field Manager service.
   *
   * @var \Drupal\Core\Entity\EntityFieldManager
   */
  protected $entityFieldManager;

  /**
   * {@inheritdoc}
   */
  public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) {
    parent::__construct($definition, $name, $parent);
    $this->entityFieldManager = \Drupal::service('entity_field.manager');
  }

  /**
   * {@inheritdoc}
   */
  public static function defaultFieldSettings() {
    return array(
      'priority' => 0,
      'user_method' => 'user',
      'synchronized_with' => '',
      'synchronized_from_target' => 0,
      'synchronized_by' => '',
    ) + parent::defaultFieldSettings();
  }

  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties = parent::propertyDefinitions($field_definition);

    // Add operations properties.
    foreach (self::$operations as $key => $value) {
      $properties[$key] = DataDefinition::create('boolean')
        ->setLabel(new TranslatableMarkup('@operation access', [
        '@operation' => $key,
      ]));
    }
    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    $schema = parent::schema($field_definition);

    // Add operations columns.
    foreach (self::$operations as $key => $value) {
      $column_value = [
        'type' => 'int',
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 0,
      ];
      $schema['columns'][$key] = $column_value;
    }
    return $schema;
  }

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

    // We support only user_role, node, taxonomy_term and user.
    $entity_type = \Drupal::service('entity_type.repository')
      ->getEntityTypeLabels();
    $options_supported = [
      'user_role' => 'user_role',
      'node' => 'node',
      'taxonomy_term' => 'taxonomy_term',
      'user' => 'user',
    ];
    $options = array_intersect_key($entity_type, $options_supported);
    $element['target_type'] = array(
      '#type' => 'select',
      '#title' => $this
        ->t('Type of item to reference'),
      '#options' => $options,
      '#default_value' => $this
        ->getSetting('target_type'),
      '#required' => TRUE,
      '#disabled' => $has_data,
      '#size' => 1,
    );
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
    $form = parent::fieldSettingsForm($form, $form_state);

    /** @var \Drupal\field\FieldConfigInterface $field */
    $field = $form_state
      ->getFormObject()
      ->getEntity();
    $entity_type = $field
      ->getTargetEntityTypeId();
    $bundle = $field
      ->getTargetBundle();
    $target_entity_type_id = $field
      ->getSetting('target_type');
    $cardinality = $field
      ->getFieldStorageDefinition()
      ->getCardinality();
    $form['synchronization'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('Synchronization'),
      '#description' => '',
      '#open' => TRUE,
      '#tree' => TRUE,
      '#process' => [
        [
          get_class($this),
          'formProcessMergeParent',
        ],
      ],
      '#weight' => 10,
    ];
    $form['synchronization']['synchronized_by'] = [
      '#type' => 'value',
      '#value' => $field
        ->getSetting('synchronized_by') ? $field
        ->getSetting('synchronized_by') : '',
    ];
    if ($cardinality === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {

      // Only fields attached to user entity type can be synchronized by.
      if ($field
        ->getSetting('synchronized_by') && empty($field
        ->getSetting('synchronized_from_target'))) {
        $form['synchronization']['info'] = [
          '#markup' => $this
            ->t('Field synchronized by @field_id', [
            '@field_id' => $field
              ->getSetting('synchronized_by'),
          ]),
          '#prefix' => '<p>',
          '#suffix' => '</p>',
        ];
      }
      elseif ($field
        ->getSetting('synchronized_by') && $field
        ->getSetting('synchronized_from_target')) {
        $form['synchronization']['info'] = [
          '#markup' => $this
            ->t('Field synchronized by @field_id and allowed to synchronize it', [
            '@field_id' => $field
              ->getSetting('synchronized_by'),
          ]),
          '#prefix' => '<p>',
          '#suffix' => '</p>',
        ];
      }
      elseif (empty($field
        ->getSetting('synchronized_by')) && $entity_type == 'user') {
        $form['synchronization']['info'] = [
          '#markup' => $this
            ->t('Field not synchronized'),
          '#prefix' => '<p>',
          '#suffix' => '</p>',
        ];
      }
      elseif ($target_entity_type_id !== 'user') {
        $form['synchronization']['info'] = [
          '#markup' => $this
            ->t('Field which reference user entity type can be synchronized if eligible fields are found.'),
          '#prefix' => '<p>',
          '#suffix' => '</p>',
        ];
      }
    }
    else {
      $form['synchronization']['info'] = [
        '#markup' => $this
          ->t('Only field with an unlimited cardinality can be synchronized'),
        '#prefix' => '<p>',
        '#suffix' => '</p>',
      ];
    }

    // No need to display theses options that are only relevant on Node entity
    // type.
    if ($entity_type !== 'node') {
      return $form;
    }

    // Priority parameter has been removed in Drupal 8, and will not be used
    // except by using Node access priority Module. See
    // https://www.drupal.org/project/napriority
    $form['priority'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('Permissions priority'),
      '#open' => TRUE,
      '#tree' => TRUE,
      '#process' => [
        [
          get_class($this),
          'formProcessMergeParent',
        ],
      ],
      '#weight' => 1,
    ];
    $form['priority']['priority'] = [
      '#type' => 'number',
      '#title' => $this
        ->t('Priority'),
      '#description' => $this
        ->t('The priority to apply on permissions.
      If not sure about this, let the default priority to 0. If you have some
      issues with the permissions set, because you use multiple modules which
      handle node access, try to increase the priority applied to
      the permissions. Priority will be only used if the module Node access
      priority is installed. Permissions with the higher priority will be then
      used.'),
      '#default_value' => $field
        ->getSetting('priority') ? $field
        ->getSetting('priority') : 0,
    ];
    if ($target_entity_type_id == 'user') {
      $options = [
        'user' => $this
          ->t('Grant access directly to users referenced'),
        'ref_user' => $this
          ->t('Grant access directly to users referenced and
         grant access to users who reference those users from the field
         <em>@field_name</em> attached to user entity type', [
          '@field_name' => $field
            ->getName(),
        ]),
      ];
      $form['user_method'] = [
        '#type' => 'details',
        '#title' => $this
          ->t('Handle permissions for users'),
        '#open' => TRUE,
        '#tree' => TRUE,
        '#process' => [
          [
            get_class($this),
            'formProcessMergeParent',
          ],
        ],
        '#weight' => 2,
      ];
      $form['user_method']['user_method'] = [
        '#type' => 'radios',
        '#title' => $this
          ->t('Choose method for grant access to users'),
        '#options' => $options,
        '#default_value' => $field
          ->getSetting('user_method') ? $field
          ->getSetting('user_method') : 'user',
      ];
      if ($cardinality === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {

        // We support for referenced user to synchronize them if they have a Pbf
        // field attached whose target bundle is the current bundle.
        // We get eligible fields to be synchronized.
        $fields = $this
          ->getPbfEligibleFields($target_entity_type_id, $bundle);
        $eligible_fields = [];
        if ($fields) {
          foreach ($fields as $field_id => $field_data) {
            $eligible_fields[$field_id] = $field_data['label'] . ' (' . $field_data['field_name'] . ')';
          }
        }
        $form['synchronization']['synchronized_with'] = [
          '#type' => 'select',
          '#title' => $this
            ->t('Select the field attached to users to synchronize'),
          '#options' => $eligible_fields,
          "#empty_option" => $this
            ->t('No synchronization'),
          '#default_value' => $field
            ->getSetting('synchronized_with') ? $field
            ->getSetting('synchronized_with') : [],
        ];
        $form['synchronization']['synchronized_from_target'] = [
          '#type' => 'checkbox',
          '#title' => $this
            ->t('Allow targeted field from users to synchronize this field'),
          '#default_value' => $field
            ->getSetting('synchronized_from_target') ? $field
            ->getSetting('synchronized_from_target') : 0,
          '#return_value' => (int) 1,
          '#empty' => 0,
          '#states' => [
            'invisible' => [
              'select[data-drupal-selector="edit-settings-synchronized-with"]' => [
                'value' => '',
              ],
            ],
          ],
        ];
      }
    }
    return $form;
  }

  /**
   * Return the pbf fields eligible to be synchronized.
   *
   * Eligible fields we can synchronize are those whose target bundle match
   * the bundle of the current field.
   *
   * @return array
   *   The list pbf fields
   */
  private function getPbfEligibleFields($entity_type_id, $target_bundle) {
    $fields = $this->entityFieldManager
      ->getFieldMapByFieldType('pbf');
    if (!isset($fields[$entity_type_id])) {
      return [];
    }
    $return = [];
    foreach ($fields[$entity_type_id] as $field_name => $field_data) {
      foreach ($field_data['bundles'] as $bundle) {
        $instance = $this->entityFieldManager
          ->getFieldDefinitions($entity_type_id, $bundle)[$field_name];

        // Only fields with an unlimited cardinality can be synchronized.
        if ($instance instanceof FieldConfigInterface && $instance
          ->getFieldStorageDefinition()
          ->getCardinality() == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
          $instance_target_bundle = $this
            ->getTargetBundles($instance);
          if (in_array($target_bundle, $instance_target_bundle)) {
            $data['entity_type'] = $instance
              ->getTargetEntityTypeId();
            $data['bundle'] = $instance
              ->getTargetBundle();
            $data['label'] = $instance
              ->getLabel();
            $data['field_name'] = $field_name;
            $return[$instance
              ->id()] = $data;
          }
        }
      }
    }
    return $return;
  }

  /**
   * Get the target bundle of a Field Pbf.
   *
   * @param \Drupal\Core\Field\FieldConfigInterface $field
   *   The field instance on which we want the target bundles.
   *
   * @return array
   *   The list of target bundles.
   */
  private function getTargetBundles(FieldConfigInterface $field) {
    $target_bundles = [];
    $settings = $field
      ->getSettings();
    if (isset($settings['handler_settings']['target_bundles'])) {
      $target_bundles = $settings['handler_settings']['target_bundles'];
    }
    return $target_bundles;
  }

  /**
   * Return the list of operations available.
   *
   * @return array
   *   The list of operations.
   */
  public function getOperations() {
    $operations = [
      'grant_public' => $this
        ->t('Public'),
      'grant_view' => $this
        ->t('Grant View'),
      'grant_update' => $this
        ->t('Grant Update'),
      'grant_delete' => $this
        ->t('Grant Delete'),
    ];
    return $operations;
  }

  /**
   * Check if the field is tag as public.
   *
   * @return bool
   *   The field is tag or not as public.
   */
  public function isPublic() {
    if ($this->grant_public) {
      return TRUE;
    }
    return FALSE;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
EntityReferenceItem::calculateDependencies public static function Calculates dependencies for field items. Overrides FieldItemBase::calculateDependencies
EntityReferenceItem::calculateStorageDependencies public static function Calculates dependencies for field items on the storage level. Overrides FieldItemBase::calculateStorageDependencies
EntityReferenceItem::defaultStorageSettings public static function Defines the storage-level settings for this plugin. Overrides FieldItemBase::defaultStorageSettings 1
EntityReferenceItem::fieldSettingsAjaxProcess public static function Render API callback: Processes the field settings form and allows access to the form state.
EntityReferenceItem::fieldSettingsAjaxProcessElement public static function Adds entity_reference specific properties to AJAX form elements from the field settings form.
EntityReferenceItem::fieldSettingsFormValidate public static function Form element validation handler; Invokes selection plugin's validation.
EntityReferenceItem::formProcessMergeParent public static function Render API callback: Moves entity_reference specific Form API elements (i.e. 'handler_settings') up a level for easier processing by the validation and submission handlers.
EntityReferenceItem::generateSampleValue public static function Generates placeholder field values. Overrides FieldItemBase::generateSampleValue 1
EntityReferenceItem::getConstraints public function Gets a list of validation constraints. Overrides TypedData::getConstraints
EntityReferenceItem::getPossibleOptions public function Returns an array of possible values with labels for display. Overrides OptionsProviderInterface::getPossibleOptions
EntityReferenceItem::getPossibleValues public function Returns an array of possible values. Overrides OptionsProviderInterface::getPossibleValues
EntityReferenceItem::getPreconfiguredOptions public static function Returns preconfigured field options for a field type. Overrides PreconfiguredFieldUiOptionsInterface::getPreconfiguredOptions 1
EntityReferenceItem::getRandomBundle protected static function Gets a bundle for a given entity type and selection options.
EntityReferenceItem::getSettableOptions public function Returns an array of settable values with labels for display. Overrides OptionsProviderInterface::getSettableOptions
EntityReferenceItem::getSettableValues public function Returns an array of settable values. Overrides OptionsProviderInterface::getSettableValues
EntityReferenceItem::getValue public function Gets the data value. Overrides Map::getValue
EntityReferenceItem::hasNewEntity public function Determines whether the item holds an unsaved entity.
EntityReferenceItem::isEmpty public function Determines whether the data structure is empty. Overrides Map::isEmpty
EntityReferenceItem::mainPropertyName public static function Returns the name of the main property, if any. Overrides FieldItemBase::mainPropertyName
EntityReferenceItem::onChange public function React to changes to a child property or item. Overrides Map::onChange
EntityReferenceItem::onDependencyRemoval public static function Informs the plugin that a dependency of the field will be deleted. Overrides FieldItemBase::onDependencyRemoval
EntityReferenceItem::preSave public function Defines custom presave behavior for field values. Overrides FieldItemBase::preSave 1
EntityReferenceItem::settingsAjax public static function Ajax callback for the handler settings form.
EntityReferenceItem::settingsAjaxSubmit public static function Submit handler for the non-JS case.
EntityReferenceItem::setValue public function Sets the data value. Overrides FieldItemBase::setValue
FieldItemBase::delete public function Defines custom delete behavior for field values. Overrides FieldItemInterface::delete 2
FieldItemBase::deleteRevision public function Defines custom revision delete behavior for field values. Overrides FieldItemInterface::deleteRevision
FieldItemBase::fieldSettingsFromConfigData public static function Returns a settings array in the field type's canonical representation. Overrides FieldItemInterface::fieldSettingsFromConfigData 1
FieldItemBase::fieldSettingsToConfigData public static function Returns a settings array that can be stored as a configuration value. Overrides FieldItemInterface::fieldSettingsToConfigData 1
FieldItemBase::getEntity public function Gets the entity that field belongs to. Overrides FieldItemInterface::getEntity
FieldItemBase::getFieldDefinition public function Gets the field definition. Overrides FieldItemInterface::getFieldDefinition
FieldItemBase::getLangcode public function Gets the langcode of the field values held in the object. Overrides FieldItemInterface::getLangcode
FieldItemBase::getSetting protected function Returns the value of a field setting.
FieldItemBase::getSettings protected function Returns the array of field settings.
FieldItemBase::postSave public function Defines custom post-save behavior for field values. Overrides FieldItemInterface::postSave 2
FieldItemBase::storageSettingsFromConfigData public static function Returns a settings array in the field type's canonical representation. Overrides FieldItemInterface::storageSettingsFromConfigData 2
FieldItemBase::storageSettingsToConfigData public static function Returns a settings array that can be stored as a configuration value. Overrides FieldItemInterface::storageSettingsToConfigData 2
FieldItemBase::view public function Returns a renderable array for a single field item. Overrides FieldItemInterface::view
FieldItemBase::writePropertyValue protected function Different to the parent Map class, we avoid creating property objects as far as possible in order to optimize performance. Thus we just update $this->values if no property object has been created yet. Overrides Map::writePropertyValue
FieldItemBase::__get public function Magic method: Gets a property value. Overrides FieldItemInterface::__get 2
FieldItemBase::__isset public function Magic method: Determines whether a property is set. Overrides FieldItemInterface::__isset
FieldItemBase::__set public function Magic method: Sets a property value. Overrides FieldItemInterface::__set 1
FieldItemBase::__unset public function Magic method: Unsets a property. Overrides FieldItemInterface::__unset
Map::$definition protected property The data definition. Overrides TypedData::$definition
Map::$properties protected property The array of properties.
Map::$values protected property An array of values for the contained properties.
Map::applyDefaultValue public function Applies the default value. Overrides TypedData::applyDefaultValue 4
Map::get public function Gets a property object. Overrides ComplexDataInterface::get
Map::getIterator public function
Map::getProperties public function Gets an array of property objects. Overrides ComplexDataInterface::getProperties
Map::getString public function Returns a string representation of the data. Overrides TypedData::getString
Map::set public function Sets a property value. Overrides ComplexDataInterface::set
Map::toArray public function Returns an array of all property values. Overrides ComplexDataInterface::toArray 1
Map::__clone public function Magic method: Implements a deep clone.
Pbf::$entityFieldManager protected property The Entity Field Manager service.
Pbf::$operations protected static property The access rights operations.
Pbf::defaultFieldSettings public static function Defines the field-level settings for this plugin. Overrides EntityReferenceItem::defaultFieldSettings
Pbf::fieldSettingsForm public function Returns a form for the field-level settings. Overrides EntityReferenceItem::fieldSettingsForm
Pbf::getOperations public function Return the list of operations available.
Pbf::getPbfEligibleFields private function Return the pbf fields eligible to be synchronized.
Pbf::getTargetBundles private function Get the target bundle of a Field Pbf.
Pbf::isPublic public function Check if the field is tag as public.
Pbf::propertyDefinitions public static function Defines field item properties. Overrides EntityReferenceItem::propertyDefinitions
Pbf::schema public static function Returns the schema for the field. Overrides EntityReferenceItem::schema
Pbf::storageSettingsForm public function Returns a form for the storage-level settings. Overrides EntityReferenceItem::storageSettingsForm
Pbf::__construct public function Constructs a TypedData object given its definition and context. Overrides FieldItemBase::__construct
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
TypedData::$name protected property The property name.
TypedData::$parent protected property The parent typed data object.
TypedData::createInstance public static function Constructs a TypedData object given its definition and context. Overrides TypedDataInterface::createInstance
TypedData::getDataDefinition public function Gets the data definition. Overrides TypedDataInterface::getDataDefinition
TypedData::getName public function Returns the name of a property or item. Overrides TypedDataInterface::getName
TypedData::getParent public function Returns the parent data structure; i.e. either complex data or a list. Overrides TypedDataInterface::getParent
TypedData::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition
TypedData::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
TypedData::getPropertyPath public function Returns the property path of the data. Overrides TypedDataInterface::getPropertyPath
TypedData::getRoot public function Returns the root of the typed data tree. Overrides TypedDataInterface::getRoot
TypedData::setContext public function Sets the context of a property or item via a context aware parent. Overrides TypedDataInterface::setContext
TypedData::validate public function Validates the currently set data value. Overrides TypedDataInterface::validate
TypedDataTrait::$typedDataManager protected property The typed data manager used for creating the data types.
TypedDataTrait::getTypedDataManager public function Gets the typed data manager. 2
TypedDataTrait::setTypedDataManager public function Sets the typed data manager. 2