/** * {@inheritdoc} */ public function view(FieldItemListInterface $items, $langcode = NULL) { // Default the language to the current content language. if (empty($langcode)) { $langcode = \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId(); } $elements = $this->viewElements($items, $langcode); // If there are actual renderable children, use #theme => field, otherwise, // let access cacheability metadata pass through for correct bubbling. if (Element::children($elements)) { $entity = $items->getEntity(); $entity_type = $entity->getEntityTypeId(); $field_name = $this->fieldDefinition->getName(); $info = array('#theme' => 'field', '#title' => $this->fieldDefinition->getLabel(), '#label_display' => $this->label, '#view_mode' => $this->viewMode, '#language' => $items->getLangcode(), '#field_name' => $field_name, '#field_type' => $this->fieldDefinition->getType(), '#field_translatable' => $this->fieldDefinition->isTranslatable(), '#entity_type' => $entity_type, '#bundle' => $entity->bundle(), '#object' => $entity, '#items' => $items, '#formatter' => $this->getPluginId(), '#is_multiple' => $this->fieldDefinition->getFieldStorageDefinition()->isMultiple()); $elements = array_merge($info, $elements); } return $elements; }
/** * {@inheritdoc} */ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) { if ($operation == 'edit') { // Only users with the "administer comments" permission can edit // administrative fields. $administrative_fields = array('uid', 'status', 'created', 'date'); if (in_array($field_definition->getName(), $administrative_fields, TRUE)) { return AccessResult::allowedIfHasPermission($account, 'administer comments'); } // No user can change read-only fields. $read_only_fields = array('hostname', 'changed', 'cid', 'thread'); // These fields can be edited during comment creation. $create_only_fields = ['comment_type', 'uuid', 'entity_id', 'entity_type', 'field_name', 'pid']; if ($items && ($entity = $items->getEntity()) && $entity->isNew() && in_array($field_definition->getName(), $create_only_fields, TRUE)) { // We are creating a new comment, user can edit create only fields. return AccessResult::allowedIfHasPermission($account, 'post comments')->addCacheableDependency($entity); } // We are editing an existing comment - create only fields are now read // only. $read_only_fields = array_merge($read_only_fields, $create_only_fields); if (in_array($field_definition->getName(), $read_only_fields, TRUE)) { return AccessResult::forbidden(); } // If the field is configured to accept anonymous contact details - admins // can edit name, homepage and mail. Anonymous users can also fill in the // fields on comment creation. if (in_array($field_definition->getName(), ['name', 'mail', 'homepage'], TRUE)) { if (!$items) { // We cannot make a decision about access to edit these fields if we // don't have any items and therefore cannot determine the Comment // entity. In this case we err on the side of caution and prevent edit // access. return AccessResult::forbidden(); } /** @var \Drupal\comment\CommentInterface $entity */ $entity = $items->getEntity(); $commented_entity = $entity->getCommentedEntity(); $anonymous_contact = $commented_entity->get($entity->getFieldName())->getFieldDefinition()->getSetting('anonymous'); $admin_access = AccessResult::allowedIfHasPermission($account, 'administer comments'); $anonymous_access = AccessResult::allowedIf($entity->isNew() && $account->isAnonymous() && $anonymous_contact != COMMENT_ANONYMOUS_MAYNOT_CONTACT && $account->hasPermission('post comments'))->cachePerPermissions()->cacheUntilEntityChanges($entity)->cacheUntilEntityChanges($field_definition->getConfig($commented_entity->bundle()))->cacheUntilEntityChanges($commented_entity); return $admin_access->orIf($anonymous_access); } } if ($operation == 'view') { $entity = $items ? $items->getEntity() : NULL; // Admins can view any fields except hostname, other users need both the // "access comments" permission and for the comment to be published. The // mail field is hidden from non-admins. $admin_access = AccessResult::allowedIf($account->hasPermission('administer comments') && $field_definition->getName() != 'hostname')->cachePerPermissions(); $anonymous_access = AccessResult::allowedIf($account->hasPermission('access comments') && (!$entity || $entity->isPublished()) && !in_array($field_definition->getName(), array('mail', 'hostname'), TRUE))->cachePerPermissions(); if ($entity) { $anonymous_access->cacheUntilEntityChanges($entity); } return $admin_access->orIf($anonymous_access); } return parent::checkFieldAccess($operation, $field_definition, $account, $items); }
/** * {@inheritdoc} */ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) { // Fields that are not implicitly allowed to administrative users. $explicit_check_fields = array('pass'); // Administrative users are allowed to edit and view all fields. if (!in_array($field_definition->getName(), $explicit_check_fields) && $account->hasPermission('administer users')) { return AccessResult::allowed()->cachePerPermissions(); } // Flag to indicate if this user entity is the own user account. $is_own_account = $items ? $items->getEntity()->id() == $account->id() : FALSE; switch ($field_definition->getName()) { case 'name': // Allow view access to anyone with access to the entity. Anonymous // users should be able to access the username field during the // registration process, otherwise the username and email constraints // are not checked. if ($operation == 'view' || $items && $account->isAnonymous() && $items->getEntity()->isAnonymous()) { return AccessResult::allowed()->cachePerPermissions(); } // Allow edit access for the own user name if the permission is // satisfied. if ($is_own_account && $account->hasPermission('change own username')) { return AccessResult::allowed()->cachePerPermissions()->cachePerUser(); } else { return AccessResult::forbidden(); } case 'preferred_langcode': case 'preferred_admin_langcode': case 'timezone': case 'mail': // Allow view access to own mail address and other personalization // settings. if ($operation == 'view') { return $is_own_account ? AccessResult::allowed()->cachePerUser() : AccessResult::forbidden(); } // Anyone that can edit the user can also edit this field. return AccessResult::allowed()->cachePerPermissions(); case 'pass': // Allow editing the password, but not viewing it. return $operation == 'edit' ? AccessResult::allowed() : AccessResult::forbidden(); case 'created': // Allow viewing the created date, but not editing it. return $operation == 'view' ? AccessResult::allowed() : AccessResult::forbidden(); case 'roles': case 'status': case 'access': case 'login': case 'init': return AccessResult::forbidden(); } return parent::checkFieldAccess($operation, $field_definition, $account, $items); }
/** * {@inheritdoc} */ public function view(FieldItemListInterface $items) { $addition = array(); $elements = $this->viewElements($items); if ($elements) { $entity = $items->getEntity(); $entity_type = $entity->getEntityTypeId(); $field_name = $this->fieldDefinition->getName(); $info = array('#theme' => 'field', '#title' => $this->fieldDefinition->getLabel(), '#label_display' => $this->label, '#view_mode' => $this->viewMode, '#language' => $items->getLangcode(), '#field_name' => $field_name, '#field_type' => $this->fieldDefinition->getType(), '#field_translatable' => $this->fieldDefinition->isTranslatable(), '#entity_type' => $entity_type, '#bundle' => $entity->bundle(), '#object' => $entity, '#items' => $items, '#formatter' => $this->getPluginId()); $addition = array_merge($info, $elements); } return $addition; }
/** * {@inheritdoc} */ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) { // No user can edit the status of a file. Prevents saving a new file as // persistent before even validating it. if ($field_definition->getName() === 'status' && $operation === 'edit') { return AccessResult::forbidden(); } return parent::checkFieldAccess($operation, $field_definition, $account, $items); }
/** * {@inheritdoc} */ public function flagErrors(FieldItemListInterface $items, ConstraintViolationListInterface $violations, array $form, FormStateInterface $form_state) { $field_name = $this->fieldDefinition->getName(); $field_state = static::getWidgetState($form['#parents'], $field_name, $form_state); if ($violations->count()) { $form_builder = \Drupal::formBuilder(); // Locate the correct element in the the form. $element = NestedArray::getValue($form_state['complete_form'], $field_state['array_parents']); // Do not report entity-level validation errors if Form API errors have // already been reported for the field. // @todo Field validation should not be run on fields with FAPI errors to // begin with. See https://drupal.org/node/2070429. $element_path = implode('][', $element['#parents']); if ($reported_errors = $form_state->getErrors()) { foreach (array_keys($reported_errors) as $error_path) { if (strpos($error_path, $element_path) === 0) { return; } } } // Only set errors if the element is accessible. if (!isset($element['#access']) || $element['#access']) { $handles_multiple = $this->handlesMultipleValues(); $violations_by_delta = array(); foreach ($violations as $violation) { // Separate violations by delta. $property_path = explode('.', $violation->getPropertyPath()); $delta = array_shift($property_path); // Violations at the ItemList level are not associated to any delta, // we file them under $delta NULL. $delta = is_numeric($delta) ? $delta : NULL; $violations_by_delta[$delta][] = $violation; $violation->arrayPropertyPath = $property_path; } /** @var \Symfony\Component\Validator\ConstraintViolationInterface[] $delta_violations */ foreach ($violations_by_delta as $delta => $delta_violations) { // Pass violations to the main element: // - if this is a multiple-value widget, // - or if the violations are at the ItemList level. if ($handles_multiple || $delta === NULL) { $delta_element = $element; } else { $original_delta = $field_state['original_deltas'][$delta]; $delta_element = $element[$original_delta]; } foreach ($delta_violations as $violation) { // @todo: Pass $violation->arrayPropertyPath as property path. $error_element = $this->errorElement($delta_element, $violation, $form, $form_state); if ($error_element !== FALSE) { $form_state->setError($error_element, $violation->getMessage()); } } } } } }
/** * {@inheritdoc} */ public static function isApplicable(FieldDefinitionInterface $field_definition) { $entity_form_display = entity_get_form_display($field_definition->getTargetEntityTypeId(), $field_definition->getTargetBundle(), 'default'); $widget = $entity_form_display->getRenderer($field_definition->getName()); $widget_id = $widget->getBaseId(); if ($field_definition->isList() && $widget_id == 'video_upload') { return TRUE; } return FALSE; }
/** * {@inheritdoc} */ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) { /** @var \Drupal\comment\CommentInterface $entity */ $entity = $items->getEntity(); if ($operation == 'edit') { // Only users with the "administer comments" permission can edit // administrative fields. $administrative_fields = array('uid', 'status', 'created', 'date'); if (in_array($field_definition->getName(), $administrative_fields, TRUE)) { return AccessResult::allowedIfHasPermission($account, 'administer comments'); } // No user can change read-only fields. $read_only_fields = array('changed', 'hostname', 'uuid', 'cid', 'thread', 'comment_type', 'pid', 'entity_id', 'entity_type', 'field_name'); if (in_array($field_definition->getName(), $read_only_fields, TRUE)) { return AccessResult::forbidden(); } $commented_entity = $entity->getCommentedEntity(); $anonymous_contact = $commented_entity->get($entity->getFieldName())->getFieldDefinition()->getSetting('anonymous_contact'); // If the field is configured to accept anonymous contact details - admins // can edit name, homepage and mail. Anonymous users can also fill in the // fields on comment creation. if (in_array($field_definition->getName(), ['name', 'mail', 'homepage'], TRUE)) { $admin_access = AccessResult::allowedIfHasPermission($account, 'administer comments'); $anonymous_access = AccessResult::allowedIf($entity->isNew() && $account->isAnonymous() && $anonymous_contact != COMMENT_ANONYMOUS_MAYNOT_CONTACT && $account->hasPermission('post comments'))->cachePerRole()->cacheUntilEntityChanges($entity)->cacheUntilEntityChanges($field_definition->getConfig($commented_entity->bundle()))->cacheUntilEntityChanges($commented_entity); return $admin_access->orIf($anonymous_access); } } if ($operation == 'view') { // Admins can view any fields except hostname, other users need both the // "access comments" permission and for the comment to be published. The // mail field is hidden from non-admins. $admin_access = AccessResult::allowedIf($account->hasPermission('administer comments') && $field_definition->getName() != 'hostname')->cachePerRole(); $anonymous_access = AccessResult::allowedIf($account->hasPermission('access comments') && $entity->isPublished() && !in_array($field_definition->getName(), array('mail', 'hostname'), TRUE))->cacheUntilEntityChanges($entity)->cachePerRole(); return $admin_access->orIf($anonymous_access); } return parent::checkFieldAccess($operation, $field_definition, $account, $items); }
/** * {@inheritdoc} */ public function createPayment(FieldDefinitionInterface $field_definition) { /** @var \Drupal\payment\Entity\PaymentInterface $payment */ $payment = $this->entityManager->getStorage('payment')->create(['bundle' => 'payment_reference']); /** @var \Drupal\payment_reference\Plugin\Payment\Type\PaymentReference $payment_type */ $payment_type = $payment->getPaymentType(); $payment_type->setEntityTypeId($field_definition->getFieldStorageDefinition()->getTargetEntityTypeId()); $payment_type->setBundle($field_definition->getTargetBundle()); $payment_type->setFieldName($field_definition->getName()); $payment->setCurrencyCode($field_definition->getSetting('currency_code')); foreach ($field_definition->getSetting('line_items_data') as $line_item_data) { $line_item = $this->paymentLineItemManager->createInstance($line_item_data['plugin_id'], $line_item_data['plugin_configuration']); $payment->setLineItem($line_item); } return $payment; }
/** * {@inheritdoc} */ public function match(ContactInterface $contact, $property = 'value') { $ids = array(); $field = $this->field->getName(); $needle = $contact->get($field)->{$property}; if (!empty($needle)) { $this->query->condition('type', $contact->bundle()); if ($contact->id()) { $this->query->condition('contact_id', $contact->id(), '<>'); } if ($field instanceof FieldConfigInterface) { $field .= '.' . $property; } $this->query->condition($field, $needle, $this->getOperator($property)); $ids = $this->query->execute(); } // Get the score for this field/propery. $score = array($this->field->getName() . '.' . $property => $this->getScore($property)); // Returning an array holding the score as value and the contact id as key. return array_fill_keys($ids, $score); }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, FieldDefinitionInterface $field_config = NULL, $delta = 0) { $input = $form_state->getUserInput(); // Store field information in $form_state. if (!static::getModalState($form_state)) { $field_state = array('page' => 1); static::setModalState($form_state, $field_state); } // Store for ajax commands. $form['delta'] = ['#type' => 'value', '#value' => $delta]; // Get the field settings for filtering and validating files. if ($field_config) { $form['field_name'] = ['#type' => 'value', '#value' => $field_config->getName()]; $field_settings = $field_config->getSettings(); $extensions = $field_settings['file_extensions']; $catalog_id = $field_settings['catalog_id']; } else { // If we are coming from the ckeditor image dialog, we don't have field // config, look for extensions in the query string instead. // TODO: Think of a better way to do this. $query = \Drupal::request()->query->all(); $extensions = $query['extensions']; $catalog_id = $query['catalog_id']; } $operation_options = ['startswith' => $this->t('Starts with'), 'matches' => $this->t('Matches')]; $form['filters'] = ['#type' => 'container', '#attributes' => ['class' => ['search-form']], 'title' => ['#markup' => '<span class="search-title">' . $this->t('Search by filename') . '</span>']]; $form['filters']['filename_op'] = array('#type' => 'select', '#title' => $this->t('Operation'), '#options' => $operation_options, '#default_value' => !empty($input['filename_op']) ? $input['filename_op'] : ''); $form['filters']['filename'] = array('#type' => 'textfield', '#title' => $this->t('Search by filename'), '#size' => 20, '#default_value' => !empty($input['filename']) ? $input['filename'] : ''); $ajax_settings = ['callback' => [$this, 'searchAjax'], 'wrapper' => self::AJAX_WRAPPER_ID, 'effect' => 'fade', 'progress' => ['type' => 'throbber']]; $form['filters']['search'] = ['#type' => 'submit', '#submit' => [[$this, 'searchSubmit']], '#ajax' => $ajax_settings, '#value' => $this->t('Search'), '#attributes' => array('class' => array('embridge-ajax-search-submit'))]; $filters = []; $filters[] = ['field' => 'fileformat', 'operator' => 'matches', 'value' => $this->massageExtensionSetting($extensions)]; // Static list of known search filters from EMDB. // TODO: Make this configurable. $known_search_filters = ['libraries', 'assettype', 'fileformat']; // Add filename filter as this always exists. if (!empty($input['filename_op'])) { $filters[] = ['field' => 'name', 'operator' => $input['filename_op'], 'value' => $input['filename']]; } // Add user chosen filters. foreach ($known_search_filters as $filter_id) { if (empty($input[$filter_id])) { continue; } $filters[] = ['field' => $filter_id, 'operator' => 'matches', 'value' => $input[$filter_id]]; } // Execute a search. $modal_state = static::getModalState($form_state); $page = $modal_state['page']; $search_response = $this->getSearchResults($page, $filters); $title = $this->t('More search options'); $form['filters']['extra_filters'] = ['#markup' => '<div class="moreOptions"><a href="#options" data-toggle="collapse">' . $title . '</a><div id="options" class="collapse">']; // Add filters from search response. if (!empty($search_response['filteroptions'])) { foreach ($search_response['filteroptions'] as $filter) { if (!in_array($filter['id'], $known_search_filters)) { continue; } // "Empty" option. $filter_options = [$this->t('-- Select --')]; // Add each option to the list. foreach ($filter['children'] as $option) { $filter_options[$option['id']] = $this->t('@name (@count)', ['@name' => $option['name'], '@count' => $option['count']]); } $form['filters']['extra_filters'][$filter['id']] = ['#type' => 'select', '#title' => $this->t('@name', ['@name' => $filter['name']]), '#options' => $filter_options, '#default_value' => !empty($input[$filter['id']]) ? $input[$filter['id']] : '']; } } $form['filters']['close_extra_filters'] = ['#markup' => '</div></div>']; if (!empty($search_response['results'])) { $form['search_results'] = ['#theme' => 'embridge_search_results', '#results' => $this->formatSearchResults($search_response, $this->assetHelper, $catalog_id)]; } else { $form['search_results'] = ['#type' => 'markup', '#markup' => $this->t('<p>No files found, please adjust your filters and try again.</p>')]; } // Add "previous page" pager. $form['pagination'] = ['#type' => 'container', '#attributes' => ['class' => ['pagination']]]; $form['pagination']['page_previous'] = ['#type' => 'submit', '#value' => $this->t('Previous page'), '#submit' => [[$this, 'previousPageSubmit']], '#ajax' => array('callback' => [$this, 'searchAjax'], 'wrapper' => self::AJAX_WRAPPER_ID, 'effect' => 'fade'), '#disabled' => !($page > 1)]; // Add "next page" pager. $form['pagination']['page_next'] = ['#type' => 'submit', '#value' => $this->t('Next page'), '#submit' => [[$this, 'nextPageSubmit']], '#ajax' => array('callback' => [$this, 'searchAjax'], 'wrapper' => self::AJAX_WRAPPER_ID, 'effect' => 'fade'), '#disabled' => !($search_response['response']['pages'] > $search_response['response']['page'])]; $form['result_chosen'] = ['#type' => 'hidden', '#value' => !empty($input['result_chosen']) ? $input['result_chosen'] : '']; $form['actions'] = ['#type' => 'actions']; $form['actions']['submit'] = ['#type' => 'submit', '#value' => $this->t('Select'), '#submit' => array(), '#ajax' => array('callback' => [$this, 'selectItemAjax'], 'event' => 'click'), '#attributes' => array('class' => array('embridge-ajax-select-file', 'hidden-button'))]; $form['#attached']['library'][] = 'embridge/embridge.lib'; $form['#prefix'] = '<div id="' . self::AJAX_WRAPPER_ID . '"><div id="' . self::MESSAGE_WRAPPER_ID . '"></div>'; $form['#sufix'] = '</div>'; return $form; }
/** * {@inheritdoc} */ public static function isApplicable(FieldDefinitionInterface $field_definition) { return $field_definition->getName() != 'deny_applicable'; }
/** * Control access to fields. * * This hook is invoked from * \Drupal\Core\Entity\EntityAccessController::fieldAccess() to let modules * grant or deny operations on fields. * * @param string $operation * The operation to be performed. See * \Drupal\Core\Access\AccessibleInterface::access() for possible values. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field definition. * @param \Drupal\Core\Session\AccountInterface $account * The user account to check. * @param \Drupal\Core\Field\FieldItemListInterface $items * (optional) The entity field object on which the operation is to be * performed. * * @return bool|null * TRUE if access should be allowed, FALSE if access should be denied and NULL * if the implementation has no opinion. */ function hook_entity_field_access($operation, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, \Drupal\Core\Session\AccountInterface $account, \Drupal\Core\Field\FieldItemListInterface $items = NULL) { if ($field_definition->getName() == 'field_of_interest' && $operation == 'edit') { return $account->hasPermission('update field of interest'); } }
/** * {@inheritdoc} */ public static function isApplicable(FieldDefinitionInterface $field_definition) { $has_cart = \Drupal::moduleHandler()->moduleExists('commerce_cart'); $entity_type = $field_definition->getTargetEntityTypeId(); $field_name = $field_definition->getName(); return $has_cart && $entity_type == 'commerce_product' && $field_name == 'variations'; }
/** * {@inheritdoc} */ public static function isApplicable(FieldDefinitionInterface $field_definition) { $entity_type = $field_definition->getTargetEntityTypeId(); $field_name = $field_definition->getName(); return $entity_type == 'commerce_order' && $field_name == 'line_items'; }
/** * Checks whether the field values changed compared to the original entity. * * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * Field definition of field to compare for changes. * @param \Drupal\Core\Entity\ContentEntityInterface $entity * Entity to check for field changes. * @param \Drupal\Core\Entity\ContentEntityInterface $original * Original entity to compare against. * * @return bool * True if the field value changed from the original entity. */ protected function hasFieldValueChanged(FieldDefinitionInterface $field_definition, ContentEntityInterface $entity, ContentEntityInterface $original) { $field_name = $field_definition->getName(); $langcodes = array_keys($entity->getTranslationLanguages()); if ($langcodes !== array_keys($original->getTranslationLanguages())) { // If the list of langcodes has changed, we need to save. return TRUE; } foreach ($langcodes as $langcode) { $items = $entity->getTranslation($langcode)->get($field_name)->filterEmptyItems(); $original_items = $original->getTranslation($langcode)->get($field_name)->filterEmptyItems(); // If the field items are not equal, we need to save. if (!$items->equals($original_items)) { return TRUE; } } return FALSE; }
/** * Processes the views data for a text field with formatting. * * @param string $table * The table the field is added to. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field definition. * @param array $views_field * The views field data. * @param string $field_column_name * The field column being processed. */ protected function processViewsDataForTextLong($table, FieldDefinitionInterface $field_definition, array &$views_field, $field_column_name) { // Connect the text field to its formatter. if ($field_column_name == 'value') { $views_field['field']['format'] = $field_definition->getName() . '__format'; $views_field['field']['id'] = 'field'; } }
/** * {@inheritdoc} * Used in \Drupal\field\Tests\EntityReference\EntityReferenceAdminTest::testAvailableFormatters(). */ public static function isApplicable(FieldDefinitionInterface $field_definition) { // Returns FALSE if machine name of the field equals field_onewidgetfield. return $field_definition->getName() != "field_onewidgetfield"; }
/** * Builds the table row structure for a single field. * * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field definition. * @param \Drupal\Core\Entity\Display\EntityDisplayInterface $entity_display * The entity display. * @param array $form * An associative array containing the structure of the form. * @param array $form_state * A reference to a keyed array containing the current state of the form. * * @return array * A table row array. */ protected function buildFieldRow(FieldDefinitionInterface $field_definition, EntityDisplayInterface $entity_display, array $form, array &$form_state) { $field_name = $field_definition->getName(); $display_options = $entity_display->getComponent($field_name); $label = $field_definition->getLabel(); $regions = array_keys($this->getRegions()); $field_row = array('#attributes' => array('class' => array('draggable', 'tabledrag-leaf')), '#row_type' => 'field', '#region_callback' => array($this, 'getRowRegion'), '#js_settings' => array('rowHandler' => 'field', 'defaultPlugin' => $this->getDefaultPlugin($field_definition->getType())), 'human_name' => array('#markup' => String::checkPlain($label)), 'weight' => array('#type' => 'textfield', '#title' => $this->t('Weight for @title', array('@title' => $label)), '#title_display' => 'invisible', '#default_value' => $display_options ? $display_options['weight'] : '0', '#size' => 3, '#attributes' => array('class' => array('field-weight'))), 'parent_wrapper' => array('parent' => array('#type' => 'select', '#title' => $this->t('Label display for @title', array('@title' => $label)), '#title_display' => 'invisible', '#options' => array_combine($regions, $regions), '#empty_value' => '', '#attributes' => array('class' => array('field-parent')), '#parents' => array('fields', $field_name, 'parent')), 'hidden_name' => array('#type' => 'hidden', '#default_value' => $field_name, '#attributes' => array('class' => array('field-name'))))); $field_row['plugin'] = array('type' => array('#type' => 'select', '#title' => $this->t('Plugin for @title', array('@title' => $label)), '#title_display' => 'invisible', '#options' => $this->getPluginOptions($field_definition->getType()), '#default_value' => $display_options ? $display_options['type'] : 'hidden', '#parents' => array('fields', $field_name, 'type'), '#attributes' => array('class' => array('field-plugin-type'))), 'settings_edit_form' => array()); // Check the currently selected plugin, and merge persisted values for its // settings. if (isset($form_state['values']['fields'][$field_name]['type'])) { $display_options['type'] = $form_state['values']['fields'][$field_name]['type']; } if (isset($form_state['plugin_settings'][$field_name]['settings'])) { $display_options['settings'] = $form_state['plugin_settings'][$field_name]['settings']; } if (isset($form_state['plugin_settings'][$field_name]['third_party_settings'])) { $display_options['third_party_settings'] = $form_state['plugin_settings'][$field_name]['third_party_settings']; } // Get the corresponding plugin object. $plugin = $this->getPlugin($field_definition, $display_options); // Base button element for the various plugin settings actions. $base_button = array('#submit' => array(array($this, 'multistepSubmit')), '#ajax' => array('callback' => array($this, 'multistepAjax'), 'wrapper' => 'field-display-overview-wrapper', 'effect' => 'fade'), '#field_name' => $field_name); if ($form_state['plugin_settings_edit'] == $field_name) { // We are currently editing this field's plugin settings. Display the // settings form and submit buttons. $field_row['plugin']['settings_edit_form'] = array(); if ($plugin) { // Generate the settings form and allow other modules to alter it. $settings_form = $plugin->settingsForm($form, $form_state); $third_party_settings_form = $this->thirdPartySettingsForm($plugin, $field_definition, $form, $form_state); if ($settings_form || $third_party_settings_form) { $field_row['plugin']['#cell_attributes'] = array('colspan' => 3); $field_row['plugin']['settings_edit_form'] = array('#type' => 'container', '#attributes' => array('class' => array('field-plugin-settings-edit-form')), '#parents' => array('fields', $field_name, 'settings_edit_form'), 'label' => array('#markup' => $this->t('Plugin settings')), 'settings' => $settings_form, 'third_party_settings' => $third_party_settings_form, 'actions' => array('#type' => 'actions', 'save_settings' => $base_button + array('#type' => 'submit', '#button_type' => 'primary', '#name' => $field_name . '_plugin_settings_update', '#value' => $this->t('Update'), '#op' => 'update'), 'cancel_settings' => $base_button + array('#type' => 'submit', '#name' => $field_name . '_plugin_settings_cancel', '#value' => $this->t('Cancel'), '#op' => 'cancel', '#limit_validation_errors' => array(array('fields', $field_name, 'type'))))); $field_row['#attributes']['class'][] = 'field-plugin-settings-editing'; } } } else { $field_row['settings_summary'] = array(); $field_row['settings_edit'] = array(); if ($plugin) { // Display a summary of the current plugin settings, and (if the // summary is not empty) a button to edit them. $summary = $plugin->settingsSummary(); // Allow other modules to alter the summary. $this->alterSettingsSummary($summary, $plugin, $field_definition); if (!empty($summary)) { $summary_escaped = ''; $separator = ''; foreach ($summary as $summary_item) { $summary_escaped .= $separator . SafeMarkup::escape($summary_item); $separator = '<br />'; } $field_row['settings_summary'] = array('#markup' => SafeMarkup::set('<div class="field-plugin-summary">' . $summary_escaped . '</div>'), '#cell_attributes' => array('class' => array('field-plugin-summary-cell'))); } // Check selected plugin settings to display edit link or not. $settings_form = $plugin->settingsForm($form, $form_state); $third_party_settings_form = $this->thirdPartySettingsForm($plugin, $field_definition, $form, $form_state); if (!empty($settings_form) || !empty($third_party_settings_form)) { $field_row['settings_edit'] = $base_button + array('#type' => 'image_button', '#name' => $field_name . '_settings_edit', '#src' => 'core/misc/configure-dark.png', '#attributes' => array('class' => array('field-plugin-settings-edit'), 'alt' => $this->t('Edit')), '#op' => 'edit', '#limit_validation_errors' => array(array('fields', $field_name, 'type')), '#prefix' => '<div class="field-plugin-settings-edit-wrapper">', '#suffix' => '</div>'); } } } return $field_row; }
/** * {@inheritdoc} */ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) { // Only users with the administer nodes permission can edit administrative // fields. $administrative_fields = array('uid', 'status', 'created', 'promote', 'sticky'); if ($operation == 'edit' && in_array($field_definition->getName(), $administrative_fields, TRUE)) { return AccessResult::allowedIfHasPermission($account, 'administer nodes'); } // No user can change read only fields. $read_only_fields = array('revision_timestamp', 'revision_uid'); if ($operation == 'edit' && in_array($field_definition->getName(), $read_only_fields, TRUE)) { return AccessResult::forbidden(); } // Users have access to the revision_log field either if they have // administrative permissions or if the new revision option is enabled. if ($operation == 'edit' && $field_definition->getName() == 'revision_log') { if ($account->hasPermission('administer nodes')) { return AccessResult::allowed()->cachePerPermissions(); } return AccessResult::allowedIf($items->getEntity()->type->entity->isNewRevision())->cachePerPermissions(); } return parent::checkFieldAccess($operation, $field_definition, $account, $items); }
/** * Control access to fields. * * This hook is invoked from * \Drupal\Core\Entity\EntityAccessControlHandler::fieldAccess() to let modules * grant or deny operations on fields. * * @param string $operation * The operation to be performed. See * \Drupal\Core\Access\AccessibleInterface::access() for possible values. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field definition. * @param \Drupal\Core\Session\AccountInterface $account * The user account to check. * @param \Drupal\Core\Field\FieldItemListInterface $items * (optional) The entity field object on which the operation is to be * performed. * * @return \Drupal\Core\Access\AccessResultInterface * The access result. */ function hook_entity_field_access($operation, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, \Drupal\Core\Session\AccountInterface $account, \Drupal\Core\Field\FieldItemListInterface $items = NULL) { if ($field_definition->getName() == 'field_of_interest' && $operation == 'edit') { return AccessResult::allowedIfHasPermission($account, 'update field of interest'); } return AccessResult::neutral(); }
/** * Builds the table row structure for a single field. * * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field definition. * @param array $form * An associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * * @return array * A table row array. */ protected function buildFieldRow(FieldDefinitionInterface $field_definition, array $form, FormStateInterface $form_state) { $field_name = $field_definition->getName(); $display_options = $this->entity->getComponent($field_name); $label = $field_definition->getLabel(); // Disable fields without any applicable plugins. if (empty($this->getApplicablePluginOptions($field_definition))) { $this->entity->removeComponent($field_name)->save(); $display_options = $this->entity->getComponent($field_name); } $regions = array_keys($this->getRegions()); $field_row = array('#attributes' => array('class' => array('draggable', 'tabledrag-leaf')), '#row_type' => 'field', '#region_callback' => array($this, 'getRowRegion'), '#js_settings' => array('rowHandler' => 'field', 'defaultPlugin' => $this->getDefaultPlugin($field_definition->getType())), 'human_name' => array('#plain_text' => $label), 'weight' => array('#type' => 'textfield', '#title' => $this->t('Weight for @title', array('@title' => $label)), '#title_display' => 'invisible', '#default_value' => $display_options ? $display_options['weight'] : '0', '#size' => 3, '#attributes' => array('class' => array('field-weight'))), 'parent_wrapper' => array('parent' => array('#type' => 'select', '#title' => $this->t('Label display for @title', array('@title' => $label)), '#title_display' => 'invisible', '#options' => array_combine($regions, $regions), '#empty_value' => '', '#attributes' => array('class' => array('js-field-parent', 'field-parent')), '#parents' => array('fields', $field_name, 'parent')), 'hidden_name' => array('#type' => 'hidden', '#default_value' => $field_name, '#attributes' => array('class' => array('field-name'))))); $field_row['plugin'] = array('type' => array('#type' => 'select', '#title' => $this->t('Plugin for @title', array('@title' => $label)), '#title_display' => 'invisible', '#options' => $this->getPluginOptions($field_definition), '#default_value' => $display_options ? $display_options['type'] : 'hidden', '#parents' => array('fields', $field_name, 'type'), '#attributes' => array('class' => array('field-plugin-type'))), 'settings_edit_form' => array()); // Get the corresponding plugin object. $plugin = $this->entity->getRenderer($field_name); // Base button element for the various plugin settings actions. $base_button = array('#submit' => array('::multistepSubmit'), '#ajax' => array('callback' => '::multistepAjax', 'wrapper' => 'field-display-overview-wrapper', 'effect' => 'fade'), '#field_name' => $field_name); if ($form_state->get('plugin_settings_edit') == $field_name) { // We are currently editing this field's plugin settings. Display the // settings form and submit buttons. $field_row['plugin']['settings_edit_form'] = array(); if ($plugin) { // Generate the settings form and allow other modules to alter it. $settings_form = $plugin->settingsForm($form, $form_state); $third_party_settings_form = $this->thirdPartySettingsForm($plugin, $field_definition, $form, $form_state); if ($settings_form || $third_party_settings_form) { $field_row['plugin']['#cell_attributes'] = array('colspan' => 3); $field_row['plugin']['settings_edit_form'] = array('#type' => 'container', '#attributes' => array('class' => array('field-plugin-settings-edit-form')), '#parents' => array('fields', $field_name, 'settings_edit_form'), 'label' => array('#markup' => $this->t('Plugin settings')), 'settings' => $settings_form, 'third_party_settings' => $third_party_settings_form, 'actions' => array('#type' => 'actions', 'save_settings' => $base_button + array('#type' => 'submit', '#button_type' => 'primary', '#name' => $field_name . '_plugin_settings_update', '#value' => $this->t('Update'), '#op' => 'update'), 'cancel_settings' => $base_button + array('#type' => 'submit', '#name' => $field_name . '_plugin_settings_cancel', '#value' => $this->t('Cancel'), '#op' => 'cancel', '#limit_validation_errors' => array(array('fields', $field_name, 'type'))))); $field_row['#attributes']['class'][] = 'field-plugin-settings-editing'; } } } else { $field_row['settings_summary'] = array(); $field_row['settings_edit'] = array(); if ($plugin) { // Display a summary of the current plugin settings, and (if the // summary is not empty) a button to edit them. $summary = $plugin->settingsSummary(); // Allow other modules to alter the summary. $this->alterSettingsSummary($summary, $plugin, $field_definition); if (!empty($summary)) { $field_row['settings_summary'] = array('#type' => 'inline_template', '#template' => '<div class="field-plugin-summary">{{ summary|safe_join("<br />") }}</div>', '#context' => array('summary' => $summary), '#cell_attributes' => array('class' => array('field-plugin-summary-cell'))); } // Check selected plugin settings to display edit link or not. $settings_form = $plugin->settingsForm($form, $form_state); $third_party_settings_form = $this->thirdPartySettingsForm($plugin, $field_definition, $form, $form_state); if (!empty($settings_form) || !empty($third_party_settings_form)) { $field_row['settings_edit'] = $base_button + array('#type' => 'image_button', '#name' => $field_name . '_settings_edit', '#src' => 'core/misc/icons/787878/cog.svg', '#attributes' => array('class' => array('field-plugin-settings-edit'), 'alt' => $this->t('Edit')), '#op' => 'edit', '#limit_validation_errors' => array(array('fields', $field_name, 'type')), '#prefix' => '<div class="field-plugin-settings-edit-wrapper">', '#suffix' => '</div>'); } } } return $field_row; }
/** * {@inheritdoc} */ public function onFieldDefinitionDelete(FieldDefinitionInterface $field_definition) { $entity_type_id = $field_definition->getTargetEntityTypeId(); $bundle = $field_definition->getTargetBundle(); $field_name = $field_definition->getName(); // Notify the storage about the field deletion. $this->getStorage($entity_type_id)->onFieldDefinitionDelete($field_definition); // Unset the bundle from the bundle field map key value collection. $bundle_field_map = $this->keyValueFactory->get('entity.definitions.bundle_field_map')->get($entity_type_id); unset($bundle_field_map[$field_name]['bundles'][$bundle]); if (empty($bundle_field_map[$field_name]['bundles'])) { // If there are no bundles left, remove the field from the map. unset($bundle_field_map[$field_name]); } $this->keyValueFactory->get('entity.definitions.bundle_field_map')->set($entity_type_id, $bundle_field_map); // Delete the cache entry. $this->cacheBackend->delete('entity_field_map'); // If the field map is initialized, update it as well, so that calls to it // do not have to rebuild it again. if ($this->fieldMap) { unset($this->fieldMap[$entity_type_id][$field_name]['bundles'][$bundle]); if (empty($this->fieldMap[$entity_type_id][$field_name]['bundles'])) { unset($this->fieldMap[$entity_type_id][$field_name]); } } }
/** * {@inheritdoc} */ public static function isApplicable(FieldDefinitionInterface $field_definition) { return ($field_definition->getTargetEntityTypeId() === 'aggregator_item' || $field_definition->getTargetEntityTypeId() === 'aggregator_feed') && $field_definition->getName() === 'title'; }
/** * {@inheritdoc} */ public static function isApplicable(FieldDefinitionInterface $field_definition) { return $field_definition->getName() === 'name' && $field_definition->getTargetEntityTypeId() === 'comment'; }
/** * {@inheritdoc} */ public function view(FieldItemListInterface $items) { $elements = $this->viewElements($items); // If there are actual renderable children, use #theme => field, otherwise, // let access cacheability metadata pass through for correct bubbling. if (Element::children($elements)) { $entity = $items->getEntity(); $entity_type = $entity->getEntityTypeId(); $field_name = $this->fieldDefinition->getName(); $info = array('#theme' => 'field', '#title' => $this->fieldDefinition->getLabel(), '#label_display' => $this->label, '#view_mode' => $this->viewMode, '#language' => $items->getLangcode(), '#field_name' => $field_name, '#field_type' => $this->fieldDefinition->getType(), '#field_translatable' => $this->fieldDefinition->isTranslatable(), '#entity_type' => $entity_type, '#bundle' => $entity->bundle(), '#object' => $entity, '#items' => $items, '#formatter' => $this->getPluginId()); $elements = array_merge($info, $elements); } return $elements; }