EditBufferItemFactory   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 148
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 0
loc 148
ccs 0
cts 67
cp 0
rs 10
c 0
b 0
f 0
wmc 18

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getParagraph() 0 4 2
A __construct() 0 3 1
A createParagraph() 0 5 1
B getBufferItem() 0 24 5
A createBufferItem() 0 4 1
C createEntityMap() 0 25 7
A duplicateBufferItem() 0 7 1
1
<?php
2
3
namespace Drupal\paragraphs_editor\EditBuffer;
4
5
use Drupal\Core\Entity\EntityTypeManagerInterface;
6
use Drupal\paragraphs\ParagraphInterface;
7
use Drupal\paragraphs_editor\EditorCommand\CommandContextInterface;
8
use Drupal\paragraphs_editor\EditorFieldValue\FieldValueManagerInterface;
9
10
/**
11
 * A factory for creating edit buffer items.
12
 */
13
class EditBufferItemFactory implements EditBufferItemFactoryInterface {
14
15
  /**
16
   * The entity storage handler for the paragraph entity type.
17
   *
18
   * @var \Drupal\Core\Entity\EntityStorageInterface
19
   */
20
  protected $storage;
21
22
  /**
23
   * The field value manager service.
24
   *
25
   * @var \Drupal\paragraphs_editor\EditorFieldValue\FieldValueManagerInterface
26
   */
27
  protected $fieldValueManager;
28
29
  /**
30
   * Creates an edit buffer item factory.
31
   *
32
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
33
   *   The entity type manager service.
34
   * @param \Drupal\paragraphs_editor\EditorFieldValue\FieldValueManagerInterface $field_value_manager
35
   *   The service for determining whether a field is a paragraphs field.
36
   */
37
  public function __construct(EntityTypeManagerInterface $entity_type_manager, FieldValueManagerInterface $field_value_manager) {
38
    $this->storage = $entity_type_manager->getStorage('paragraph');
39
    $this->fieldValueManager = $field_value_manager;
40
  }
41
42
  /**
43
   * {@inheritdoc}
44
   */
45
  public function createBufferItem(CommandContextInterface $context, $bundle_name) {
46
    // We don't have to verify that getBuffer doesn't return NULL here since
47
    // this should never be called until after context validation is complete.
48
    return $context->getEditBuffer()->createItem($this->createParagraph($bundle_name));
49
  }
50
51
  /**
52
   * {@inheritdoc}
53
   */
54
  public function getBufferItem(CommandContextInterface $context, $paragraph_uuid) {
55
    // Since this could be called before the context is validated, we need to
56
    // account for the buffer being invalid.
57
    $buffer = $context->getEditBuffer();
58
    if ($buffer) {
59
      $item = $buffer->getItem($paragraph_uuid);
60
61
      // If the paragraph didn't already exist in the buffer we attempt to load
62
      // it from the database. After loading it, we also have to verify that it
63
      // belonged to the entity the the editor context belongs to. If that
64
      // succeeds, we add it to the buffer.
65
      if (empty($item)) {
66
        $paragraph = $this->getParagraph($paragraph_uuid);
67
        if ($paragraph) {
68
          if ($paragraph->getParentEntity() == $context->getEntity()) {
69
            $item = $buffer->createItem($paragraph);
70
          }
71
        }
72
      }
73
    }
74
    else {
75
      $item = NULL;
76
    }
77
    return $item;
78
  }
79
80
  /**
81
   * {@inheritdoc}
82
   */
83
  public function duplicateBufferItem(CommandContextInterface $context, EditBufferItemInterface $item) {
84
    $new_item = $context->getEditBuffer()->createItem($item->getEntity()->createDuplicate());
85
86
    $entity_map = [];
87
    $this->createEntityMap($item->getEntity(), $new_item->getEntity(), $entity_map);
88
    $context->addAdditionalContext('entityMap', $entity_map);
89
    return $new_item;
90
  }
91
92
  /**
93
   * Maps all entities in a duplicated content tree to their originals.
94
   *
95
   * @param \Drupal\paragraphs\ParagraphInterface $entity1
96
   *   The original entity.
97
   * @param \Drupal\paragraphs\ParagraphInterface $entity2
98
   *   The duplicate entity.
99
   * @param array &$map
100
   *   The map to be built.
101
   */
102
  protected function createEntityMap(ParagraphInterface $entity1, ParagraphInterface $entity2, array &$map) {
103
    $map[$entity1->uuid()] = $entity2->uuid();
104
105
    if ($entity1->bundle() != $entity2->bundle()) {
106
      throw new \Exception('mismatch');
107
    }
108
    foreach ($entity1->getFields() as $field) {
109
      $field_definition = $field->getFieldDefinition();
110
      $field_name = $field_definition->getName();
111
      if (!isset($entity2->{$field_name})) {
112
        throw new \Exception('mismatch');
113
      }
114
115
      if ($this->fieldValueManager->isParagraphsField($field_definition)) {
116
        $items1 = $entity1->{$field_name};
117
        $items2 = $entity2->{$field_name};
118
119
        if (count($items1) != count($items2)) {
120
          throw new \Exception('mismatch');
121
        }
122
123
        foreach ($items1 as $delta => $item) {
124
          $cmp_entity1 = $items1[$delta]->entity;
125
          $cmp_entity2 = $items2[$delta]->entity;
126
          $this->createEntityMap($cmp_entity1, $cmp_entity2, $map);
127
        }
128
      }
129
    }
130
  }
131
132
  /**
133
   * Creates a new paragraph entity.
134
   *
135
   * @param string $bundle_name
136
   *   The bundle name of the paragraph entity to be created.
137
   *
138
   * @return \Drupal\paragraphs\ParagraphInterface
139
   *   The newly created paragraph.
140
   */
141
  protected function createParagraph($bundle_name) {
142
    $paragraph = $this->storage->create([
143
      'type' => $bundle_name,
144
    ]);
145
    return $paragraph;
146
  }
147
148
  /**
149
   * Retrieves a paragraph by uuid.
150
   *
151
   * @param string $paragraph_uuid
152
   *   The uuid of the paragraph to be retrieved.
153
   *
154
   * @return \Drupal\paragraphs\ParagraphInterface|null
155
   *   The retrieved paragraph, or NULL if no such paragraph could be found.
156
   */
157
  protected function getParagraph($paragraph_uuid) {
158
    $entities = $this->storage->loadByProperties(['uuid' => $paragraph_uuid]);
159
    $entity = reset($entities);
160
    return $entity ? $entity : NULL;
161
  }
162
163
}
164