Completed
Branch EDTR/refactor-master (bcaf81)
by
unknown
41:30 queued 30:37
created

AdvancedEditorEntityData::addDefaultEntities()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 4
nop 2
dl 0
loc 19
rs 9.0111
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_Datetime;
8
use EE_Error;
9
use EE_Event;
10
use EEM_Datetime;
11
use EEM_Event;
12
use EEM_Price;
13
use EEM_Price_Type;
14
use EEM_Ticket;
15
use EE_Ticket;
16
use EEM_Venue;
17
use EventEspresso\core\domain\services\assets\EspressoEditorAssetManager;
18
use EventEspresso\core\domain\services\converters\RestApiSpoofer;
19
use EventEspresso\core\exceptions\InvalidDataTypeException;
20
use EventEspresso\core\exceptions\InvalidInterfaceException;
21
use EventEspresso\core\exceptions\ModelConfigurationException;
22
use EventEspresso\core\exceptions\RestPasswordIncorrectException;
23
use EventEspresso\core\exceptions\RestPasswordRequiredException;
24
use EventEspresso\core\exceptions\UnexpectedEntityException;
25
use EventEspresso\core\libraries\rest_api\RestException;
26
use InvalidArgumentException;
27
use ReflectionException;
28
use WP_Post;
29
use WPGraphQL\Router;
30
31
/**
32
 * Class AdvancedEditorEntityData
33
 * Description
34
 *
35
 * @package EventEspresso\core\domain\services\admin\events\editor
36
 * @author  Brent Christensen
37
 * @since   $VID:$
38
 */
