ParagraphEntityForm   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 164
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 0
loc 164
ccs 0
cts 64
cp 0
rs 10
c 0
b 0
f 0
wmc 8

6 Methods

Rating   Name   Duplication   Size   Complexity  
A form() 0 7 1
A actions() 0 23 1
A ajaxSubmit() 0 12 1
A bootstrapContext() 0 10 3
A save() 0 10 1
B __construct() 0 24 1
1
<?php
2
3
namespace Drupal\paragraphs_editor\Form;
4
5
use Drupal\Core\Ajax\AjaxResponse;
6
use Drupal\Core\Entity\ContentEntityForm;
7
use Drupal\Core\Entity\EntityManagerInterface;
8
use Drupal\Core\Entity\EntityTypeManagerInterface;
9
use Drupal\Core\Extension\ModuleHandlerInterface;
10
use Drupal\Core\Form\FormStateInterface;
11
use Drupal\paragraphs_editor\EditBuffer\EditBufferItemInterface;
12
use Drupal\paragraphs_editor\EditorCommand\CommandContextInterface;
13
use Drupal\paragraphs_editor\Utility\TypeUtility;
14
use Drupal\paragraphs_editor\WidgetBinder\WidgetBinderDataCompilerInterface;
15
16
/**
17
 * The form that is shown for editing paragraph entities in ckeditor.
18
 *
19
 * This is basically just the core content entity form with a few overrides to
20
 * ajaxify the experience and integrate with the delivery provider plugin
21
 * system.
22
 */
