Completed
Branch BUG/reg-status-change-recursio... (2db0c9)
by
unknown
20:03 queued 10:32
created

EspressoEventAttendees   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 338
Duplicated Lines 5.92 %

Coupling/Cohesion

Components 1
Dependencies 12

Importance

Changes 0
Metric Value
dl 20
loc 338
rs 8.96
c 0
b 0
f 0
wmc 43
lcom 1
cbo 12

12 Methods

Rating   Name   Duplication   Size   Complexity  
A cacheExpiration() 0 4 1
A getDatetime() 10 10 3
A getTicket() 10 10 3
A getTag() 0 4 1
A initializeShortcode() 0 4 1
B processShortcode() 0 31 6
A getAttributes() 0 15 1
A setBaseTemplateArguments() 0 11 4
B validateEntities() 0 25 9
A setBaseQueryParams() 0 23 4
B getEvent() 0 43 7
A setAdditionalQueryParams() 0 15 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EspressoEventAttendees often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EspressoEventAttendees, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace EventEspresso\core\domain\entities\shortcodes;
4
5
use DomainException;
6
use EE_Datetime;
7
use EE_Error;
8
use EE_Event;
9
use EE_Ticket;
10
use EEH_Event_View;
11
use EEH_Template;
12
use EEM_Attendee;
13
use EEM_Datetime;
14
use EEM_Event;
15
use EEM_Registration;
16
use EEM_Ticket;
17
use EventEspresso\core\exceptions\EntityNotFoundException;
18
use EventEspresso\core\exceptions\InvalidDataTypeException;
19
use EventEspresso\core\exceptions\InvalidInterfaceException;
20
use EventEspresso\core\services\shortcodes\EspressoShortcode;
21
use InvalidArgumentException;
22
23
/**
24
 * Class EspressoEventAttendees
25
 * ESPRESSO_EVENT_ATTENDEES shortcode
26
 *
27
 * @package Event Espresso
28
 * @author  Darren Ethier
29
 * @since   4.9.26
30
 */
31
class EspressoEventAttendees extends EspressoShortcode
32
{
33
34
    private $query_params = array(
35
        0 => array(),
36
    );
37
38
    private $template_args = array(
39
        'contacts' => array(),
40
        'event'    => null,
41
        'datetime' => null,
42
        'ticket'   => null,
43
    );
44
45
    /**
46
     * the actual shortcode tag that gets registered with WordPress
47
     *
48
     * @return string
49
     */
50
    public function getTag()
51
    {
52
        return 'ESPRESSO_EVENT_ATTENDEES';
53
    }
54
55
56
    /**
57
     * the time in seconds to cache the results of the processShortcode() method
58
     * 0 means the processShortcode() results will NOT be cached at all
59
     *
60
     * @return int
61
     */
62
    public function cacheExpiration()
63
    {
64
        return 0;
65
    }
66
67
68
    /**
69
     * a place for adding any initialization code that needs to run prior to wp_header().
70
     * this may be required for shortcodes that utilize a corresponding module,
71
     * and need to enqueue assets for that module
72
     *
73
     * @return void
74
     */
75
    public function initializeShortcode()
76
    {
77
        $this->shortcodeHasBeenInitialized();
78
    }
79
80
81
    /**
82
     * process_shortcode - ESPRESSO_EVENT_ATTENDEES - Returns a list of attendees to an event.
83
     *  [ESPRESSO_EVENT_ATTENDEES]
84
     *  - defaults to attendees for earliest active event, or earliest upcoming event.
85
     *  [ESPRESSO_EVENT_ATTENDEES event_id=123]
86
     *  - attendees for specific event.
87
     *  [ESPRESSO_EVENT_ATTENDEES datetime_id=245]
88
     *  - attendees for a specific datetime.
89
     *  [ESPRESSO_EVENT_ATTENDEES ticket_id=123]
90
     *  - attendees for a specific ticket.
91
     *  [ESPRESSO_EVENT_ATTENDEES status=all]
92
     *  - specific registration status (use status id) or all for all attendees regardless of status.
93
     *  Note default is to only return approved attendees
94
     *  [ESPRESSO_EVENT_ATTENDEES show_gravatar=true]
95
     *  - default is to not return gravatar.  Otherwise if this is set then return gravatar for email address given.
96
     *  [ESPRESSO_EVENT_ATTENDEES display_on_archives=true]
97
     *  - default is to not display attendees list on archive pages.
98
     * Note: because of the relationship between event_id, ticket_id, and datetime_id:
99
     * If more than one of those params is included, then preference is given to the following:
100
     *  - event_id is used whenever its present and any others are ignored.
101
     *  - if no event_id then datetime is used whenever its present and any others are ignored.
102
     *  - otherwise ticket_id is used if present.
103
     *
104
     * @param array $attributes
105
     * @return string
106
     * @throws EE_Error
107
     * @throws InvalidDataTypeException
108
     * @throws InvalidInterfaceException
109
     * @throws InvalidArgumentException
110
     * @throws DomainException
111
     */
112
    public function processShortcode($attributes = array())
113
    {
114
        // grab attributes and merge with defaults
115
        $attributes = $this->getAttributes((array) $attributes);
116
        $attributes['limit'] = (int) $attributes['limit'];
117
        $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN);
118
        // don't display on archives unless 'display_on_archives' is true
119
        if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) {
120
            return '';
121
        }
