Completed
Branch EDTR/master (7034fa)
by
unknown
35:45 queued 26:17
created

AdvancedEditorData::getJedLocaleData()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 21

Duplication

Lines 21
Ratio 100 %

Importance

Changes 0
Metric Value
cc 4
nc 8
nop 1
dl 21
loc 21
rs 9.584
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\domain\services\admin\events\editor;
4
5
use DomainException;
6
use EE_Admin_Config;
7
use EE_Error;
8
use EE_Event;
9
use EEM_Datetime;
10
use EE_Datetime;
11
use EEM_Price;
12
use EEM_Price_Type;
13
use EEM_Ticket;
14
use EEM_Venue;
15
use EEH_DTT_Helper;
16
use EventEspresso\core\domain\services\assets\EspressoEditorAssetManager;
17
use EventEspresso\core\exceptions\InvalidDataTypeException;
18
use EventEspresso\core\exceptions\InvalidInterfaceException;
19
use EventEspresso\core\exceptions\ModelConfigurationException;
20
use EventEspresso\core\exceptions\UnexpectedEntityException;
21
use InvalidArgumentException;
22
use ReflectionException;
23
use WP_Post;
24
use WPGraphQL\Router;
25
use GraphQLRelay\Relay;
26
27
/**
28
 * Class AdvancedEditorData
29
 * Description
30
 *
31
 * @package EventEspresso\core\domain\services\admin\events\editor
32
 * @author  Brent Christensen
33
 * @since   $VID:$
34
 */