39
class AdvancedEditorEntityData
40
{
41
42
    /**
43
     * @var EE_Event
44
     */
45
    protected $event;
46
47
    /**
48
     * @var RestApiSpoofer
49
     */
50
    protected $spoofer;
51
52
    /**
53
     * @var EE_Admin_Config
54
     */
55
    protected $admin_config;
56
57
    /**
58
     * @var EEM_Datetime $datetime_model
59
     */
60
    protected $datetime_model;
61
62
    /**
63
     * @var EEM_Event $event_model
64
     */
65
    protected $event_model;
66
67
    /**
68
     * @var EEM_Price $price_model
69
     */
70
    protected $price_model;
71
72
    /**
73
     * @var EEM_Price_Type $price_type_model
74
     */
75
    protected $price_type_model;
76
77
    /**
78
     * @var EEM_Ticket $ticket_model
79
     */
80
    protected $ticket_model;
81
    /**
82
     * @var EEM_Venue $venue_model
83
     */
84
    protected $venue_model;
85
86
87
    /**
88
     * AdvancedEditorAdminForm constructor.
89
     *
90
     * @param EE_Event        $event
91
     * @param RestApiSpoofer  $spoofer
92
     * @param EE_Admin_Config $admin_config
93
     * @param EEM_Datetime    $datetime_model
94
     * @param EEM_Event       $event_model
95
     * @param EEM_Price       $price_model
96
     * @param EEM_Price_Type  $price_type_model
97
     * @param EEM_Ticket      $ticket_model
98
     * @param EEM_Venue       $venue_model
99
     */
100
    public function __construct(
101
        EE_Event $event,
102
        RestApiSpoofer $spoofer,
103
        EE_Admin_Config $admin_config,
104
        EEM_Datetime $datetime_model,
105
        EEM_Event $event_model,
106
        EEM_Price $price_model,
107
        EEM_Price_Type $price_type_model,
108
        EEM_Ticket $ticket_model,
109
        EEM_Venue $venue_model
110
    ) {
111
        $this->event = $event;
112
        $this->admin_config = $admin_config;
113
        $this->spoofer = $spoofer;
114
        $this->datetime_model = $datetime_model;
115
        $this->event_model = $event_model;
116
        $this->price_model = $price_model;
117
        $this->price_type_model = $price_type_model;
118
        $this->ticket_model = $ticket_model;
119
        $this->venue_model = $venue_model;
120
        add_action('admin_enqueue_scripts', [$this, 'loadScriptsStyles']);
121
    }
122
123
124
    /**
125
     * @throws EE_Error
126
     * @throws InvalidArgumentException
127
     * @throws InvalidDataTypeException
128
     * @throws InvalidInterfaceException
129
     * @throws ModelConfigurationException
130
     * @throws ReflectionException
131
     * @throws RestException
132
     * @throws RestPasswordIncorrectException
133
     * @throws RestPasswordRequiredException
134
     * @throws UnexpectedEntityException
135
     * @throws DomainException
136
     * @since $VID:$
137
     */
138
    public function loadScriptsStyles()
139
    {
140
        if ($this->admin_config->useAdvancedEditor()) {
141
            $eventId = $this->event instanceof EE_Event ? $this->event->ID() : 0;
142
            if (! $eventId) {
143
                global $post;
144
                $eventId = isset($_REQUEST['post']) ? absint($_REQUEST['post']) : 0;
145
                $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...
146
                    ? $post->ID
147
                    : $eventId;
148
            }
149
            $graphqlEndpoint = class_exists('WPGraphQL') ? trailingslashit(site_url()) . Router::$route : '';
150
            $graphqlEndpoint = esc_url($graphqlEndpoint);
151
            if ($eventId) {
152
                $data = $this->getAllEventData($eventId);
153
                $data = wp_json_encode($data);
154
                add_action(
155
                    'admin_footer',
156
                    static function () use ($data, $graphqlEndpoint) {
157
                        wp_add_inline_script(
158
                            EspressoEditorAssetManager::JS_HANDLE_EDITOR,
159
                            "
160
var eeEditorEventData={$data};
161
var graphqlEndpoint='{$graphqlEndpoint}';
162
",
163
                            'before'
164
                        );
165
                    }
166
                );
167
            }
168
        }
169
    }
170
171
172
    /**
173
     * @param int $eventId
174
     * @return array
175
     * @throws DomainException
176
     * @throws EE_Error
177
     * @throws InvalidArgumentException
178
     * @throws InvalidDataTypeException
179
     * @throws InvalidInterfaceException
180
     * @throws ModelConfigurationException
181
     * @throws ReflectionException
182
     * @throws RestException
183
     * @throws RestPasswordIncorrectException
184
     * @throws RestPasswordRequiredException
185
     * @throws UnexpectedEntityException
186
     * @since $VID:$
187
     */
188
    protected function getEventDates($eventId)
189
    {
190
        return $this->spoofer->getApiResults(
191
            $this->datetime_model,
192
            [
193
                [
194
                    'EVT_ID'      => $eventId,
195
                    'DTT_deleted' => ['IN', [true, false]]
196
                ]
197
            ]
198
        );
199
    }
200
201
202
    /**
203
     * @param int $eventId
204
     * @param array $eventDates
205
     * @throws DomainException
206
     * @throws EE_Error
207
     * @throws InvalidArgumentException
208
     * @throws InvalidDataTypeException
209
     * @throws InvalidInterfaceException
210
     * @throws ModelConfigurationException
211
     * @throws ReflectionException
212
     * @throws RestException
213
     * @throws RestPasswordIncorrectException
214
     * @throws RestPasswordRequiredException
215
     * @throws UnexpectedEntityException
216
     * @since $VID:$
217
     */
218
    protected function addDefaultEntities($eventId, array $eventDates = [])
219
    {
220
        $default_dates = $this->datetime_model->create_new_blank_datetime();
221
        if (is_array($default_dates) && isset($default_dates[0]) && $default_dates[0] instanceof EE_Datetime) {
222
            $default_date = $default_dates[0];
223
            $default_date->save();
224
            $default_date->_add_relation_to($eventId, 'Event');
225
            $default_tickets = $this->ticket_model->get_all_default_tickets();
226
            $default_prices = $this->price_model->get_all_default_prices();
227
            foreach ($default_tickets as $default_ticket) {
228
                $default_ticket->save();
229
                $default_ticket->_add_relation_to($default_date, 'Datetime');
230
                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...
231
                    $default_price->save();
232
                    $default_price->_add_relation_to($default_ticket, 'Ticket');
233
                }
234
            }
235
        }
236
    }
237
238
239
    /**
240
     * @param int $eventId
241
     * @return array
242
     * @throws EE_Error
243
     * @throws InvalidDataTypeException
244
     * @throws InvalidInterfaceException
245
     * @throws ModelConfigurationException
246
     * @throws RestPasswordIncorrectException
247
     * @throws RestPasswordRequiredException
248
     * @throws UnexpectedEntityException
249
     * @throws RestException
250
     * @throws InvalidArgumentException
251
     * @throws ReflectionException
252
     * @throws DomainException
253
     * @since $VID:$
254
     */
255
    protected function getAllEventData($eventId)