122
        try {
123
            $this->setBaseTemplateArguments($attributes);
124
            $this->validateEntities($attributes);
125
            $this->setBaseQueryParams();
126
        } catch (EntityNotFoundException $e) {
127
            if (WP_DEBUG) {
128
                return '<div class="important-notice ee-error">'
129
                       . $e->getMessage()
130
                       . '</div>';
131
            }
132
            return '';
133
        }
134
        $this->setAdditionalQueryParams($attributes);
135
        // get contacts!
136
        $this->template_args['contacts'] = EEM_Attendee::instance()->get_all($this->query_params);
137
        // all set let's load up the template and return.
138
        return EEH_Template::locate_template(
139
            'loop-espresso_event_attendees.php',
140
            $this->template_args
141
        );
142
    }
143
144
145
    /**
146
     * merge incoming attributes with filtered defaults
147
     *
148
     * @param array $attributes
149
     * @return array
150
     */
151
    private function getAttributes(array $attributes)
152
    {
153
        return (array) apply_filters(
154
            'EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts',
155
            $attributes + array(
156
                'event_id'            => null,
157
                'datetime_id'         => null,
158
                'ticket_id'           => null,
159
                'status'              => EEM_Registration::status_id_approved,
160
                'show_gravatar'       => false,
161
                'display_on_archives' => false,
162
                'limit'               => 10,
163
            )
164
        );
165
    }
166
167
168
    /**
169
     * Set all the base template arguments from the incoming attributes.
170
     * * Note: because of the relationship between event_id, ticket_id, and datetime_id:
171
     * If more than one of those params is included, then preference is given to the following:
172
     *  - event_id is used whenever its present and any others are ignored.
173
     *  - if no event_id then datetime is used whenever its present and any others are ignored.
174
     *  - otherwise ticket_id is used if present.
175
     *
176
     * @param array $attributes
177
     * @throws EE_Error
178
     * @throws InvalidDataTypeException
179
     * @throws InvalidInterfaceException
180
     * @throws InvalidArgumentException
181
     */
182
    private function setBaseTemplateArguments(array $attributes)
183
    {
184
        $this->template_args['show_gravatar'] = $attributes['show_gravatar'];
185
        $this->template_args['event'] = $this->getEvent($attributes);
186
        $this->template_args['datetime'] = empty($attributes['event_id'])
187
            ? $this->getDatetime($attributes)
188
            : null;
189
        $this->template_args['ticket'] = empty($attributes['datetime_id']) && empty($attributes['event_id'])
190
            ? $this->getTicket($attributes)
191
            : null;
192
    }
193
194
195
    /**
196
     * Validates the presence of entities for the given attribute values.
197
     *
198
     * @param array $attributes
199
     * @throws EntityNotFoundException
200
     */
201
    private function validateEntities(array $attributes)
202
    {
203
        if (! $this->template_args['event'] instanceof EE_Event
204
            || (
205
                empty($attributes['event_id'])
206
                && $attributes['datetime_id']
207
                && ! $this->template_args['datetime'] instanceof EE_Datetime
208
            )
209
            || (
210
                empty($attributes['event_id'])
211
                && empty($attributes['datetime_id'])
212
                && $attributes['ticket_id']
213
                && ! $this->template_args['ticket'] instanceof EE_Ticket
214
            )
215
        ) {
216
            throw new EntityNotFoundException(
217
                '',
218
                '',
219
                esc_html__(
220
                    'The [ESPRESSO_EVENT_ATTENDEES] shortcode has been used incorrectly.  Please double check the arguments you used for any typos.  In the case of ID type arguments, its possible the given ID does not correspond to existing data in the database.',
221
                    'event_espresso'
222
                )
223
            );
224
        }
225
    }
