Same name and namespace in other branches
  1. 8.x-1.x src/Plugin/Field/FieldFormatter/EntityReferenceAjaxFormatter.php \Drupal\entity_reference_ajax_formatter\Plugin\Field\FieldFormatter\EntityReferenceAjaxFormatter::viewElements() 1 comment

File

src/Plugin/Field/FieldFormatter/EntityReferenceAjaxFormatter.php, line 188

Class

EntityReferenceAjaxFormatter
Plugin implementation of the 'entity reference rendered entity' formatter.

Namespace

Drupal\entity_reference_ajax_formatter\Plugin\Field\FieldFormatter

Code

public function viewElements(FieldItemListInterface $items, $langcode) {
    $view_mode = $this->getSetting('view_mode');
    $elements = [];
    $parameters = $this->currentRoute
        ->getParameters();
    $start = $parameters->get('start') ? $parameters->get('start') : 0;
    $printed = [];
    if ($parameters->get('printed')) {
        $printed = explode('-', $parameters->get('printed'));
    }
    $count = $this->getSetting('number');
    $max = $this->getSetting('max');
    $id = "ajax-field-{$this->fieldDefinition->getTargetEntityTypeId()}-{$items->getEntity()->id()}-{$this->fieldDefinition->getName()}";
    $entities = $this->getEntitiesToView($items, $langcode);
    switch ($this->getSetting('sort')) {
        case 1:
            shuffle($entities);
            break;
        case 2:
            usort($entities, function (ContentEntityInterface $a, ContentEntityInterface $b) {
                if (method_exists($a, 'getChangedTime') && method_exists($b, 'getChangedTime')) {
                    return $a->getChangedTime() <=> $b->getChangedTime();
                }
                // If entity doesn't have changed time record, return order unchanged.
                return 0;
            });
            break;
        case 3:
            usort($entities, function (ContentEntityInterface $a, ContentEntityInterface $b) {
                if (method_exists($a, 'getChangedTime') && method_exists($b, 'getChangedTime')) {
                    return -1 * ($a->getChangedTime() <=> $b->getChangedTime());
                }
                // If entity doesn't have changed time record, return order unchanged.
                return 0;
            });
            rsort($entities);
            break;
        case 4:
            usort($entities, function ($a, $b) {
                if (method_exists($a, 'getCreatedTime') && method_exists($b, 'getCreatedTime')) {
                    return $a->getCreatedTime() <=> $b->getCreatedTime();
                }
                // If entity doesn't have created time record, return order unchanged.
                return 0;
            });
            break;
        case 5:
            usort($entities, function ($a, $b) {
                if (method_exists($a, 'getCreatedTime') && method_exists($b, 'getCreatedTime')) {
                    return -1 * ($a->getCreatedTime() <=> $b->getCreatedTime());
                }
                // If entity doesn't have created time record, return order unchanged.
                return 0;
            });
            break;
    }
    foreach ($entities as $delta => $entity) {
        if (count($elements) >= $count) {
            break;
        }
        if ($this->getSetting('sort') === 1) {
            if (in_array($entity->id(), $printed)) {
                continue;
            }
            $printed[] = $entity->id();
        }
        elseif ($start > $delta) {
            continue;
        }
        if ($max && count($elements) + $start >= $max) {
            break;
        }
        // Due to render caching and delayed calls, the viewElements() method
        // will be called later in the rendering process through a '#pre_render'
        // callback, so we need to generate a counter that takes into account
        // all the relevant information about this field and the referenced
        // entity that is being rendered.
        $recursive_render_id = $items->getFieldDefinition()
            ->getTargetEntityTypeId() . $items->getFieldDefinition()
            ->getTargetBundle() . $items->getName() . $items->getEntity()
            ->id() . $entity->getEntityTypeId() . $entity->id();
        if (isset(static::$recursiveRenderDepth[$recursive_render_id])) {
            static::$recursiveRenderDepth[$recursive_render_id]++;
        }
        else {
            static::$recursiveRenderDepth[$recursive_render_id] = 1;
        }
        // Protect ourselves from recursive rendering.
        if (static::$recursiveRenderDepth[$recursive_render_id] > static::RECURSIVE_RENDER_LIMIT) {
            $this->loggerFactory
                ->get('entity')
                ->error('Recursive rendering detected when rendering entity %entity_type: %entity_id, using the %field_name field on the %bundle_name bundle. Aborting rendering.', [
                '%entity_type' => $entity->getEntityTypeId(),
                '%entity_id' => $entity->id(),
                '%field_name' => $items->getName(),
                '%bundle_name' => $items->getFieldDefinition()
                    ->getTargetBundle(),
            ]);
            return $elements;
        }
        $view_builder = $this->entityTypeManager
            ->getViewBuilder($entity->getEntityTypeId());
        $elements[$delta] = $view_builder->view($entity, $view_mode, $entity->language()
            ->getId());
        // Add a resource attribute to set the mapping property's value to the
        // entity's url. Since we don't know what the markup of the entity will
        // be, we shouldn't rely on it for structured data such as RDFa.
        if (!empty($items[$delta]->_attributes) && !$entity->isNew() && $entity->hasLinkTemplate('canonical')) {
            $items[$delta]->_attributes += [
                'resource' => $entity->toUrl()
                    ->toString(),
            ];
        }
    }
    $total = $count + $start;
    if ($this->getSetting('load_more') && count($items) > $total && (!$max || $max > $total)) {
        $elements[$delta + 1] = [
            '#type' => 'container',
            '#attributes' => [
                'class' => [
                    'text-align-center',
                    'ajax-field-entity-ref',
                ],
                'id' => $id,
            ],
        ];
        $elements[$delta + 1]['more'] = [
            '#type' => 'link',
            '#title' => t('Load More'),
            '#url' => Url::fromRoute('entity_reference_ajax_formatter.ajax_field', [
                'entity_type' => $this->fieldDefinition
                    ->getTargetEntityTypeId(),
                'entity' => $items->getEntity()
                    ->id(),
                'field_name' => $this->fieldDefinition
                    ->getName(),
                'view_mode' => $this->viewMode,
                'language' => $langcode,
                'start' => $start + count($elements) - 1,
                'printed' => implode('-', $printed),
            ]),
            '#attributes' => [
                'class' => [
                    'use-ajax',
                ],
            ],
        ];
        $elements['#attached']['library'][] = 'core/drupal.ajax';
    }
    return $elements;
}