Skip to content

Commit e384185

Browse files
committed
Cleaned up webform import list
1 parent 8172c0a commit e384185

9 files changed

Lines changed: 232 additions & 176 deletions

assets/css/webform-index.css

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,17 @@
22
width: 100%;
33
}
44

5-
.os2forms-sync-webform-index .div + div {
6-
margin-top: 1em;
5+
.os2forms-sync-webform-index .filters ul,
6+
.os2forms-sync-webform-index .filters li {
7+
margin-left: 0;
8+
}
9+
10+
.os2forms-sync-webform-index .filters li {
11+
display: inline-block;
12+
padding-right: 1em;
713
}
814

915
.os2forms-sync-webform-index .metadata {
1016
display: flex;
1117
justify-content: space-between;
1218
}
13-
14-
.os2forms-sync-webform-index .metadata .category .label::after {
15-
content: ': ';
16-
}
17-
18-
.os2forms-sync-webform-index .metadata div + div {
19-
margin-top: 0;
20-
}
21-
22-
.os2forms-sync-webform-index .fieldset__wrapper {
23-
margin-bottom: 0;
24-
}

assets/js/webform-index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ document.addEventListener('DOMContentLoaded', () => {
22
const webforms = document.querySelectorAll('.os2forms-sync-webform-index .os2forms-sync-webform')
33
const searchInput = document.querySelector('.os2forms-sync-webform-index [type="search"]')
44

5+
if (!(webforms && searchInput)) {
6+
return
7+
}
8+
59
/**
610
* Combine values of all `data-indexed` attributes on descendants.
711
*/

os2forms_sync.routing.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ os2forms_sync.admin.settings:
99
os2forms_sync.webform.index:
1010
path: '/admin/os2forms/sync/webform'
1111
defaults:
12+
_title: 'Import webforms'
1213
_controller: '\Drupal\os2forms_sync\Controller\WebformController::index'
1314
requirements:
1415
_permission: 'access webform overview'

os2forms_sync.services.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,3 @@ services:
1919
- '@cache.default'
2020

2121
Drupal\os2forms_sync\Helper\JsonAPISerializer:
22-
23-
Drupal\os2forms_sync\Twig\TwigExtension:
24-
arguments:
25-
- '@renderer'
26-
tags:
27-
- { name: twig.extension }

src/Controller/WebformController.php

Lines changed: 192 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,26 @@
33
namespace Drupal\os2forms_sync\Controller;
44

55
use Drupal\Core\Controller\ControllerBase;
6+
use Drupal\Core\Datetime\DrupalDateTime;
67
use Drupal\Core\Http\RequestStack;
8+
use Drupal\Core\Link;
9+
use Drupal\Core\Render\Markup;
710
use Drupal\Core\Routing\TrustedRedirectResponse;
11+
use Drupal\Core\Serialization\Yaml;
812
use Drupal\Core\Url;
913
use Drupal\os2forms_sync\Helper\ImportHelper;
14+
use Drupal\os2forms_sync\Helper\WebformHelper;
1015
use Symfony\Component\DependencyInjection\ContainerInterface;
1116
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
1217

1318
/**
1419
* Webform controller.
1520
*/
1621
final class WebformController extends ControllerBase {
22+
private const FILTER_QUERY_NAME = 'show';
23+
private const FILTER_WEBFORMS_IMPORTED = 'imported';
24+
private const FILTER_WEBFORMS_NOT_IMPORTED = 'not imported';
25+
1726
/**
1827
* The request stack.
1928
*
@@ -28,12 +37,20 @@ final class WebformController extends ControllerBase {
2837
*/
2938
private ImportHelper $importHelper;
3039

40+
/**
41+
* The webform helper.
42+
*
43+
* @var \Drupal\os2forms_sync\Helper\WebformHelper
44+
*/
45+
private WebformHelper $webformHelper;
46+
3147
/**
3248
* Constructor.
3349
*/
34-
public function __construct(RequestStack $requestStack, ImportHelper $importHelper) {
50+
public function __construct(RequestStack $requestStack, ImportHelper $importHelper, WebformHelper $webformHelper) {
3551
$this->requestStack = $requestStack;
3652
$this->importHelper = $importHelper;
53+
$this->webformHelper = $webformHelper;
3754
}
3855

3956
/**
@@ -42,7 +59,8 @@ public function __construct(RequestStack $requestStack, ImportHelper $importHelp
4259
public static function create(ContainerInterface $container): self {
4360
return new static(
4461
$container->get('request_stack'),
45-
$container->get(ImportHelper::class)
62+
$container->get(ImportHelper::class),
63+
$container->get(WebformHelper::class)
4664
);
4765
}
4866

@@ -56,15 +74,182 @@ public static function create(ContainerInterface $container): self {
5674
*/
5775
public function index(): array {
5876
$webforms = $this->importHelper->getAvailableWebforms();
77+
$importedWebforms = $this->importHelper->loadImportedWebforms();
78+
79+
// Filter available webforms.
80+
switch ($this->requestStack->getCurrentRequest()->get(self::FILTER_QUERY_NAME)) {
81+
case self::FILTER_WEBFORMS_IMPORTED:
82+
$webforms = array_filter($webforms, static function (array $webform) use ($importedWebforms) {
83+
return isset($importedWebforms[$webform['links']['self']]);
84+
});
85+
break;
86+
87+
case self::FILTER_WEBFORMS_NOT_IMPORTED:
88+
$webforms = array_filter($webforms, static function (array $webform) use ($importedWebforms) {
89+
return !isset($importedWebforms[$webform['links']['self']]);
90+
});
91+
break;
92+
}
93+
94+
$elements = [
95+
'#attached' => ['library' => ['os2forms_sync/webform-index']],
96+
];
97+
98+
$elements['search'] = [
99+
'#type' => 'container',
100+
101+
'search' => [
102+
'#type' => 'search',
103+
'#title' => $this->t('Search'),
104+
'#title_display' => 'invisible',
105+
'#attributes' => [
106+
'placeholder' => $this->t('Search title, description and category …'),
107+
],
108+
],
109+
110+
'filters' => [
111+
'#type' => 'container',
112+
'#attributes' => [
113+
'class' => ['filters'],
114+
],
115+
116+
'links' => [
117+
'#theme' => 'item_list',
118+
'#list_type' => 'ul',
119+
'#items' => [
120+
(new Link($this->t('Show all webforms'), Url::fromRoute('os2forms_sync.webform.index')))->toRenderable(),
121+
(new Link($this->t('Show imported webforms'), Url::fromRoute('os2forms_sync.webform.index', ['show' => self::FILTER_WEBFORMS_IMPORTED])))->toRenderable(),
122+
(new Link($this->t('Show not imported webforms'), Url::fromRoute('os2forms_sync.webform.index', ['show' => self::FILTER_WEBFORMS_NOT_IMPORTED])))->toRenderable(),
123+
],
124+
],
125+
],
126+
];
127+
128+
foreach ($webforms as $webform) {
129+
$attributes = $webform['attributes'];
130+
$form = $this->webformHelper->getSubmissionForm($attributes['elements']);
131+
// Make sure that the form cannot be submitted (hopefully).
132+
$form['#attributes']['onsubmit'] = 'return false';
133+
134+
$sourceUrl = $webform['links']['self'];
135+
$importedWebform = $importedWebforms[$sourceUrl] ?? NULL;
136+
137+
$item = [
138+
'#type' => 'fieldset',
139+
'#title' => $attributes['title'] ?? 'xxx',
140+
'#attributes' => ['class' => ['os2forms-sync-webform']],
141+
142+
'description' => [
143+
'#type' => 'container',
144+
'#attributes' => [
145+
'class' => ['description'],
146+
'data-indexed' => strip_tags($attributes['description']),
147+
],
148+
'#markup' => Markup::create($attributes['description']),
149+
],
150+
151+
'form_display' => [
152+
'#type' => 'details',
153+
'#title' => $this->t('Form display'),
154+
'form' => $form,
155+
],
156+
157+
'elements' => [
158+
'#type' => 'details',
159+
'#title' => $this->t('Elements'),
160+
'#markup' => '<pre>' . Yaml::encode($attributes['elements']) . '</pre>',
161+
],
162+
163+
'metadata' => [
164+
'#type' => 'container',
165+
'#attributes' => [
166+
'class' => ['metadata'],
167+
],
168+
169+
'category' => [
170+
'#type' => 'container',
171+
'#attributes' => [
172+
'class' => ['category'],
173+
'data-indexed' => strip_tags($attributes['category']),
174+
],
175+
176+
'label' => [
177+
'#type' => 'label',
178+
'#title' => $this->t('Category'),
179+
'#title_display' => 'above',
180+
],
181+
182+
'value' => [
183+
'#type' => 'html_tag',
184+
'#tag' => 'span',
185+
'#attributes' => [
186+
'class' => ['value'],
187+
],
188+
'#value' => $attributes['category'],
189+
],
190+
],
191+
192+
'source_url' => [
193+
'#type' => 'container',
194+
195+
'label' => [
196+
'#type' => 'label',
197+
'#title' => $this->t('Source url'),
198+
'#title_display' => 'above',
199+
],
200+
201+
'value' => [
202+
'#type' => 'html_tag',
203+
'#tag' => 'span',
204+
'#attributes' => [
205+
'class' => ['value'],
206+
],
207+
'link' => (new Link($sourceUrl, Url::fromUri($sourceUrl)))->toRenderable(),
208+
],
209+
],
210+
],
211+
];
212+
213+
$item['import_form'] = [
214+
'#type' => 'html_tag',
215+
'#tag' => 'form',
216+
'#attributes' => [
217+
'method' => 'post',
218+
'action' => Url::fromRoute('os2forms_sync.webform.import', ['url' => $sourceUrl])->toString(TRUE)->getGeneratedUrl(),
219+
],
220+
221+
'button' => [
222+
'#type' => 'button',
223+
'#value' => NULL === $importedWebform ? $this->t('Import webform') : $this->t('Update webform'),
224+
],
225+
];
226+
227+
if (NULL !== $importedWebform) {
228+
$item['import_form']['info'] = [
229+
'#markup' => $this->t('<a href=":webform_url">Webform</a> updated at @updated_at.', [
230+
':webform_url' => Url::fromRoute('entity.webform.edit_form', ['webform' => $importedWebform->webformId])->toString(TRUE)->getGeneratedUrl(),
231+
'@updated_at' => $importedWebform->updatedAt->format(DrupalDateTime::FORMAT),
232+
]),
233+
];
234+
}
235+
236+
$elements[] = $item;
237+
}
238+
59239
$settingsUrl = Url::fromRoute('os2forms_sync.admin.settings');
60-
if (!$settingsUrl->access($this->currentUser())) {
61-
$settingsUrl = NULL;
240+
if ($settingsUrl->access($this->currentUser())) {
241+
$elements['settings'] = [
242+
'#type' => 'container',
243+
244+
'link' => (new Link($this->t('O2Forms sync settings'), $settingsUrl))->toRenderable(),
245+
];
62246
}
63247

64248
return [
65-
'#theme' => 'os2forms_sync_webform_index',
66-
'#webforms' => $webforms,
67-
'#settings_url' => $settingsUrl,
249+
'#type' => 'container',
250+
'#attributes' => ['class' => ['os2forms-sync-webform-index']],
251+
252+
'elements' => $elements,
68253
];
69254
}
70255

src/Helper/ImportHelper.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ private function loadWebformBySourceUrl(string $sourceUrl): ?WebformInterface {
214214
}
215215

216216
/**
217-
* Load all imported webforms.
217+
* Load all imported webforms keyed by sourceUrl.
218218
*
219219
* @return \Drupal\os2forms_sync\Entity\ImportedWebform[]|array
220220
* The imported webforms.
@@ -227,7 +227,8 @@ static function ($result) {
227227
$this->database
228228
->select(self::TABLE_NAME, 't')
229229
->fields('t')
230-
->execute()->fetchAll()
230+
->execute()
231+
->fetchAllAssoc('source_url')
231232
);
232233
}
233234

src/Helper/WebformHelper.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
namespace Drupal\os2forms_sync\Helper;
44

55
use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
6+
use Drupal\Component\Utility\Random;
67
use Drupal\Core\Datetime\DrupalDateTime;
78
use Drupal\Core\Entity\EntityTypeManagerInterface;
89
use Drupal\Core\Form\FormStateInterface;
910
use Drupal\Core\Http\RequestStack;
1011
use Drupal\Core\Serialization\Yaml;
1112
use Drupal\Core\StringTranslation\StringTranslationTrait;
1213
use Drupal\Core\Url;
14+
use Drupal\webform\Entity\Webform;
1315
use Drupal\webform\WebformEntityStorageInterface;
1416
use Drupal\webform\WebformInterface;
1517

@@ -208,4 +210,26 @@ public function theme(array $existing, string $type, string $theme, string $path
208210
];
209211
}
210212

213+
/**
214+
* Get submission form render array from webform elements.
215+
*
216+
* @phpstan-param array<string, mixed> $elements
217+
* @phpstan-return array<string, mixed>
218+
*/
219+
public function getSubmissionForm(array $elements): array {
220+
$webform = Webform::create([
221+
'id' => (new Random())->name(32),
222+
'elements' => Yaml::encode($elements),
223+
]);
224+
225+
// Hack: Needed to prevent an error in the webform module:
226+
// Warning: array_intersect_key(): Expected parameter 2 to be an array, null
227+
// given in Drupal\webform\Entity\Webform->invokeHandlers() ….
228+
$prop = new \ReflectionProperty($webform, 'settingsOriginal');
229+
$prop->setAccessible(TRUE);
230+
$prop->setValue($webform, []);
231+
232+
return $webform->getSubmissionForm();
233+
}
234+
211235
}

0 commit comments

Comments
 (0)