226
227
228
    /**
229
     * Sets the query params for the base query elements.
230
     */
231
    private function setBaseQueryParams()
232
    {
233
        switch (true) {
234
            case $this->template_args['datetime'] instanceof EE_Datetime:
235
                $this->query_params = array(
236
                    0                          => array(
237
                        'Registration.Ticket.Datetime.DTT_ID' => $this->template_args['datetime']->ID(),
238
                    ),
239
                    'default_where_conditions' => 'this_model_only',
240
                );
241
                break;
242
            case $this->template_args['ticket'] instanceof EE_Ticket:
243
                $this->query_params[0] = array(
244
                    'Registration.TKT_ID' => $this->template_args['ticket']->ID(),
245
                );
246
                break;
247
            case $this->template_args['event'] instanceof EE_Event:
248
                $this->query_params[0] = array(
249
                    'Registration.EVT_ID' => $this->template_args['event']->ID(),
250
                );
251
                break;
252
        }
253
    }
254
255
256
    /**
257
     * @param array $attributes
258
     * @return EE_Event|null
259
     * @throws EE_Error
260
     * @throws InvalidDataTypeException
261
     * @throws InvalidInterfaceException
262
     * @throws InvalidArgumentException
263
     */
264
    private function getEvent(array $attributes)
265
    {
266
        switch (true) {
267
            case ! empty($attributes['event_id']):
268
                $event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']);
269
                break;
270
            case ! empty($attributes['datetime_id']):
271
                $event = EEM_Event::instance()->get_one(array(
272
                    array(
273
                        'Datetime.DTT_ID' => $attributes['datetime_id'],
274
                    ),
275
                ));
276
                break;
277
            case ! empty($attributes['ticket_id']):
278
                $event = EEM_Event::instance()->get_one(array(
279
                    array(
280
                        'Datetime.Ticket.TKT_ID' => $attributes['ticket_id'],
281
                    ),
282
                    'default_where_conditions' => 'none'
283
                ));
284
                break;
285
            case is_espresso_event():
286
                $event = EEH_Event_View::get_event();
287
                break;
288
            default:
289
                // one last shot...
290
                // try getting the earliest active event
291
                $events = EEM_Event::instance()->get_active_events(array(
292
                    'limit'    => 1,
293
                    'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'),
294
                ));
295
                //  if none then get the next upcoming
296
                $events = empty($events)
297
                    ? EEM_Event::instance()->get_upcoming_events(array(
298
                        'limit'    => 1,
299
                        'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'),
300
                    ))
301
                    : $events;
302
                $event = reset($events);
303
        }
304
305
        return $event instanceof EE_Event ? $event : null;
306
    }
307
308
309
    /**
310
     * @param array $attributes
311
     * @return EE_Datetime|null
312
     * @throws EE_Error
313
     * @throws InvalidDataTypeException
314
     * @throws InvalidInterfaceException
315
     * @throws InvalidArgumentException
316
     */
317 View Code Duplication
    private function getDatetime(array $attributes)
318
    {
319
        if (! empty($attributes['datetime_id'])) {
320
            $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']);
321
            if ($datetime instanceof EE_Datetime) {
322
                return $datetime;
323
            }
324
        }
325
        return null;
326
    }
327
328
329
    /**
330
     * @param array $attributes
331
     * @return \EE_Base_Class|EE_Ticket|null
332
     * @throws EE_Error
333
     * @throws InvalidDataTypeException
334
     * @throws InvalidInterfaceException
335
     * @throws InvalidArgumentException
336
     */
337 View Code Duplication
    private function getTicket(array $attributes)
338
    {
339
        if (! empty($attributes['ticket_id'])) {
340
            $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']);
341
            if ($ticket instanceof EE_Ticket) {
342
                return $ticket;
343
            }
344
        }
345
        return null;
346
    }
347
348
349
    /**
350
     * @param array $attributes
351
     * @throws EE_Error
352
     */
353
    private function setAdditionalQueryParams(array $attributes)
354
    {
355
        $reg_status_array = EEM_Registration::reg_status_array();
356
        if (isset($reg_status_array[ $attributes['status'] ])) {
357
            $this->query_params[0]['Registration.STS_ID'] = $attributes['status'];
358
        }
359
        if (absint($attributes['limit'])) {
360
            $this->query_params['limit'] = $attributes['limit'];
361
        }
362
        $this->query_params['group_by'] = array('ATT_ID');
363
        $this->query_params['order_by'] = (array) apply_filters(
364
            'FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by',
365
            array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC')
366
        );
367
    }
368
}
369