23
class ParagraphEntityForm extends ContentEntityForm {
24
25
  /**
26
   * The context the editor command is being executed in.
27
   *
28
   * @var \Drupal\paragraphs_editor\EditorCommand\CommandContextInterface
29
   */
30
  protected $context;
31
32
  /**
33
   * The buffer item being edited by this form.
34
   *
35
   * @var \Drupal\paragraphs_editor\EditBuffer\EditBufferItemInterface
36
   */
37
  protected $bufferItem;
38
39
  /**
40
   * The widget binder data compiler service.
41
   *
42
   * @var \Drupal\paragraphs_editor\WidgetBinder\WidgetBinderDataCompilerInterface
43
   */
44
  protected $dataCompiler;
45
46
  /**
47
   * Creates a ParagraphEntityForm object.
48
   *
49
   * @param \Drupal\paragraphs_editor\EditorCommand\CommandContextInterface $context
50
   *   The context of the command that is invoking this form.
51
   * @param \Drupal\paragraphs_editor\EditBuffer\EditBufferItemInterface $item
52
   *   An editor item (wrapped paragraph entity) to show the edit form for.
53
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
54
   *   The module handler service.
55
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
56
   *   The entity type manager service.
57
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
58
   *   The entity manager service.
59
   * @param \Drupal\paragraphs_editor\WidgetBinder\WidgetBinderDataCompilerInterface $data_compiler
60
   *   The widget binder data compiler service.
61
   */
62
  public function __construct(CommandContextInterface $context,
63
    EditBufferItemInterface $item,
64
    ModuleHandlerInterface $module_handler,
65
    EntityTypeManagerInterface $entity_type_manager,
66
    EntityManagerInterface $entity_manager,
67
    WidgetBinderDataCompilerInterface $data_compiler) {
68
69
    // The ContentEntityForm class actually has a whole bunch of hidden
70
    // dependendencies. They are injected by core via setters, however we
71
    // explicitly use constructor injection here to make them clear. I realize
72
    // this is ugly, but at least its clear (I hope).
73
    // The code we rely on still uses the old (deprecated) EntityManager. We
74
    // will rely on the standard EntityTypeManager within this class.
75
    parent::__construct($entity_manager);
76
77
    // Inject dependencies for parent classes.
78
    $this->setEntityTypeManager($entity_type_manager);
79
    $this->setModuleHandler($module_handler);
80
    $this->setEntity($item->getEntity());
81
82
    // Set dependencies for this class.
83
    $this->context = $context;
84
    $this->bufferItem = $item;
85
    $this->dataCompiler = $data_compiler;
86
  }
87
88
  /**
89
   * Rebuilds the additional temporary context key value pairs in the context.
90
   *
91
   * @param \Drupal\Core\Form\FormStateInterface $form_state
92
   *   The form state to bootstrap the additional context from.
93
   *
94
   * @return \Drupal\paragraphs_editor\EditorCommand\CommandContextInterface
95
   *   The bootstrapped context.
96
   */
97
  protected function bootstrapContext(FormStateInterface $form_state) {
98
    $saved = $form_state->getValue('paragraphs_editor_additional_context');
99
    if ($saved) {
100
      $saved = unserialize($saved);
101
      foreach ($saved as $key => $value) {
102
        $this->context->addAdditionalContext($key, $value);
103
      }
104
    }
105
106
    return $this->context;
107
  }
108
109
  /**
110
   * {@inheritdoc}
111
   */
112
  public function form(array $form, FormStateInterface $form_state) {
113
    $form = parent::form($form, $form_state);
114
    $form['paragraphs_editor_additional_context'] = [
115
      '#type' => 'hidden',
116
      '#default_value' => serialize($this->bootstrapContext($form_state)->getAdditionalContext()),
117
    ];
118
    return $form;
119
  }
120
121
  /**
122
   * {@inheritdoc}
123
   */
124
  public function save(array $form, FormStateInterface $form_state) {
125
    $context = $this->bootstrapContext($form_state);
126
127
    // Save the changes to the editor buffer.
128
    $this->bufferItem->overwrite(TypeUtility::ensureParagraph($this->entity));
129
    $this->bufferItem->save();
130
131
    // Make properties available to the static ajax handler.
132
    $form_state->setTemporaryValue(['paragraphs_editor', 'data'], $this->dataCompiler->compile($context, $this->bufferItem));
133
    $form_state->setTemporaryValue(['paragraphs_editor', 'context'], $this->context);
134
  }
135
136
  /**
137
   * {@inheritdoc}
138
   */
139
  protected function actions(array $form, FormStateInterface $form_state) {
140
    $actions = parent::actions($form, $form_state);
141
142
    // Make the default entity save button submit via ajax.
143
    $actions['submit']['#ajax'] = [
144
      'callback' => [get_class($this), 'ajaxSubmit'],
145
    ];
146
147
    // Provide a cancel link for users to cancel the edit operation.
148
    $url = $this->context->createCommandUrl('cancel');
149
    $actions['cancel'] = [
150
      '#type' => 'button',
151
      '#value' => $this->t('Cancel'),
152
      '#weight' => 10,
153
      '#ajax' => [
154
        'url' => $url,
155
        'options' => $url->getOptions(),
156
      ],
157
    ];
158
159
    unset($actions['delete']);
160
161
    return $actions;
162
  }
163
164
  /**
165
   * Handles submissions via ajax.
166
   *
167
   * @param array $form
168
   *   The complete form render array.
169
   * @param \Drupal\Core\Form\FormStateInterface $form_state
170
   *   The associated form state.
171
   *
172
   * @return \Drupal\Core\Ajax\AjaxResponse
173
   *   An ajax response object that delivers a rendered paragraph.
174
   */
175
  public static function ajaxSubmit(array $form, FormStateInterface $form_state) {
176
    // Retrieve class mambers needed to build a response.
177
    $data = $form_state->getTemporaryValue(['paragraphs_editor', 'data']);
178
    $delivery = $form_state->getTemporaryValue(['paragraphs_editor', 'context'])->getPlugin('delivery_provider');
179
180
    // Create a response that includes the rendered paragraph and signal that
181
    // the ajax workflow is completed.
182
    $response = new AjaxResponse();
183
    $delivery->sendData($response, $data);
184
    $delivery->close($response);
185
186
    return $response;
187
  }
188
189
}
190