77use Drupal \content_fixtures \Fixture \FixtureGroupInterface ;
88use Drupal \Core \Session \AccountInterface ;
99use Drupal \Core \Session \AccountSwitcherInterface ;
10+ use Drupal \Core \Site \Settings ;
1011use Drupal \datetime \Plugin \Field \FieldType \DateTimeItemInterface ;
12+ use Drupal \itk_pretix \Pretix \EventHelper as PretixEventHelper ;
13+ use Drupal \itk_pretix \Pretix \OrderHelper as PretixOrderHelper ;
1114use Drupal \node \Entity \Node ;
1215use Drupal \node \NodeInterface ;
16+ use Symfony \Component \Console \Output \ConsoleOutput ;
17+ use Symfony \Component \Console \Output \NullOutput ;
1318
1419/**
1520 * Page fixture.
@@ -20,6 +25,8 @@ final class PublicMeetingFixture extends AbstractFixture implements DependentFix
2025
2126 public function __construct (
2227 private readonly AccountSwitcherInterface $ accountSwitcher ,
28+ private readonly PretixEventHelper $ pretixEventHelper ,
29+ private readonly PretixOrderHelper $ pretixOrderHelper ,
2330 ) {
2431 }
2532
@@ -49,9 +56,9 @@ public function load() {
4956 'field_content_state ' => 'active ' ,
5057 'field_email_address ' =>
'[email protected] ' ,
5158 'field_first_meeting_time ' => date ('Y-m-d ' , 1283166912 ),
52- 'field_media_document ' => [[$ this ->getReference ('media_library:Fil:MTM ' )]],
59+ 'field_media_document ' => [[$ this ->getReference ('media_library:Fil:MTM ' )]],
5360 'field_media_image_single ' => [
54- ['target_id ' => $ this ->getReference ('media:Large1 ' )->id ()],
61+ ['target_id ' => $ this ->getReference ('media:Large1 ' )->id ()],
5562 ],
5663 'field_pretix_event_settings ' => [
5764 'template_event ' => 'template-series ' ,
@@ -145,17 +152,209 @@ public function load() {
145152 $ node = $ node ->createDuplicate ();
146153 $ node ->setTitle ('Public meeting with pretix signup and monthly occurrences ' );
147154 $ node ->set ('field_pretix_dates ' , array_map (
148- static fn (int $ offset ) => [
155+ static fn (int $ offset ) => [
149156 'location ' => sprintf ('Location %d ' , $ offset + 1 ),
150157 'address ' => 'Hack Kampmanns Plads 2, 8000 Aarhus C ' ,
151- 'registration_deadline_value ' => (new \DateTimeImmutable (sprintf ('10:00 first day of %d month ' , $ offset - 1 )))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
152- 'time_from_value ' => (new \DateTimeImmutable (sprintf ('12:00 first day of %d month ' , $ offset - 1 )))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
153- 'time_to_value ' => (new \DateTimeImmutable (sprintf ('13:00 first day of %d month ' , $ offset - 1 )))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
158+ 'registration_deadline_value ' => (new \DateTimeImmutable (sprintf ('10:00 first day of %d month ' ,
159+ $ offset - 1 )))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
160+ 'time_from_value ' => (new \DateTimeImmutable (sprintf ('12:00 first day of %d month ' ,
161+ $ offset - 1 )))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
162+ 'time_to_value ' => (new \DateTimeImmutable (sprintf ('13:00 first day of %d month ' ,
163+ $ offset - 1 )))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
154164 'spots ' => 10 * $ offset + 7 ,
155165 ],
156166 range (0 , 12 )
157167 ));
158168 $ node ->save ();
169+
170+ $ node = $ node ->createDuplicate ();
171+ $ node ->setTitle ('Public meeting with pretix signup and daily occurrences ' );
172+ $ node ->set ('field_pretix_dates ' , array_map (
173+ static fn (int $ offset ) => [
174+ 'location ' => sprintf ('Location %d ' , $ offset ),
175+ 'address ' => 'Hack Kampmanns Plads 2, 8000 Aarhus C ' ,
176+ 'registration_deadline_value ' => (new \DateTimeImmutable ('10:00 first day of this month ' ))->modify (sprintf ('+%d day ' ,
177+ $ offset - 1 ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
178+ 'time_from_value ' => (new \DateTimeImmutable ('12:00 first day of this month ' ))->modify (sprintf ('+%d day ' ,
179+ $ offset - 1 ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
180+ 'time_to_value ' => (new \DateTimeImmutable ('13:00 first day of this month ' ))->modify (sprintf ('+%d day ' ,
181+ $ offset - 1 ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
182+ 'spots ' => 87 ,
183+ ],
184+ range (1 , (int ) (new \DateTimeImmutable ('this month ' ))->format ('t ' )),
185+ ));
186+ $ node ->save ();
187+
188+ $ node = $ node ->createDuplicate ();
189+ $ node ->setTitle ('Public meeting with orders ' );
190+ $ node ->set ('field_pretix_dates ' , [
191+ [
192+ 'location ' => 'The location ' ,
193+ 'address ' => 'Hack Kampmanns Plads 2, 8000 Aarhus C ' ,
194+ 'registration_deadline_value ' => (new \DateTimeImmutable ('2024-12-31T00:00:00+0100 ' ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
195+ 'time_from_value ' => (new \DateTimeImmutable ('2025-01-01T19:00:00+0100 ' ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
196+ 'time_to_value ' => (new \DateTimeImmutable ('2025-01-01T21:00:00+0100 ' ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
197+ 'spots ' => 10 ,
198+ ],
199+ [
200+ 'location ' => 'Another location ' ,
201+ 'address ' => 'Rådhuspladsen 1, 8000 Aarhus C ' ,
202+ 'registration_deadline_value ' => (new \DateTimeImmutable ('2025-11-30T00:00:00+0100 ' ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
203+ 'time_from_value ' => (new \DateTimeImmutable ('2025-12-01T15:00:00+0100 ' ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
204+ 'time_to_value ' => (new \DateTimeImmutable ('2025-12-01T16:30:00+0100 ' ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
205+ 'spots ' => 10 ,
206+ ],
207+ [
208+ 'location ' => 'The location ' ,
209+ 'address ' => 'Hack Kampmanns Plads 2, 8000 Aarhus C ' ,
210+ 'registration_deadline_value ' => (new \DateTimeImmutable ('2025-11-30T00:00:00+0100 ' ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
211+ 'time_from_value ' => (new \DateTimeImmutable ('2025-12-02T15:00:00+0100 ' ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
212+ 'time_to_value ' => (new \DateTimeImmutable ('2025-12-02T16:30:00+0100 ' ))->format (DateTimeItemInterface::DATETIME_STORAGE_FORMAT ),
213+ 'spots ' => 10 ,
214+ ],
215+ ]);
216+ $ node ->save ();
217+
218+ $ this ->createOrders ($ node ,
219+ [
220+ 'lines ' => [
221+ [
222+ 'dates_delta ' => 0 ,
223+ ],
224+ ],
225+ ],
226+ [
227+ 228+ 'lines ' => [
229+ [
230+ 'dates_delta ' => 1 ,
231+ 'quantity ' => 7 ,
232+ ],
233+ ],
234+ ],
235+
236+ // Sell out.
237+ [
238+ 'lines ' => [
239+ [
240+ 'dates_delta ' => 2 ,
241+ 'quantity ' => 10 ,
242+ ],
243+ ],
244+ ],
245+ );
246+ }
247+
248+ /**
249+ * Create orders in pretix.
250+ *
251+ * @param \Drupal\node\NodeInterface $node
252+ * The public meeting node.
253+ * @param array ...$specs
254+ * Order specs, e.g.
255+ *
256+ * <code>
257+ * [
258+ * [
259+ * // Optional email; defaults to '[email protected] '. 260+ 261+ * 'lines' => [
262+ * [
263+ * // The date to create an order line for
264+ * 'dates_delta' => 0,
265+ * // The quantity; defaults to 1.
266+ * 'quantity' => 9,
267+ * ],
268+ * ],
269+ * ],
270+ * [
271+ * 'lines' => [
272+ * [
273+ * 'dates_delta' => 1,
274+ * ],
275+ * ],
276+ * ],
277+ *
278+ * // Sell out.
279+ * [
280+ * 'lines' => [
281+ * [
282+ * 'dates_delta' => 2,
283+ * 'quantity' => 10,
284+ * ],
285+ * ],
286+ * ],
287+ * ]
288+ * </code>.
289+ */
290+ public function createOrders (NodeInterface $ node , array ...$ specs ): void {
291+ $ output = 'cli ' === PHP_SAPI ? new ConsoleOutput () : new NullOutput ();
292+
293+ if (empty ($ specs )) {
294+ throw new \InvalidArgumentException ('Missing specs ' );
295+ }
296+
297+ $ output ->writeln (sprintf ('Creating orders for %s (#%d) ' , $ node ->label (),
298+ $ node ->id ()));
299+
300+ $ client = $ this ->pretixEventHelper ->getPretixClient ($ node );
301+ $ request = new \ReflectionMethod ($ client , 'request ' );
302+
303+ // Add setting to create a proper webhook in pretix
304+ // (http://pretix.hoeringsportal.local.itkdev.dk/control/organizer/hoeringsportal/webhooks)
305+ // (see PretixOrderHelper::ensureWebhook() for details).
306+ $ settings = Settings::getAll ();
307+ if (!isset ($ settings ['itk_pretix ' ]['drupal_base_url ' ])) {
308+ $ settings ['itk_pretix ' ]['drupal_base_url ' ] = 'http://hoeringsportal.local.itkdev.dk:8080 ' ;
309+ }
310+ new Settings ($ settings );
311+ $ output ->writeln (sprintf ('Ensuring that webhook (%s) exists in pretix ' ,
312+ $ settings ['itk_pretix ' ]['drupal_base_url ' ]));
313+ $ this ->pretixOrderHelper ->ensureWebhook ($ client );
314+
315+ $ eventInfo = $ this ->pretixEventHelper ->loadPretixEventInfo ($ node );
316+ /** @var \Drupal\Core\Field\FieldItemListInterface $dates */
317+ $ dates = $ node ->get ('field_pretix_dates ' );
318+ foreach ($ specs as $ spec ) {
319+ $ lines = $ spec ['lines ' ] ?? NULL ;
320+ if (!is_array ($ lines )) {
321+ continue ;
322+ }
323+ foreach ($ spec ['lines ' ] as $ line ) {
324+ $ date = $ dates [$ line ['dates_delta ' ]] ?? NULL ;
325+ if (!$ date ) {
326+ continue ;
327+ }
328+
329+ $ subEventInfo = $ this ->pretixEventHelper ->loadPretixSubEventInfo ($ date );
330+ // https://docs.pretix.eu/dev/api/resources/orders.html#creating-orders
331+ $ path = sprintf (
332+ 'organizers/%s/events/%s/orders/ ' ,
333+ $ eventInfo ['pretix_organizer_slug ' ],
334+ $ eventInfo ['pretix_event_slug ' ],
335+ );
336+ $ payload = [
337+ 'json ' => [
338+ 'email ' =>
$ spec[
'email ' ] ??
'[email protected] ' ,
339+ 'positions ' => array_map (
340+ static fn (int $ index ) => [
341+ 'subevent ' => $ subEventInfo ['pretix_subevent_id ' ],
342+ 'attendee_name ' => sprintf ('Attendee %d ' , $ index ),
343+ 'attendee_email ' =>
sprintf (
'test%[email protected] ' ,
$ index),
344+ 'item ' => reset ($ subEventInfo ['data ' ]['subevent ' ]['item_price_overrides ' ])['item ' ],
345+ ],
346+ range (1 , $ line ['quantity ' ] ?? 1 ),
347+ ),
348+ ],
349+ ];
350+
351+ $ output ->writeln (sprintf ('POST \'ing %s to %s ' , json_encode ($ payload , JSON_PRETTY_PRINT ), $ path ));
352+ /** @var \Psr\Http\Message\ResponseInterface $response */
353+ $ response = $ request ->invoke ($ client , 'POST ' , $ path , $ payload );
354+
355+ $ output ->writeln (sprintf ('Response: %d ' , $ response ->getStatusCode ()));
356+ }
357+ }
159358 }
160359
161360 /**
0 commit comments