256
    {
257
        // these should ultimately be extracted out into their own classes (one per model)
258
        $event = $this->spoofer->getOneApiResult(
259
            $this->event_model,
260
            [['EVT_ID' => $eventId]]
261
        );
262
        if (! (is_array($event) && isset($event['EVT_ID']) && $event['EVT_ID'] === $eventId)) {
263
            return [];
264
        }
265
        $eventDates = $this->getEventDates($eventId);
266
        if ((! is_array($eventDates) || empty($eventDates))
267
            || (isset($_REQUEST['action']) && $_REQUEST['action'] === 'create_new')
268
        ) {
269
            $this->addDefaultEntities($eventId);
270
            $eventDates = $this->getEventDates($eventId);
271
        }
272
273
        $event = [$eventId => $event];
274
        $relations = [
275
            'event'    => [
276
                $eventId => [
277
                    'datetime' => []
278
                ]
279
            ],
280
            'datetime' => [],
281
            'ticket'   => [],
282
            'price'    => [],
283
        ];
284
285
        $datetimes = [];
286
        $eventDateTickets = [];
287
        if (is_array($eventDates)) {
288
            foreach ($eventDates as $eventDate) {
289
                if (isset($eventDate['DTT_ID']) && $eventDate['DTT_ID']) {
290
                    $DTT_ID = $eventDate['DTT_ID'];
291
                    $datetimes[ $DTT_ID ] = $eventDate;
292
                    $relations['event'][ $eventId ]['datetime'][] = $DTT_ID;
293
                    $eventDateTickets[ $DTT_ID ] = $this->spoofer->getApiResults(
294
                        $this->ticket_model,
295
                        [[
296
                            'Datetime.DTT_ID' => $DTT_ID,
297
                            'TKT_deleted' => ['IN', [true, false]]
298
                        ]]
299
                    );
300
                }
301
            }
302
        }
303
304
        $prices = [];
305
        $tickets = [];
306
        if (is_array($eventDateTickets)) {
307
            foreach ($eventDateTickets as $DTT_ID => $dateTickets) {
308
                if (is_array($dateTickets)) {
309
                    $relations['datetime'][ $DTT_ID ]['ticket'] = [];
310
                    foreach ($dateTickets as $ticket) {
311
                        if (isset($ticket['TKT_ID']) && $ticket['TKT_ID']) {
312
                            $TKT_ID = $ticket['TKT_ID'];
313
                            $tickets[ $TKT_ID ] = $ticket;
314
                            $relations['datetime'][ $DTT_ID ]['ticket'][] = $TKT_ID;
315
                            $ticketPrices[ $TKT_ID ] = $this->spoofer->getApiResults(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ticketPrices was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ticketPrices = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
316
                                $this->price_model,
317
                                [['Ticket.TKT_ID' => $TKT_ID]]
318
                            );
319
                            if (is_array($ticketPrices[ $TKT_ID ])) {
320
                                $relations['ticket'][ $TKT_ID ]['price'] = [];
321
                                foreach ($ticketPrices[ $TKT_ID ] as $ticketPrice) {
322
                                    $PRC_ID = $ticketPrice['PRC_ID'];
323
                                    $prices[ $PRC_ID ] = $ticketPrice;
324
                                    $relations['ticket'][ $TKT_ID ]['price'][] = $PRC_ID;
325
                                }
326
                            }
327
                        }
328
                    }
329
                }
330
            }
331
        }
332
        $price_type_results = $this->spoofer->getApiResults(
333
            $this->price_type_model,
334
            [['PRT_deleted' => false]]
335
        );
336
        $price_types = [];
337
        foreach ($price_type_results as $price_type) {
338
            $price_types[ $price_type['PRT_ID'] ] = $price_type;
339
        }
340
        $venue = $this->spoofer->getOneApiResult(
341
            $this->venue_model,
342
            [['Event.EVT_ID' => $eventId]]
343
        );
344
        if (is_array($venue) && isset($venue['VNU_ID'])) {
345
            $relations['event'][ $eventId ]['venue'] = [ $venue['VNU_ID'] ];
346
            $venue = [$venue['VNU_ID'] => $venue];
347
        }
348
349
        $schemas = [
350
            'event'      => $this->spoofer->getModelSchema('events'),
351
            'datetime'   => $this->spoofer->getModelSchema('datetimes'),
352
            'ticket'     => $this->spoofer->getModelSchema('tickets'),
353
            'price'      => $this->spoofer->getModelSchema('prices'),
354
            'price_type' => $this->spoofer->getModelSchema('price_types'),
355
            'venue'      => $this->spoofer->getModelSchema('venues'),
356
        ];
357
358
        $tktRegCount = [];
359
        foreach ($tickets as $ticket) {
360
            $tkt_instance = $this->ticket_model->get_one_by_ID($ticket['TKT_ID']);
361
362
            $tktRegCount[ $ticket['TKT_ID'] ] = $tkt_instance instanceof EE_Ticket ?
363
            $tkt_instance->count_registrations()
364
            : 0;
365
        }
366
        return [
367
            'eventId'         => $eventId,
368
            'event'           => $event,
369
            'datetime'        => $datetimes,
370
            'ticket'          => $tickets,
371
            'price'           => $prices,
372
            'price_type'      => $price_types,
373
            'venue'           => $venue,
374
            'schemas'         => $schemas,
375
            'relations'       => $relations,
376
            'tktRegCount'     => $tktRegCount,
377
        ];
378
    }
379
}
380