35
class AdvancedEditorData
36
{
37
38
    /**
39
     * @var string $namespace The graphql namespace/prefix.
40
     */
41
    protected $namespace = 'Espresso';
42
43
    /**
44
     * @var EE_Event
45
     */
46
    protected $event;
47
48
    /**
49
     * @var EE_Admin_Config
50
     */
51
    protected $admin_config;
52
    /**
53
     * @var EEM_Datetime $datetime_model
54
     */
55
    protected $datetime_model;
56
    /**
57
     * @var EEM_Price $price_model
58
     */
59
    protected $price_model;
60
    /**
61
     * @var EEM_Ticket $ticket_model
62
     */
63
    protected $ticket_model;
64
65
66
    /**
67
     * AdvancedEditorAdminForm constructor.
68
     *
69
     * @param EE_Event        $event
70
     * @param EE_Admin_Config $admin_config
71
     * @param EEM_Datetime    $datetime_model
72
     * @param EEM_Price       $price_model
73
     * @param EEM_Ticket      $ticket_model
74
     */
75
    public function __construct(
76
        EE_Event $event,
77
        EE_Admin_Config $admin_config,
78
        EEM_Datetime $datetime_model,
79
        EEM_Price $price_model,
80
        EEM_Ticket $ticket_model
81
    ) {
82
        $this->event = $event;
83
        $this->admin_config = $admin_config;
84
        $this->datetime_model = $datetime_model;
85
        $this->price_model = $price_model;
86
        $this->ticket_model = $ticket_model;
87
        add_action('admin_enqueue_scripts', [$this, 'loadScriptsStyles']);
88
    }
89
90
91
    /**
92
     * @throws EE_Error
93
     * @throws InvalidArgumentException
94
     * @throws InvalidDataTypeException
95
     * @throws InvalidInterfaceException
96
     * @throws ModelConfigurationException
97
     * @throws ReflectionException
98
     * @throws UnexpectedEntityException
99
     * @throws DomainException
100
     * @since $VID:$
101
     */
102
    public function loadScriptsStyles()
103
    {
104
        if ($this->admin_config->useAdvancedEditor()) {
105
            $eventId = $this->event instanceof EE_Event ? $this->event->ID() : 0;
106
            if (! $eventId) {
107
                global $post;
108
                $eventId = isset($_REQUEST['post']) ? absint($_REQUEST['post']) : 0;
109
                $eventId = $eventId === 0 && $post instanceof WP_Post && $post->post_type === 'espresso_events'
0 ignored issues
show
Bug introduced by
The class WP_Post does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
110
                    ? $post->ID
111
                    : $eventId;
112
            }
113
            if ($eventId) {
114
                $data = $this->getEditorData($eventId);
115
                $data = wp_json_encode($data);
116
                add_action(
117
                    'admin_footer',
118
                    static function () use ($data) {
119
                        wp_add_inline_script(
120
                            EspressoEditorAssetManager::JS_HANDLE_EDITOR,
121
                            "
122
var eeEditorData={$data};
123
",
124
                            'before'
125
                        );
126
                    }
127
                );
128
                add_action(
129
                    'admin_footer',
130
                    static function () use ($data) {
131
                        wp_add_inline_script(
132
                            EspressoEditorAssetManager::JS_HANDLE_EDITOR_PROTOTYPE,
133
                            "
134
var eeEditorData={$data};
135
",
136
                            'before'
137
                        );
138
                    }
139
                );
140
            }
141
        }
142
    }
143
144
145
    /**
146
     * @param int $eventId
147
     * @return array
148
     * @throws EE_Error
149
     * @throws InvalidDataTypeException
150
     * @throws InvalidInterfaceException
151
     * @throws ModelConfigurationException
152
     * @throws UnexpectedEntityException
153
     * @throws InvalidArgumentException
154
     * @throws ReflectionException
155
     * @throws DomainException
156
     * @since $VID:$
157
     */
158
    protected function getEditorData($eventId)
159
    {
160
        $event = $this->getEventGraphQLData($eventId);
161
        $event['dbId'] = $eventId;
162
163
        $graphqlEndpoint = class_exists('WPGraphQL') ? trailingslashit(site_url()) . Router::$route : '';
164
        $graphqlEndpoint = esc_url($graphqlEndpoint);
165
166
        $currentUser = $this->getGraphQLCurrentUser();
167
168
        $generalSettings = $this->getGraphQLGeneralSettings();
169
170
        $i18n = self::getJedLocaleData('event_espresso');
171
172
        return compact('event', 'graphqlEndpoint', 'currentUser', 'generalSettings', 'i18n');
173
    }
174
175
176
    /**
177
     * @param int $eventId
178
     * @return array
179
     * @since $VID:$
180
     */
181
    protected function getEventGraphQLData($eventId)
182
    {
183
        $datetimes = $this->getGraphQLDatetimes($eventId);
184
185
        if (empty($datetimes['nodes']) || (isset($_REQUEST['action']) && $_REQUEST['action'] === 'create_new')) {
186
            $this->addDefaultEntities($eventId);
187
            $datetimes = $this->getGraphQLDatetimes($eventId);
188
        }
189
190
        if (! empty($datetimes['nodes'])) {
191
            $datetimeIn = wp_list_pluck($datetimes['nodes'], 'id');
192
193
            if (! empty($datetimeIn)) {
194
                $tickets = $this->getGraphQLTickets($datetimeIn);
195
            }
196
        }
197
198
        if (! empty($tickets['nodes'])) {
199
            $ticketIn = wp_list_pluck($tickets['nodes'], 'id');
200
201
            if (! empty($ticketIn)) {
202
                $prices = $this->getGraphQLPrices($ticketIn);
203
            }
204
        }
205
206
        $priceTypes = $this->getGraphQLPriceTypes();
207
208
        $relations = $this->getRelationalData($eventId);
209
210
        return compact('datetimes', 'tickets', 'prices', 'priceTypes', 'relations');
211
    }
212
213
    /**
214
     * @param int $eventId
215
     * @throws DomainException
216
     * @throws EE_Error
217
     * @throws InvalidArgumentException
218
     * @throws InvalidDataTypeException
219
     * @throws InvalidInterfaceException
220
     * @throws ModelConfigurationException
221
     * @throws ReflectionException
222
     * @throws UnexpectedEntityException
223
     * @since $VID:$
224
     */
225
    protected function addDefaultEntities($eventId)
226
    {
227
        $default_dates = $this->datetime_model->create_new_blank_datetime();
228
        if (is_array($default_dates) && isset($default_dates[0]) && $default_dates[0] instanceof EE_Datetime) {
229
            $default_date = $default_dates[0];
230
            $default_date->save();
231
            $default_date->_add_relation_to($eventId, 'Event');
232
            $default_tickets = $this->ticket_model->get_all_default_tickets();
233
            $default_prices = $this->price_model->get_all_default_prices();
234
            foreach ($default_tickets as $default_ticket) {
235
                $default_ticket->save();
236
                $default_ticket->_add_relation_to($default_date, 'Datetime');
237
                foreach ($default_prices as $default_price) {
0 ignored issues
show
Bug introduced by
The expression $default_prices of type integer|array<integer,object<EE_Base_Class>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
238
                    $default_price->save();
239
                    $default_price->_add_relation_to($default_ticket, 'Ticket');
240
                }
241
            }
242
        }
243
    }
244
245
246
    /**
247
     * @param int $eventId
248
     * @return array|null
249
     * @since $VID:$
250
     */
251 View Code Duplication
    protected function getGraphQLDatetimes($eventId)
252
    {
253
        $field_key = lcfirst($this->namespace) . 'Datetimes';
254
        $query = <<<QUERY
255
        query GET_DATETIMES(\$where: {$this->namespace}RootQueryDatetimesConnectionWhereArgs) {
256
            {$field_key}(where: \$where) {
257
                nodes {
258
                    id
259
                    dbId
260
                    capacity
261
                    description
262
                    endDate
263
                    isActive
264
                    isExpired
265
                    isPrimary
266
                    isSoldOut
267
                    isTrashed
268
                    isUpcoming
269
                    length
270
                    name
271
                    order
272
                    reserved
273
                    sold
274
                    status
275
                    startDate
276
                    __typename
277
                }
278
                __typename
279
            }
280
        }
281
QUERY;
282
        $data = [
283
            'operation_name' => 'GET_DATETIMES',
284
            'variables' => [
285
                'first' => 50,
286
                'where' => [
287
                    'eventId' => $eventId,
288
                ],
289
            ],
290
            'query' => $query,
291
        ];
292
293
        $responseData = $this->makeGraphQLRequest($data);
294
        return !empty($responseData[ $field_key ]) ? $responseData[ $field_key ] : null;
295
    }
296
297
298
    /**
299
     * @param array $datetimeIn
300
     * @return array|null
301
     * @since $VID:$
302
     */
303 View Code Duplication
    protected function getGraphQLTickets(array $datetimeIn)
304
    {
305
        $field_key = lcfirst($this->namespace) . 'Tickets';
306
        $query = <<<QUERY
307
        query GET_TICKETS(\$where: {$this->namespace}RootQueryTicketsConnectionWhereArgs) {
308
            {$field_key}(where: \$where) {
309
                nodes {
310
                    id
311
                    dbId
312
                    description
313
                    endDate
314
                    isDefault
315
                    isFree
316
                    isRequired
317
                    isSoldOut
318
                    isTaxable
319
                    isTrashed
320
                    max
321
                    min
322
                    name
323
                    order
324
                    price
325
                    quantity
326
                    reserved
327
                    reverseCalculate
328
                    sold
329
                    startDate
330
                    uses
331
                    __typename
332
                }
333
                __typename
334
            }
335
        }
336
QUERY;
337
        $data = [
338
            'operation_name' => 'GET_TICKETS',
339
            'variables' => [
340
                'where' => [
341
                    'datetimeIn' => $datetimeIn,
342
                ],
343
            ],
344
            'query' => $query,
345
        ];
346
347
        $responseData = $this->makeGraphQLRequest($data);
348
        return !empty($responseData[ $field_key ]) ? $responseData[ $field_key ] : null;
349
    }
350
351
352
    /**
353
     * @param array $ticketIn
354
     * @return array|null
355
     * @since $VID:$
356
     */
357 View Code Duplication
    protected function getGraphQLPrices(array $ticketIn)
358
    {
359
        $field_key = lcfirst($this->namespace) . 'Prices';
360
        $query = <<<QUERY
361
        query GET_PRICES(\$where: {$this->namespace}RootQueryPricesConnectionWhereArgs) {
362
            {$field_key}(where: \$where) {
363
                nodes {
364
                    id
365
                    dbId
366
                    amount
367
                    desc
368
                    isBasePrice
369
                    isDefault
370
                    isDiscount
371
                    isPercent
372
                    isTax
373
                    isTrashed
374
                    name
375
                    order
376
                    overrides
377
                    priceTypeOrder
378
                    __typename
379
                }
380
                __typename
381
            }
382
        }
383
QUERY;
384
        $data = [
385
            'operation_name' => 'GET_PRICES',
386
            'variables' => [
387
                'where' => [
388
                    'ticketIn' => $ticketIn,
389
                ],
390
            ],
391
            'query' => $query,
392
        ];
393
394
        $responseData = $this->makeGraphQLRequest($data);
395
        return !empty($responseData[ $field_key ]) ? $responseData[ $field_key ] : null;
396
    }
397
398
399
    /**
400
     * @return array|null
401
     * @since $VID:$
402
     */
403 View Code Duplication
    protected function getGraphQLPriceTypes()
404
    {
405
        $field_key = lcfirst($this->namespace) . 'PriceTypes';
406
        $query = <<<QUERY
407
        query GET_PRICES {
408
            {$field_key} {
409
                nodes {
410
                    id
411
                    dbId
412
                    baseType
413
                    isBasePrice
414
                    isDiscount
415
                    isPercent
416
                    isTax
417
                    isTrashed
418
                    name
419
                    order
420
                    __typename
421
                }
422
                __typename
423
            }
424
        }
425
QUERY;
426
        $data = [
427
            'operation_name' => 'GET_PRICES',
428
            'query' => $query,
429
        ];
430
431
        $responseData = $this->makeGraphQLRequest($data);
432
        return !empty($responseData[ $field_key ]) ? $responseData[ $field_key ] : null;
433
    }
434
435
436
    /**
437
     * @return array|null
438
     * @since $VID:$
439
     */
440 View Code Duplication
    protected function getGraphQLCurrentUser()
441
    {
442
        $field_key = 'viewer';
443
        $query = <<<QUERY
444
        query GET_CURRENT_USER {
445
            {$field_key} {
446
                description
447
                email
448
                firstName
449
                id
450
                name
451
                nicename
452
                nickname
453
                lastName
454
                locale
455
                userId
456
                username
457
                __typename
458
            }
459
        }
460
QUERY;
461
        $data = [
462
            'operation_name' => 'GET_CURRENT_USER',
463
            'query' => $query,
464
        ];
465
466
        $responseData = $this->makeGraphQLRequest($data);
467
        return !empty($responseData[ $field_key ]) ? $responseData[ $field_key ] : null;
468
    }
469
470
471
    /**
472
     * @return array|null
473
     * @since $VID:$
474
     */
475 View Code Duplication
    protected function getGraphQLGeneralSettings()
476
    {
477
        $field_key = 'generalSettings';
478
        $query = <<<QUERY
479
        query GET_GENERAL_SETTINGS {
480
            {$field_key} {
481
                dateFormat
482
                timeFormat
483
                timezone
484
                __typename
485
            }
486
        }
487
QUERY;
488
        $data = [
489
            'operation_name' => 'GET_CURRENT_USER',
490
            'query' => $query,
491
        ];
492
493
        $responseData = $this->makeGraphQLRequest($data);
494
        return !empty($responseData[ $field_key ]) ? $responseData[ $field_key ] : null;
495
    }
496
497
498
    /**
499
     * @param array $data
500
     * @return array
501
     * @since $VID:$
502
     */
503
    protected function makeGraphQLRequest($data)
504
    {
505
        try {
506
            $response = graphql($data);
507
            if (!empty($response['data'])) {
508
                return $response['data'];
509
            }
510
            return null;
511
        } catch (\Exception $e) {
512
            // do something with the errors thrown
513
            return null;
514
        }
515
    }
516
517
518
    /**
519
     * @param mixed       $source  The source that's passed down the GraphQL queries
0 ignored issues
show
Bug introduced by
There is no parameter named $source. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
520
     * @param array       $args    The inputArgs on the field
0 ignored issues
show
Bug introduced by
There is no parameter named $args. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
521
     * @param AppContext  $context The AppContext passed down the GraphQL tree
0 ignored issues
show
Bug introduced by
There is no parameter named $context. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
522
     * @param ResolveInfo $info    The ResolveInfo passed down the GraphQL tree
0 ignored issues
show
Bug introduced by
There is no parameter named $info. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
523
     * @return string
524
     * @throws EE_Error
525
     * @throws Exception
526
     * @throws InvalidArgumentException
527
     * @throws InvalidDataTypeException
528
     * @throws InvalidInterfaceException
529
     * @throws ReflectionException
530
     * @throws UserError
531
     * @throws UnexpectedEntityException
532
     * @since $VID:$
533
     */
534
    public static function getRelationalData($eventId)
535
    {
536
        $data = [
537
            'datetimes'  => [],
538
            'tickets'    => [],
539
            'prices'     => [],
540
        ];
541
542
        $eem_datetime   = EEM_Datetime::instance();
543
        $eem_ticket     = EEM_Ticket::instance();
544
        $eem_price      = EEM_Price::instance();
545
        $eem_price_type = EEM_Price_Type::instance();
546
547
        // PROCESS DATETIMES
548
        $related_models = [
549
            'tickets' => $eem_ticket,
550
        ];
551
        // Get the IDs of event datetimes.
552
        $datetimeIds = $eem_datetime->get_col([[
553
            'EVT_ID' => $eventId,
554
            'DTT_deleted' => ['IN', [true, false]],
555
        ]]);
556 View Code Duplication
        foreach ($datetimeIds as $datetimeId) {
557
            $GID = self::convertToGlobalId($eem_datetime->item_name(), $datetimeId);
558
            foreach ($related_models as $key => $model) {
559
                // Get the IDs of related entities for the datetime ID.
560
                $Ids = $model->get_col([['Datetime.DTT_ID' => $datetimeId]]);
561
                if (! empty($Ids)) {
562
                    $data['datetimes'][ $GID ][ $key ] = self::convertToGlobalId($model->item_name(), $Ids);
563
                }
564
            }
565
        }
566
567
        // PROCESS TICKETS
568
        $related_models = [
569
            'datetimes' => $eem_datetime,
570
            'prices'    => $eem_price,
571
        ];
572
        // Get the IDs of all datetime tickets.
573
        $ticketIds = $eem_ticket->get_col([[
574
            'Datetime.DTT_ID' => ['in', $datetimeIds],
575
            'TKT_deleted' => ['IN', [true, false]],
576
        ]]);
577 View Code Duplication
        foreach ($ticketIds as $ticketId) {
578
            $GID = self::convertToGlobalId($eem_ticket->item_name(), $ticketId);
579
580
            foreach ($related_models as $key => $model) {
581
                // Get the IDs of related entities for the ticket ID.
582
                $Ids = $model->get_col([['Ticket.TKT_ID' => $ticketId]]);
583
                if (! empty($Ids)) {
584
                    $data['tickets'][ $GID ][ $key ] = self::convertToGlobalId($model->item_name(), $Ids);
585
                }
586
            }
587
        }
588
589
        // PROCESS PRICES
590
        $related_models = [
591
            'tickets'    => $eem_ticket,
592
            'priceTypes' => $eem_price_type,
593
        ];
594
        // Get the IDs of all ticket prices.
595
        $priceIds = $eem_price->get_col([['Ticket.TKT_ID' => ['in', $ticketIds]]]);
596 View Code Duplication
        foreach ($priceIds as $priceId) {
597
            $GID = self::convertToGlobalId($eem_price->item_name(), $priceId);
598
599
            foreach ($related_models as $key => $model) {
600
                // Get the IDs of related entities for the price ID.
601
                $Ids = $model->get_col([['Price.PRC_ID' => $priceId]]);
602
                if (! empty($Ids)) {
603
                    $data['prices'][ $GID ][ $key ] = self::convertToGlobalId($model->item_name(), $Ids);
604
                }
605
            }
606
        }
607
608
        return $data;
609
    }
610
611
    /**
612
     * Convert the DB ID into GID
613
     *
614
     * @param string    $type
615
     * @param int|int[] $ID
616
     * @return mixed
617
     */
618
    public static function convertToGlobalId($type, $ID)
619
    {
620
        if (is_array($ID)) {
621
            return array_map(function ($id) use ($type) {
622
                return self::convertToGlobalId($type, $id);
623
            }, $ID);
624
        }
625
        return Relay::toGlobalId($type, $ID);
626
    }
627
628
629
    /**
630
     * Returns Jed-formatted localization data.
631
     *
632
     * @param  string $domain Translation domain.
633
     * @return array
634
     */
635 View Code Duplication
    public static function getJedLocaleData($domain)
636
    {
637
        $translations = get_translations_for_domain($domain);
638
639
        $locale = array(
640
            '' => array(
641
                'domain' => $domain,
642
                'lang'   => is_admin() ? EEH_DTT_Helper::get_user_locale() : get_locale()
643
            ),
644
        );
645
646
        if (! empty($translations->headers['Plural-Forms'])) {
647
            $locale['']['plural_forms'] = $translations->headers['Plural-Forms'];
648
        }
649
650
        foreach ($translations->entries as $msgid => $entry) {
651
            $locale[ $msgid ] = $entry->translations;
652
        }
653
654
        return $locale;
655
    }
656
}
657