Completed
Branch BUG-10626-dst-unit-test (1e1790)
by
unknown
45:29 queued 34:12
created
modules/ticket_selector/DisplayTicketSelector.php 1 patch
Indentation   +680 added lines, -680 removed lines patch added patch discarded remove patch
@@ -17,7 +17,7 @@  discard block
 block discarded – undo
17 17
 use WP_Post;
18 18
 
19 19
 if ( ! defined( 'EVENT_ESPRESSO_VERSION' ) ) {
20
-    exit( 'No direct script access allowed' );
20
+	exit( 'No direct script access allowed' );
21 21
 }
22 22
 
23 23
 
@@ -34,688 +34,688 @@  discard block
 block discarded – undo
34 34
 class DisplayTicketSelector
35 35
 {
36 36
 
37
-    /**
38
-     * event that ticket selector is being generated for
39
-     *
40
-     * @access protected
41
-     * @var EE_Event $event
42
-     */
43
-    protected $event;
44
-
45
-    /**
46
-     * Used to flag when the ticket selector is being called from an external iframe.
47
-     *
48
-     * @var bool $iframe
49
-     */
50
-    protected $iframe = false;
51
-
52
-    /**
53
-     * max attendees that can register for event at one time
54
-     *
55
-     * @var int $max_attendees
56
-     */
57
-    private $max_attendees = EE_INF;
58
-
59
-    /**
60
-     *@var string $date_format
61
-     */
62
-    private $date_format;
63
-
64
-    /**
65
-     *@var string $time_format
66
-     */
67
-    private $time_format;
68
-
69
-
70
-
71
-    /**
72
-     * DisplayTicketSelector constructor.
73
-     */
74
-    public function __construct()
75
-    {
76
-        $this->date_format = apply_filters(
77
-            'FHEE__EED_Ticket_Selector__display_ticket_selector__date_format',
78
-            get_option('date_format')
79
-        );
80
-        $this->time_format = apply_filters(
81
-            'FHEE__EED_Ticket_Selector__display_ticket_selector__time_format',
82
-            get_option('time_format')
83
-        );
84
-    }
85
-
86
-
87
-
88
-    /**
89
-     * @param boolean $iframe
90
-     */
91
-    public function setIframe( $iframe = true )
92
-    {
93
-        $this->iframe = filter_var( $iframe, FILTER_VALIDATE_BOOLEAN );
94
-    }
95
-
96
-
97
-    /**
98
-     * finds and sets the \EE_Event object for use throughout class
99
-     *
100
-     * @param mixed $event
101
-     * @return bool
102
-     * @throws EE_Error
103
-     */
104
-    protected function setEvent( $event = null )
105
-    {
106
-        if ( $event === null ) {
107
-            global $post;
108
-            $event = $post;
109
-        }
110
-        if ( $event instanceof EE_Event ) {
111
-            $this->event = $event;
112
-        } else if ( $event instanceof WP_Post ) {
113
-            if ( isset( $event->EE_Event ) && $event->EE_Event instanceof EE_Event ) {
114
-                $this->event = $event->EE_Event;
115
-            } else if ( $event->post_type === 'espresso_events' ) {
116
-                $event->EE_Event = EEM_Event::instance()->instantiate_class_from_post_object( $event );
117
-                $this->event = $event->EE_Event;
118
-            }
119
-        } else {
120
-            $user_msg = __( 'No Event object or an invalid Event object was supplied.', 'event_espresso' );
121
-            $dev_msg = $user_msg . __(
122
-                    'In order to generate a ticket selector, please ensure you are passing either an EE_Event object or a WP_Post object of the post type "espresso_event" to the EE_Ticket_Selector class constructor.',
123
-                    'event_espresso'
124
-                );
125
-            EE_Error::add_error( $user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__ );
126
-            return false;
127
-        }
128
-        return true;
129
-    }
130
-
131
-
132
-
133
-    /**
134
-     * @return int
135
-     */
136
-    public function getMaxAttendees()
137
-    {
138
-        return $this->max_attendees;
139
-    }
140
-
141
-
142
-
143
-    /**
144
-     * @param int $max_attendees
145
-     */
146
-    public function setMaxAttendees($max_attendees)
147
-    {
148
-        $this->max_attendees = absint(
149
-            apply_filters(
150
-                'FHEE__EE_Ticket_Selector__display_ticket_selector__max_tickets',
151
-                $max_attendees
152
-            )
153
-        );
154
-    }
155
-
156
-
157
-
158
-    /**
159
-     * creates buttons for selecting number of attendees for an event
160
-     *
161
-     * @param WP_Post|int $event
162
-     * @param bool         $view_details
163
-     * @return string
164
-     * @throws EE_Error
165
-     */
166
-    public function display( $event = null, $view_details = false )
167
-    {
168
-        // reset filter for displaying submit button
169
-        remove_filter( 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true' );
170
-        // poke and prod incoming event till it tells us what it is
171
-        if ( ! $this->setEvent( $event ) ) {
172
-            return false;
173
-        }
174
-        // begin gathering template arguments by getting event status
175
-        $template_args = array( 'event_status' => $this->event->get_active_status() );
176
-        if ( $this->activeEventAndShowTicketSelector($event, $template_args['event_status'], $view_details) ) {
177
-            return ! is_single() ? $this->displayViewDetailsButton() : '';
178
-        }
179
-        // filter the maximum qty that can appear in the Ticket Selector qty dropdowns
180
-        $this->setMaxAttendees($this->event->additional_limit());
181
-        if ($this->getMaxAttendees() < 1) {
182
-            return $this->ticketSalesClosedMessage();
183
-        }
184
-        // is the event expired ?
185
-        $template_args['event_is_expired'] = $this->event->is_expired();
186
-        if ( $template_args[ 'event_is_expired' ] ) {
187
-            return $this->expiredEventMessage();
188
-        }
189
-        // get all tickets for this event ordered by the datetime
190
-        $tickets = $this->getTickets();
191
-        if (count($tickets) < 1) {
192
-            return $this->noTicketAvailableMessage();
193
-        }
194
-        if (EED_Events_Archive::is_iframe()){
195
-            $this->setIframe();
196
-        }
197
-        // redirecting to another site for registration ??
198
-        $external_url = (string) $this->event->external_url();
199
-        // if redirecting to another site for registration, then we don't load the TS
200
-        $ticket_selector = $external_url
201
-            ? $this->externalEventRegistration()
202
-            : $this->loadTicketSelector($tickets,$template_args);
203
-        // now set up the form (but not for the admin)
204
-        $ticket_selector = ! is_admin()
205
-            ? $this->formOpen($this->event->ID(), $external_url) . $ticket_selector
206
-            : $ticket_selector;
207
-        // submit button and form close tag
208
-        $ticket_selector .= ! is_admin() ? $this->displaySubmitButton($external_url) : '';
209
-        return $ticket_selector;
210
-    }
211
-
212
-
213
-
214
-    /**
215
-     * displayTicketSelector
216
-     * examines the event properties and determines whether a Ticket Selector should be displayed
217
-     *
218
-     * @param WP_Post|int $event
219
-     * @param string       $_event_active_status
220
-     * @param bool         $view_details
221
-     * @return bool
222
-     * @throws EE_Error
223
-     */
224
-    protected function activeEventAndShowTicketSelector($event, $_event_active_status, $view_details)
225
-    {
226
-        $event_post = $this->event instanceof EE_Event ? $this->event->ID() : $event;
227
-        return ! is_admin()
228
-               && (
229
-                   ! $this->event->display_ticket_selector()
230
-                   || $view_details
231
-                   || post_password_required($event_post)
232
-                   || (
233
-                       $_event_active_status !== EE_Datetime::active
234
-                       && $_event_active_status !== EE_Datetime::upcoming
235
-                       && $_event_active_status !== EE_Datetime::sold_out
236
-                       && ! (
237
-                           $_event_active_status === EE_Datetime::inactive
238
-                           && is_user_logged_in()
239
-                       )
240
-                   )
241
-               );
242
-    }
243
-
244
-
245
-
246
-    /**
247
-     * noTicketAvailableMessage
248
-     * notice displayed if event is expired
249
-     *
250
-     * @return string
251
-     * @throws EE_Error
252
-     */
253
-    protected function expiredEventMessage()
254
-    {
255
-        return '<div class="ee-event-expired-notice"><span class="important-notice">' . esc_html__(
256
-            'We\'re sorry, but all tickets sales have ended because the event is expired.',
257
-            'event_espresso'
258
-        ) . '</span></div><!-- .ee-event-expired-notice -->';
259
-    }
260
-
261
-
262
-
263
-    /**
264
-     * noTicketAvailableMessage
265
-     * notice displayed if event has no more tickets available
266
-     *
267
-     * @return string
268
-     * @throws EE_Error
269
-     */
270
-    protected function noTicketAvailableMessage()
271
-    {
272
-        $no_ticket_available_msg = esc_html__( 'We\'re sorry, but all ticket sales have ended.', 'event_espresso' );
273
-        if (current_user_can('edit_post', $this->event->ID())) {
274
-            $no_ticket_available_msg .= sprintf(
275
-                esc_html__(
276
-                    '%1$sNote to Event Admin:%2$sNo tickets were found for this event. This effectively turns off ticket sales. Please ensure that at least one ticket is available for if you want people to be able to register.%3$s(click to edit this event)%4$s',
277
-                    'event_espresso'
278
-                ),
279
-                '<div class="ee-attention" style="text-align: left;"><b>',
280
-                '</b><br />',
281
-                '<span class="edit-link"><a class="post-edit-link" href="'.get_edit_post_link($this->event->ID()).'">',
282
-                '</a></span></div><!-- .ee-attention noTicketAvailableMessage -->'
283
-            );
284
-        }
285
-        return '
37
+	/**
38
+	 * event that ticket selector is being generated for
39
+	 *
40
+	 * @access protected
41
+	 * @var EE_Event $event
42
+	 */
43
+	protected $event;
44
+
45
+	/**
46
+	 * Used to flag when the ticket selector is being called from an external iframe.
47
+	 *
48
+	 * @var bool $iframe
49
+	 */
50
+	protected $iframe = false;
51
+
52
+	/**
53
+	 * max attendees that can register for event at one time
54
+	 *
55
+	 * @var int $max_attendees
56
+	 */
57
+	private $max_attendees = EE_INF;
58
+
59
+	/**
60
+	 *@var string $date_format
61
+	 */
62
+	private $date_format;
63
+
64
+	/**
65
+	 *@var string $time_format
66
+	 */
67
+	private $time_format;
68
+
69
+
70
+
71
+	/**
72
+	 * DisplayTicketSelector constructor.
73
+	 */
74
+	public function __construct()
75
+	{
76
+		$this->date_format = apply_filters(
77
+			'FHEE__EED_Ticket_Selector__display_ticket_selector__date_format',
78
+			get_option('date_format')
79
+		);
80
+		$this->time_format = apply_filters(
81
+			'FHEE__EED_Ticket_Selector__display_ticket_selector__time_format',
82
+			get_option('time_format')
83
+		);
84
+	}
85
+
86
+
87
+
88
+	/**
89
+	 * @param boolean $iframe
90
+	 */
91
+	public function setIframe( $iframe = true )
92
+	{
93
+		$this->iframe = filter_var( $iframe, FILTER_VALIDATE_BOOLEAN );
94
+	}
95
+
96
+
97
+	/**
98
+	 * finds and sets the \EE_Event object for use throughout class
99
+	 *
100
+	 * @param mixed $event
101
+	 * @return bool
102
+	 * @throws EE_Error
103
+	 */
104
+	protected function setEvent( $event = null )
105
+	{
106
+		if ( $event === null ) {
107
+			global $post;
108
+			$event = $post;
109
+		}
110
+		if ( $event instanceof EE_Event ) {
111
+			$this->event = $event;
112
+		} else if ( $event instanceof WP_Post ) {
113
+			if ( isset( $event->EE_Event ) && $event->EE_Event instanceof EE_Event ) {
114
+				$this->event = $event->EE_Event;
115
+			} else if ( $event->post_type === 'espresso_events' ) {
116
+				$event->EE_Event = EEM_Event::instance()->instantiate_class_from_post_object( $event );
117
+				$this->event = $event->EE_Event;
118
+			}
119
+		} else {
120
+			$user_msg = __( 'No Event object or an invalid Event object was supplied.', 'event_espresso' );
121
+			$dev_msg = $user_msg . __(
122
+					'In order to generate a ticket selector, please ensure you are passing either an EE_Event object or a WP_Post object of the post type "espresso_event" to the EE_Ticket_Selector class constructor.',
123
+					'event_espresso'
124
+				);
125
+			EE_Error::add_error( $user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__ );
126
+			return false;
127
+		}
128
+		return true;
129
+	}
130
+
131
+
132
+
133
+	/**
134
+	 * @return int
135
+	 */
136
+	public function getMaxAttendees()
137
+	{
138
+		return $this->max_attendees;
139
+	}
140
+
141
+
142
+
143
+	/**
144
+	 * @param int $max_attendees
145
+	 */
146
+	public function setMaxAttendees($max_attendees)
147
+	{
148
+		$this->max_attendees = absint(
149
+			apply_filters(
150
+				'FHEE__EE_Ticket_Selector__display_ticket_selector__max_tickets',
151
+				$max_attendees
152
+			)
153
+		);
154
+	}
155
+
156
+
157
+
158
+	/**
159
+	 * creates buttons for selecting number of attendees for an event
160
+	 *
161
+	 * @param WP_Post|int $event
162
+	 * @param bool         $view_details
163
+	 * @return string
164
+	 * @throws EE_Error
165
+	 */
166
+	public function display( $event = null, $view_details = false )
167
+	{
168
+		// reset filter for displaying submit button
169
+		remove_filter( 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true' );
170
+		// poke and prod incoming event till it tells us what it is
171
+		if ( ! $this->setEvent( $event ) ) {
172
+			return false;
173
+		}
174
+		// begin gathering template arguments by getting event status
175
+		$template_args = array( 'event_status' => $this->event->get_active_status() );
176
+		if ( $this->activeEventAndShowTicketSelector($event, $template_args['event_status'], $view_details) ) {
177
+			return ! is_single() ? $this->displayViewDetailsButton() : '';
178
+		}
179
+		// filter the maximum qty that can appear in the Ticket Selector qty dropdowns
180
+		$this->setMaxAttendees($this->event->additional_limit());
181
+		if ($this->getMaxAttendees() < 1) {
182
+			return $this->ticketSalesClosedMessage();
183
+		}
184
+		// is the event expired ?
185
+		$template_args['event_is_expired'] = $this->event->is_expired();
186
+		if ( $template_args[ 'event_is_expired' ] ) {
187
+			return $this->expiredEventMessage();
188
+		}
189
+		// get all tickets for this event ordered by the datetime
190
+		$tickets = $this->getTickets();
191
+		if (count($tickets) < 1) {
192
+			return $this->noTicketAvailableMessage();
193
+		}
194
+		if (EED_Events_Archive::is_iframe()){
195
+			$this->setIframe();
196
+		}
197
+		// redirecting to another site for registration ??
198
+		$external_url = (string) $this->event->external_url();
199
+		// if redirecting to another site for registration, then we don't load the TS
200
+		$ticket_selector = $external_url
201
+			? $this->externalEventRegistration()
202
+			: $this->loadTicketSelector($tickets,$template_args);
203
+		// now set up the form (but not for the admin)
204
+		$ticket_selector = ! is_admin()
205
+			? $this->formOpen($this->event->ID(), $external_url) . $ticket_selector
206
+			: $ticket_selector;
207
+		// submit button and form close tag
208
+		$ticket_selector .= ! is_admin() ? $this->displaySubmitButton($external_url) : '';
209
+		return $ticket_selector;
210
+	}
211
+
212
+
213
+
214
+	/**
215
+	 * displayTicketSelector
216
+	 * examines the event properties and determines whether a Ticket Selector should be displayed
217
+	 *
218
+	 * @param WP_Post|int $event
219
+	 * @param string       $_event_active_status
220
+	 * @param bool         $view_details
221
+	 * @return bool
222
+	 * @throws EE_Error
223
+	 */
224
+	protected function activeEventAndShowTicketSelector($event, $_event_active_status, $view_details)
225
+	{
226
+		$event_post = $this->event instanceof EE_Event ? $this->event->ID() : $event;
227
+		return ! is_admin()
228
+			   && (
229
+				   ! $this->event->display_ticket_selector()
230
+				   || $view_details
231
+				   || post_password_required($event_post)
232
+				   || (
233
+					   $_event_active_status !== EE_Datetime::active
234
+					   && $_event_active_status !== EE_Datetime::upcoming
235
+					   && $_event_active_status !== EE_Datetime::sold_out
236
+					   && ! (
237
+						   $_event_active_status === EE_Datetime::inactive
238
+						   && is_user_logged_in()
239
+					   )
240
+				   )
241
+			   );
242
+	}
243
+
244
+
245
+
246
+	/**
247
+	 * noTicketAvailableMessage
248
+	 * notice displayed if event is expired
249
+	 *
250
+	 * @return string
251
+	 * @throws EE_Error
252
+	 */
253
+	protected function expiredEventMessage()
254
+	{
255
+		return '<div class="ee-event-expired-notice"><span class="important-notice">' . esc_html__(
256
+			'We\'re sorry, but all tickets sales have ended because the event is expired.',
257
+			'event_espresso'
258
+		) . '</span></div><!-- .ee-event-expired-notice -->';
259
+	}
260
+
261
+
262
+
263
+	/**
264
+	 * noTicketAvailableMessage
265
+	 * notice displayed if event has no more tickets available
266
+	 *
267
+	 * @return string
268
+	 * @throws EE_Error
269
+	 */
270
+	protected function noTicketAvailableMessage()
271
+	{
272
+		$no_ticket_available_msg = esc_html__( 'We\'re sorry, but all ticket sales have ended.', 'event_espresso' );
273
+		if (current_user_can('edit_post', $this->event->ID())) {
274
+			$no_ticket_available_msg .= sprintf(
275
+				esc_html__(
276
+					'%1$sNote to Event Admin:%2$sNo tickets were found for this event. This effectively turns off ticket sales. Please ensure that at least one ticket is available for if you want people to be able to register.%3$s(click to edit this event)%4$s',
277
+					'event_espresso'
278
+				),
279
+				'<div class="ee-attention" style="text-align: left;"><b>',
280
+				'</b><br />',
281
+				'<span class="edit-link"><a class="post-edit-link" href="'.get_edit_post_link($this->event->ID()).'">',
282
+				'</a></span></div><!-- .ee-attention noTicketAvailableMessage -->'
283
+			);
284
+		}
285
+		return '
286 286
             <div class="ee-event-expired-notice">
287 287
                 <span class="important-notice">' . $no_ticket_available_msg . '</span>
288 288
             </div><!-- .ee-event-expired-notice -->';
289
-    }
290
-
291
-
292
-
293
-    /**
294
-     * ticketSalesClosed
295
-     * notice displayed if event ticket sales are turned off
296
-     *
297
-     * @return string
298
-     * @throws EE_Error
299
-     */
300
-    protected function ticketSalesClosedMessage()
301
-    {
302
-        $sales_closed_msg = esc_html__(
303
-            'We\'re sorry, but ticket sales have been closed at this time. Please check back again later.',
304
-            'event_espresso'
305
-        );
306
-        if (current_user_can('edit_post', $this->event->ID())) {
307
-            $sales_closed_msg .= sprintf(
308
-                esc_html__(
309
-                    '%sNote to Event Admin:%sThe "Maximum number of tickets allowed per order for this event" in the Event Registration Options has been set to "0". This effectively turns off ticket sales. %s(click to edit this event)%s',
310
-                    'event_espresso'
311
-                ),
312
-                '<div class="ee-attention" style="text-align: left;"><b>',
313
-                '</b><br />',
314
-                '<span class="edit-link"><a class="post-edit-link" href="'.get_edit_post_link($this->event->ID()).'">',
315
-                '</a></span></div><!-- .ee-attention ticketSalesClosedMessage -->'
316
-            );
317
-        }
318
-        return '<p><span class="important-notice">' . $sales_closed_msg . '</span></p>';
319
-    }
320
-
321
-
322
-
323
-    /**
324
-     * getTickets
325
-     *
326
-     * @return \EE_Base_Class[]|\EE_Ticket[]
327
-     * @throws EE_Error
328
-     */
329
-    protected function getTickets()
330
-    {
331
-        $ticket_query_args = array(
332
-            array('Datetime.EVT_ID' => $this->event->ID()),
333
-            'order_by' => array(
334
-                'TKT_order'              => 'ASC',
335
-                'TKT_required'           => 'DESC',
336
-                'TKT_start_date'         => 'ASC',
337
-                'TKT_end_date'           => 'ASC',
338
-                'Datetime.DTT_EVT_start' => 'DESC',
339
-            ),
340
-        );
341
-        if (
342
-            ! (
343
-                EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config
344
-                && EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector->show_expired_tickets
345
-            )
346
-        ) {
347
-            //use the correct applicable time query depending on what version of core is being run.
348
-            $current_time = method_exists('EEM_Datetime', 'current_time_for_query')
349
-                ? time()
350
-                : current_time('timestamp');
351
-            $ticket_query_args[0]['TKT_end_date'] = array('>', $current_time);
352
-        }
353
-        return EEM_Ticket::instance()->get_all($ticket_query_args);
354
-    }
355
-
356
-
357
-
358
-    /**
359
-     * loadTicketSelector
360
-     * begins to assemble template arguments
361
-     * and decides whether to load a "simple" ticket selector, or the standard
362
-     *
363
-     * @param \EE_Ticket[] $tickets
364
-     * @param array $template_args
365
-     * @return string
366
-     * @throws EE_Error
367
-     */
368
-    protected function loadTicketSelector(array $tickets, array $template_args)
369
-    {
370
-        $template_args['event'] = $this->event;
371
-        $template_args['EVT_ID'] = $this->event->ID();
372
-        $template_args['event_is_expired'] = $this->event->is_expired();
373
-        $template_args['max_atndz'] = $this->getMaxAttendees();
374
-        $template_args['date_format'] = $this->date_format;
375
-        $template_args['time_format'] = $this->time_format;
376
-        /**
377
-         * Filters the anchor ID used when redirecting to the Ticket Selector if no quantity selected
378
-         *
379
-         * @since 4.9.13
380
-         * @param     string  '#tkt-slctr-tbl-' . $EVT_ID The html ID to anchor to
381
-         * @param int $EVT_ID The Event ID
382
-         */
383
-        $template_args['anchor_id'] = apply_filters(
384
-            'FHEE__EE_Ticket_Selector__redirect_anchor_id',
385
-            '#tkt-slctr-tbl-' . $this->event->ID(),
386
-            $this->event->ID()
387
-        );
388
-        $template_args['tickets'] = $tickets;
389
-        $template_args['ticket_count'] = count($tickets);
390
-        $ticket_selector = $this->simpleTicketSelector( $tickets, $template_args);
391
-        return $ticket_selector instanceof TicketSelectorSimple
392
-            ? $ticket_selector
393
-            : new TicketSelectorStandard(
394
-                $this->event,
395
-                $tickets,
396
-                $this->getMaxAttendees(),
397
-                $template_args,
398
-                $this->date_format,
399
-                $this->time_format
400
-            );
401
-    }
402
-
403
-
404
-
405
-    /**
406
-     * simpleTicketSelector
407
-     * there's one ticket, and max attendees is set to one,
408
-     * so if the event is free, then this is a "simple" ticket selector
409
-     * a.k.a. "Dude Where's my Ticket Selector?"
410
-     *
411
-     * @param \EE_Ticket[] $tickets
412
-     * @param array  $template_args
413
-     * @return string
414
-     * @throws EE_Error
415
-     */
416
-    protected function simpleTicketSelector($tickets, array $template_args)
417
-    {
418
-        // if there is only ONE ticket with a max qty of ONE
419
-        if (count($tickets) > 1 || $this->getMaxAttendees() !== 1) {
420
-            return '';
421
-        }
422
-        /** @var \EE_Ticket $ticket */
423
-        $ticket = reset($tickets);
424
-        // if the ticket is free... then not much need for the ticket selector
425
-        if (
426
-            apply_filters(
427
-                'FHEE__ticket_selector_chart_template__hide_ticket_selector',
428
-                $ticket->is_free(),
429
-                $this->event->ID()
430
-            )
431
-        ) {
432
-            return new TicketSelectorSimple(
433
-                $this->event,
434
-                $ticket,
435
-                $this->getMaxAttendees(),
436
-                $template_args
437
-            );
438
-        }
439
-        return '';
440
-    }
441
-
442
-
443
-
444
-    /**
445
-     * externalEventRegistration
446
-     *
447
-     * @return string
448
-     */
449
-    public function externalEventRegistration()
450
-    {
451
-        // if not we still need to trigger the display of the submit button
452
-        add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
453
-        //display notice to admin that registration is external
454
-        return is_admin()
455
-            ? esc_html__(
456
-                'Registration is at an external URL for this event.',
457
-                'event_espresso'
458
-            )
459
-            : '';
460
-    }
461
-
462
-
463
-
464
-    /**
465
-     * formOpen
466
-     *
467
-     * @param        int    $ID
468
-     * @param        string $external_url
469
-     * @return        string
470
-     */
471
-    public function formOpen( $ID = 0, $external_url = '' )
472
-    {
473
-        // if redirecting, we don't need any anything else
474
-        if ( $external_url ) {
475
-            $html = '<form method="GET" action="' . EEH_URL::refactor_url($external_url) . '"';
476
-            // open link in new window ?
477
-            $html .= apply_filters(
478
-                'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__formOpen__external_url_target_blank',
479
-                EED_Events_Archive::is_iframe()
480
-            )
481
-                ? ' target="_blank"'
482
-                : '';
483
-            $html .= '>';
484
-            $query_args = EEH_URL::get_query_string( $external_url );
485
-            foreach ( (array)$query_args as $query_arg => $value ) {
486
-                $html .= '<input type="hidden" name="' . $query_arg . '" value="' . $value . '">';
487
-            }
488
-            return $html;
489
-        }
490
-        // if there is no submit button, then don't start building a form
491
-        // because the "View Details" button will build its own form
492
-        if ( ! apply_filters( 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false ) ) {
493
-            return '';
494
-        }
495
-        $checkout_url = EEH_Event_View::event_link_url( $ID );
496
-        if ( ! $checkout_url ) {
497
-            EE_Error::add_error(
498
-                esc_html__( 'The URL for the Event Details page could not be retrieved.', 'event_espresso' ),
499
-                __FILE__,
500
-                __FUNCTION__,
501
-                __LINE__
502
-            );
503
-        }
504
-        // set no cache headers and constants
505
-        EE_System::do_not_cache();
506
-        $extra_params = $this->iframe ? ' target="_blank"' : '';
507
-        $html = '<form method="POST" action="' . $checkout_url . '"' . $extra_params . '>';
508
-        $html .= '<input type="hidden" name="ee" value="process_ticket_selections">';
509
-        $html = apply_filters( 'FHEE__EE_Ticket_Selector__ticket_selector_form_open__html', $html, $this->event );
510
-        return $html;
511
-    }
512
-
513
-
514
-
515
-    /**
516
-     * displaySubmitButton
517
-     *
518
-     * @param  string $external_url
519
-     * @return string
520
-     * @throws EE_Error
521
-     */
522
-    public function displaySubmitButton($external_url = '')
523
-    {
524
-        $html = '';
525
-        if ( ! is_admin()) {
526
-            // standard TS displayed with submit button, ie: "Register Now"
527
-            if (apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) {
528
-                $html .= $this->displayRegisterNowButton();
529
-                $html .= empty($external_url)
530
-                    ? $this->ticketSelectorEndDiv()
531
-                    : $this->clearTicketSelector();
532
-                $html .= '<br/>' . $this->formClose();
533
-            } else if ($this->getMaxAttendees() === 1) {
534
-                // its a "Dude Where's my Ticket Selector?" (DWMTS) type event (ie: $_max_atndz === 1)
535
-                if ($this->event->is_sold_out()) {
536
-                    // then instead of a View Details or Submit button, just display a "Sold Out" message
537
-                    $html .= apply_filters(
538
-                        'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__sold_out_msg',
539
-                        sprintf(
540
-                            __(
541
-                                '%1$s"%2$s" is currently sold out.%4$sPlease check back again later, as spots may become available.%3$s',
542
-                                'event_espresso'
543
-                            ),
544
-                            '<p class="no-ticket-selector-msg clear-float">',
545
-                            $this->event->name(),
546
-                            '</p>',
547
-                            '<br />'
548
-                        ),
549
-                        $this->event
550
-                    );
551
-                    if (
552
-                        apply_filters(
553
-                            'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
554
-                            false,
555
-                            $this->event
556
-                        )
557
-                    ) {
558
-                        $html .= $this->displayRegisterNowButton();
559
-                    }
560
-                    // sold out DWMTS event, no TS, no submit or view details button, but has additional content
561
-                    $html .=  $this->ticketSelectorEndDiv();
562
-                } else if (
563
-                    apply_filters('FHEE__EE_Ticket_Selector__hide_ticket_selector', false)
564
-                    && ! is_single()
565
-                ) {
566
-                    // this is a "Dude Where's my Ticket Selector?" (DWMTS) type event,
567
-                    // but no tickets are available, so display event's "View Details" button.
568
-                    // it is being viewed via somewhere other than a single post
569
-                    $html .= $this->displayViewDetailsButton(true);
570
-                } else {
571
-                    $html .= $this->ticketSelectorEndDiv();
572
-                }
573
-            } else if (is_archive()) {
574
-                // event list, no tickets available so display event's "View Details" button
575
-                $html .= $this->ticketSelectorEndDiv();
576
-                $html .= $this->displayViewDetailsButton();
577
-            } else {
578
-                if (
579
-                    apply_filters(
580
-                        'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
581
-                        false,
582
-                        $this->event
583
-                    )
584
-                ) {
585
-                    $html .= $this->displayRegisterNowButton();
586
-                }
587
-                // no submit or view details button, and no additional content
588
-                $html .= $this->ticketSelectorEndDiv();
589
-            }
590
-            if ( ! $this->iframe && ! is_archive()) {
591
-                $html .= EEH_Template::powered_by_event_espresso('', '', array('utm_content' => 'ticket_selector'));
592
-            }
593
-        }
594
-	    return apply_filters(
595
-		    'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displaySubmitButton__html',
596
-		    $html,
597
-		    $this->event
598
-	    );
599
-    }
600
-
601
-
602
-
603
-    /**
604
-     * @return string
605
-     * @throws EE_Error
606
-     */
607
-    public function displayRegisterNowButton()
608
-    {
609
-        $btn_text = apply_filters(
610
-            'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__btn_text',
611
-            __('Register Now', 'event_espresso'),
612
-            $this->event
613
-        );
614
-        $external_url = $this->event->external_url();
615
-        $html = EEH_HTML::div(
616
-            '', 'ticket-selector-submit-' . $this->event->ID() . '-btn-wrap', 'ticket-selector-submit-btn-wrap'
617
-        );
618
-        $html .= '<input id="ticket-selector-submit-' . $this->event->ID() . '-btn"';
619
-        $html .= ' class="ticket-selector-submit-btn ';
620
-        $html .= empty($external_url) ? 'ticket-selector-submit-ajax"' : '"';
621
-        $html .= ' type="submit" value="' . $btn_text . '" />';
622
-        $html .= EEH_HTML::divx() . '<!-- .ticket-selector-submit-btn-wrap -->';
623
-        $html .= apply_filters(
624
-            'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
625
-            '',
626
-            $this->event
627
-        );
628
-        return $html;
629
-    }
630
-
631
-
632
-    /**
633
-     * displayViewDetailsButton
634
-     *
635
-     * @param bool $DWMTS indicates a "Dude Where's my Ticket Selector?" (DWMTS) type event
636
-     *                    (ie: $_max_atndz === 1) where there are no available tickets,
637
-     *                    either because they are sold out, expired, or not yet on sale.
638
-     *                    In this case, we need to close the form BEFORE adding any closing divs
639
-     * @return string
640
-     * @throws EE_Error
641
-     */
642
-    public function displayViewDetailsButton( $DWMTS = false )
643
-    {
644
-        if ( ! $this->event->get_permalink() ) {
645
-            EE_Error::add_error(
646
-                esc_html__( 'The URL for the Event Details page could not be retrieved.', 'event_espresso' ),
647
-                __FILE__, __FUNCTION__, __LINE__
648
-            );
649
-        }
650
-        $view_details_btn = '<form method="POST" action="';
651
-        $view_details_btn .= apply_filters(
652
-            'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_url',
653
-            $this->event->get_permalink(),
654
-            $this->event
655
-        );
656
-        $view_details_btn .= '"';
657
-        // open link in new window ?
658
-        $view_details_btn .= apply_filters(
659
-            'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displayViewDetailsButton__url_target_blank',
660
-            EED_Events_Archive::is_iframe()
661
-        )
662
-            ? ' target="_blank"'
663
-            : '';
664
-        $view_details_btn .='>';
665
-        $btn_text = apply_filters(
666
-            'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_text',
667
-            esc_html__('View Details', 'event_espresso'),
668
-            $this->event
669
-        );
670
-        $view_details_btn .= '<input id="ticket-selector-submit-'
671
-                             . $this->event->ID()
672
-                             . '-btn" class="ticket-selector-submit-btn view-details-btn" type="submit" value="'
673
-                             . $btn_text
674
-                             . '" />';
675
-        $view_details_btn .= apply_filters( 'FHEE__EE_Ticket_Selector__after_view_details_btn', '', $this->event );
676
-        if ($DWMTS) {
677
-            $view_details_btn .= $this->formClose();
678
-            $view_details_btn .= $this->ticketSelectorEndDiv();
679
-            $view_details_btn .= '<br/>';
680
-        } else {
681
-            $view_details_btn .= $this->clearTicketSelector();
682
-            $view_details_btn .= '<br/>';
683
-            $view_details_btn .= $this->formClose();
684
-        }
685
-        return $view_details_btn;
686
-    }
687
-
688
-
689
-
690
-    /**
691
-     * @return string
692
-     */
693
-    public function ticketSelectorEndDiv()
694
-    {
695
-        return $this->clearTicketSelector() . '</div><!-- ticketSelectorEndDiv -->';
696
-    }
697
-
698
-
699
-
700
-    /**
701
-     * @return string
702
-     */
703
-    public function clearTicketSelector()
704
-    {
705
-        // standard TS displayed, appears after a "Register Now" or "view Details" button
706
-        return '<div class="clear"></div><!-- clearTicketSelector -->';
707
-    }
708
-
709
-
710
-
711
-    /**
712
-     * @access        public
713
-     * @return        string
714
-     */
715
-    public function formClose()
716
-    {
717
-        return '</form>';
718
-    }
289
+	}
290
+
291
+
292
+
293
+	/**
294
+	 * ticketSalesClosed
295
+	 * notice displayed if event ticket sales are turned off
296
+	 *
297
+	 * @return string
298
+	 * @throws EE_Error
299
+	 */
300
+	protected function ticketSalesClosedMessage()
301
+	{
302
+		$sales_closed_msg = esc_html__(
303
+			'We\'re sorry, but ticket sales have been closed at this time. Please check back again later.',
304
+			'event_espresso'
305
+		);
306
+		if (current_user_can('edit_post', $this->event->ID())) {
307
+			$sales_closed_msg .= sprintf(
308
+				esc_html__(
309
+					'%sNote to Event Admin:%sThe "Maximum number of tickets allowed per order for this event" in the Event Registration Options has been set to "0". This effectively turns off ticket sales. %s(click to edit this event)%s',
310
+					'event_espresso'
311
+				),
312
+				'<div class="ee-attention" style="text-align: left;"><b>',
313
+				'</b><br />',
314
+				'<span class="edit-link"><a class="post-edit-link" href="'.get_edit_post_link($this->event->ID()).'">',
315
+				'</a></span></div><!-- .ee-attention ticketSalesClosedMessage -->'
316
+			);
317
+		}
318
+		return '<p><span class="important-notice">' . $sales_closed_msg . '</span></p>';
319
+	}
320
+
321
+
322
+
323
+	/**
324
+	 * getTickets
325
+	 *
326
+	 * @return \EE_Base_Class[]|\EE_Ticket[]
327
+	 * @throws EE_Error
328
+	 */
329
+	protected function getTickets()
330
+	{
331
+		$ticket_query_args = array(
332
+			array('Datetime.EVT_ID' => $this->event->ID()),
333
+			'order_by' => array(
334
+				'TKT_order'              => 'ASC',
335
+				'TKT_required'           => 'DESC',
336
+				'TKT_start_date'         => 'ASC',
337
+				'TKT_end_date'           => 'ASC',
338
+				'Datetime.DTT_EVT_start' => 'DESC',
339
+			),
340
+		);
341
+		if (
342
+			! (
343
+				EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config
344
+				&& EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector->show_expired_tickets
345
+			)
346
+		) {
347
+			//use the correct applicable time query depending on what version of core is being run.
348
+			$current_time = method_exists('EEM_Datetime', 'current_time_for_query')
349
+				? time()
350
+				: current_time('timestamp');
351
+			$ticket_query_args[0]['TKT_end_date'] = array('>', $current_time);
352
+		}
353
+		return EEM_Ticket::instance()->get_all($ticket_query_args);
354
+	}
355
+
356
+
357
+
358
+	/**
359
+	 * loadTicketSelector
360
+	 * begins to assemble template arguments
361
+	 * and decides whether to load a "simple" ticket selector, or the standard
362
+	 *
363
+	 * @param \EE_Ticket[] $tickets
364
+	 * @param array $template_args
365
+	 * @return string
366
+	 * @throws EE_Error
367
+	 */
368
+	protected function loadTicketSelector(array $tickets, array $template_args)
369
+	{
370
+		$template_args['event'] = $this->event;
371
+		$template_args['EVT_ID'] = $this->event->ID();
372
+		$template_args['event_is_expired'] = $this->event->is_expired();
373
+		$template_args['max_atndz'] = $this->getMaxAttendees();
374
+		$template_args['date_format'] = $this->date_format;
375
+		$template_args['time_format'] = $this->time_format;
376
+		/**
377
+		 * Filters the anchor ID used when redirecting to the Ticket Selector if no quantity selected
378
+		 *
379
+		 * @since 4.9.13
380
+		 * @param     string  '#tkt-slctr-tbl-' . $EVT_ID The html ID to anchor to
381
+		 * @param int $EVT_ID The Event ID
382
+		 */
383
+		$template_args['anchor_id'] = apply_filters(
384
+			'FHEE__EE_Ticket_Selector__redirect_anchor_id',
385
+			'#tkt-slctr-tbl-' . $this->event->ID(),
386
+			$this->event->ID()
387
+		);
388
+		$template_args['tickets'] = $tickets;
389
+		$template_args['ticket_count'] = count($tickets);
390
+		$ticket_selector = $this->simpleTicketSelector( $tickets, $template_args);
391
+		return $ticket_selector instanceof TicketSelectorSimple
392
+			? $ticket_selector
393
+			: new TicketSelectorStandard(
394
+				$this->event,
395
+				$tickets,
396
+				$this->getMaxAttendees(),
397
+				$template_args,
398
+				$this->date_format,
399
+				$this->time_format
400
+			);
401
+	}
402
+
403
+
404
+
405
+	/**
406
+	 * simpleTicketSelector
407
+	 * there's one ticket, and max attendees is set to one,
408
+	 * so if the event is free, then this is a "simple" ticket selector
409
+	 * a.k.a. "Dude Where's my Ticket Selector?"
410
+	 *
411
+	 * @param \EE_Ticket[] $tickets
412
+	 * @param array  $template_args
413
+	 * @return string
414
+	 * @throws EE_Error
415
+	 */
416
+	protected function simpleTicketSelector($tickets, array $template_args)
417
+	{
418
+		// if there is only ONE ticket with a max qty of ONE
419
+		if (count($tickets) > 1 || $this->getMaxAttendees() !== 1) {
420
+			return '';
421
+		}
422
+		/** @var \EE_Ticket $ticket */
423
+		$ticket = reset($tickets);
424
+		// if the ticket is free... then not much need for the ticket selector
425
+		if (
426
+			apply_filters(
427
+				'FHEE__ticket_selector_chart_template__hide_ticket_selector',
428
+				$ticket->is_free(),
429
+				$this->event->ID()
430
+			)
431
+		) {
432
+			return new TicketSelectorSimple(
433
+				$this->event,
434
+				$ticket,
435
+				$this->getMaxAttendees(),
436
+				$template_args
437
+			);
438
+		}
439
+		return '';
440
+	}
441
+
442
+
443
+
444
+	/**
445
+	 * externalEventRegistration
446
+	 *
447
+	 * @return string
448
+	 */
449
+	public function externalEventRegistration()
450
+	{
451
+		// if not we still need to trigger the display of the submit button
452
+		add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
453
+		//display notice to admin that registration is external
454
+		return is_admin()
455
+			? esc_html__(
456
+				'Registration is at an external URL for this event.',
457
+				'event_espresso'
458
+			)
459
+			: '';
460
+	}
461
+
462
+
463
+
464
+	/**
465
+	 * formOpen
466
+	 *
467
+	 * @param        int    $ID
468
+	 * @param        string $external_url
469
+	 * @return        string
470
+	 */
471
+	public function formOpen( $ID = 0, $external_url = '' )
472
+	{
473
+		// if redirecting, we don't need any anything else
474
+		if ( $external_url ) {
475
+			$html = '<form method="GET" action="' . EEH_URL::refactor_url($external_url) . '"';
476
+			// open link in new window ?
477
+			$html .= apply_filters(
478
+				'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__formOpen__external_url_target_blank',
479
+				EED_Events_Archive::is_iframe()
480
+			)
481
+				? ' target="_blank"'
482
+				: '';
483
+			$html .= '>';
484
+			$query_args = EEH_URL::get_query_string( $external_url );
485
+			foreach ( (array)$query_args as $query_arg => $value ) {
486
+				$html .= '<input type="hidden" name="' . $query_arg . '" value="' . $value . '">';
487
+			}
488
+			return $html;
489
+		}
490
+		// if there is no submit button, then don't start building a form
491
+		// because the "View Details" button will build its own form
492
+		if ( ! apply_filters( 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false ) ) {
493
+			return '';
494
+		}
495
+		$checkout_url = EEH_Event_View::event_link_url( $ID );
496
+		if ( ! $checkout_url ) {
497
+			EE_Error::add_error(
498
+				esc_html__( 'The URL for the Event Details page could not be retrieved.', 'event_espresso' ),
499
+				__FILE__,
500
+				__FUNCTION__,
501
+				__LINE__
502
+			);
503
+		}
504
+		// set no cache headers and constants
505
+		EE_System::do_not_cache();
506
+		$extra_params = $this->iframe ? ' target="_blank"' : '';
507
+		$html = '<form method="POST" action="' . $checkout_url . '"' . $extra_params . '>';
508
+		$html .= '<input type="hidden" name="ee" value="process_ticket_selections">';
509
+		$html = apply_filters( 'FHEE__EE_Ticket_Selector__ticket_selector_form_open__html', $html, $this->event );
510
+		return $html;
511
+	}
512
+
513
+
514
+
515
+	/**
516
+	 * displaySubmitButton
517
+	 *
518
+	 * @param  string $external_url
519
+	 * @return string
520
+	 * @throws EE_Error
521
+	 */
522
+	public function displaySubmitButton($external_url = '')
523
+	{
524
+		$html = '';
525
+		if ( ! is_admin()) {
526
+			// standard TS displayed with submit button, ie: "Register Now"
527
+			if (apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) {
528
+				$html .= $this->displayRegisterNowButton();
529
+				$html .= empty($external_url)
530
+					? $this->ticketSelectorEndDiv()
531
+					: $this->clearTicketSelector();
532
+				$html .= '<br/>' . $this->formClose();
533
+			} else if ($this->getMaxAttendees() === 1) {
534
+				// its a "Dude Where's my Ticket Selector?" (DWMTS) type event (ie: $_max_atndz === 1)
535
+				if ($this->event->is_sold_out()) {
536
+					// then instead of a View Details or Submit button, just display a "Sold Out" message
537
+					$html .= apply_filters(
538
+						'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__sold_out_msg',
539
+						sprintf(
540
+							__(
541
+								'%1$s"%2$s" is currently sold out.%4$sPlease check back again later, as spots may become available.%3$s',
542
+								'event_espresso'
543
+							),
544
+							'<p class="no-ticket-selector-msg clear-float">',
545
+							$this->event->name(),
546
+							'</p>',
547
+							'<br />'
548
+						),
549
+						$this->event
550
+					);
551
+					if (
552
+						apply_filters(
553
+							'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
554
+							false,
555
+							$this->event
556
+						)
557
+					) {
558
+						$html .= $this->displayRegisterNowButton();
559
+					}
560
+					// sold out DWMTS event, no TS, no submit or view details button, but has additional content
561
+					$html .=  $this->ticketSelectorEndDiv();
562
+				} else if (
563
+					apply_filters('FHEE__EE_Ticket_Selector__hide_ticket_selector', false)
564
+					&& ! is_single()
565
+				) {
566
+					// this is a "Dude Where's my Ticket Selector?" (DWMTS) type event,
567
+					// but no tickets are available, so display event's "View Details" button.
568
+					// it is being viewed via somewhere other than a single post
569
+					$html .= $this->displayViewDetailsButton(true);
570
+				} else {
571
+					$html .= $this->ticketSelectorEndDiv();
572
+				}
573
+			} else if (is_archive()) {
574
+				// event list, no tickets available so display event's "View Details" button
575
+				$html .= $this->ticketSelectorEndDiv();
576
+				$html .= $this->displayViewDetailsButton();
577
+			} else {
578
+				if (
579
+					apply_filters(
580
+						'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
581
+						false,
582
+						$this->event
583
+					)
584
+				) {
585
+					$html .= $this->displayRegisterNowButton();
586
+				}
587
+				// no submit or view details button, and no additional content
588
+				$html .= $this->ticketSelectorEndDiv();
589
+			}
590
+			if ( ! $this->iframe && ! is_archive()) {
591
+				$html .= EEH_Template::powered_by_event_espresso('', '', array('utm_content' => 'ticket_selector'));
592
+			}
593
+		}
594
+		return apply_filters(
595
+			'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displaySubmitButton__html',
596
+			$html,
597
+			$this->event
598
+		);
599
+	}
600
+
601
+
602
+
603
+	/**
604
+	 * @return string
605
+	 * @throws EE_Error
606
+	 */
607
+	public function displayRegisterNowButton()
608
+	{
609
+		$btn_text = apply_filters(
610
+			'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__btn_text',
611
+			__('Register Now', 'event_espresso'),
612
+			$this->event
613
+		);
614
+		$external_url = $this->event->external_url();
615
+		$html = EEH_HTML::div(
616
+			'', 'ticket-selector-submit-' . $this->event->ID() . '-btn-wrap', 'ticket-selector-submit-btn-wrap'
617
+		);
618
+		$html .= '<input id="ticket-selector-submit-' . $this->event->ID() . '-btn"';
619
+		$html .= ' class="ticket-selector-submit-btn ';
620
+		$html .= empty($external_url) ? 'ticket-selector-submit-ajax"' : '"';
621
+		$html .= ' type="submit" value="' . $btn_text . '" />';
622
+		$html .= EEH_HTML::divx() . '<!-- .ticket-selector-submit-btn-wrap -->';
623
+		$html .= apply_filters(
624
+			'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
625
+			'',
626
+			$this->event
627
+		);
628
+		return $html;
629
+	}
630
+
631
+
632
+	/**
633
+	 * displayViewDetailsButton
634
+	 *
635
+	 * @param bool $DWMTS indicates a "Dude Where's my Ticket Selector?" (DWMTS) type event
636
+	 *                    (ie: $_max_atndz === 1) where there are no available tickets,
637
+	 *                    either because they are sold out, expired, or not yet on sale.
638
+	 *                    In this case, we need to close the form BEFORE adding any closing divs
639
+	 * @return string
640
+	 * @throws EE_Error
641
+	 */
642
+	public function displayViewDetailsButton( $DWMTS = false )
643
+	{
644
+		if ( ! $this->event->get_permalink() ) {
645
+			EE_Error::add_error(
646
+				esc_html__( 'The URL for the Event Details page could not be retrieved.', 'event_espresso' ),
647
+				__FILE__, __FUNCTION__, __LINE__
648
+			);
649
+		}
650
+		$view_details_btn = '<form method="POST" action="';
651
+		$view_details_btn .= apply_filters(
652
+			'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_url',
653
+			$this->event->get_permalink(),
654
+			$this->event
655
+		);
656
+		$view_details_btn .= '"';
657
+		// open link in new window ?
658
+		$view_details_btn .= apply_filters(
659
+			'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displayViewDetailsButton__url_target_blank',
660
+			EED_Events_Archive::is_iframe()
661
+		)
662
+			? ' target="_blank"'
663
+			: '';
664
+		$view_details_btn .='>';
665
+		$btn_text = apply_filters(
666
+			'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_text',
667
+			esc_html__('View Details', 'event_espresso'),
668
+			$this->event
669
+		);
670
+		$view_details_btn .= '<input id="ticket-selector-submit-'
671
+							 . $this->event->ID()
672
+							 . '-btn" class="ticket-selector-submit-btn view-details-btn" type="submit" value="'
673
+							 . $btn_text
674
+							 . '" />';
675
+		$view_details_btn .= apply_filters( 'FHEE__EE_Ticket_Selector__after_view_details_btn', '', $this->event );
676
+		if ($DWMTS) {
677
+			$view_details_btn .= $this->formClose();
678
+			$view_details_btn .= $this->ticketSelectorEndDiv();
679
+			$view_details_btn .= '<br/>';
680
+		} else {
681
+			$view_details_btn .= $this->clearTicketSelector();
682
+			$view_details_btn .= '<br/>';
683
+			$view_details_btn .= $this->formClose();
684
+		}
685
+		return $view_details_btn;
686
+	}
687
+
688
+
689
+
690
+	/**
691
+	 * @return string
692
+	 */
693
+	public function ticketSelectorEndDiv()
694
+	{
695
+		return $this->clearTicketSelector() . '</div><!-- ticketSelectorEndDiv -->';
696
+	}
697
+
698
+
699
+
700
+	/**
701
+	 * @return string
702
+	 */
703
+	public function clearTicketSelector()
704
+	{
705
+		// standard TS displayed, appears after a "Register Now" or "view Details" button
706
+		return '<div class="clear"></div><!-- clearTicketSelector -->';
707
+	}
708
+
709
+
710
+
711
+	/**
712
+	 * @access        public
713
+	 * @return        string
714
+	 */
715
+	public function formClose()
716
+	{
717
+		return '</form>';
718
+	}
719 719
 
720 720
 
721 721
 
Please login to merge, or discard this patch.
core/domain/entities/shortcodes/EspressoEventAttendees.php 2 patches
Indentation   +260 added lines, -260 removed lines patch added patch discarded remove patch
@@ -29,266 +29,266 @@
 block discarded – undo
29 29
 class EspressoEventAttendees extends EspressoShortcode
30 30
 {
31 31
 
32
-    private $query_params = array(
33
-        0 => array()
34
-    );
35
-
36
-    private $template_args = array(
37
-        'contacts'      => array(),
38
-        'event'         => null,
39
-        'datetime'      => null,
40
-        'ticket'        => null,
41
-    );
42
-
43
-    /**
44
-     * the actual shortcode tag that gets registered with WordPress
45
-     *
46
-     * @return string
47
-     */
48
-    public function getTag()
49
-    {
50
-        return 'ESPRESSO_EVENT_ATTENDEES';
51
-    }
52
-
53
-
54
-
55
-    /**
56
-     * the time in seconds to cache the results of the processShortcode() method
57
-     * 0 means the processShortcode() results will NOT be cached at all
58
-     *
59
-     * @return int
60
-     */
61
-    public function cacheExpiration()
62
-    {
63
-        return 0;
64
-    }
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
-    /**
83
-     * process_shortcode - ESPRESSO_EVENT_ATTENDEES - Returns a list of attendees to an event.
84
-     *  [ESPRESSO_EVENT_ATTENDEES]
85
-     *  - defaults to attendees for earliest active event, or earliest upcoming event.
86
-     *
87
-     *  [ESPRESSO_EVENT_ATTENDEES event_id=123]
88
-     *  - attendees for specific event.
89
-     *
90
-     *  [ESPRESSO_EVENT_ATTENDEES datetime_id=245]
91
-     *  - attendees for a specific datetime.
92
-     *
93
-     *  [ESPRESSO_EVENT_ATTENDEES ticket_id=123]
94
-     *  - attendees for a specific ticket.
95
-     *
96
-     *  [ESPRESSO_EVENT_ATTENDEES status=all]
97
-     *  - specific registration status (use status id) or all for all attendees regardless of status.
98
-     *  Note default is to only return approved attendees
99
-     *
100
-     *  [ESPRESSO_EVENT_ATTENDEES show_gravatar=true]
101
-     *  - default is to not return gravatar.  Otherwise if this is set then return gravatar for email address given.
102
-     *
103
-     *  [ESPRESSO_EVENT_ATTENDEES display_on_archives=true]
104
-     *  - default is to not display attendees list on archive pages.
105
-     *
106
-     * Note: because of the relationship between event_id, ticket_id, and datetime_id:
107
-     * If more than one of those params is included, then preference is given to the following:
108
-     *  - event_id is used whenever its present and any others are ignored.
109
-     *  - if no event_id then datetime is used whenever its present and any others are ignored.
110
-     *  - otherwise ticket_id is used if present.
111
-     *
112
-     * @param array $attributes
113
-     * @return string
114
-     * @throws EE_Error
115
-     */
116
-    public function processShortcode($attributes = array())
117
-    {
118
-        // grab attributes and merge with defaults
119
-        $attributes = $this->getAttributes((array)$attributes);
120
-        $archive = is_archive();
121
-        $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN);
122
-        // don't display on archives unless 'display_on_archives' is true
123
-        if($archive && ! $display_on_archives) {
124
-            return '';
125
-        }
126
-        // add attributes to template args
127
-        $this->template_args['show_gravatar'] = $attributes['show_gravatar'];
128
-        // add required objects: event, datetime, and ticket
129
-        $this->template_args['event'] = $this->getEventAndQueryParams($attributes);
130
-        $this->template_args['datetime'] = $this->getDatetimeAndQueryParams($attributes);
131
-        $this->template_args['ticket'] = $this->getTicketAndQueryParams($attributes);
132
-
133
-        // if any of the above objects is invalid or missing,
134
-        // then there was an invalid parameter or the shortcode was used incorrectly
135
-        // so when WP_DEBUG is set and true, we'll show a message,
136
-        // otherwise we'll just return an empty string.
137
-         if (
138
-            ! $this->template_args['event'] instanceof EE_Event
139
-            || empty($this->query_params[0])
140
-            || ($attributes['datetime_id'] && ! $this->template_args['datetime'] instanceof EE_Datetime)
141
-            || ($attributes['ticket_id'] && ! $this->template_args['ticket'] instanceof EE_Ticket)
142
-        ) {
143
-            if (WP_DEBUG) {
144
-                return '<div class="important-notice ee-attention">'
145
-                       . esc_html__('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.',
146
-                        'event_espresso')
147
-                       . '</div>';
148
-            }
149
-             return '';
150
-        }
151
-        $this->setAdditionalQueryParams($attributes);
152
-        //get contacts!
153
-        $this->template_args['contacts'] = EEM_Attendee::instance()->get_all($this->query_params);
154
-        //all set let's load up the template and return.
155
-        return EEH_Template::locate_template(
156
-            'loop-espresso_event_attendees.php',
157
-            $this->template_args
158
-        );
159
-
160
-    }
161
-
162
-
163
-
164
-    /**
165
-     * merge incoming attributes with filtered defaults
166
-     *
167
-     * @param array $attributes
168
-     * @return array
169
-     */
170
-    private function getAttributes(array $attributes)
171
-    {
172
-        return (array) apply_filters(
173
-            'EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts',
174
-            $attributes + array(
175
-                'event_id'            => null,
176
-                'datetime_id'         => null,
177
-                'ticket_id'           => null,
178
-                'status'              => EEM_Registration::status_id_approved,
179
-                'show_gravatar'       => false,
180
-                'display_on_archives' => false,
181
-            )
182
-        );
183
-    }
184
-
185
-
186
-
187
-    /**
188
-     * @param array $attributes
189
-     * @return EE_Event|null
190
-     * @throws EE_Error
191
-     */
192
-    private function getEventAndQueryParams(array $attributes){
193
-        if ( ! empty($attributes['event_id'])) {
194
-            $event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']);
195
-            if ($event instanceof EE_Event) {
196
-                $this->query_params[0]['Registration.EVT_ID'] = $attributes['event_id'];
197
-                return $event;
198
-            }
199
-        }
200
-        if (is_espresso_event()) {
201
-            $event = EEH_Event_View::get_event();
202
-            if ($event instanceof EE_Event) {
203
-                $this->query_params[0]['Registration.EVT_ID'] = $event->ID();
204
-                return $event;
205
-            }
206
-        }
207
-        // one last shot...
208
-        // try getting the earliest active event
209
-        $events = EEM_Event::instance()->get_active_events(array(
210
-            'limit'    => 1,
211
-            'order_by' => array('Datetime.DTT_EVT_start' => 'ASC')
212
-        ));
213
-        //  if none then get the next upcoming
214
-        $events = empty($events)
215
-            ? EEM_Event::instance()->get_upcoming_events(array(
216
-                'limit'    => 1,
217
-                'order_by' => array('Datetime.DTT_EVT_start' => 'ASC')
218
-            ))
219
-            : $events;
220
-        $event = reset($events);
221
-        if ($event instanceof EE_Event) {
222
-            $this->query_params[0]['Registration.EVT_ID'] = $event->ID();
223
-            return $event;
224
-        }
225
-        return null;
226
-    }
227
-
228
-
229
-
230
-    /**
231
-     * @param array $attributes
232
-     * @return EE_Datetime|null
233
-     */
234
-    private function getDatetimeAndQueryParams(array $attributes)
235
-    {
236
-        if ( ! empty($attributes['datetime_id'])) {
237
-            $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']);
238
-            if ($datetime instanceof EE_Datetime) {
239
-                $this->query_params[0]['Registration.Ticket.Datetime.DTT_ID'] = $attributes['datetime_id'];
240
-                $this->query_params['default_where_conditions'] = 'this_model_only';
241
-                if ( ! $this->template_args['event'] instanceof EE_Event) {
242
-                    $this->template_args['event'] = $datetime->event();
243
-                }
244
-                return $datetime;
245
-            }
246
-        }
247
-        return null;
248
-    }
249
-
250
-
251
-
252
-    /**
253
-     * @param array $attributes
254
-     * @return \EE_Base_Class|null
255
-     * @throws EE_Error
256
-     */
257
-    private function getTicketAndQueryParams(array $attributes)
258
-    {
259
-        if ( ! empty($attributes['ticket_id']) && empty($attributes['event_id']) && empty($attributes['datetime_id'])) {
260
-            $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']);
261
-            if ($ticket instanceof EE_Ticket) {
262
-                $this->query_params[0]['Registration.TKT_ID'] = $attributes['ticket_id'];
263
-                if ( ! $this->template_args['event'] instanceof EE_Event) {
264
-                    $this->template_args['event'] = $ticket->first_datetime() instanceof EE_Datetime
265
-                        ? $ticket->first_datetime()->event()
266
-                        : null;
267
-                }
268
-                return $ticket;
269
-            }
270
-        }
271
-        return null;
272
-    }
273
-
274
-
275
-
276
-    /**
277
-     * @param array $attributes
278
-     * @throws EE_Error
279
-     */
280
-    private function setAdditionalQueryParams(array $attributes)
281
-    {
282
-        $reg_status_array = EEM_Registration::reg_status_array();
283
-        if ($attributes['status'] !== 'all' && isset($reg_status_array[$attributes['status']])) {
284
-            $this->query_params[0]['Registration.STS_ID'] = $attributes['status'];
285
-        }
286
-        $this->query_params['group_by'] = array('ATT_ID');
287
-        $this->query_params['order_by'] = (array) apply_filters(
288
-            'FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by',
289
-            array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC')
290
-        );
291
-    }
32
+	private $query_params = array(
33
+		0 => array()
34
+	);
35
+
36
+	private $template_args = array(
37
+		'contacts'      => array(),
38
+		'event'         => null,
39
+		'datetime'      => null,
40
+		'ticket'        => null,
41
+	);
42
+
43
+	/**
44
+	 * the actual shortcode tag that gets registered with WordPress
45
+	 *
46
+	 * @return string
47
+	 */
48
+	public function getTag()
49
+	{
50
+		return 'ESPRESSO_EVENT_ATTENDEES';
51
+	}
52
+
53
+
54
+
55
+	/**
56
+	 * the time in seconds to cache the results of the processShortcode() method
57
+	 * 0 means the processShortcode() results will NOT be cached at all
58
+	 *
59
+	 * @return int
60
+	 */
61
+	public function cacheExpiration()
62
+	{
63
+		return 0;
64
+	}
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
+	/**
83
+	 * process_shortcode - ESPRESSO_EVENT_ATTENDEES - Returns a list of attendees to an event.
84
+	 *  [ESPRESSO_EVENT_ATTENDEES]
85
+	 *  - defaults to attendees for earliest active event, or earliest upcoming event.
86
+	 *
87
+	 *  [ESPRESSO_EVENT_ATTENDEES event_id=123]
88
+	 *  - attendees for specific event.
89
+	 *
90
+	 *  [ESPRESSO_EVENT_ATTENDEES datetime_id=245]
91
+	 *  - attendees for a specific datetime.
92
+	 *
93
+	 *  [ESPRESSO_EVENT_ATTENDEES ticket_id=123]
94
+	 *  - attendees for a specific ticket.
95
+	 *
96
+	 *  [ESPRESSO_EVENT_ATTENDEES status=all]
97
+	 *  - specific registration status (use status id) or all for all attendees regardless of status.
98
+	 *  Note default is to only return approved attendees
99
+	 *
100
+	 *  [ESPRESSO_EVENT_ATTENDEES show_gravatar=true]
101
+	 *  - default is to not return gravatar.  Otherwise if this is set then return gravatar for email address given.
102
+	 *
103
+	 *  [ESPRESSO_EVENT_ATTENDEES display_on_archives=true]
104
+	 *  - default is to not display attendees list on archive pages.
105
+	 *
106
+	 * Note: because of the relationship between event_id, ticket_id, and datetime_id:
107
+	 * If more than one of those params is included, then preference is given to the following:
108
+	 *  - event_id is used whenever its present and any others are ignored.
109
+	 *  - if no event_id then datetime is used whenever its present and any others are ignored.
110
+	 *  - otherwise ticket_id is used if present.
111
+	 *
112
+	 * @param array $attributes
113
+	 * @return string
114
+	 * @throws EE_Error
115
+	 */
116
+	public function processShortcode($attributes = array())
117
+	{
118
+		// grab attributes and merge with defaults
119
+		$attributes = $this->getAttributes((array)$attributes);
120
+		$archive = is_archive();
121
+		$display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN);
122
+		// don't display on archives unless 'display_on_archives' is true
123
+		if($archive && ! $display_on_archives) {
124
+			return '';
125
+		}
126
+		// add attributes to template args
127
+		$this->template_args['show_gravatar'] = $attributes['show_gravatar'];
128
+		// add required objects: event, datetime, and ticket
129
+		$this->template_args['event'] = $this->getEventAndQueryParams($attributes);
130
+		$this->template_args['datetime'] = $this->getDatetimeAndQueryParams($attributes);
131
+		$this->template_args['ticket'] = $this->getTicketAndQueryParams($attributes);
132
+
133
+		// if any of the above objects is invalid or missing,
134
+		// then there was an invalid parameter or the shortcode was used incorrectly
135
+		// so when WP_DEBUG is set and true, we'll show a message,
136
+		// otherwise we'll just return an empty string.
137
+		 if (
138
+			! $this->template_args['event'] instanceof EE_Event
139
+			|| empty($this->query_params[0])
140
+			|| ($attributes['datetime_id'] && ! $this->template_args['datetime'] instanceof EE_Datetime)
141
+			|| ($attributes['ticket_id'] && ! $this->template_args['ticket'] instanceof EE_Ticket)
142
+		) {
143
+			if (WP_DEBUG) {
144
+				return '<div class="important-notice ee-attention">'
145
+					   . esc_html__('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.',
146
+						'event_espresso')
147
+					   . '</div>';
148
+			}
149
+			 return '';
150
+		}
151
+		$this->setAdditionalQueryParams($attributes);
152
+		//get contacts!
153
+		$this->template_args['contacts'] = EEM_Attendee::instance()->get_all($this->query_params);
154
+		//all set let's load up the template and return.
155
+		return EEH_Template::locate_template(
156
+			'loop-espresso_event_attendees.php',
157
+			$this->template_args
158
+		);
159
+
160
+	}
161
+
162
+
163
+
164
+	/**
165
+	 * merge incoming attributes with filtered defaults
166
+	 *
167
+	 * @param array $attributes
168
+	 * @return array
169
+	 */
170
+	private function getAttributes(array $attributes)
171
+	{
172
+		return (array) apply_filters(
173
+			'EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts',
174
+			$attributes + array(
175
+				'event_id'            => null,
176
+				'datetime_id'         => null,
177
+				'ticket_id'           => null,
178
+				'status'              => EEM_Registration::status_id_approved,
179
+				'show_gravatar'       => false,
180
+				'display_on_archives' => false,
181
+			)
182
+		);
183
+	}
184
+
185
+
186
+
187
+	/**
188
+	 * @param array $attributes
189
+	 * @return EE_Event|null
190
+	 * @throws EE_Error
191
+	 */
192
+	private function getEventAndQueryParams(array $attributes){
193
+		if ( ! empty($attributes['event_id'])) {
194
+			$event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']);
195
+			if ($event instanceof EE_Event) {
196
+				$this->query_params[0]['Registration.EVT_ID'] = $attributes['event_id'];
197
+				return $event;
198
+			}
199
+		}
200
+		if (is_espresso_event()) {
201
+			$event = EEH_Event_View::get_event();
202
+			if ($event instanceof EE_Event) {
203
+				$this->query_params[0]['Registration.EVT_ID'] = $event->ID();
204
+				return $event;
205
+			}
206
+		}
207
+		// one last shot...
208
+		// try getting the earliest active event
209
+		$events = EEM_Event::instance()->get_active_events(array(
210
+			'limit'    => 1,
211
+			'order_by' => array('Datetime.DTT_EVT_start' => 'ASC')
212
+		));
213
+		//  if none then get the next upcoming
214
+		$events = empty($events)
215
+			? EEM_Event::instance()->get_upcoming_events(array(
216
+				'limit'    => 1,
217
+				'order_by' => array('Datetime.DTT_EVT_start' => 'ASC')
218
+			))
219
+			: $events;
220
+		$event = reset($events);
221
+		if ($event instanceof EE_Event) {
222
+			$this->query_params[0]['Registration.EVT_ID'] = $event->ID();
223
+			return $event;
224
+		}
225
+		return null;
226
+	}
227
+
228
+
229
+
230
+	/**
231
+	 * @param array $attributes
232
+	 * @return EE_Datetime|null
233
+	 */
234
+	private function getDatetimeAndQueryParams(array $attributes)
235
+	{
236
+		if ( ! empty($attributes['datetime_id'])) {
237
+			$datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']);
238
+			if ($datetime instanceof EE_Datetime) {
239
+				$this->query_params[0]['Registration.Ticket.Datetime.DTT_ID'] = $attributes['datetime_id'];
240
+				$this->query_params['default_where_conditions'] = 'this_model_only';
241
+				if ( ! $this->template_args['event'] instanceof EE_Event) {
242
+					$this->template_args['event'] = $datetime->event();
243
+				}
244
+				return $datetime;
245
+			}
246
+		}
247
+		return null;
248
+	}
249
+
250
+
251
+
252
+	/**
253
+	 * @param array $attributes
254
+	 * @return \EE_Base_Class|null
255
+	 * @throws EE_Error
256
+	 */
257
+	private function getTicketAndQueryParams(array $attributes)
258
+	{
259
+		if ( ! empty($attributes['ticket_id']) && empty($attributes['event_id']) && empty($attributes['datetime_id'])) {
260
+			$ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']);
261
+			if ($ticket instanceof EE_Ticket) {
262
+				$this->query_params[0]['Registration.TKT_ID'] = $attributes['ticket_id'];
263
+				if ( ! $this->template_args['event'] instanceof EE_Event) {
264
+					$this->template_args['event'] = $ticket->first_datetime() instanceof EE_Datetime
265
+						? $ticket->first_datetime()->event()
266
+						: null;
267
+				}
268
+				return $ticket;
269
+			}
270
+		}
271
+		return null;
272
+	}
273
+
274
+
275
+
276
+	/**
277
+	 * @param array $attributes
278
+	 * @throws EE_Error
279
+	 */
280
+	private function setAdditionalQueryParams(array $attributes)
281
+	{
282
+		$reg_status_array = EEM_Registration::reg_status_array();
283
+		if ($attributes['status'] !== 'all' && isset($reg_status_array[$attributes['status']])) {
284
+			$this->query_params[0]['Registration.STS_ID'] = $attributes['status'];
285
+		}
286
+		$this->query_params['group_by'] = array('ATT_ID');
287
+		$this->query_params['order_by'] = (array) apply_filters(
288
+			'FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by',
289
+			array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC')
290
+		);
291
+	}
292 292
 
293 293
 
294 294
 
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -116,11 +116,11 @@  discard block
 block discarded – undo
116 116
     public function processShortcode($attributes = array())
117 117
     {
118 118
         // grab attributes and merge with defaults
119
-        $attributes = $this->getAttributes((array)$attributes);
119
+        $attributes = $this->getAttributes((array) $attributes);
120 120
         $archive = is_archive();
121 121
         $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN);
122 122
         // don't display on archives unless 'display_on_archives' is true
123
-        if($archive && ! $display_on_archives) {
123
+        if ($archive && ! $display_on_archives) {
124 124
             return '';
125 125
         }
126 126
         // add attributes to template args
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
      * @return EE_Event|null
190 190
      * @throws EE_Error
191 191
      */
192
-    private function getEventAndQueryParams(array $attributes){
192
+    private function getEventAndQueryParams(array $attributes) {
193 193
         if ( ! empty($attributes['event_id'])) {
194 194
             $event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']);
195 195
             if ($event instanceof EE_Event) {
Please login to merge, or discard this patch.
core/db_classes/EE_Base_Class.class.php 1 patch
Indentation   +2681 added lines, -2681 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 do_action('AHEE_log', __FILE__, ' FILE LOADED', '');
5 5
 
@@ -25,2686 +25,2686 @@  discard block
 block discarded – undo
25 25
 abstract class EE_Base_Class
26 26
 {
27 27
 
28
-    /**
29
-     * This is an array of the original properties and values provided during construction
30
-     * of this model object. (keys are model field names, values are their values).
31
-     * This list is important to remember so that when we are merging data from the db, we know
32
-     * which values to override and which to not override.
33
-     *
34
-     * @var array
35
-     */
36
-    protected $_props_n_values_provided_in_constructor;
37
-
38
-    /**
39
-     * Timezone
40
-     * This gets set by the "set_timezone()" method so that we know what timezone incoming strings|timestamps are in.
41
-     * This can also be used before a get to set what timezone you want strings coming out of the object to be in.  NOT
42
-     * all EE_Base_Class child classes use this property but any that use a EE_Datetime_Field data type will have
43
-     * access to it.
44
-     *
45
-     * @var string
46
-     */
47
-    protected $_timezone;
48
-
49
-
50
-
51
-    /**
52
-     * date format
53
-     * pattern or format for displaying dates
54
-     *
55
-     * @var string $_dt_frmt
56
-     */
57
-    protected $_dt_frmt;
58
-
59
-
60
-
61
-    /**
62
-     * time format
63
-     * pattern or format for displaying time
64
-     *
65
-     * @var string $_tm_frmt
66
-     */
67
-    protected $_tm_frmt;
68
-
69
-
70
-
71
-    /**
72
-     * This property is for holding a cached array of object properties indexed by property name as the key.
73
-     * The purpose of this is for setting a cache on properties that may have calculated values after a
74
-     * prepare_for_get.  That way the cache can be checked first and the calculated property returned instead of having
75
-     * to recalculate. Used by _set_cached_property() and _get_cached_property() methods.
76
-     *
77
-     * @var array
78
-     */
79
-    protected $_cached_properties = array();
80
-
81
-    /**
82
-     * An array containing keys of the related model, and values are either an array of related mode objects or a
83
-     * single
84
-     * related model object. see the model's _model_relations. The keys should match those specified. And if the
85
-     * relation is of type EE_Belongs_To (or one of its children), then there should only be ONE related model object,
86
-     * all others have an array)
87
-     *
88
-     * @var array
89
-     */
90
-    protected $_model_relations = array();
91
-
92
-    /**
93
-     * Array where keys are field names (see the model's _fields property) and values are their values. To see what
94
-     * their types should be, look at what that field object returns on its prepare_for_get and prepare_for_set methods)
95
-     *
96
-     * @var array
97
-     */
98
-    protected $_fields = array();
99
-
100
-    /**
101
-     * @var boolean indicating whether or not this model object is intended to ever be saved
102
-     * For example, we might create model objects intended to only be used for the duration
103
-     * of this request and to be thrown away, and if they were accidentally saved
104
-     * it would be a bug.
105
-     */
106
-    protected $_allow_persist = true;
107
-
108
-    /**
109
-     * @var boolean indicating whether or not this model object's properties have changed since construction
110
-     */
111
-    protected $_has_changes = false;
112
-
113
-
114
-
115
-    /**
116
-     * basic constructor for Event Espresso classes, performs any necessary initialization, and verifies it's children
117
-     * play nice
118
-     *
119
-     * @param array   $fieldValues                             where each key is a field (ie, array key in the 2nd
120
-     *                                                         layer of the model's _fields array, (eg, EVT_ID,
121
-     *                                                         TXN_amount, QST_name, etc) and values are their values
122
-     * @param boolean $bydb                                    a flag for setting if the class is instantiated by the
123
-     *                                                         corresponding db model or not.
124
-     * @param string  $timezone                                indicate what timezone you want any datetime fields to
125
-     *                                                         be in when instantiating a EE_Base_Class object.
126
-     * @param array   $date_formats                            An array of date formats to set on construct where first
127
-     *                                                         value is the date_format and second value is the time
128
-     *                                                         format.
129
-     * @throws EE_Error
130
-     */
131
-    protected function __construct($fieldValues = array(), $bydb = false, $timezone = '', $date_formats = array())
132
-    {
133
-        $className = get_class($this);
134
-        do_action("AHEE__{$className}__construct", $this, $fieldValues);
135
-        $model = $this->get_model();
136
-        $model_fields = $model->field_settings(false);
137
-        // ensure $fieldValues is an array
138
-        $fieldValues = is_array($fieldValues) ? $fieldValues : array($fieldValues);
139
-        // EEH_Debug_Tools::printr( $fieldValues, '$fieldValues  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
140
-        // verify client code has not passed any invalid field names
141
-        foreach ($fieldValues as $field_name => $field_value) {
142
-            if ( ! isset($model_fields[$field_name])) {
143
-                throw new EE_Error(sprintf(__("Invalid field (%s) passed to constructor of %s. Allowed fields are :%s",
144
-                    "event_espresso"), $field_name, get_class($this), implode(", ", array_keys($model_fields))));
145
-            }
146
-        }
147
-        // EEH_Debug_Tools::printr( $model_fields, '$model_fields  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
148
-        $this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
149
-        if ( ! empty($date_formats) && is_array($date_formats)) {
150
-            list($this->_dt_frmt, $this->_tm_frmt) = $date_formats;
151
-        } else {
152
-            //set default formats for date and time
153
-            $this->_dt_frmt = (string)get_option('date_format', 'Y-m-d');
154
-            $this->_tm_frmt = (string)get_option('time_format', 'g:i a');
155
-        }
156
-        //if db model is instantiating
157
-        if ($bydb) {
158
-            //client code has indicated these field values are from the database
159
-            foreach ($model_fields as $fieldName => $field) {
160
-                $this->set_from_db($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null);
161
-            }
162
-        } else {
163
-            //we're constructing a brand
164
-            //new instance of the model object. Generally, this means we'll need to do more field validation
165
-            foreach ($model_fields as $fieldName => $field) {
166
-                $this->set($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null, true);
167
-            }
168
-        }
169
-        //remember what values were passed to this constructor
170
-        $this->_props_n_values_provided_in_constructor = $fieldValues;
171
-        //remember in entity mapper
172
-        if ( ! $bydb && $model->has_primary_key_field() && $this->ID()) {
173
-            $model->add_to_entity_map($this);
174
-        }
175
-        //setup all the relations
176
-        foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
177
-            if ($relation_obj instanceof EE_Belongs_To_Relation) {
178
-                $this->_model_relations[$relation_name] = null;
179
-            } else {
180
-                $this->_model_relations[$relation_name] = array();
181
-            }
182
-        }
183
-        /**
184
-         * Action done at the end of each model object construction
185
-         *
186
-         * @param EE_Base_Class $this the model object just created
187
-         */
188
-        do_action('AHEE__EE_Base_Class__construct__finished', $this);
189
-    }
190
-
191
-
192
-
193
-    /**
194
-     * Gets whether or not this model object is allowed to persist/be saved to the database.
195
-     *
196
-     * @return boolean
197
-     */
198
-    public function allow_persist()
199
-    {
200
-        return $this->_allow_persist;
201
-    }
202
-
203
-
204
-
205
-    /**
206
-     * Sets whether or not this model object should be allowed to be saved to the DB.
207
-     * Normally once this is set to FALSE you wouldn't set it back to TRUE, unless
208
-     * you got new information that somehow made you change your mind.
209
-     *
210
-     * @param boolean $allow_persist
211
-     * @return boolean
212
-     */
213
-    public function set_allow_persist($allow_persist)
214
-    {
215
-        return $this->_allow_persist = $allow_persist;
216
-    }
217
-
218
-
219
-
220
-    /**
221
-     * Gets the field's original value when this object was constructed during this request.
222
-     * This can be helpful when determining if a model object has changed or not
223
-     *
224
-     * @param string $field_name
225
-     * @return mixed|null
226
-     * @throws \EE_Error
227
-     */
228
-    public function get_original($field_name)
229
-    {
230
-        if (isset($this->_props_n_values_provided_in_constructor[$field_name])
231
-            && $field_settings = $this->get_model()->field_settings_for($field_name)
232
-        ) {
233
-            return $field_settings->prepare_for_get($this->_props_n_values_provided_in_constructor[$field_name]);
234
-        } else {
235
-            return null;
236
-        }
237
-    }
238
-
239
-
240
-
241
-    /**
242
-     * @param EE_Base_Class $obj
243
-     * @return string
244
-     */
245
-    public function get_class($obj)
246
-    {
247
-        return get_class($obj);
248
-    }
249
-
250
-
251
-
252
-    /**
253
-     * Overrides parent because parent expects old models.
254
-     * This also doesn't do any validation, and won't work for serialized arrays
255
-     *
256
-     * @param    string $field_name
257
-     * @param    mixed  $field_value
258
-     * @param bool      $use_default
259
-     * @throws \EE_Error
260
-     */
261
-    public function set($field_name, $field_value, $use_default = false)
262
-    {
263
-        // if not using default and nothing has changed, and object has already been setup (has ID),
264
-        // then don't do anything
265
-        if (
266
-            ! $use_default
267
-            && $this->_fields[$field_name] === $field_value
268
-            && $this->ID()
269
-        ) {
270
-            return;
271
-        }
272
-        $this->_has_changes = true;
273
-        $field_obj = $this->get_model()->field_settings_for($field_name);
274
-        if ($field_obj instanceof EE_Model_Field_Base) {
275
-            //			if ( method_exists( $field_obj, 'set_timezone' )) {
276
-            if ($field_obj instanceof EE_Datetime_Field) {
277
-                $field_obj->set_timezone($this->_timezone);
278
-                $field_obj->set_date_format($this->_dt_frmt);
279
-                $field_obj->set_time_format($this->_tm_frmt);
280
-            }
281
-            $holder_of_value = $field_obj->prepare_for_set($field_value);
282
-            //should the value be null?
283
-            if (($field_value === null || $holder_of_value === null || $holder_of_value === '') && $use_default) {
284
-                $this->_fields[$field_name] = $field_obj->get_default_value();
285
-                /**
286
-                 * To save having to refactor all the models, if a default value is used for a
287
-                 * EE_Datetime_Field, and that value is not null nor is it a DateTime
288
-                 * object.  Then let's do a set again to ensure that it becomes a DateTime
289
-                 * object.
290
-                 *
291
-                 * @since 4.6.10+
292
-                 */
293
-                if (
294
-                    $field_obj instanceof EE_Datetime_Field
295
-                    && $this->_fields[$field_name] !== null
296
-                    && ! $this->_fields[$field_name] instanceof DateTime
297
-                ) {
298
-                    empty($this->_fields[$field_name])
299
-                        ? $this->set($field_name, time())
300
-                        : $this->set($field_name, $this->_fields[$field_name]);
301
-                }
302
-            } else {
303
-                $this->_fields[$field_name] = $holder_of_value;
304
-            }
305
-            //if we're not in the constructor...
306
-            //now check if what we set was a primary key
307
-            if (
308
-                //note: props_n_values_provided_in_constructor is only set at the END of the constructor
309
-                $this->_props_n_values_provided_in_constructor
310
-                && $field_value
311
-                && $field_name === self::_get_primary_key_name(get_class($this))
312
-            ) {
313
-                //if so, we want all this object's fields to be filled either with
314
-                //what we've explicitly set on this model
315
-                //or what we have in the db
316
-                // echo "setting primary key!";
317
-                $fields_on_model = self::_get_model(get_class($this))->field_settings();
318
-                $obj_in_db = self::_get_model(get_class($this))->get_one_by_ID($field_value);
319
-                foreach ($fields_on_model as $field_obj) {
320
-                    if ( ! array_key_exists($field_obj->get_name(), $this->_props_n_values_provided_in_constructor)
321
-                         && $field_obj->get_name() !== $field_name
322
-                    ) {
323
-                        $this->set($field_obj->get_name(), $obj_in_db->get($field_obj->get_name()));
324
-                    }
325
-                }
326
-                //oh this model object has an ID? well make sure its in the entity mapper
327
-                $this->get_model()->add_to_entity_map($this);
328
-            }
329
-            //let's unset any cache for this field_name from the $_cached_properties property.
330
-            $this->_clear_cached_property($field_name);
331
-        } else {
332
-            throw new EE_Error(sprintf(__("A valid EE_Model_Field_Base could not be found for the given field name: %s",
333
-                "event_espresso"), $field_name));
334
-        }
335
-    }
336
-
337
-
338
-
339
-    /**
340
-     * This sets the field value on the db column if it exists for the given $column_name or
341
-     * saves it to EE_Extra_Meta if the given $column_name does not match a db column.
342
-     *
343
-     * @see EE_message::get_column_value for related documentation on the necessity of this method.
344
-     * @param string $field_name  Must be the exact column name.
345
-     * @param mixed  $field_value The value to set.
346
-     * @return int|bool @see EE_Base_Class::update_extra_meta() for return docs.
347
-     * @throws \EE_Error
348
-     */
349
-    public function set_field_or_extra_meta($field_name, $field_value)
350
-    {
351
-        if ($this->get_model()->has_field($field_name)) {
352
-            $this->set($field_name, $field_value);
353
-            return true;
354
-        } else {
355
-            //ensure this object is saved first so that extra meta can be properly related.
356
-            $this->save();
357
-            return $this->update_extra_meta($field_name, $field_value);
358
-        }
359
-    }
360
-
361
-
362
-
363
-    /**
364
-     * This retrieves the value of the db column set on this class or if that's not present
365
-     * it will attempt to retrieve from extra_meta if found.
366
-     * Example Usage:
367
-     * Via EE_Message child class:
368
-     * Due to the dynamic nature of the EE_messages system, EE_messengers will always have a "to",
369
-     * "from", "subject", and "content" field (as represented in the EE_Message schema), however they may
370
-     * also have additional main fields specific to the messenger.  The system accommodates those extra
371
-     * fields through the EE_Extra_Meta table.  This method allows for EE_messengers to retrieve the
372
-     * value for those extra fields dynamically via the EE_message object.
373
-     *
374
-     * @param  string $field_name expecting the fully qualified field name.
375
-     * @return mixed|null  value for the field if found.  null if not found.
376
-     * @throws \EE_Error
377
-     */
378
-    public function get_field_or_extra_meta($field_name)
379
-    {
380
-        if ($this->get_model()->has_field($field_name)) {
381
-            $column_value = $this->get($field_name);
382
-        } else {
383
-            //This isn't a column in the main table, let's see if it is in the extra meta.
384
-            $column_value = $this->get_extra_meta($field_name, true, null);
385
-        }
386
-        return $column_value;
387
-    }
388
-
389
-
390
-
391
-    /**
392
-     * See $_timezone property for description of what the timezone property is for.  This SETS the timezone internally
393
-     * for being able to reference what timezone we are running conversions on when converting TO the internal timezone
394
-     * (UTC Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp). This is
395
-     * available to all child classes that may be using the EE_Datetime_Field for a field data type.
396
-     *
397
-     * @access public
398
-     * @param string $timezone A valid timezone string as described by @link http://www.php.net/manual/en/timezones.php
399
-     * @return void
400
-     * @throws \EE_Error
401
-     */
402
-    public function set_timezone($timezone = '')
403
-    {
404
-        $this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
405
-        //make sure we clear all cached properties because they won't be relevant now
406
-        $this->_clear_cached_properties();
407
-        //make sure we update field settings and the date for all EE_Datetime_Fields
408
-        $model_fields = $this->get_model()->field_settings(false);
409
-        foreach ($model_fields as $field_name => $field_obj) {
410
-            if ($field_obj instanceof EE_Datetime_Field) {
411
-                $field_obj->set_timezone($this->_timezone);
412
-                if (isset($this->_fields[$field_name]) && $this->_fields[$field_name] instanceof DateTime) {
413
-                    $this->_fields[$field_name]->setTimezone(new DateTimeZone($this->_timezone));
414
-                }
415
-            }
416
-        }
417
-    }
418
-
419
-
420
-
421
-    /**
422
-     * This just returns whatever is set for the current timezone.
423
-     *
424
-     * @access public
425
-     * @return string timezone string
426
-     */
427
-    public function get_timezone()
428
-    {
429
-        return $this->_timezone;
430
-    }
431
-
432
-
433
-
434
-    /**
435
-     * This sets the internal date format to what is sent in to be used as the new default for the class
436
-     * internally instead of wp set date format options
437
-     *
438
-     * @since 4.6
439
-     * @param string $format should be a format recognizable by PHP date() functions.
440
-     */
441
-    public function set_date_format($format)
442
-    {
443
-        $this->_dt_frmt = $format;
444
-        //clear cached_properties because they won't be relevant now.
445
-        $this->_clear_cached_properties();
446
-    }
447
-
448
-
449
-
450
-    /**
451
-     * This sets the internal time format string to what is sent in to be used as the new default for the
452
-     * class internally instead of wp set time format options.
453
-     *
454
-     * @since 4.6
455
-     * @param string $format should be a format recognizable by PHP date() functions.
456
-     */
457
-    public function set_time_format($format)
458
-    {
459
-        $this->_tm_frmt = $format;
460
-        //clear cached_properties because they won't be relevant now.
461
-        $this->_clear_cached_properties();
462
-    }
463
-
464
-
465
-
466
-    /**
467
-     * This returns the current internal set format for the date and time formats.
468
-     *
469
-     * @param bool $full           if true (default), then return the full format.  Otherwise will return an array
470
-     *                             where the first value is the date format and the second value is the time format.
471
-     * @return mixed string|array
472
-     */
473
-    public function get_format($full = true)
474
-    {
475
-        return $full ? $this->_dt_frmt . ' ' . $this->_tm_frmt : array($this->_dt_frmt, $this->_tm_frmt);
476
-    }
477
-
478
-
479
-
480
-    /**
481
-     * cache
482
-     * stores the passed model object on the current model object.
483
-     * In certain circumstances, we can use this cached model object instead of querying for another one entirely.
484
-     *
485
-     * @param string        $relationName    one of the keys in the _model_relations array on the model. Eg
486
-     *                                       'Registration' associated with this model object
487
-     * @param EE_Base_Class $object_to_cache that has a relation to this model object. (Eg, if this is a Transaction,
488
-     *                                       that could be a payment or a registration)
489
-     * @param null          $cache_id        a string or number that will be used as the key for any Belongs_To_Many
490
-     *                                       items which will be stored in an array on this object
491
-     * @throws EE_Error
492
-     * @return mixed    index into cache, or just TRUE if the relation is of type Belongs_To (because there's only one
493
-     *                  related thing, no array)
494
-     */
495
-    public function cache($relationName = '', $object_to_cache = null, $cache_id = null)
496
-    {
497
-        // its entirely possible that there IS no related object yet in which case there is nothing to cache.
498
-        if ( ! $object_to_cache instanceof EE_Base_Class) {
499
-            return false;
500
-        }
501
-        // also get "how" the object is related, or throw an error
502
-        if ( ! $relationship_to_model = $this->get_model()->related_settings_for($relationName)) {
503
-            throw new EE_Error(sprintf(__('There is no relationship to %s on a %s. Cannot cache it', 'event_espresso'),
504
-                $relationName, get_class($this)));
505
-        }
506
-        // how many things are related ?
507
-        if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
508
-            // if it's a "belongs to" relationship, then there's only one related model object  eg, if this is a registration, there's only 1 attendee for it
509
-            // so for these model objects just set it to be cached
510
-            $this->_model_relations[$relationName] = $object_to_cache;
511
-            $return = true;
512
-        } else {
513
-            // otherwise, this is the "many" side of a one to many relationship, so we'll add the object to the array of related objects for that type.
514
-            // eg: if this is an event, there are many registrations for that event, so we cache the registrations in an array
515
-            if ( ! is_array($this->_model_relations[$relationName])) {
516
-                // if for some reason, the cached item is a model object, then stick that in the array, otherwise start with an empty array
517
-                $this->_model_relations[$relationName] = $this->_model_relations[$relationName] instanceof EE_Base_Class
518
-                    ? array($this->_model_relations[$relationName]) : array();
519
-            }
520
-            // first check for a cache_id which is normally empty
521
-            if ( ! empty($cache_id)) {
522
-                // if the cache_id exists, then it means we are purposely trying to cache this with a known key that can then be used to retrieve the object later on
523
-                $this->_model_relations[$relationName][$cache_id] = $object_to_cache;
524
-                $return = $cache_id;
525
-            } elseif ($object_to_cache->ID()) {
526
-                // OR the cached object originally came from the db, so let's just use it's PK for an ID
527
-                $this->_model_relations[$relationName][$object_to_cache->ID()] = $object_to_cache;
528
-                $return = $object_to_cache->ID();
529
-            } else {
530
-                // OR it's a new object with no ID, so just throw it in the array with an auto-incremented ID
531
-                $this->_model_relations[$relationName][] = $object_to_cache;
532
-                // move the internal pointer to the end of the array
533
-                end($this->_model_relations[$relationName]);
534
-                // and grab the key so that we can return it
535
-                $return = key($this->_model_relations[$relationName]);
536
-            }
537
-        }
538
-        return $return;
539
-    }
540
-
541
-
542
-
543
-    /**
544
-     * For adding an item to the cached_properties property.
545
-     *
546
-     * @access protected
547
-     * @param string      $fieldname the property item the corresponding value is for.
548
-     * @param mixed       $value     The value we are caching.
549
-     * @param string|null $cache_type
550
-     * @return void
551
-     * @throws \EE_Error
552
-     */
553
-    protected function _set_cached_property($fieldname, $value, $cache_type = null)
554
-    {
555
-        //first make sure this property exists
556
-        $this->get_model()->field_settings_for($fieldname);
557
-        $cache_type = empty($cache_type) ? 'standard' : $cache_type;
558
-        $this->_cached_properties[$fieldname][$cache_type] = $value;
559
-    }
560
-
561
-
562
-
563
-    /**
564
-     * This returns the value cached property if it exists OR the actual property value if the cache doesn't exist.
565
-     * This also SETS the cache if we return the actual property!
566
-     *
567
-     * @param string $fieldname        the name of the property we're trying to retrieve
568
-     * @param bool   $pretty
569
-     * @param string $extra_cache_ref  This allows the user to specify an extra cache ref for the given property
570
-     *                                 (in cases where the same property may be used for different outputs
571
-     *                                 - i.e. datetime, money etc.)
572
-     *                                 It can also accept certain pre-defined "schema" strings
573
-     *                                 to define how to output the property.
574
-     *                                 see the field's prepare_for_pretty_echoing for what strings can be used
575
-     * @return mixed                   whatever the value for the property is we're retrieving
576
-     * @throws \EE_Error
577
-     */
578
-    protected function _get_cached_property($fieldname, $pretty = false, $extra_cache_ref = null)
579
-    {
580
-        //verify the field exists
581
-        $this->get_model()->field_settings_for($fieldname);
582
-        $cache_type = $pretty ? 'pretty' : 'standard';
583
-        $cache_type .= ! empty($extra_cache_ref) ? '_' . $extra_cache_ref : '';
584
-        if (isset($this->_cached_properties[$fieldname][$cache_type])) {
585
-            return $this->_cached_properties[$fieldname][$cache_type];
586
-        }
587
-        $value = $this->_get_fresh_property($fieldname, $pretty, $extra_cache_ref);
588
-        $this->_set_cached_property($fieldname, $value, $cache_type);
589
-        return $value;
590
-    }
591
-
592
-
593
-
594
-    /**
595
-     * If the cache didn't fetch the needed item, this fetches it.
596
-     * @param string $fieldname
597
-     * @param bool $pretty
598
-     * @param string $extra_cache_ref
599
-     * @return mixed
600
-     */
601
-    protected function _get_fresh_property($fieldname, $pretty = false, $extra_cache_ref = null)
602
-    {
603
-        $field_obj = $this->get_model()->field_settings_for($fieldname);
604
-        // If this is an EE_Datetime_Field we need to make sure timezone, formats, and output are correct
605
-        if ($field_obj instanceof EE_Datetime_Field) {
606
-            $this->_prepare_datetime_field($field_obj, $pretty, $extra_cache_ref);
607
-        }
608
-        if ( ! isset($this->_fields[$fieldname])) {
609
-            $this->_fields[$fieldname] = null;
610
-        }
611
-        $value = $pretty
612
-            ? $field_obj->prepare_for_pretty_echoing($this->_fields[$fieldname], $extra_cache_ref)
613
-            : $field_obj->prepare_for_get($this->_fields[$fieldname]);
614
-        return $value;
615
-    }
616
-
617
-
618
-
619
-    /**
620
-     * set timezone, formats, and output for EE_Datetime_Field objects
621
-     *
622
-     * @param \EE_Datetime_Field $datetime_field
623
-     * @param bool               $pretty
624
-     * @param null $date_or_time
625
-     * @return void
626
-     * @throws \EE_Error
627
-     */
628
-    protected function _prepare_datetime_field(
629
-        EE_Datetime_Field $datetime_field,
630
-        $pretty = false,
631
-        $date_or_time = null
632
-    ) {
633
-        $datetime_field->set_timezone($this->_timezone);
634
-        $datetime_field->set_date_format($this->_dt_frmt, $pretty);
635
-        $datetime_field->set_time_format($this->_tm_frmt, $pretty);
636
-        //set the output returned
637
-        switch ($date_or_time) {
638
-            case 'D' :
639
-                $datetime_field->set_date_time_output('date');
640
-                break;
641
-            case 'T' :
642
-                $datetime_field->set_date_time_output('time');
643
-                break;
644
-            default :
645
-                $datetime_field->set_date_time_output();
646
-        }
647
-    }
648
-
649
-
650
-
651
-    /**
652
-     * This just takes care of clearing out the cached_properties
653
-     *
654
-     * @return void
655
-     */
656
-    protected function _clear_cached_properties()
657
-    {
658
-        $this->_cached_properties = array();
659
-    }
660
-
661
-
662
-
663
-    /**
664
-     * This just clears out ONE property if it exists in the cache
665
-     *
666
-     * @param  string $property_name the property to remove if it exists (from the _cached_properties array)
667
-     * @return void
668
-     */
669
-    protected function _clear_cached_property($property_name)
670
-    {
671
-        if (isset($this->_cached_properties[$property_name])) {
672
-            unset($this->_cached_properties[$property_name]);
673
-        }
674
-    }
675
-
676
-
677
-
678
-    /**
679
-     * Ensures that this related thing is a model object.
680
-     *
681
-     * @param mixed  $object_or_id EE_base_Class/int/string either a related model object, or its ID
682
-     * @param string $model_name   name of the related thing, eg 'Attendee',
683
-     * @return EE_Base_Class
684
-     * @throws \EE_Error
685
-     */
686
-    protected function ensure_related_thing_is_model_obj($object_or_id, $model_name)
687
-    {
688
-        $other_model_instance = self::_get_model_instance_with_name(
689
-            self::_get_model_classname($model_name),
690
-            $this->_timezone
691
-        );
692
-        return $other_model_instance->ensure_is_obj($object_or_id);
693
-    }
694
-
695
-
696
-
697
-    /**
698
-     * Forgets the cached model of the given relation Name. So the next time we request it,
699
-     * we will fetch it again from the database. (Handy if you know it's changed somehow).
700
-     * If a specific object is supplied, and the relationship to it is either a HasMany or HABTM,
701
-     * then only remove that one object from our cached array. Otherwise, clear the entire list
702
-     *
703
-     * @param string $relationName                         one of the keys in the _model_relations array on the model.
704
-     *                                                     Eg 'Registration'
705
-     * @param mixed  $object_to_remove_or_index_into_array or an index into the array of cached things, or NULL
706
-     *                                                     if you intend to use $clear_all = TRUE, or the relation only
707
-     *                                                     has 1 object anyways (ie, it's a BelongsToRelation)
708
-     * @param bool   $clear_all                            This flags clearing the entire cache relation property if
709
-     *                                                     this is HasMany or HABTM.
710
-     * @throws EE_Error
711
-     * @return EE_Base_Class | boolean from which was cleared from the cache, or true if we requested to remove a
712
-     *                       relation from all
713
-     */
714
-    public function clear_cache($relationName, $object_to_remove_or_index_into_array = null, $clear_all = false)
715
-    {
716
-        $relationship_to_model = $this->get_model()->related_settings_for($relationName);
717
-        $index_in_cache = '';
718
-        if ( ! $relationship_to_model) {
719
-            throw new EE_Error(
720
-                sprintf(
721
-                    __("There is no relationship to %s on a %s. Cannot clear that cache", 'event_espresso'),
722
-                    $relationName,
723
-                    get_class($this)
724
-                )
725
-            );
726
-        }
727
-        if ($clear_all) {
728
-            $obj_removed = true;
729
-            $this->_model_relations[$relationName] = null;
730
-        } elseif ($relationship_to_model instanceof EE_Belongs_To_Relation) {
731
-            $obj_removed = $this->_model_relations[$relationName];
732
-            $this->_model_relations[$relationName] = null;
733
-        } else {
734
-            if ($object_to_remove_or_index_into_array instanceof EE_Base_Class
735
-                && $object_to_remove_or_index_into_array->ID()
736
-            ) {
737
-                $index_in_cache = $object_to_remove_or_index_into_array->ID();
738
-                if (is_array($this->_model_relations[$relationName])
739
-                    && ! isset($this->_model_relations[$relationName][$index_in_cache])
740
-                ) {
741
-                    $index_found_at = null;
742
-                    //find this object in the array even though it has a different key
743
-                    foreach ($this->_model_relations[$relationName] as $index => $obj) {
744
-                        if (
745
-                            $obj instanceof EE_Base_Class
746
-                            && (
747
-                                $obj == $object_to_remove_or_index_into_array
748
-                                || $obj->ID() === $object_to_remove_or_index_into_array->ID()
749
-                            )
750
-                        ) {
751
-                            $index_found_at = $index;
752
-                            break;
753
-                        }
754
-                    }
755
-                    if ($index_found_at) {
756
-                        $index_in_cache = $index_found_at;
757
-                    } else {
758
-                        //it wasn't found. huh. well obviously it doesn't need to be removed from teh cache
759
-                        //if it wasn't in it to begin with. So we're done
760
-                        return $object_to_remove_or_index_into_array;
761
-                    }
762
-                }
763
-            } elseif ($object_to_remove_or_index_into_array instanceof EE_Base_Class) {
764
-                //so they provided a model object, but it's not yet saved to the DB... so let's go hunting for it!
765
-                foreach ($this->get_all_from_cache($relationName) as $index => $potentially_obj_we_want) {
766
-                    if ($potentially_obj_we_want == $object_to_remove_or_index_into_array) {
767
-                        $index_in_cache = $index;
768
-                    }
769
-                }
770
-            } else {
771
-                $index_in_cache = $object_to_remove_or_index_into_array;
772
-            }
773
-            //supposedly we've found it. But it could just be that the client code
774
-            //provided a bad index/object
775
-            if (
776
-            isset(
777
-                $this->_model_relations[$relationName],
778
-                $this->_model_relations[$relationName][$index_in_cache]
779
-            )
780
-            ) {
781
-                $obj_removed = $this->_model_relations[$relationName][$index_in_cache];
782
-                unset($this->_model_relations[$relationName][$index_in_cache]);
783
-            } else {
784
-                //that thing was never cached anyways.
785
-                $obj_removed = null;
786
-            }
787
-        }
788
-        return $obj_removed;
789
-    }
790
-
791
-
792
-
793
-    /**
794
-     * update_cache_after_object_save
795
-     * Allows a cached item to have it's cache ID (within the array of cached items) reset using the new ID it has
796
-     * obtained after being saved to the db
797
-     *
798
-     * @param string         $relationName       - the type of object that is cached
799
-     * @param \EE_Base_Class $newly_saved_object - the newly saved object to be re-cached
800
-     * @param string         $current_cache_id   - the ID that was used when originally caching the object
801
-     * @return boolean TRUE on success, FALSE on fail
802
-     * @throws \EE_Error
803
-     */
804
-    public function update_cache_after_object_save(
805
-        $relationName,
806
-        EE_Base_Class $newly_saved_object,
807
-        $current_cache_id = ''
808
-    ) {
809
-        // verify that incoming object is of the correct type
810
-        $obj_class = 'EE_' . $relationName;
811
-        if ($newly_saved_object instanceof $obj_class) {
812
-            /* @type EE_Base_Class $newly_saved_object */
813
-            // now get the type of relation
814
-            $relationship_to_model = $this->get_model()->related_settings_for($relationName);
815
-            // if this is a 1:1 relationship
816
-            if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
817
-                // then just replace the cached object with the newly saved object
818
-                $this->_model_relations[$relationName] = $newly_saved_object;
819
-                return true;
820
-                // or if it's some kind of sordid feral polyamorous relationship...
821
-            } elseif (is_array($this->_model_relations[$relationName])
822
-                      && isset($this->_model_relations[$relationName][$current_cache_id])
823
-            ) {
824
-                // then remove the current cached item
825
-                unset($this->_model_relations[$relationName][$current_cache_id]);
826
-                // and cache the newly saved object using it's new ID
827
-                $this->_model_relations[$relationName][$newly_saved_object->ID()] = $newly_saved_object;
828
-                return true;
829
-            }
830
-        }
831
-        return false;
832
-    }
833
-
834
-
835
-
836
-    /**
837
-     * Fetches a single EE_Base_Class on that relation. (If the relation is of type
838
-     * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
839
-     *
840
-     * @param string $relationName
841
-     * @return EE_Base_Class
842
-     */
843
-    public function get_one_from_cache($relationName)
844
-    {
845
-        $cached_array_or_object = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName]
846
-            : null;
847
-        if (is_array($cached_array_or_object)) {
848
-            return array_shift($cached_array_or_object);
849
-        } else {
850
-            return $cached_array_or_object;
851
-        }
852
-    }
853
-
854
-
855
-
856
-    /**
857
-     * Fetches a single EE_Base_Class on that relation. (If the relation is of type
858
-     * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
859
-     *
860
-     * @param string $relationName
861
-     * @throws \EE_Error
862
-     * @return EE_Base_Class[] NOT necessarily indexed by primary keys
863
-     */
864
-    public function get_all_from_cache($relationName)
865
-    {
866
-        $objects = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName] : array();
867
-        // if the result is not an array, but exists, make it an array
868
-        $objects = is_array($objects) ? $objects : array($objects);
869
-        //bugfix for https://events.codebasehq.com/projects/event-espresso/tickets/7143
870
-        //basically, if this model object was stored in the session, and these cached model objects
871
-        //already have IDs, let's make sure they're in their model's entity mapper
872
-        //otherwise we will have duplicates next time we call
873
-        // EE_Registry::instance()->load_model( $relationName )->get_one_by_ID( $result->ID() );
874
-        $model = EE_Registry::instance()->load_model($relationName);
875
-        foreach ($objects as $model_object) {
876
-            if ($model instanceof EEM_Base && $model_object instanceof EE_Base_Class) {
877
-                //ensure its in the map if it has an ID; otherwise it will be added to the map when its saved
878
-                if ($model_object->ID()) {
879
-                    $model->add_to_entity_map($model_object);
880
-                }
881
-            } else {
882
-                throw new EE_Error(
883
-                    sprintf(
884
-                        __(
885
-                            'Error retrieving related model objects. Either $1%s is not a model or $2%s is not a model object',
886
-                            'event_espresso'
887
-                        ),
888
-                        $relationName,
889
-                        gettype($model_object)
890
-                    )
891
-                );
892
-            }
893
-        }
894
-        return $objects;
895
-    }
896
-
897
-
898
-
899
-    /**
900
-     * Returns the next x number of EE_Base_Class objects in sequence from this object as found in the database
901
-     * matching the given query conditions.
902
-     *
903
-     * @param null  $field_to_order_by  What field is being used as the reference point.
904
-     * @param int   $limit              How many objects to return.
905
-     * @param array $query_params       Any additional conditions on the query.
906
-     * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
907
-     *                                  you can indicate just the columns you want returned
908
-     * @return array|EE_Base_Class[]
909
-     * @throws \EE_Error
910
-     */
911
-    public function next_x($field_to_order_by = null, $limit = 1, $query_params = array(), $columns_to_select = null)
912
-    {
913
-        $field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
914
-            ? $this->get_model()->get_primary_key_field()->get_name()
915
-            : $field_to_order_by;
916
-        $current_value = ! empty($field) ? $this->get($field) : null;
917
-        if (empty($field) || empty($current_value)) {
918
-            return array();
919
-        }
920
-        return $this->get_model()->next_x($current_value, $field, $limit, $query_params, $columns_to_select);
921
-    }
922
-
923
-
924
-
925
-    /**
926
-     * Returns the previous x number of EE_Base_Class objects in sequence from this object as found in the database
927
-     * matching the given query conditions.
928
-     *
929
-     * @param null  $field_to_order_by  What field is being used as the reference point.
930
-     * @param int   $limit              How many objects to return.
931
-     * @param array $query_params       Any additional conditions on the query.
932
-     * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
933
-     *                                  you can indicate just the columns you want returned
934
-     * @return array|EE_Base_Class[]
935
-     * @throws \EE_Error
936
-     */
937
-    public function previous_x(
938
-        $field_to_order_by = null,
939
-        $limit = 1,
940
-        $query_params = array(),
941
-        $columns_to_select = null
942
-    ) {
943
-        $field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
944
-            ? $this->get_model()->get_primary_key_field()->get_name()
945
-            : $field_to_order_by;
946
-        $current_value = ! empty($field) ? $this->get($field) : null;
947
-        if (empty($field) || empty($current_value)) {
948
-            return array();
949
-        }
950
-        return $this->get_model()->previous_x($current_value, $field, $limit, $query_params, $columns_to_select);
951
-    }
952
-
953
-
954
-
955
-    /**
956
-     * Returns the next EE_Base_Class object in sequence from this object as found in the database
957
-     * matching the given query conditions.
958
-     *
959
-     * @param null  $field_to_order_by  What field is being used as the reference point.
960
-     * @param array $query_params       Any additional conditions on the query.
961
-     * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
962
-     *                                  you can indicate just the columns you want returned
963
-     * @return array|EE_Base_Class
964
-     * @throws \EE_Error
965
-     */
966
-    public function next($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
967
-    {
968
-        $field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
969
-            ? $this->get_model()->get_primary_key_field()->get_name()
970
-            : $field_to_order_by;
971
-        $current_value = ! empty($field) ? $this->get($field) : null;
972
-        if (empty($field) || empty($current_value)) {
973
-            return array();
974
-        }
975
-        return $this->get_model()->next($current_value, $field, $query_params, $columns_to_select);
976
-    }
977
-
978
-
979
-
980
-    /**
981
-     * Returns the previous EE_Base_Class object in sequence from this object as found in the database
982
-     * matching the given query conditions.
983
-     *
984
-     * @param null  $field_to_order_by  What field is being used as the reference point.
985
-     * @param array $query_params       Any additional conditions on the query.
986
-     * @param null  $columns_to_select  If left null, then an EE_Base_Class object is returned, otherwise
987
-     *                                  you can indicate just the column you want returned
988
-     * @return array|EE_Base_Class
989
-     * @throws \EE_Error
990
-     */
991
-    public function previous($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
992
-    {
993
-        $field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
994
-            ? $this->get_model()->get_primary_key_field()->get_name()
995
-            : $field_to_order_by;
996
-        $current_value = ! empty($field) ? $this->get($field) : null;
997
-        if (empty($field) || empty($current_value)) {
998
-            return array();
999
-        }
1000
-        return $this->get_model()->previous($current_value, $field, $query_params, $columns_to_select);
1001
-    }
1002
-
1003
-
1004
-
1005
-    /**
1006
-     * Overrides parent because parent expects old models.
1007
-     * This also doesn't do any validation, and won't work for serialized arrays
1008
-     *
1009
-     * @param string $field_name
1010
-     * @param mixed  $field_value_from_db
1011
-     * @throws \EE_Error
1012
-     */
1013
-    public function set_from_db($field_name, $field_value_from_db)
1014
-    {
1015
-        $field_obj = $this->get_model()->field_settings_for($field_name);
1016
-        if ($field_obj instanceof EE_Model_Field_Base) {
1017
-            //you would think the DB has no NULLs for non-null label fields right? wrong!
1018
-            //eg, a CPT model object could have an entry in the posts table, but no
1019
-            //entry in the meta table. Meaning that all its columns in the meta table
1020
-            //are null! yikes! so when we find one like that, use defaults for its meta columns
1021
-            if ($field_value_from_db === null) {
1022
-                if ($field_obj->is_nullable()) {
1023
-                    //if the field allows nulls, then let it be null
1024
-                    $field_value = null;
1025
-                } else {
1026
-                    $field_value = $field_obj->get_default_value();
1027
-                }
1028
-            } else {
1029
-                $field_value = $field_obj->prepare_for_set_from_db($field_value_from_db);
1030
-            }
1031
-            $this->_fields[$field_name] = $field_value;
1032
-            $this->_clear_cached_property($field_name);
1033
-        }
1034
-    }
1035
-
1036
-
1037
-
1038
-    /**
1039
-     * verifies that the specified field is of the correct type
1040
-     *
1041
-     * @param string $field_name
1042
-     * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1043
-     *                                (in cases where the same property may be used for different outputs
1044
-     *                                - i.e. datetime, money etc.)
1045
-     * @return mixed
1046
-     * @throws \EE_Error
1047
-     */
1048
-    public function get($field_name, $extra_cache_ref = null)
1049
-    {
1050
-        return $this->_get_cached_property($field_name, false, $extra_cache_ref);
1051
-    }
1052
-
1053
-
1054
-
1055
-    /**
1056
-     * This method simply returns the RAW unprocessed value for the given property in this class
1057
-     *
1058
-     * @param  string $field_name A valid fieldname
1059
-     * @return mixed              Whatever the raw value stored on the property is.
1060
-     * @throws EE_Error if fieldSettings is misconfigured or the field doesn't exist.
1061
-     */
1062
-    public function get_raw($field_name)
1063
-    {
1064
-        $field_settings = $this->get_model()->field_settings_for($field_name);
1065
-        return $field_settings instanceof EE_Datetime_Field && $this->_fields[$field_name] instanceof DateTime
1066
-            ? $this->_fields[$field_name]->format('U')
1067
-            : $this->_fields[$field_name];
1068
-    }
1069
-
1070
-
1071
-
1072
-    /**
1073
-     * This is used to return the internal DateTime object used for a field that is a
1074
-     * EE_Datetime_Field.
1075
-     *
1076
-     * @param string $field_name               The field name retrieving the DateTime object.
1077
-     * @return mixed null | false | DateTime  If the requested field is NOT a EE_Datetime_Field then
1078
-     * @throws \EE_Error
1079
-     *                                         an error is set and false returned.  If the field IS an
1080
-     *                                         EE_Datetime_Field and but the field value is null, then
1081
-     *                                         just null is returned (because that indicates that likely
1082
-     *                                         this field is nullable).
1083
-     */
1084
-    public function get_DateTime_object($field_name)
1085
-    {
1086
-        $field_settings = $this->get_model()->field_settings_for($field_name);
1087
-        if ( ! $field_settings instanceof EE_Datetime_Field) {
1088
-            EE_Error::add_error(
1089
-                sprintf(
1090
-                    __(
1091
-                        'The field %s is not an EE_Datetime_Field field.  There is no DateTime object stored on this field type.',
1092
-                        'event_espresso'
1093
-                    ),
1094
-                    $field_name
1095
-                ),
1096
-                __FILE__,
1097
-                __FUNCTION__,
1098
-                __LINE__
1099
-            );
1100
-            return false;
1101
-        }
1102
-        return $this->_fields[$field_name];
1103
-    }
1104
-
1105
-
1106
-
1107
-    /**
1108
-     * To be used in template to immediately echo out the value, and format it for output.
1109
-     * Eg, should call stripslashes and whatnot before echoing
1110
-     *
1111
-     * @param string $field_name      the name of the field as it appears in the DB
1112
-     * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1113
-     *                                (in cases where the same property may be used for different outputs
1114
-     *                                - i.e. datetime, money etc.)
1115
-     * @return void
1116
-     * @throws \EE_Error
1117
-     */
1118
-    public function e($field_name, $extra_cache_ref = null)
1119
-    {
1120
-        echo $this->get_pretty($field_name, $extra_cache_ref);
1121
-    }
1122
-
1123
-
1124
-
1125
-    /**
1126
-     * Exactly like e(), echoes out the field, but sets its schema to 'form_input', so that it
1127
-     * can be easily used as the value of form input.
1128
-     *
1129
-     * @param string $field_name
1130
-     * @return void
1131
-     * @throws \EE_Error
1132
-     */
1133
-    public function f($field_name)
1134
-    {
1135
-        $this->e($field_name, 'form_input');
1136
-    }
1137
-
1138
-
1139
-
1140
-    /**
1141
-     * Gets a pretty view of the field's value. $extra_cache_ref can specify different formats for this.
1142
-     * The $extra_cache_ref will be passed to the model field's prepare_for_pretty_echoing, so consult the field's class
1143
-     * to see what options are available.
1144
-     * @param string $field_name
1145
-     * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1146
-     *                                (in cases where the same property may be used for different outputs
1147
-     *                                - i.e. datetime, money etc.)
1148
-     * @return mixed
1149
-     * @throws \EE_Error
1150
-     */
1151
-    public function get_pretty($field_name, $extra_cache_ref = null)
1152
-    {
1153
-        return $this->_get_cached_property($field_name, true, $extra_cache_ref);
1154
-    }
1155
-
1156
-
1157
-
1158
-    /**
1159
-     * This simply returns the datetime for the given field name
1160
-     * Note: this protected function is called by the wrapper get_date or get_time or get_datetime functions
1161
-     * (and the equivalent e_date, e_time, e_datetime).
1162
-     *
1163
-     * @access   protected
1164
-     * @param string   $field_name   Field on the instantiated EE_Base_Class child object
1165
-     * @param string   $dt_frmt      valid datetime format used for date
1166
-     *                               (if '' then we just use the default on the field,
1167
-     *                               if NULL we use the last-used format)
1168
-     * @param string   $tm_frmt      Same as above except this is for time format
1169
-     * @param string   $date_or_time if NULL then both are returned, otherwise "D" = only date and "T" = only time.
1170
-     * @param  boolean $echo         Whether the dtt is echoing using pretty echoing or just returned using vanilla get
1171
-     * @return string|bool|EE_Error string on success, FALSE on fail, or EE_Error Exception is thrown
1172
-     *                               if field is not a valid dtt field, or void if echoing
1173
-     * @throws \EE_Error
1174
-     */
1175
-    protected function _get_datetime($field_name, $dt_frmt = '', $tm_frmt = '', $date_or_time = '', $echo = false)
1176
-    {
1177
-        // clear cached property
1178
-        $this->_clear_cached_property($field_name);
1179
-        //reset format properties because they are used in get()
1180
-        $this->_dt_frmt = $dt_frmt !== '' ? $dt_frmt : $this->_dt_frmt;
1181
-        $this->_tm_frmt = $tm_frmt !== '' ? $tm_frmt : $this->_tm_frmt;
1182
-        if ($echo) {
1183
-            $this->e($field_name, $date_or_time);
1184
-            return '';
1185
-        }
1186
-        return $this->get($field_name, $date_or_time);
1187
-    }
1188
-
1189
-
1190
-
1191
-    /**
1192
-     * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the date
1193
-     * portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1194
-     * other echoes the pretty value for dtt)
1195
-     *
1196
-     * @param  string $field_name name of model object datetime field holding the value
1197
-     * @param  string $format     format for the date returned (if NULL we use default in dt_frmt property)
1198
-     * @return string            datetime value formatted
1199
-     * @throws \EE_Error
1200
-     */
1201
-    public function get_date($field_name, $format = '')
1202
-    {
1203
-        return $this->_get_datetime($field_name, $format, null, 'D');
1204
-    }
1205
-
1206
-
1207
-
1208
-    /**
1209
-     * @param      $field_name
1210
-     * @param string $format
1211
-     * @throws \EE_Error
1212
-     */
1213
-    public function e_date($field_name, $format = '')
1214
-    {
1215
-        $this->_get_datetime($field_name, $format, null, 'D', true);
1216
-    }
1217
-
1218
-
1219
-
1220
-    /**
1221
-     * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the time
1222
-     * portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1223
-     * other echoes the pretty value for dtt)
1224
-     *
1225
-     * @param  string $field_name name of model object datetime field holding the value
1226
-     * @param  string $format     format for the time returned ( if NULL we use default in tm_frmt property)
1227
-     * @return string             datetime value formatted
1228
-     * @throws \EE_Error
1229
-     */
1230
-    public function get_time($field_name, $format = '')
1231
-    {
1232
-        return $this->_get_datetime($field_name, null, $format, 'T');
1233
-    }
1234
-
1235
-
1236
-
1237
-    /**
1238
-     * @param      $field_name
1239
-     * @param string $format
1240
-     * @throws \EE_Error
1241
-     */
1242
-    public function e_time($field_name, $format = '')
1243
-    {
1244
-        $this->_get_datetime($field_name, null, $format, 'T', true);
1245
-    }
1246
-
1247
-
1248
-
1249
-    /**
1250
-     * below are wrapper functions for the various datetime outputs that can be obtained for returning the date AND
1251
-     * time portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1252
-     * other echoes the pretty value for dtt)
1253
-     *
1254
-     * @param  string $field_name name of model object datetime field holding the value
1255
-     * @param  string $dt_frmt    format for the date returned (if NULL we use default in dt_frmt property)
1256
-     * @param  string $tm_frmt    format for the time returned (if NULL we use default in tm_frmt property)
1257
-     * @return string             datetime value formatted
1258
-     * @throws \EE_Error
1259
-     */
1260
-    public function get_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1261
-    {
1262
-        return $this->_get_datetime($field_name, $dt_frmt, $tm_frmt);
1263
-    }
1264
-
1265
-
1266
-
1267
-    /**
1268
-     * @param string $field_name
1269
-     * @param string $dt_frmt
1270
-     * @param string $tm_frmt
1271
-     * @throws \EE_Error
1272
-     */
1273
-    public function e_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1274
-    {
1275
-        $this->_get_datetime($field_name, $dt_frmt, $tm_frmt, null, true);
1276
-    }
1277
-
1278
-
1279
-
1280
-    /**
1281
-     * Get the i8ln value for a date using the WordPress @see date_i18n function.
1282
-     *
1283
-     * @param string $field_name The EE_Datetime_Field reference for the date being retrieved.
1284
-     * @param string $format     PHP valid date/time string format.  If none is provided then the internal set format
1285
-     *                           on the object will be used.
1286
-     * @return string Date and time string in set locale or false if no field exists for the given
1287
-     * @throws \EE_Error
1288
-     *                           field name.
1289
-     */
1290
-    public function get_i18n_datetime($field_name, $format = '')
1291
-    {
1292
-        $format = empty($format) ? $this->_dt_frmt . ' ' . $this->_tm_frmt : $format;
1293
-        return date_i18n(
1294
-            $format,
1295
-            EEH_DTT_Helper::get_timestamp_with_offset($this->get_raw($field_name), $this->_timezone)
1296
-        );
1297
-    }
1298
-
1299
-
1300
-
1301
-    /**
1302
-     * This method validates whether the given field name is a valid field on the model object as well as it is of a
1303
-     * type EE_Datetime_Field.  On success there will be returned the field settings.  On fail an EE_Error exception is
1304
-     * thrown.
1305
-     *
1306
-     * @param  string $field_name The field name being checked
1307
-     * @throws EE_Error
1308
-     * @return EE_Datetime_Field
1309
-     */
1310
-    protected function _get_dtt_field_settings($field_name)
1311
-    {
1312
-        $field = $this->get_model()->field_settings_for($field_name);
1313
-        //check if field is dtt
1314
-        if ($field instanceof EE_Datetime_Field) {
1315
-            return $field;
1316
-        } else {
1317
-            throw new EE_Error(sprintf(__('The field name "%s" has been requested for the EE_Base_Class datetime functions and it is not a valid EE_Datetime_Field.  Please check the spelling of the field and make sure it has been setup as a EE_Datetime_Field in the %s model constructor',
1318
-                'event_espresso'), $field_name, self::_get_model_classname(get_class($this))));
1319
-        }
1320
-    }
1321
-
1322
-
1323
-
1324
-
1325
-    /**
1326
-     * NOTE ABOUT BELOW:
1327
-     * These convenience date and time setters are for setting date and time independently.  In other words you might
1328
-     * want to change the time on a datetime_field but leave the date the same (or vice versa). IF on the other hand
1329
-     * you want to set both date and time at the same time, you can just use the models default set($fieldname,$value)
1330
-     * method and make sure you send the entire datetime value for setting.
1331
-     */
1332
-    /**
1333
-     * sets the time on a datetime property
1334
-     *
1335
-     * @access protected
1336
-     * @param string|Datetime $time      a valid time string for php datetime functions (or DateTime object)
1337
-     * @param string          $fieldname the name of the field the time is being set on (must match a EE_Datetime_Field)
1338
-     * @throws \EE_Error
1339
-     */
1340
-    protected function _set_time_for($time, $fieldname)
1341
-    {
1342
-        $this->_set_date_time('T', $time, $fieldname);
1343
-    }
1344
-
1345
-
1346
-
1347
-    /**
1348
-     * sets the date on a datetime property
1349
-     *
1350
-     * @access protected
1351
-     * @param string|DateTime $date      a valid date string for php datetime functions ( or DateTime object)
1352
-     * @param string          $fieldname the name of the field the date is being set on (must match a EE_Datetime_Field)
1353
-     * @throws \EE_Error
1354
-     */
1355
-    protected function _set_date_for($date, $fieldname)
1356
-    {
1357
-        $this->_set_date_time('D', $date, $fieldname);
1358
-    }
1359
-
1360
-
1361
-
1362
-    /**
1363
-     * This takes care of setting a date or time independently on a given model object property. This method also
1364
-     * verifies that the given fieldname matches a model object property and is for a EE_Datetime_Field field
1365
-     *
1366
-     * @access protected
1367
-     * @param string          $what           "T" for time, 'B' for both, 'D' for Date.
1368
-     * @param string|DateTime $datetime_value A valid Date or Time string (or DateTime object)
1369
-     * @param string          $fieldname      the name of the field the date OR time is being set on (must match a
1370
-     *                                        EE_Datetime_Field property)
1371
-     * @throws \EE_Error
1372
-     */
1373
-    protected function _set_date_time($what = 'T', $datetime_value, $fieldname)
1374
-    {
1375
-        $field = $this->_get_dtt_field_settings($fieldname);
1376
-        $field->set_timezone($this->_timezone);
1377
-        $field->set_date_format($this->_dt_frmt);
1378
-        $field->set_time_format($this->_tm_frmt);
1379
-        switch ($what) {
1380
-            case 'T' :
1381
-                $this->_fields[$fieldname] = $field->prepare_for_set_with_new_time(
1382
-                    $datetime_value,
1383
-                    $this->_fields[$fieldname]
1384
-                );
1385
-                break;
1386
-            case 'D' :
1387
-                $this->_fields[$fieldname] = $field->prepare_for_set_with_new_date(
1388
-                    $datetime_value,
1389
-                    $this->_fields[$fieldname]
1390
-                );
1391
-                break;
1392
-            case 'B' :
1393
-                $this->_fields[$fieldname] = $field->prepare_for_set($datetime_value);
1394
-                break;
1395
-        }
1396
-        $this->_clear_cached_property($fieldname);
1397
-    }
1398
-
1399
-
1400
-
1401
-    /**
1402
-     * This will return a timestamp for the website timezone but ONLY when the current website timezone is different
1403
-     * than the timezone set for the website. NOTE, this currently only works well with methods that return values.  If
1404
-     * you use it with methods that echo values the $_timestamp property may not get reset to its original value and
1405
-     * that could lead to some unexpected results!
1406
-     *
1407
-     * @access public
1408
-     * @param string               $field_name This is the name of the field on the object that contains the date/time
1409
-     *                                         value being returned.
1410
-     * @param string               $callback   must match a valid method in this class (defaults to get_datetime)
1411
-     * @param mixed (array|string) $args       This is the arguments that will be passed to the callback.
1412
-     * @param string               $prepend    You can include something to prepend on the timestamp
1413
-     * @param string               $append     You can include something to append on the timestamp
1414
-     * @throws EE_Error
1415
-     * @return string timestamp
1416
-     */
1417
-    public function display_in_my_timezone(
1418
-        $field_name,
1419
-        $callback = 'get_datetime',
1420
-        $args = null,
1421
-        $prepend = '',
1422
-        $append = ''
1423
-    ) {
1424
-        $timezone = EEH_DTT_Helper::get_timezone();
1425
-        if ($timezone === $this->_timezone) {
1426
-            return '';
1427
-        }
1428
-        $original_timezone = $this->_timezone;
1429
-        $this->set_timezone($timezone);
1430
-        $fn = (array)$field_name;
1431
-        $args = array_merge($fn, (array)$args);
1432
-        if ( ! method_exists($this, $callback)) {
1433
-            throw new EE_Error(
1434
-                sprintf(
1435
-                    __(
1436
-                        'The method named "%s" given as the callback param in "display_in_my_timezone" does not exist.  Please check your spelling',
1437
-                        'event_espresso'
1438
-                    ),
1439
-                    $callback
1440
-                )
1441
-            );
1442
-        }
1443
-        $args = (array)$args;
1444
-        $return = $prepend . call_user_func_array(array($this, $callback), $args) . $append;
1445
-        $this->set_timezone($original_timezone);
1446
-        return $return;
1447
-    }
1448
-
1449
-
1450
-
1451
-    /**
1452
-     * Deletes this model object.
1453
-     * This calls the `EE_Base_Class::_delete` method.  Child classes wishing to change default behaviour should
1454
-     * override
1455
-     * `EE_Base_Class::_delete` NOT this class.
1456
-     *
1457
-     * @return boolean | int
1458
-     * @throws \EE_Error
1459
-     */
1460
-    public function delete()
1461
-    {
1462
-        /**
1463
-         * Called just before the `EE_Base_Class::_delete` method call.
1464
-         * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1465
-         * should be aware that `_delete` may not always result in a permanent delete.  For example, `EE_Soft_Delete_Base_Class::_delete`
1466
-         * soft deletes (trash) the object and does not permanently delete it.
1467
-         *
1468
-         * @param EE_Base_Class $model_object about to be 'deleted'
1469
-         */
1470
-        do_action('AHEE__EE_Base_Class__delete__before', $this);
1471
-        $result = $this->_delete();
1472
-        /**
1473
-         * Called just after the `EE_Base_Class::_delete` method call.
1474
-         * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1475
-         * should be aware that `_delete` may not always result in a permanent delete.  For example `EE_Soft_Base_Class::_delete`
1476
-         * soft deletes (trash) the object and does not permanently delete it.
1477
-         *
1478
-         * @param EE_Base_Class $model_object that was just 'deleted'
1479
-         * @param boolean       $result
1480
-         */
1481
-        do_action('AHEE__EE_Base_Class__delete__end', $this, $result);
1482
-        return $result;
1483
-    }
1484
-
1485
-
1486
-
1487
-    /**
1488
-     * Calls the specific delete method for the instantiated class.
1489
-     * This method is called by the public `EE_Base_Class::delete` method.  Any child classes desiring to override
1490
-     * default functionality for "delete" (which is to call `permanently_delete`) should override this method NOT
1491
-     * `EE_Base_Class::delete`
1492
-     *
1493
-     * @return bool|int
1494
-     * @throws \EE_Error
1495
-     */
1496
-    protected function _delete()
1497
-    {
1498
-        return $this->delete_permanently();
1499
-    }
1500
-
1501
-
1502
-
1503
-    /**
1504
-     * Deletes this model object permanently from db (but keep in mind related models my block the delete and return an
1505
-     * error)
1506
-     *
1507
-     * @return bool | int
1508
-     * @throws \EE_Error
1509
-     */
1510
-    public function delete_permanently()
1511
-    {
1512
-        /**
1513
-         * Called just before HARD deleting a model object
1514
-         *
1515
-         * @param EE_Base_Class $model_object about to be 'deleted'
1516
-         */
1517
-        do_action('AHEE__EE_Base_Class__delete_permanently__before', $this);
1518
-        $model = $this->get_model();
1519
-        $result = $model->delete_permanently_by_ID($this->ID());
1520
-        $this->refresh_cache_of_related_objects();
1521
-        /**
1522
-         * Called just after HARD deleting a model object
1523
-         *
1524
-         * @param EE_Base_Class $model_object that was just 'deleted'
1525
-         * @param boolean       $result
1526
-         */
1527
-        do_action('AHEE__EE_Base_Class__delete_permanently__end', $this, $result);
1528
-        return $result;
1529
-    }
1530
-
1531
-
1532
-
1533
-    /**
1534
-     * When this model object is deleted, it may still be cached on related model objects. This clears the cache of
1535
-     * related model objects
1536
-     *
1537
-     * @throws \EE_Error
1538
-     */
1539
-    public function refresh_cache_of_related_objects()
1540
-    {
1541
-        foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
1542
-            if ( ! empty($this->_model_relations[$relation_name])) {
1543
-                $related_objects = $this->_model_relations[$relation_name];
1544
-                if ($relation_obj instanceof EE_Belongs_To_Relation) {
1545
-                    //this relation only stores a single model object, not an array
1546
-                    //but let's make it consistent
1547
-                    $related_objects = array($related_objects);
1548
-                }
1549
-                foreach ($related_objects as $related_object) {
1550
-                    //only refresh their cache if they're in memory
1551
-                    if ($related_object instanceof EE_Base_Class) {
1552
-                        $related_object->clear_cache($this->get_model()->get_this_model_name(), $this);
1553
-                    }
1554
-                }
1555
-            }
1556
-        }
1557
-    }
1558
-
1559
-
1560
-
1561
-    /**
1562
-     *        Saves this object to the database. An array may be supplied to set some values on this
1563
-     * object just before saving.
1564
-     *
1565
-     * @access public
1566
-     * @param array $set_cols_n_values keys are field names, values are their new values,
1567
-     *                                 if provided during the save() method (often client code will change the fields'
1568
-     *                                 values before calling save)
1569
-     * @throws \EE_Error
1570
-     * @return int , 1 on a successful update, the ID of the new entry on insert; 0 on failure or if the model object
1571
-     *                                 isn't allowed to persist (as determined by EE_Base_Class::allow_persist())
1572
-     */
1573
-    public function save($set_cols_n_values = array())
1574
-    {
1575
-        /**
1576
-         * Filters the fields we're about to save on the model object
1577
-         *
1578
-         * @param array         $set_cols_n_values
1579
-         * @param EE_Base_Class $model_object
1580
-         */
1581
-        $set_cols_n_values = (array)apply_filters('FHEE__EE_Base_Class__save__set_cols_n_values', $set_cols_n_values,
1582
-            $this);
1583
-        //set attributes as provided in $set_cols_n_values
1584
-        foreach ($set_cols_n_values as $column => $value) {
1585
-            $this->set($column, $value);
1586
-        }
1587
-        // no changes ? then don't do anything
1588
-        if (! $this->_has_changes && $this->ID() && $this->get_model()->get_primary_key_field()->is_auto_increment()) {
1589
-            return 0;
1590
-        }
1591
-        /**
1592
-         * Saving a model object.
1593
-         * Before we perform a save, this action is fired.
1594
-         *
1595
-         * @param EE_Base_Class $model_object the model object about to be saved.
1596
-         */
1597
-        do_action('AHEE__EE_Base_Class__save__begin', $this);
1598
-        if ( ! $this->allow_persist()) {
1599
-            return 0;
1600
-        }
1601
-        //now get current attribute values
1602
-        $save_cols_n_values = $this->_fields;
1603
-        //if the object already has an ID, update it. Otherwise, insert it
1604
-        //also: change the assumption about values passed to the model NOT being prepare dby the model object. They have been
1605
-        $old_assumption_concerning_value_preparation = $this->get_model()
1606
-                                                            ->get_assumption_concerning_values_already_prepared_by_model_object();
1607
-        $this->get_model()->assume_values_already_prepared_by_model_object(true);
1608
-        //does this model have an autoincrement PK?
1609
-        if ($this->get_model()->has_primary_key_field()) {
1610
-            if ($this->get_model()->get_primary_key_field()->is_auto_increment()) {
1611
-                //ok check if it's set, if so: update; if not, insert
1612
-                if ( ! empty($save_cols_n_values[self::_get_primary_key_name(get_class($this))])) {
1613
-                    $results = $this->get_model()->update_by_ID($save_cols_n_values, $this->ID());
1614
-                } else {
1615
-                    unset($save_cols_n_values[self::_get_primary_key_name(get_class($this))]);
1616
-                    $results = $this->get_model()->insert($save_cols_n_values);
1617
-                    if ($results) {
1618
-                        //if successful, set the primary key
1619
-                        //but don't use the normal SET method, because it will check if
1620
-                        //an item with the same ID exists in the mapper & db, then
1621
-                        //will find it in the db (because we just added it) and THAT object
1622
-                        //will get added to the mapper before we can add this one!
1623
-                        //but if we just avoid using the SET method, all that headache can be avoided
1624
-                        $pk_field_name = self::_get_primary_key_name(get_class($this));
1625
-                        $this->_fields[$pk_field_name] = $results;
1626
-                        $this->_clear_cached_property($pk_field_name);
1627
-                        $this->get_model()->add_to_entity_map($this);
1628
-                        $this->_update_cached_related_model_objs_fks();
1629
-                    }
1630
-                }
1631
-            } else {//PK is NOT auto-increment
1632
-                //so check if one like it already exists in the db
1633
-                if ($this->get_model()->exists_by_ID($this->ID())) {
1634
-                    if (WP_DEBUG && ! $this->in_entity_map()) {
1635
-                        throw new EE_Error(
1636
-                            sprintf(
1637
-                                __('Using a model object %1$s that is NOT in the entity map, can lead to unexpected errors. You should either: %4$s 1. Put it in the entity mapper by calling %2$s %4$s 2. Discard this model object and use what is in the entity mapper %4$s 3. Fetch from the database using %3$s',
1638
-                                    'event_espresso'),
1639
-                                get_class($this),
1640
-                                get_class($this->get_model()) . '::instance()->add_to_entity_map()',
1641
-                                get_class($this->get_model()) . '::instance()->get_one_by_ID()',
1642
-                                '<br />'
1643
-                            )
1644
-                        );
1645
-                    }
1646
-                    $results = $this->get_model()->update_by_ID($save_cols_n_values, $this->ID());
1647
-                } else {
1648
-                    $results = $this->get_model()->insert($save_cols_n_values);
1649
-                    $this->_update_cached_related_model_objs_fks();
1650
-                }
1651
-            }
1652
-        } else {//there is NO primary key
1653
-            $already_in_db = false;
1654
-            foreach ($this->get_model()->unique_indexes() as $index) {
1655
-                $uniqueness_where_params = array_intersect_key($save_cols_n_values, $index->fields());
1656
-                if ($this->get_model()->exists(array($uniqueness_where_params))) {
1657
-                    $already_in_db = true;
1658
-                }
1659
-            }
1660
-            if ($already_in_db) {
1661
-                $combined_pk_fields_n_values = array_intersect_key($save_cols_n_values,
1662
-                    $this->get_model()->get_combined_primary_key_fields());
1663
-                $results = $this->get_model()->update($save_cols_n_values, $combined_pk_fields_n_values);
1664
-            } else {
1665
-                $results = $this->get_model()->insert($save_cols_n_values);
1666
-            }
1667
-        }
1668
-        //restore the old assumption about values being prepared by the model object
1669
-        $this->get_model()
1670
-             ->assume_values_already_prepared_by_model_object($old_assumption_concerning_value_preparation);
1671
-        /**
1672
-         * After saving the model object this action is called
1673
-         *
1674
-         * @param EE_Base_Class $model_object which was just saved
1675
-         * @param boolean|int   $results      if it were updated, TRUE or FALSE; if it were newly inserted
1676
-         *                                    the new ID (or 0 if an error occurred and it wasn't updated)
1677
-         */
1678
-        do_action('AHEE__EE_Base_Class__save__end', $this, $results);
1679
-        $this->_has_changes = false;
1680
-        return $results;
1681
-    }
1682
-
1683
-
1684
-
1685
-    /**
1686
-     * Updates the foreign key on related models objects pointing to this to have this model object's ID
1687
-     * as their foreign key.  If the cached related model objects already exist in the db, saves them (so that the DB
1688
-     * is consistent) Especially useful in case we JUST added this model object ot the database and we want to let its
1689
-     * cached relations with foreign keys to it know about that change. Eg: we've created a transaction but haven't
1690
-     * saved it to the db. We also create a registration and don't save it to the DB, but we DO cache it on the
1691
-     * transaction. Now, when we save the transaction, the registration's TXN_ID will be automatically updated, whether
1692
-     * or not they exist in the DB (if they do, their DB records will be automatically updated)
1693
-     *
1694
-     * @return void
1695
-     * @throws \EE_Error
1696
-     */
1697
-    protected function _update_cached_related_model_objs_fks()
1698
-    {
1699
-        foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
1700
-            if ($relation_obj instanceof EE_Has_Many_Relation) {
1701
-                foreach ($this->get_all_from_cache($relation_name) as $related_model_obj_in_cache) {
1702
-                    $fk_to_this = $related_model_obj_in_cache->get_model()->get_foreign_key_to(
1703
-                        $this->get_model()->get_this_model_name()
1704
-                    );
1705
-                    $related_model_obj_in_cache->set($fk_to_this->get_name(), $this->ID());
1706
-                    if ($related_model_obj_in_cache->ID()) {
1707
-                        $related_model_obj_in_cache->save();
1708
-                    }
1709
-                }
1710
-            }
1711
-        }
1712
-    }
1713
-
1714
-
1715
-
1716
-    /**
1717
-     * Saves this model object and its NEW cached relations to the database.
1718
-     * (Meaning, for now, IT DOES NOT WORK if the cached items already exist in the DB.
1719
-     * In order for that to work, we would need to mark model objects as dirty/clean...
1720
-     * because otherwise, there's a potential for infinite looping of saving
1721
-     * Saves the cached related model objects, and ensures the relation between them
1722
-     * and this object and properly setup
1723
-     *
1724
-     * @return int ID of new model object on save; 0 on failure+
1725
-     * @throws \EE_Error
1726
-     */
1727
-    public function save_new_cached_related_model_objs()
1728
-    {
1729
-        //make sure this has been saved
1730
-        if ( ! $this->ID()) {
1731
-            $id = $this->save();
1732
-        } else {
1733
-            $id = $this->ID();
1734
-        }
1735
-        //now save all the NEW cached model objects  (ie they don't exist in the DB)
1736
-        foreach ($this->get_model()->relation_settings() as $relationName => $relationObj) {
1737
-            if ($this->_model_relations[$relationName]) {
1738
-                //is this a relation where we should expect just ONE related object (ie, EE_Belongs_To_relation)
1739
-                //or MANY related objects (ie, EE_HABTM_Relation or EE_Has_Many_Relation)?
1740
-                if ($relationObj instanceof EE_Belongs_To_Relation) {
1741
-                    //add a relation to that relation type (which saves the appropriate thing in the process)
1742
-                    //but ONLY if it DOES NOT exist in the DB
1743
-                    /* @var $related_model_obj EE_Base_Class */
1744
-                    $related_model_obj = $this->_model_relations[$relationName];
1745
-                    //					if( ! $related_model_obj->ID()){
1746
-                    $this->_add_relation_to($related_model_obj, $relationName);
1747
-                    $related_model_obj->save_new_cached_related_model_objs();
1748
-                    //					}
1749
-                } else {
1750
-                    foreach ($this->_model_relations[$relationName] as $related_model_obj) {
1751
-                        //add a relation to that relation type (which saves the appropriate thing in the process)
1752
-                        //but ONLY if it DOES NOT exist in the DB
1753
-                        //						if( ! $related_model_obj->ID()){
1754
-                        $this->_add_relation_to($related_model_obj, $relationName);
1755
-                        $related_model_obj->save_new_cached_related_model_objs();
1756
-                        //						}
1757
-                    }
1758
-                }
1759
-            }
1760
-        }
1761
-        return $id;
1762
-    }
1763
-
1764
-
1765
-
1766
-    /**
1767
-     * for getting a model while instantiated.
1768
-     *
1769
-     * @return \EEM_Base | \EEM_CPT_Base
1770
-     */
1771
-    public function get_model()
1772
-    {
1773
-        $modelName = self::_get_model_classname(get_class($this));
1774
-        return self::_get_model_instance_with_name($modelName, $this->_timezone);
1775
-    }
1776
-
1777
-
1778
-
1779
-    /**
1780
-     * @param $props_n_values
1781
-     * @param $classname
1782
-     * @return mixed bool|EE_Base_Class|EEM_CPT_Base
1783
-     * @throws \EE_Error
1784
-     */
1785
-    protected static function _get_object_from_entity_mapper($props_n_values, $classname)
1786
-    {
1787
-        //TODO: will not work for Term_Relationships because they have no PK!
1788
-        $primary_id_ref = self::_get_primary_key_name($classname);
1789
-        if (array_key_exists($primary_id_ref, $props_n_values) && ! empty($props_n_values[$primary_id_ref])) {
1790
-            $id = $props_n_values[$primary_id_ref];
1791
-            return self::_get_model($classname)->get_from_entity_map($id);
1792
-        }
1793
-        return false;
1794
-    }
1795
-
1796
-
1797
-
1798
-    /**
1799
-     * This is called by child static "new_instance" method and we'll check to see if there is an existing db entry for
1800
-     * the primary key (if present in incoming values). If there is a key in the incoming array that matches the
1801
-     * primary key for the model AND it is not null, then we check the db. If there's a an object we return it.  If not
1802
-     * we return false.
1803
-     *
1804
-     * @param  array  $props_n_values   incoming array of properties and their values
1805
-     * @param  string $classname        the classname of the child class
1806
-     * @param null    $timezone
1807
-     * @param array   $date_formats     incoming date_formats in an array where the first value is the
1808
-     *                                  date_format and the second value is the time format
1809
-     * @return mixed (EE_Base_Class|bool)
1810
-     * @throws \EE_Error
1811
-     */
1812
-    protected static function _check_for_object($props_n_values, $classname, $timezone = null, $date_formats = array())
1813
-    {
1814
-        $existing = null;
1815
-        if (self::_get_model($classname)->has_primary_key_field()) {
1816
-            $primary_id_ref = self::_get_primary_key_name($classname);
1817
-            if (array_key_exists($primary_id_ref, $props_n_values)
1818
-                && ! empty($props_n_values[$primary_id_ref])
1819
-            ) {
1820
-                $existing = self::_get_model($classname, $timezone)->get_one_by_ID(
1821
-                    $props_n_values[$primary_id_ref]
1822
-                );
1823
-            }
1824
-        } elseif (self::_get_model($classname, $timezone)->has_all_combined_primary_key_fields($props_n_values)) {
1825
-            //no primary key on this model, but there's still a matching item in the DB
1826
-            $existing = self::_get_model($classname, $timezone)->get_one_by_ID(
1827
-                self::_get_model($classname, $timezone)->get_index_primary_key_string($props_n_values)
1828
-            );
1829
-        }
1830
-        if ($existing) {
1831
-            //set date formats if present before setting values
1832
-            if ( ! empty($date_formats) && is_array($date_formats)) {
1833
-                $existing->set_date_format($date_formats[0]);
1834
-                $existing->set_time_format($date_formats[1]);
1835
-            } else {
1836
-                //set default formats for date and time
1837
-                $existing->set_date_format(get_option('date_format'));
1838
-                $existing->set_time_format(get_option('time_format'));
1839
-            }
1840
-            foreach ($props_n_values as $property => $field_value) {
1841
-                $existing->set($property, $field_value);
1842
-            }
1843
-            return $existing;
1844
-        } else {
1845
-            return false;
1846
-        }
1847
-    }
1848
-
1849
-
1850
-
1851
-    /**
1852
-     * Gets the EEM_*_Model for this class
1853
-     *
1854
-     * @access public now, as this is more convenient
1855
-     * @param      $classname
1856
-     * @param null $timezone
1857
-     * @throws EE_Error
1858
-     * @return EEM_Base
1859
-     */
1860
-    protected static function _get_model($classname, $timezone = null)
1861
-    {
1862
-        //find model for this class
1863
-        if ( ! $classname) {
1864
-            throw new EE_Error(
1865
-                sprintf(
1866
-                    __(
1867
-                        "What were you thinking calling _get_model(%s)?? You need to specify the class name",
1868
-                        "event_espresso"
1869
-                    ),
1870
-                    $classname
1871
-                )
1872
-            );
1873
-        }
1874
-        $modelName = self::_get_model_classname($classname);
1875
-        return self::_get_model_instance_with_name($modelName, $timezone);
1876
-    }
1877
-
1878
-
1879
-
1880
-    /**
1881
-     * Gets the model instance (eg instance of EEM_Attendee) given its classname (eg EE_Attendee)
1882
-     *
1883
-     * @param string $model_classname
1884
-     * @param null   $timezone
1885
-     * @return EEM_Base
1886
-     */
1887
-    protected static function _get_model_instance_with_name($model_classname, $timezone = null)
1888
-    {
1889
-        $model_classname = str_replace('EEM_', '', $model_classname);
1890
-        $model = EE_Registry::instance()->load_model($model_classname);
1891
-        $model->set_timezone($timezone);
1892
-        return $model;
1893
-    }
1894
-
1895
-
1896
-
1897
-    /**
1898
-     * If a model name is provided (eg Registration), gets the model classname for that model.
1899
-     * Also works if a model class's classname is provided (eg EE_Registration).
1900
-     *
1901
-     * @param null $model_name
1902
-     * @return string like EEM_Attendee
1903
-     */
1904
-    private static function _get_model_classname($model_name = null)
1905
-    {
1906
-        if (strpos($model_name, "EE_") === 0) {
1907
-            $model_classname = str_replace("EE_", "EEM_", $model_name);
1908
-        } else {
1909
-            $model_classname = "EEM_" . $model_name;
1910
-        }
1911
-        return $model_classname;
1912
-    }
1913
-
1914
-
1915
-
1916
-    /**
1917
-     * returns the name of the primary key attribute
1918
-     *
1919
-     * @param null $classname
1920
-     * @throws EE_Error
1921
-     * @return string
1922
-     */
1923
-    protected static function _get_primary_key_name($classname = null)
1924
-    {
1925
-        if ( ! $classname) {
1926
-            throw new EE_Error(
1927
-                sprintf(
1928
-                    __("What were you thinking calling _get_primary_key_name(%s)", "event_espresso"),
1929
-                    $classname
1930
-                )
1931
-            );
1932
-        }
1933
-        return self::_get_model($classname)->get_primary_key_field()->get_name();
1934
-    }
1935
-
1936
-
1937
-
1938
-    /**
1939
-     * Gets the value of the primary key.
1940
-     * If the object hasn't yet been saved, it should be whatever the model field's default was
1941
-     * (eg, if this were the EE_Event class, look at the primary key field on EEM_Event and see what its default value
1942
-     * is. Usually defaults for integer primary keys are 0; string primary keys are usually NULL).
1943
-     *
1944
-     * @return mixed, if the primary key is of type INT it'll be an int. Otherwise it could be a string
1945
-     * @throws \EE_Error
1946
-     */
1947
-    public function ID()
1948
-    {
1949
-        //now that we know the name of the variable, use a variable variable to get its value and return its
1950
-        if ($this->get_model()->has_primary_key_field()) {
1951
-            return $this->_fields[self::_get_primary_key_name(get_class($this))];
1952
-        } else {
1953
-            return $this->get_model()->get_index_primary_key_string($this->_fields);
1954
-        }
1955
-    }
1956
-
1957
-
1958
-
1959
-    /**
1960
-     * Adds a relationship to the specified EE_Base_Class object, given the relationship's name. Eg, if the current
1961
-     * model is related to a group of events, the $relationName should be 'Event', and should be a key in the EE
1962
-     * Model's $_model_relations array. If this model object doesn't exist in the DB, just caches the related thing
1963
-     *
1964
-     * @param mixed  $otherObjectModelObjectOrID       EE_Base_Class or the ID of the other object
1965
-     * @param string $relationName                     eg 'Events','Question',etc.
1966
-     *                                                 an attendee to a group, you also want to specify which role they
1967
-     *                                                 will have in that group. So you would use this parameter to
1968
-     *                                                 specify array('role-column-name'=>'role-id')
1969
-     * @param array  $extra_join_model_fields_n_values You can optionally include an array of key=>value pairs that
1970
-     *                                                 allow you to further constrict the relation to being added.
1971
-     *                                                 However, keep in mind that the columns (keys) given must match a
1972
-     *                                                 column on the JOIN table and currently only the HABTM models
1973
-     *                                                 accept these additional conditions.  Also remember that if an
1974
-     *                                                 exact match isn't found for these extra cols/val pairs, then a
1975
-     *                                                 NEW row is created in the join table.
1976
-     * @param null   $cache_id
1977
-     * @throws EE_Error
1978
-     * @return EE_Base_Class the object the relation was added to
1979
-     */
1980
-    public function _add_relation_to(
1981
-        $otherObjectModelObjectOrID,
1982
-        $relationName,
1983
-        $extra_join_model_fields_n_values = array(),
1984
-        $cache_id = null
1985
-    ) {
1986
-        //if this thing exists in the DB, save the relation to the DB
1987
-        if ($this->ID()) {
1988
-            $otherObject = $this->get_model()
1989
-                                ->add_relationship_to($this, $otherObjectModelObjectOrID, $relationName,
1990
-                                    $extra_join_model_fields_n_values);
1991
-            //clear cache so future get_many_related and get_first_related() return new results.
1992
-            $this->clear_cache($relationName, $otherObject, true);
1993
-            if ($otherObject instanceof EE_Base_Class) {
1994
-                $otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
1995
-            }
1996
-        } else {
1997
-            //this thing doesn't exist in the DB,  so just cache it
1998
-            if ( ! $otherObjectModelObjectOrID instanceof EE_Base_Class) {
1999
-                throw new EE_Error(sprintf(
2000
-                    __('Before a model object is saved to the database, calls to _add_relation_to must be passed an actual object, not just an ID. You provided %s as the model object to a %s',
2001
-                        'event_espresso'),
2002
-                    $otherObjectModelObjectOrID,
2003
-                    get_class($this)
2004
-                ));
2005
-            } else {
2006
-                $otherObject = $otherObjectModelObjectOrID;
2007
-            }
2008
-            $this->cache($relationName, $otherObjectModelObjectOrID, $cache_id);
2009
-        }
2010
-        if ($otherObject instanceof EE_Base_Class) {
2011
-            //fix the reciprocal relation too
2012
-            if ($otherObject->ID()) {
2013
-                //its saved so assumed relations exist in the DB, so we can just
2014
-                //clear the cache so future queries use the updated info in the DB
2015
-                $otherObject->clear_cache($this->get_model()->get_this_model_name(), null, true);
2016
-            } else {
2017
-                //it's not saved, so it caches relations like this
2018
-                $otherObject->cache($this->get_model()->get_this_model_name(), $this);
2019
-            }
2020
-        }
2021
-        return $otherObject;
2022
-    }
2023
-
2024
-
2025
-
2026
-    /**
2027
-     * Removes a relationship to the specified EE_Base_Class object, given the relationships' name. Eg, if the current
2028
-     * model is related to a group of events, the $relationName should be 'Events', and should be a key in the EE
2029
-     * Model's $_model_relations array. If this model object doesn't exist in the DB, just removes the related thing
2030
-     * from the cache
2031
-     *
2032
-     * @param mixed  $otherObjectModelObjectOrID
2033
-     *                EE_Base_Class or the ID of the other object, OR an array key into the cache if this isn't saved
2034
-     *                to the DB yet
2035
-     * @param string $relationName
2036
-     * @param array  $where_query
2037
-     *                You can optionally include an array of key=>value pairs that allow you to further constrict the
2038
-     *                relation to being added. However, keep in mind that the columns (keys) given must match a column
2039
-     *                on the JOIN table and currently only the HABTM models accept these additional conditions. Also
2040
-     *                remember that if an exact match isn't found for these extra cols/val pairs, then a NEW row is
2041
-     *                created in the join table.
2042
-     * @return EE_Base_Class the relation was removed from
2043
-     * @throws \EE_Error
2044
-     */
2045
-    public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = array())
2046
-    {
2047
-        if ($this->ID()) {
2048
-            //if this exists in the DB, save the relation change to the DB too
2049
-            $otherObject = $this->get_model()
2050
-                                ->remove_relationship_to($this, $otherObjectModelObjectOrID, $relationName,
2051
-                                    $where_query);
2052
-            $this->clear_cache($relationName, $otherObject);
2053
-        } else {
2054
-            //this doesn't exist in the DB, just remove it from the cache
2055
-            $otherObject = $this->clear_cache($relationName, $otherObjectModelObjectOrID);
2056
-        }
2057
-        if ($otherObject instanceof EE_Base_Class) {
2058
-            $otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
2059
-        }
2060
-        return $otherObject;
2061
-    }
2062
-
2063
-
2064
-
2065
-    /**
2066
-     * Removes ALL the related things for the $relationName.
2067
-     *
2068
-     * @param string $relationName
2069
-     * @param array  $where_query_params like EEM_Base::get_all's $query_params[0] (where conditions)
2070
-     * @return EE_Base_Class
2071
-     * @throws \EE_Error
2072
-     */
2073
-    public function _remove_relations($relationName, $where_query_params = array())
2074
-    {
2075
-        if ($this->ID()) {
2076
-            //if this exists in the DB, save the relation change to the DB too
2077
-            $otherObjects = $this->get_model()->remove_relations($this, $relationName, $where_query_params);
2078
-            $this->clear_cache($relationName, null, true);
2079
-        } else {
2080
-            //this doesn't exist in the DB, just remove it from the cache
2081
-            $otherObjects = $this->clear_cache($relationName, null, true);
2082
-        }
2083
-        if (is_array($otherObjects)) {
2084
-            foreach ($otherObjects as $otherObject) {
2085
-                $otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
2086
-            }
2087
-        }
2088
-        return $otherObjects;
2089
-    }
2090
-
2091
-
2092
-
2093
-    /**
2094
-     * Gets all the related model objects of the specified type. Eg, if the current class if
2095
-     * EE_Event, you could call $this->get_many_related('Registration') to get an array of all the
2096
-     * EE_Registration objects which related to this event. Note: by default, we remove the "default query params"
2097
-     * because we want to get even deleted items etc.
2098
-     *
2099
-     * @param string $relationName key in the model's _model_relations array
2100
-     * @param array  $query_params like EEM_Base::get_all
2101
-     * @return EE_Base_Class[] Results not necessarily indexed by IDs, because some results might not have primary keys
2102
-     * @throws \EE_Error
2103
-     *                             or might not be saved yet. Consider using EEM_Base::get_IDs() on these results if
2104
-     *                             you want IDs
2105
-     */
2106
-    public function get_many_related($relationName, $query_params = array())
2107
-    {
2108
-        if ($this->ID()) {
2109
-            //this exists in the DB, so get the related things from either the cache or the DB
2110
-            //if there are query parameters, forget about caching the related model objects.
2111
-            if ($query_params) {
2112
-                $related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
2113
-            } else {
2114
-                //did we already cache the result of this query?
2115
-                $cached_results = $this->get_all_from_cache($relationName);
2116
-                if ( ! $cached_results) {
2117
-                    $related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
2118
-                    //if no query parameters were passed, then we got all the related model objects
2119
-                    //for that relation. We can cache them then.
2120
-                    foreach ($related_model_objects as $related_model_object) {
2121
-                        $this->cache($relationName, $related_model_object);
2122
-                    }
2123
-                } else {
2124
-                    $related_model_objects = $cached_results;
2125
-                }
2126
-            }
2127
-        } else {
2128
-            //this doesn't exist in the DB, so just get the related things from the cache
2129
-            $related_model_objects = $this->get_all_from_cache($relationName);
2130
-        }
2131
-        return $related_model_objects;
2132
-    }
2133
-
2134
-
2135
-
2136
-    /**
2137
-     * Instead of getting the related model objects, simply counts them. Ignores default_where_conditions by default,
2138
-     * unless otherwise specified in the $query_params
2139
-     *
2140
-     * @param string $relation_name  model_name like 'Event', or 'Registration'
2141
-     * @param array  $query_params   like EEM_Base::get_all's
2142
-     * @param string $field_to_count name of field to count by. By default, uses primary key
2143
-     * @param bool   $distinct       if we want to only count the distinct values for the column then you can trigger
2144
-     *                               that by the setting $distinct to TRUE;
2145
-     * @return int
2146
-     */
2147
-    public function count_related($relation_name, $query_params = array(), $field_to_count = null, $distinct = false)
2148
-    {
2149
-        return $this->get_model()->count_related($this, $relation_name, $query_params, $field_to_count, $distinct);
2150
-    }
2151
-
2152
-
2153
-
2154
-    /**
2155
-     * Instead of getting the related model objects, simply sums up the values of the specified field.
2156
-     * Note: ignores default_where_conditions by default, unless otherwise specified in the $query_params
2157
-     *
2158
-     * @param string $relation_name model_name like 'Event', or 'Registration'
2159
-     * @param array  $query_params  like EEM_Base::get_all's
2160
-     * @param string $field_to_sum  name of field to count by.
2161
-     *                              By default, uses primary key (which doesn't make much sense, so you should probably
2162
-     *                              change it)
2163
-     * @return int
2164
-     */
2165
-    public function sum_related($relation_name, $query_params = array(), $field_to_sum = null)
2166
-    {
2167
-        return $this->get_model()->sum_related($this, $relation_name, $query_params, $field_to_sum);
2168
-    }
2169
-
2170
-
2171
-
2172
-    /**
2173
-     * Gets the first (ie, one) related model object of the specified type.
2174
-     *
2175
-     * @param string $relationName key in the model's _model_relations array
2176
-     * @param array  $query_params like EEM_Base::get_all
2177
-     * @return EE_Base_Class (not an array, a single object)
2178
-     * @throws \EE_Error
2179
-     */
2180
-    public function get_first_related($relationName, $query_params = array())
2181
-    {
2182
-        if ($this->ID()) {//this exists in the DB, get from the cache OR the DB
2183
-            //if they've provided some query parameters, don't bother trying to cache the result
2184
-            //also make sure we're not caching the result of get_first_related
2185
-            //on a relation which should have an array of objects (because the cache might have an array of objects)
2186
-            if ($query_params
2187
-                || ! $this->get_model()->related_settings_for($relationName)
2188
-                     instanceof
2189
-                     EE_Belongs_To_Relation
2190
-            ) {
2191
-                $related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2192
-            } else {
2193
-                //first, check if we've already cached the result of this query
2194
-                $cached_result = $this->get_one_from_cache($relationName);
2195
-                if ( ! $cached_result) {
2196
-                    $related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2197
-                    $this->cache($relationName, $related_model_object);
2198
-                } else {
2199
-                    $related_model_object = $cached_result;
2200
-                }
2201
-            }
2202
-        } else {
2203
-            $related_model_object = null;
2204
-            //this doesn't exist in the Db, but maybe the relation is of type belongs to, and so the related thing might
2205
-            if ($this->get_model()->related_settings_for($relationName) instanceof EE_Belongs_To_Relation) {
2206
-                $related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2207
-            }
2208
-            //this doesn't exist in the DB and apparently the thing it belongs to doesn't either, just get what's cached on this object
2209
-            if ( ! $related_model_object) {
2210
-                $related_model_object = $this->get_one_from_cache($relationName);
2211
-            }
2212
-        }
2213
-        return $related_model_object;
2214
-    }
2215
-
2216
-
2217
-
2218
-    /**
2219
-     * Does a delete on all related objects of type $relationName and removes
2220
-     * the current model object's relation to them. If they can't be deleted (because
2221
-     * of blocking related model objects) does nothing. If the related model objects are
2222
-     * soft-deletable, they will be soft-deleted regardless of related blocking model objects.
2223
-     * If this model object doesn't exist yet in the DB, just removes its related things
2224
-     *
2225
-     * @param string $relationName
2226
-     * @param array  $query_params like EEM_Base::get_all's
2227
-     * @return int how many deleted
2228
-     * @throws \EE_Error
2229
-     */
2230
-    public function delete_related($relationName, $query_params = array())
2231
-    {
2232
-        if ($this->ID()) {
2233
-            $count = $this->get_model()->delete_related($this, $relationName, $query_params);
2234
-        } else {
2235
-            $count = count($this->get_all_from_cache($relationName));
2236
-            $this->clear_cache($relationName, null, true);
2237
-        }
2238
-        return $count;
2239
-    }
2240
-
2241
-
2242
-
2243
-    /**
2244
-     * Does a hard delete (ie, removes the DB row) on all related objects of type $relationName and removes
2245
-     * the current model object's relation to them. If they can't be deleted (because
2246
-     * of blocking related model objects) just does a soft delete on it instead, if possible.
2247
-     * If the related thing isn't a soft-deletable model object, this function is identical
2248
-     * to delete_related(). If this model object doesn't exist in the DB, just remove its related things
2249
-     *
2250
-     * @param string $relationName
2251
-     * @param array  $query_params like EEM_Base::get_all's
2252
-     * @return int how many deleted (including those soft deleted)
2253
-     * @throws \EE_Error
2254
-     */
2255
-    public function delete_related_permanently($relationName, $query_params = array())
2256
-    {
2257
-        if ($this->ID()) {
2258
-            $count = $this->get_model()->delete_related_permanently($this, $relationName, $query_params);
2259
-        } else {
2260
-            $count = count($this->get_all_from_cache($relationName));
2261
-        }
2262
-        $this->clear_cache($relationName, null, true);
2263
-        return $count;
2264
-    }
2265
-
2266
-
2267
-
2268
-    /**
2269
-     * is_set
2270
-     * Just a simple utility function children can use for checking if property exists
2271
-     *
2272
-     * @access  public
2273
-     * @param  string $field_name property to check
2274
-     * @return bool                              TRUE if existing,FALSE if not.
2275
-     */
2276
-    public function is_set($field_name)
2277
-    {
2278
-        return isset($this->_fields[$field_name]);
2279
-    }
2280
-
2281
-
2282
-
2283
-    /**
2284
-     * Just a simple utility function children can use for checking if property (or properties) exists and throwing an
2285
-     * EE_Error exception if they don't
2286
-     *
2287
-     * @param  mixed (string|array) $properties properties to check
2288
-     * @throws EE_Error
2289
-     * @return bool                              TRUE if existing, throw EE_Error if not.
2290
-     */
2291
-    protected function _property_exists($properties)
2292
-    {
2293
-        foreach ((array)$properties as $property_name) {
2294
-            //first make sure this property exists
2295
-            if ( ! $this->_fields[$property_name]) {
2296
-                throw new EE_Error(
2297
-                    sprintf(
2298
-                        __(
2299
-                            'Trying to retrieve a non-existent property (%s).  Double check the spelling please',
2300
-                            'event_espresso'
2301
-                        ),
2302
-                        $property_name
2303
-                    )
2304
-                );
2305
-            }
2306
-        }
2307
-        return true;
2308
-    }
2309
-
2310
-
2311
-
2312
-    /**
2313
-     * This simply returns an array of model fields for this object
2314
-     *
2315
-     * @return array
2316
-     * @throws \EE_Error
2317
-     */
2318
-    public function model_field_array()
2319
-    {
2320
-        $fields = $this->get_model()->field_settings(false);
2321
-        $properties = array();
2322
-        //remove prepended underscore
2323
-        foreach ($fields as $field_name => $settings) {
2324
-            $properties[$field_name] = $this->get($field_name);
2325
-        }
2326
-        return $properties;
2327
-    }
2328
-
2329
-
2330
-
2331
-    /**
2332
-     * Very handy general function to allow for plugins to extend any child of EE_Base_Class.
2333
-     * If a method is called on a child of EE_Base_Class that doesn't exist, this function is called
2334
-     * (http://www.garfieldtech.com/blog/php-magic-call) and passed the method's name and arguments. Instead of
2335
-     * requiring a plugin to extend the EE_Base_Class (which works fine is there's only 1 plugin, but when will that
2336
-     * happen?) they can add a hook onto 'filters_hook_espresso__{className}__{methodName}' (eg,
2337
-     * filters_hook_espresso__EE_Answer__my_great_function) and accepts 2 arguments: the object on which the function
2338
-     * was called, and an array of the original arguments passed to the function. Whatever their callback function
2339
-     * returns will be returned by this function. Example: in functions.php (or in a plugin):
2340
-     * add_filter('FHEE__EE_Answer__my_callback','my_callback',10,3); function
2341
-     * my_callback($previousReturnValue,EE_Base_Class $object,$argsArray){
2342
-     * $returnString= "you called my_callback! and passed args:".implode(",",$argsArray);
2343
-     *        return $previousReturnValue.$returnString;
2344
-     * }
2345
-     * require('EE_Answer.class.php');
2346
-     * $answer= EE_Answer::new_instance(array('REG_ID' => 2,'QST_ID' => 3,'ANS_value' => The answer is 42'));
2347
-     * echo $answer->my_callback('monkeys',100);
2348
-     * //will output "you called my_callback! and passed args:monkeys,100"
2349
-     *
2350
-     * @param string $methodName name of method which was called on a child of EE_Base_Class, but which
2351
-     * @param array  $args       array of original arguments passed to the function
2352
-     * @throws EE_Error
2353
-     * @return mixed whatever the plugin which calls add_filter decides
2354
-     */
2355
-    public function __call($methodName, $args)
2356
-    {
2357
-        $className = get_class($this);
2358
-        $tagName = "FHEE__{$className}__{$methodName}";
2359
-        if ( ! has_filter($tagName)) {
2360
-            throw new EE_Error(
2361
-                sprintf(
2362
-                    __(
2363
-                        "Method %s on class %s does not exist! You can create one with the following code in functions.php or in a plugin: add_filter('%s','my_callback',10,3);function my_callback(\$previousReturnValue,EE_Base_Class \$object, \$argsArray){/*function body*/return \$whatever;}",
2364
-                        "event_espresso"
2365
-                    ),
2366
-                    $methodName,
2367
-                    $className,
2368
-                    $tagName
2369
-                )
2370
-            );
2371
-        }
2372
-        return apply_filters($tagName, null, $this, $args);
2373
-    }
2374
-
2375
-
2376
-
2377
-    /**
2378
-     * Similar to insert_post_meta, adds a record in the Extra_Meta model's table with the given key and value.
2379
-     * A $previous_value can be specified in case there are many meta rows with the same key
2380
-     *
2381
-     * @param string $meta_key
2382
-     * @param mixed  $meta_value
2383
-     * @param mixed  $previous_value
2384
-     * @return bool|int # of records updated (or BOOLEAN if we actually ended up inserting the extra meta row)
2385
-     * @throws \EE_Error
2386
-     * NOTE: if the values haven't changed, returns 0
2387
-     */
2388
-    public function update_extra_meta($meta_key, $meta_value, $previous_value = null)
2389
-    {
2390
-        $query_params = array(
2391
-            array(
2392
-                'EXM_key'  => $meta_key,
2393
-                'OBJ_ID'   => $this->ID(),
2394
-                'EXM_type' => $this->get_model()->get_this_model_name(),
2395
-            ),
2396
-        );
2397
-        if ($previous_value !== null) {
2398
-            $query_params[0]['EXM_value'] = $meta_value;
2399
-        }
2400
-        $existing_rows_like_that = EEM_Extra_Meta::instance()->get_all($query_params);
2401
-        if ( ! $existing_rows_like_that) {
2402
-            return $this->add_extra_meta($meta_key, $meta_value);
2403
-        }
2404
-        foreach ($existing_rows_like_that as $existing_row) {
2405
-            $existing_row->save(array('EXM_value' => $meta_value));
2406
-        }
2407
-        return count($existing_rows_like_that);
2408
-    }
2409
-
2410
-
2411
-
2412
-    /**
2413
-     * Adds a new extra meta record. If $unique is set to TRUE, we'll first double-check
2414
-     * no other extra meta for this model object have the same key. Returns TRUE if the
2415
-     * extra meta row was entered, false if not
2416
-     *
2417
-     * @param string  $meta_key
2418
-     * @param string  $meta_value
2419
-     * @param boolean $unique
2420
-     * @return boolean
2421
-     * @throws \EE_Error
2422
-     */
2423
-    public function add_extra_meta($meta_key, $meta_value, $unique = false)
2424
-    {
2425
-        if ($unique) {
2426
-            $existing_extra_meta = EEM_Extra_Meta::instance()->get_one(
2427
-                array(
2428
-                    array(
2429
-                        'EXM_key'  => $meta_key,
2430
-                        'OBJ_ID'   => $this->ID(),
2431
-                        'EXM_type' => $this->get_model()->get_this_model_name(),
2432
-                    ),
2433
-                )
2434
-            );
2435
-            if ($existing_extra_meta) {
2436
-                return false;
2437
-            }
2438
-        }
2439
-        $new_extra_meta = EE_Extra_Meta::new_instance(
2440
-            array(
2441
-                'EXM_key'   => $meta_key,
2442
-                'EXM_value' => $meta_value,
2443
-                'OBJ_ID'    => $this->ID(),
2444
-                'EXM_type'  => $this->get_model()->get_this_model_name(),
2445
-            )
2446
-        );
2447
-        $new_extra_meta->save();
2448
-        return true;
2449
-    }
2450
-
2451
-
2452
-
2453
-    /**
2454
-     * Deletes all the extra meta rows for this record as specified by key. If $meta_value
2455
-     * is specified, only deletes extra meta records with that value.
2456
-     *
2457
-     * @param string $meta_key
2458
-     * @param string $meta_value
2459
-     * @return int number of extra meta rows deleted
2460
-     * @throws \EE_Error
2461
-     */
2462
-    public function delete_extra_meta($meta_key, $meta_value = null)
2463
-    {
2464
-        $query_params = array(
2465
-            array(
2466
-                'EXM_key'  => $meta_key,
2467
-                'OBJ_ID'   => $this->ID(),
2468
-                'EXM_type' => $this->get_model()->get_this_model_name(),
2469
-            ),
2470
-        );
2471
-        if ($meta_value !== null) {
2472
-            $query_params[0]['EXM_value'] = $meta_value;
2473
-        }
2474
-        return EEM_Extra_Meta::instance()->delete($query_params);
2475
-    }
2476
-
2477
-
2478
-
2479
-    /**
2480
-     * Gets the extra meta with the given meta key. If you specify "single" we just return 1, otherwise
2481
-     * an array of everything found. Requires that this model actually have a relation of type EE_Has_Many_Any_Relation.
2482
-     * You can specify $default is case you haven't found the extra meta
2483
-     *
2484
-     * @param string  $meta_key
2485
-     * @param boolean $single
2486
-     * @param mixed   $default if we don't find anything, what should we return?
2487
-     * @return mixed single value if $single; array if ! $single
2488
-     * @throws \EE_Error
2489
-     */
2490
-    public function get_extra_meta($meta_key, $single = false, $default = null)
2491
-    {
2492
-        if ($single) {
2493
-            $result = $this->get_first_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2494
-            if ($result instanceof EE_Extra_Meta) {
2495
-                return $result->value();
2496
-            } else {
2497
-                return $default;
2498
-            }
2499
-        } else {
2500
-            $results = $this->get_many_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2501
-            if ($results) {
2502
-                $values = array();
2503
-                foreach ($results as $result) {
2504
-                    if ($result instanceof EE_Extra_Meta) {
2505
-                        $values[$result->ID()] = $result->value();
2506
-                    }
2507
-                }
2508
-                return $values;
2509
-            } else {
2510
-                return $default;
2511
-            }
2512
-        }
2513
-    }
2514
-
2515
-
2516
-
2517
-    /**
2518
-     * Returns a simple array of all the extra meta associated with this model object.
2519
-     * If $one_of_each_key is true (Default), it will be an array of simple key-value pairs, keys being the
2520
-     * extra meta's key, and teh value being its value. However, if there are duplicate extra meta rows with
2521
-     * the same key, only one will be used. (eg array('foo'=>'bar','monkey'=>123))
2522
-     * If $one_of_each_key is false, it will return an array with the top-level keys being
2523
-     * the extra meta keys, but their values are also arrays, which have the extra-meta's ID as their sub-key, and
2524
-     * finally the extra meta's value as each sub-value. (eg
2525
-     * array('foo'=>array(1=>'bar',2=>'bill'),'monkey'=>array(3=>123)))
2526
-     *
2527
-     * @param boolean $one_of_each_key
2528
-     * @return array
2529
-     * @throws \EE_Error
2530
-     */
2531
-    public function all_extra_meta_array($one_of_each_key = true)
2532
-    {
2533
-        $return_array = array();
2534
-        if ($one_of_each_key) {
2535
-            $extra_meta_objs = $this->get_many_related('Extra_Meta', array('group_by' => 'EXM_key'));
2536
-            foreach ($extra_meta_objs as $extra_meta_obj) {
2537
-                if ($extra_meta_obj instanceof EE_Extra_Meta) {
2538
-                    $return_array[$extra_meta_obj->key()] = $extra_meta_obj->value();
2539
-                }
2540
-            }
2541
-        } else {
2542
-            $extra_meta_objs = $this->get_many_related('Extra_Meta');
2543
-            foreach ($extra_meta_objs as $extra_meta_obj) {
2544
-                if ($extra_meta_obj instanceof EE_Extra_Meta) {
2545
-                    if ( ! isset($return_array[$extra_meta_obj->key()])) {
2546
-                        $return_array[$extra_meta_obj->key()] = array();
2547
-                    }
2548
-                    $return_array[$extra_meta_obj->key()][$extra_meta_obj->ID()] = $extra_meta_obj->value();
2549
-                }
2550
-            }
2551
-        }
2552
-        return $return_array;
2553
-    }
2554
-
2555
-
2556
-
2557
-    /**
2558
-     * Gets a pretty nice displayable nice for this model object. Often overridden
2559
-     *
2560
-     * @return string
2561
-     * @throws \EE_Error
2562
-     */
2563
-    public function name()
2564
-    {
2565
-        //find a field that's not a text field
2566
-        $field_we_can_use = $this->get_model()->get_a_field_of_type('EE_Text_Field_Base');
2567
-        if ($field_we_can_use) {
2568
-            return $this->get($field_we_can_use->get_name());
2569
-        } else {
2570
-            $first_few_properties = $this->model_field_array();
2571
-            $first_few_properties = array_slice($first_few_properties, 0, 3);
2572
-            $name_parts = array();
2573
-            foreach ($first_few_properties as $name => $value) {
2574
-                $name_parts[] = "$name:$value";
2575
-            }
2576
-            return implode(",", $name_parts);
2577
-        }
2578
-    }
2579
-
2580
-
2581
-
2582
-    /**
2583
-     * in_entity_map
2584
-     * Checks if this model object has been proven to already be in the entity map
2585
-     *
2586
-     * @return boolean
2587
-     * @throws \EE_Error
2588
-     */
2589
-    public function in_entity_map()
2590
-    {
2591
-        if ($this->ID() && $this->get_model()->get_from_entity_map($this->ID()) === $this) {
2592
-            //well, if we looked, did we find it in the entity map?
2593
-            return true;
2594
-        } else {
2595
-            return false;
2596
-        }
2597
-    }
2598
-
2599
-
2600
-
2601
-    /**
2602
-     * refresh_from_db
2603
-     * Makes sure the fields and values on this model object are in-sync with what's in the database.
2604
-     *
2605
-     * @throws EE_Error if this model object isn't in the entity mapper (because then you should
2606
-     * just use what's in the entity mapper and refresh it) and WP_DEBUG is TRUE
2607
-     */
2608
-    public function refresh_from_db()
2609
-    {
2610
-        if ($this->ID() && $this->in_entity_map()) {
2611
-            $this->get_model()->refresh_entity_map_from_db($this->ID());
2612
-        } else {
2613
-            //if it doesn't have ID, you shouldn't be asking to refresh it from teh database (because its not in the database)
2614
-            //if it has an ID but it's not in the map, and you're asking me to refresh it
2615
-            //that's kinda dangerous. You should just use what's in the entity map, or add this to the entity map if there's
2616
-            //absolutely nothing in it for this ID
2617
-            if (WP_DEBUG) {
2618
-                throw new EE_Error(
2619
-                    sprintf(
2620
-                        __('Trying to refresh a model object with ID "%1$s" that\'s not in the entity map? First off: you should put it in the entity map by calling %2$s. Second off, if you want what\'s in the database right now, you should just call %3$s yourself and discard this model object.',
2621
-                            'event_espresso'),
2622
-                        $this->ID(),
2623
-                        get_class($this->get_model()) . '::instance()->add_to_entity_map()',
2624
-                        get_class($this->get_model()) . '::instance()->refresh_entity_map()'
2625
-                    )
2626
-                );
2627
-            }
2628
-        }
2629
-    }
2630
-
2631
-
2632
-
2633
-    /**
2634
-     * Because some other plugins, like Advanced Cron Manager, expect all objects to have this method
2635
-     * (probably a bad assumption they have made, oh well)
2636
-     *
2637
-     * @return string
2638
-     */
2639
-    public function __toString()
2640
-    {
2641
-        try {
2642
-            return sprintf('%s (%s)', $this->name(), $this->ID());
2643
-        } catch (Exception $e) {
2644
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
2645
-            return '';
2646
-        }
2647
-    }
2648
-
2649
-
2650
-
2651
-    /**
2652
-     * Clear related model objects if they're already in the DB, because otherwise when we
2653
-     * UN-serialize this model object we'll need to be careful to add them to the entity map.
2654
-     * This means if we have made changes to those related model objects, and want to unserialize
2655
-     * the this model object on a subsequent request, changes to those related model objects will be lost.
2656
-     * Instead, those related model objects should be directly serialized and stored.
2657
-     * Eg, the following won't work:
2658
-     * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2659
-     * $att = $reg->attendee();
2660
-     * $att->set( 'ATT_fname', 'Dirk' );
2661
-     * update_option( 'my_option', serialize( $reg ) );
2662
-     * //END REQUEST
2663
-     * //START NEXT REQUEST
2664
-     * $reg = get_option( 'my_option' );
2665
-     * $reg->attendee()->save();
2666
-     * And would need to be replace with:
2667
-     * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2668
-     * $att = $reg->attendee();
2669
-     * $att->set( 'ATT_fname', 'Dirk' );
2670
-     * update_option( 'my_option', serialize( $reg ) );
2671
-     * //END REQUEST
2672
-     * //START NEXT REQUEST
2673
-     * $att = get_option( 'my_option' );
2674
-     * $att->save();
2675
-     *
2676
-     * @return array
2677
-     * @throws \EE_Error
2678
-     */
2679
-    public function __sleep()
2680
-    {
2681
-        foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
2682
-            if ($relation_obj instanceof EE_Belongs_To_Relation) {
2683
-                $classname = 'EE_' . $this->get_model()->get_this_model_name();
2684
-                if (
2685
-                    $this->get_one_from_cache($relation_name) instanceof $classname
2686
-                    && $this->get_one_from_cache($relation_name)->ID()
2687
-                ) {
2688
-                    $this->clear_cache($relation_name, $this->get_one_from_cache($relation_name)->ID());
2689
-                }
2690
-            }
2691
-        }
2692
-        $this->_props_n_values_provided_in_constructor = array();
2693
-        return array_keys(get_object_vars($this));
2694
-    }
2695
-
2696
-
2697
-
2698
-    /**
2699
-     * restore _props_n_values_provided_in_constructor
2700
-     * PLZ NOTE: this will reset the array to whatever fields values were present prior to serialization,
2701
-     * and therefore should NOT be used to determine if state change has occurred since initial construction.
2702
-     * At best, you would only be able to detect if state change has occurred during THIS request.
2703
-     */
2704
-    public function __wakeup()
2705
-    {
2706
-        $this->_props_n_values_provided_in_constructor = $this->_fields;
2707
-    }
28
+	/**
29
+	 * This is an array of the original properties and values provided during construction
30
+	 * of this model object. (keys are model field names, values are their values).
31
+	 * This list is important to remember so that when we are merging data from the db, we know
32
+	 * which values to override and which to not override.
33
+	 *
34
+	 * @var array
35
+	 */
36
+	protected $_props_n_values_provided_in_constructor;
37
+
38
+	/**
39
+	 * Timezone
40
+	 * This gets set by the "set_timezone()" method so that we know what timezone incoming strings|timestamps are in.
41
+	 * This can also be used before a get to set what timezone you want strings coming out of the object to be in.  NOT
42
+	 * all EE_Base_Class child classes use this property but any that use a EE_Datetime_Field data type will have
43
+	 * access to it.
44
+	 *
45
+	 * @var string
46
+	 */
47
+	protected $_timezone;
48
+
49
+
50
+
51
+	/**
52
+	 * date format
53
+	 * pattern or format for displaying dates
54
+	 *
55
+	 * @var string $_dt_frmt
56
+	 */
57
+	protected $_dt_frmt;
58
+
59
+
60
+
61
+	/**
62
+	 * time format
63
+	 * pattern or format for displaying time
64
+	 *
65
+	 * @var string $_tm_frmt
66
+	 */
67
+	protected $_tm_frmt;
68
+
69
+
70
+
71
+	/**
72
+	 * This property is for holding a cached array of object properties indexed by property name as the key.
73
+	 * The purpose of this is for setting a cache on properties that may have calculated values after a
74
+	 * prepare_for_get.  That way the cache can be checked first and the calculated property returned instead of having
75
+	 * to recalculate. Used by _set_cached_property() and _get_cached_property() methods.
76
+	 *
77
+	 * @var array
78
+	 */
79
+	protected $_cached_properties = array();
80
+
81
+	/**
82
+	 * An array containing keys of the related model, and values are either an array of related mode objects or a
83
+	 * single
84
+	 * related model object. see the model's _model_relations. The keys should match those specified. And if the
85
+	 * relation is of type EE_Belongs_To (or one of its children), then there should only be ONE related model object,
86
+	 * all others have an array)
87
+	 *
88
+	 * @var array
89
+	 */
90
+	protected $_model_relations = array();
91
+
92
+	/**
93
+	 * Array where keys are field names (see the model's _fields property) and values are their values. To see what
94
+	 * their types should be, look at what that field object returns on its prepare_for_get and prepare_for_set methods)
95
+	 *
96
+	 * @var array
97
+	 */
98
+	protected $_fields = array();
99
+
100
+	/**
101
+	 * @var boolean indicating whether or not this model object is intended to ever be saved
102
+	 * For example, we might create model objects intended to only be used for the duration
103
+	 * of this request and to be thrown away, and if they were accidentally saved
104
+	 * it would be a bug.
105
+	 */
106
+	protected $_allow_persist = true;
107
+
108
+	/**
109
+	 * @var boolean indicating whether or not this model object's properties have changed since construction
110
+	 */
111
+	protected $_has_changes = false;
112
+
113
+
114
+
115
+	/**
116
+	 * basic constructor for Event Espresso classes, performs any necessary initialization, and verifies it's children
117
+	 * play nice
118
+	 *
119
+	 * @param array   $fieldValues                             where each key is a field (ie, array key in the 2nd
120
+	 *                                                         layer of the model's _fields array, (eg, EVT_ID,
121
+	 *                                                         TXN_amount, QST_name, etc) and values are their values
122
+	 * @param boolean $bydb                                    a flag for setting if the class is instantiated by the
123
+	 *                                                         corresponding db model or not.
124
+	 * @param string  $timezone                                indicate what timezone you want any datetime fields to
125
+	 *                                                         be in when instantiating a EE_Base_Class object.
126
+	 * @param array   $date_formats                            An array of date formats to set on construct where first
127
+	 *                                                         value is the date_format and second value is the time
128
+	 *                                                         format.
129
+	 * @throws EE_Error
130
+	 */
131
+	protected function __construct($fieldValues = array(), $bydb = false, $timezone = '', $date_formats = array())
132
+	{
133
+		$className = get_class($this);
134
+		do_action("AHEE__{$className}__construct", $this, $fieldValues);
135
+		$model = $this->get_model();
136
+		$model_fields = $model->field_settings(false);
137
+		// ensure $fieldValues is an array
138
+		$fieldValues = is_array($fieldValues) ? $fieldValues : array($fieldValues);
139
+		// EEH_Debug_Tools::printr( $fieldValues, '$fieldValues  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
140
+		// verify client code has not passed any invalid field names
141
+		foreach ($fieldValues as $field_name => $field_value) {
142
+			if ( ! isset($model_fields[$field_name])) {
143
+				throw new EE_Error(sprintf(__("Invalid field (%s) passed to constructor of %s. Allowed fields are :%s",
144
+					"event_espresso"), $field_name, get_class($this), implode(", ", array_keys($model_fields))));
145
+			}
146
+		}
147
+		// EEH_Debug_Tools::printr( $model_fields, '$model_fields  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
148
+		$this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
149
+		if ( ! empty($date_formats) && is_array($date_formats)) {
150
+			list($this->_dt_frmt, $this->_tm_frmt) = $date_formats;
151
+		} else {
152
+			//set default formats for date and time
153
+			$this->_dt_frmt = (string)get_option('date_format', 'Y-m-d');
154
+			$this->_tm_frmt = (string)get_option('time_format', 'g:i a');
155
+		}
156
+		//if db model is instantiating
157
+		if ($bydb) {
158
+			//client code has indicated these field values are from the database
159
+			foreach ($model_fields as $fieldName => $field) {
160
+				$this->set_from_db($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null);
161
+			}
162
+		} else {
163
+			//we're constructing a brand
164
+			//new instance of the model object. Generally, this means we'll need to do more field validation
165
+			foreach ($model_fields as $fieldName => $field) {
166
+				$this->set($fieldName, isset($fieldValues[$fieldName]) ? $fieldValues[$fieldName] : null, true);
167
+			}
168
+		}
169
+		//remember what values were passed to this constructor
170
+		$this->_props_n_values_provided_in_constructor = $fieldValues;
171
+		//remember in entity mapper
172
+		if ( ! $bydb && $model->has_primary_key_field() && $this->ID()) {
173
+			$model->add_to_entity_map($this);
174
+		}
175
+		//setup all the relations
176
+		foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
177
+			if ($relation_obj instanceof EE_Belongs_To_Relation) {
178
+				$this->_model_relations[$relation_name] = null;
179
+			} else {
180
+				$this->_model_relations[$relation_name] = array();
181
+			}
182
+		}
183
+		/**
184
+		 * Action done at the end of each model object construction
185
+		 *
186
+		 * @param EE_Base_Class $this the model object just created
187
+		 */
188
+		do_action('AHEE__EE_Base_Class__construct__finished', $this);
189
+	}
190
+
191
+
192
+
193
+	/**
194
+	 * Gets whether or not this model object is allowed to persist/be saved to the database.
195
+	 *
196
+	 * @return boolean
197
+	 */
198
+	public function allow_persist()
199
+	{
200
+		return $this->_allow_persist;
201
+	}
202
+
203
+
204
+
205
+	/**
206
+	 * Sets whether or not this model object should be allowed to be saved to the DB.
207
+	 * Normally once this is set to FALSE you wouldn't set it back to TRUE, unless
208
+	 * you got new information that somehow made you change your mind.
209
+	 *
210
+	 * @param boolean $allow_persist
211
+	 * @return boolean
212
+	 */
213
+	public function set_allow_persist($allow_persist)
214
+	{
215
+		return $this->_allow_persist = $allow_persist;
216
+	}
217
+
218
+
219
+
220
+	/**
221
+	 * Gets the field's original value when this object was constructed during this request.
222
+	 * This can be helpful when determining if a model object has changed or not
223
+	 *
224
+	 * @param string $field_name
225
+	 * @return mixed|null
226
+	 * @throws \EE_Error
227
+	 */
228
+	public function get_original($field_name)
229
+	{
230
+		if (isset($this->_props_n_values_provided_in_constructor[$field_name])
231
+			&& $field_settings = $this->get_model()->field_settings_for($field_name)
232
+		) {
233
+			return $field_settings->prepare_for_get($this->_props_n_values_provided_in_constructor[$field_name]);
234
+		} else {
235
+			return null;
236
+		}
237
+	}
238
+
239
+
240
+
241
+	/**
242
+	 * @param EE_Base_Class $obj
243
+	 * @return string
244
+	 */
245
+	public function get_class($obj)
246
+	{
247
+		return get_class($obj);
248
+	}
249
+
250
+
251
+
252
+	/**
253
+	 * Overrides parent because parent expects old models.
254
+	 * This also doesn't do any validation, and won't work for serialized arrays
255
+	 *
256
+	 * @param    string $field_name
257
+	 * @param    mixed  $field_value
258
+	 * @param bool      $use_default
259
+	 * @throws \EE_Error
260
+	 */
261
+	public function set($field_name, $field_value, $use_default = false)
262
+	{
263
+		// if not using default and nothing has changed, and object has already been setup (has ID),
264
+		// then don't do anything
265
+		if (
266
+			! $use_default
267
+			&& $this->_fields[$field_name] === $field_value
268
+			&& $this->ID()
269
+		) {
270
+			return;
271
+		}
272
+		$this->_has_changes = true;
273
+		$field_obj = $this->get_model()->field_settings_for($field_name);
274
+		if ($field_obj instanceof EE_Model_Field_Base) {
275
+			//			if ( method_exists( $field_obj, 'set_timezone' )) {
276
+			if ($field_obj instanceof EE_Datetime_Field) {
277
+				$field_obj->set_timezone($this->_timezone);
278
+				$field_obj->set_date_format($this->_dt_frmt);
279
+				$field_obj->set_time_format($this->_tm_frmt);
280
+			}
281
+			$holder_of_value = $field_obj->prepare_for_set($field_value);
282
+			//should the value be null?
283
+			if (($field_value === null || $holder_of_value === null || $holder_of_value === '') && $use_default) {
284
+				$this->_fields[$field_name] = $field_obj->get_default_value();
285
+				/**
286
+				 * To save having to refactor all the models, if a default value is used for a
287
+				 * EE_Datetime_Field, and that value is not null nor is it a DateTime
288
+				 * object.  Then let's do a set again to ensure that it becomes a DateTime
289
+				 * object.
290
+				 *
291
+				 * @since 4.6.10+
292
+				 */
293
+				if (
294
+					$field_obj instanceof EE_Datetime_Field
295
+					&& $this->_fields[$field_name] !== null
296
+					&& ! $this->_fields[$field_name] instanceof DateTime
297
+				) {
298
+					empty($this->_fields[$field_name])
299
+						? $this->set($field_name, time())
300
+						: $this->set($field_name, $this->_fields[$field_name]);
301
+				}
302
+			} else {
303
+				$this->_fields[$field_name] = $holder_of_value;
304
+			}
305
+			//if we're not in the constructor...
306
+			//now check if what we set was a primary key
307
+			if (
308
+				//note: props_n_values_provided_in_constructor is only set at the END of the constructor
309
+				$this->_props_n_values_provided_in_constructor
310
+				&& $field_value
311
+				&& $field_name === self::_get_primary_key_name(get_class($this))
312
+			) {
313
+				//if so, we want all this object's fields to be filled either with
314
+				//what we've explicitly set on this model
315
+				//or what we have in the db
316
+				// echo "setting primary key!";
317
+				$fields_on_model = self::_get_model(get_class($this))->field_settings();
318
+				$obj_in_db = self::_get_model(get_class($this))->get_one_by_ID($field_value);
319
+				foreach ($fields_on_model as $field_obj) {
320
+					if ( ! array_key_exists($field_obj->get_name(), $this->_props_n_values_provided_in_constructor)
321
+						 && $field_obj->get_name() !== $field_name
322
+					) {
323
+						$this->set($field_obj->get_name(), $obj_in_db->get($field_obj->get_name()));
324
+					}
325
+				}
326
+				//oh this model object has an ID? well make sure its in the entity mapper
327
+				$this->get_model()->add_to_entity_map($this);
328
+			}
329
+			//let's unset any cache for this field_name from the $_cached_properties property.
330
+			$this->_clear_cached_property($field_name);
331
+		} else {
332
+			throw new EE_Error(sprintf(__("A valid EE_Model_Field_Base could not be found for the given field name: %s",
333
+				"event_espresso"), $field_name));
334
+		}
335
+	}
336
+
337
+
338
+
339
+	/**
340
+	 * This sets the field value on the db column if it exists for the given $column_name or
341
+	 * saves it to EE_Extra_Meta if the given $column_name does not match a db column.
342
+	 *
343
+	 * @see EE_message::get_column_value for related documentation on the necessity of this method.
344
+	 * @param string $field_name  Must be the exact column name.
345
+	 * @param mixed  $field_value The value to set.
346
+	 * @return int|bool @see EE_Base_Class::update_extra_meta() for return docs.
347
+	 * @throws \EE_Error
348
+	 */
349
+	public function set_field_or_extra_meta($field_name, $field_value)
350
+	{
351
+		if ($this->get_model()->has_field($field_name)) {
352
+			$this->set($field_name, $field_value);
353
+			return true;
354
+		} else {
355
+			//ensure this object is saved first so that extra meta can be properly related.
356
+			$this->save();
357
+			return $this->update_extra_meta($field_name, $field_value);
358
+		}
359
+	}
360
+
361
+
362
+
363
+	/**
364
+	 * This retrieves the value of the db column set on this class or if that's not present
365
+	 * it will attempt to retrieve from extra_meta if found.
366
+	 * Example Usage:
367
+	 * Via EE_Message child class:
368
+	 * Due to the dynamic nature of the EE_messages system, EE_messengers will always have a "to",
369
+	 * "from", "subject", and "content" field (as represented in the EE_Message schema), however they may
370
+	 * also have additional main fields specific to the messenger.  The system accommodates those extra
371
+	 * fields through the EE_Extra_Meta table.  This method allows for EE_messengers to retrieve the
372
+	 * value for those extra fields dynamically via the EE_message object.
373
+	 *
374
+	 * @param  string $field_name expecting the fully qualified field name.
375
+	 * @return mixed|null  value for the field if found.  null if not found.
376
+	 * @throws \EE_Error
377
+	 */
378
+	public function get_field_or_extra_meta($field_name)
379
+	{
380
+		if ($this->get_model()->has_field($field_name)) {
381
+			$column_value = $this->get($field_name);
382
+		} else {
383
+			//This isn't a column in the main table, let's see if it is in the extra meta.
384
+			$column_value = $this->get_extra_meta($field_name, true, null);
385
+		}
386
+		return $column_value;
387
+	}
388
+
389
+
390
+
391
+	/**
392
+	 * See $_timezone property for description of what the timezone property is for.  This SETS the timezone internally
393
+	 * for being able to reference what timezone we are running conversions on when converting TO the internal timezone
394
+	 * (UTC Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp). This is
395
+	 * available to all child classes that may be using the EE_Datetime_Field for a field data type.
396
+	 *
397
+	 * @access public
398
+	 * @param string $timezone A valid timezone string as described by @link http://www.php.net/manual/en/timezones.php
399
+	 * @return void
400
+	 * @throws \EE_Error
401
+	 */
402
+	public function set_timezone($timezone = '')
403
+	{
404
+		$this->_timezone = EEH_DTT_Helper::get_valid_timezone_string($timezone);
405
+		//make sure we clear all cached properties because they won't be relevant now
406
+		$this->_clear_cached_properties();
407
+		//make sure we update field settings and the date for all EE_Datetime_Fields
408
+		$model_fields = $this->get_model()->field_settings(false);
409
+		foreach ($model_fields as $field_name => $field_obj) {
410
+			if ($field_obj instanceof EE_Datetime_Field) {
411
+				$field_obj->set_timezone($this->_timezone);
412
+				if (isset($this->_fields[$field_name]) && $this->_fields[$field_name] instanceof DateTime) {
413
+					$this->_fields[$field_name]->setTimezone(new DateTimeZone($this->_timezone));
414
+				}
415
+			}
416
+		}
417
+	}
418
+
419
+
420
+
421
+	/**
422
+	 * This just returns whatever is set for the current timezone.
423
+	 *
424
+	 * @access public
425
+	 * @return string timezone string
426
+	 */
427
+	public function get_timezone()
428
+	{
429
+		return $this->_timezone;
430
+	}
431
+
432
+
433
+
434
+	/**
435
+	 * This sets the internal date format to what is sent in to be used as the new default for the class
436
+	 * internally instead of wp set date format options
437
+	 *
438
+	 * @since 4.6
439
+	 * @param string $format should be a format recognizable by PHP date() functions.
440
+	 */
441
+	public function set_date_format($format)
442
+	{
443
+		$this->_dt_frmt = $format;
444
+		//clear cached_properties because they won't be relevant now.
445
+		$this->_clear_cached_properties();
446
+	}
447
+
448
+
449
+
450
+	/**
451
+	 * This sets the internal time format string to what is sent in to be used as the new default for the
452
+	 * class internally instead of wp set time format options.
453
+	 *
454
+	 * @since 4.6
455
+	 * @param string $format should be a format recognizable by PHP date() functions.
456
+	 */
457
+	public function set_time_format($format)
458
+	{
459
+		$this->_tm_frmt = $format;
460
+		//clear cached_properties because they won't be relevant now.
461
+		$this->_clear_cached_properties();
462
+	}
463
+
464
+
465
+
466
+	/**
467
+	 * This returns the current internal set format for the date and time formats.
468
+	 *
469
+	 * @param bool $full           if true (default), then return the full format.  Otherwise will return an array
470
+	 *                             where the first value is the date format and the second value is the time format.
471
+	 * @return mixed string|array
472
+	 */
473
+	public function get_format($full = true)
474
+	{
475
+		return $full ? $this->_dt_frmt . ' ' . $this->_tm_frmt : array($this->_dt_frmt, $this->_tm_frmt);
476
+	}
477
+
478
+
479
+
480
+	/**
481
+	 * cache
482
+	 * stores the passed model object on the current model object.
483
+	 * In certain circumstances, we can use this cached model object instead of querying for another one entirely.
484
+	 *
485
+	 * @param string        $relationName    one of the keys in the _model_relations array on the model. Eg
486
+	 *                                       'Registration' associated with this model object
487
+	 * @param EE_Base_Class $object_to_cache that has a relation to this model object. (Eg, if this is a Transaction,
488
+	 *                                       that could be a payment or a registration)
489
+	 * @param null          $cache_id        a string or number that will be used as the key for any Belongs_To_Many
490
+	 *                                       items which will be stored in an array on this object
491
+	 * @throws EE_Error
492
+	 * @return mixed    index into cache, or just TRUE if the relation is of type Belongs_To (because there's only one
493
+	 *                  related thing, no array)
494
+	 */
495
+	public function cache($relationName = '', $object_to_cache = null, $cache_id = null)
496
+	{
497
+		// its entirely possible that there IS no related object yet in which case there is nothing to cache.
498
+		if ( ! $object_to_cache instanceof EE_Base_Class) {
499
+			return false;
500
+		}
501
+		// also get "how" the object is related, or throw an error
502
+		if ( ! $relationship_to_model = $this->get_model()->related_settings_for($relationName)) {
503
+			throw new EE_Error(sprintf(__('There is no relationship to %s on a %s. Cannot cache it', 'event_espresso'),
504
+				$relationName, get_class($this)));
505
+		}
506
+		// how many things are related ?
507
+		if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
508
+			// if it's a "belongs to" relationship, then there's only one related model object  eg, if this is a registration, there's only 1 attendee for it
509
+			// so for these model objects just set it to be cached
510
+			$this->_model_relations[$relationName] = $object_to_cache;
511
+			$return = true;
512
+		} else {
513
+			// otherwise, this is the "many" side of a one to many relationship, so we'll add the object to the array of related objects for that type.
514
+			// eg: if this is an event, there are many registrations for that event, so we cache the registrations in an array
515
+			if ( ! is_array($this->_model_relations[$relationName])) {
516
+				// if for some reason, the cached item is a model object, then stick that in the array, otherwise start with an empty array
517
+				$this->_model_relations[$relationName] = $this->_model_relations[$relationName] instanceof EE_Base_Class
518
+					? array($this->_model_relations[$relationName]) : array();
519
+			}
520
+			// first check for a cache_id which is normally empty
521
+			if ( ! empty($cache_id)) {
522
+				// if the cache_id exists, then it means we are purposely trying to cache this with a known key that can then be used to retrieve the object later on
523
+				$this->_model_relations[$relationName][$cache_id] = $object_to_cache;
524
+				$return = $cache_id;
525
+			} elseif ($object_to_cache->ID()) {
526
+				// OR the cached object originally came from the db, so let's just use it's PK for an ID
527
+				$this->_model_relations[$relationName][$object_to_cache->ID()] = $object_to_cache;
528
+				$return = $object_to_cache->ID();
529
+			} else {
530
+				// OR it's a new object with no ID, so just throw it in the array with an auto-incremented ID
531
+				$this->_model_relations[$relationName][] = $object_to_cache;
532
+				// move the internal pointer to the end of the array
533
+				end($this->_model_relations[$relationName]);
534
+				// and grab the key so that we can return it
535
+				$return = key($this->_model_relations[$relationName]);
536
+			}
537
+		}
538
+		return $return;
539
+	}
540
+
541
+
542
+
543
+	/**
544
+	 * For adding an item to the cached_properties property.
545
+	 *
546
+	 * @access protected
547
+	 * @param string      $fieldname the property item the corresponding value is for.
548
+	 * @param mixed       $value     The value we are caching.
549
+	 * @param string|null $cache_type
550
+	 * @return void
551
+	 * @throws \EE_Error
552
+	 */
553
+	protected function _set_cached_property($fieldname, $value, $cache_type = null)
554
+	{
555
+		//first make sure this property exists
556
+		$this->get_model()->field_settings_for($fieldname);
557
+		$cache_type = empty($cache_type) ? 'standard' : $cache_type;
558
+		$this->_cached_properties[$fieldname][$cache_type] = $value;
559
+	}
560
+
561
+
562
+
563
+	/**
564
+	 * This returns the value cached property if it exists OR the actual property value if the cache doesn't exist.
565
+	 * This also SETS the cache if we return the actual property!
566
+	 *
567
+	 * @param string $fieldname        the name of the property we're trying to retrieve
568
+	 * @param bool   $pretty
569
+	 * @param string $extra_cache_ref  This allows the user to specify an extra cache ref for the given property
570
+	 *                                 (in cases where the same property may be used for different outputs
571
+	 *                                 - i.e. datetime, money etc.)
572
+	 *                                 It can also accept certain pre-defined "schema" strings
573
+	 *                                 to define how to output the property.
574
+	 *                                 see the field's prepare_for_pretty_echoing for what strings can be used
575
+	 * @return mixed                   whatever the value for the property is we're retrieving
576
+	 * @throws \EE_Error
577
+	 */
578
+	protected function _get_cached_property($fieldname, $pretty = false, $extra_cache_ref = null)
579
+	{
580
+		//verify the field exists
581
+		$this->get_model()->field_settings_for($fieldname);
582
+		$cache_type = $pretty ? 'pretty' : 'standard';
583
+		$cache_type .= ! empty($extra_cache_ref) ? '_' . $extra_cache_ref : '';
584
+		if (isset($this->_cached_properties[$fieldname][$cache_type])) {
585
+			return $this->_cached_properties[$fieldname][$cache_type];
586
+		}
587
+		$value = $this->_get_fresh_property($fieldname, $pretty, $extra_cache_ref);
588
+		$this->_set_cached_property($fieldname, $value, $cache_type);
589
+		return $value;
590
+	}
591
+
592
+
593
+
594
+	/**
595
+	 * If the cache didn't fetch the needed item, this fetches it.
596
+	 * @param string $fieldname
597
+	 * @param bool $pretty
598
+	 * @param string $extra_cache_ref
599
+	 * @return mixed
600
+	 */
601
+	protected function _get_fresh_property($fieldname, $pretty = false, $extra_cache_ref = null)
602
+	{
603
+		$field_obj = $this->get_model()->field_settings_for($fieldname);
604
+		// If this is an EE_Datetime_Field we need to make sure timezone, formats, and output are correct
605
+		if ($field_obj instanceof EE_Datetime_Field) {
606
+			$this->_prepare_datetime_field($field_obj, $pretty, $extra_cache_ref);
607
+		}
608
+		if ( ! isset($this->_fields[$fieldname])) {
609
+			$this->_fields[$fieldname] = null;
610
+		}
611
+		$value = $pretty
612
+			? $field_obj->prepare_for_pretty_echoing($this->_fields[$fieldname], $extra_cache_ref)
613
+			: $field_obj->prepare_for_get($this->_fields[$fieldname]);
614
+		return $value;
615
+	}
616
+
617
+
618
+
619
+	/**
620
+	 * set timezone, formats, and output for EE_Datetime_Field objects
621
+	 *
622
+	 * @param \EE_Datetime_Field $datetime_field
623
+	 * @param bool               $pretty
624
+	 * @param null $date_or_time
625
+	 * @return void
626
+	 * @throws \EE_Error
627
+	 */
628
+	protected function _prepare_datetime_field(
629
+		EE_Datetime_Field $datetime_field,
630
+		$pretty = false,
631
+		$date_or_time = null
632
+	) {
633
+		$datetime_field->set_timezone($this->_timezone);
634
+		$datetime_field->set_date_format($this->_dt_frmt, $pretty);
635
+		$datetime_field->set_time_format($this->_tm_frmt, $pretty);
636
+		//set the output returned
637
+		switch ($date_or_time) {
638
+			case 'D' :
639
+				$datetime_field->set_date_time_output('date');
640
+				break;
641
+			case 'T' :
642
+				$datetime_field->set_date_time_output('time');
643
+				break;
644
+			default :
645
+				$datetime_field->set_date_time_output();
646
+		}
647
+	}
648
+
649
+
650
+
651
+	/**
652
+	 * This just takes care of clearing out the cached_properties
653
+	 *
654
+	 * @return void
655
+	 */
656
+	protected function _clear_cached_properties()
657
+	{
658
+		$this->_cached_properties = array();
659
+	}
660
+
661
+
662
+
663
+	/**
664
+	 * This just clears out ONE property if it exists in the cache
665
+	 *
666
+	 * @param  string $property_name the property to remove if it exists (from the _cached_properties array)
667
+	 * @return void
668
+	 */
669
+	protected function _clear_cached_property($property_name)
670
+	{
671
+		if (isset($this->_cached_properties[$property_name])) {
672
+			unset($this->_cached_properties[$property_name]);
673
+		}
674
+	}
675
+
676
+
677
+
678
+	/**
679
+	 * Ensures that this related thing is a model object.
680
+	 *
681
+	 * @param mixed  $object_or_id EE_base_Class/int/string either a related model object, or its ID
682
+	 * @param string $model_name   name of the related thing, eg 'Attendee',
683
+	 * @return EE_Base_Class
684
+	 * @throws \EE_Error
685
+	 */
686
+	protected function ensure_related_thing_is_model_obj($object_or_id, $model_name)
687
+	{
688
+		$other_model_instance = self::_get_model_instance_with_name(
689
+			self::_get_model_classname($model_name),
690
+			$this->_timezone
691
+		);
692
+		return $other_model_instance->ensure_is_obj($object_or_id);
693
+	}
694
+
695
+
696
+
697
+	/**
698
+	 * Forgets the cached model of the given relation Name. So the next time we request it,
699
+	 * we will fetch it again from the database. (Handy if you know it's changed somehow).
700
+	 * If a specific object is supplied, and the relationship to it is either a HasMany or HABTM,
701
+	 * then only remove that one object from our cached array. Otherwise, clear the entire list
702
+	 *
703
+	 * @param string $relationName                         one of the keys in the _model_relations array on the model.
704
+	 *                                                     Eg 'Registration'
705
+	 * @param mixed  $object_to_remove_or_index_into_array or an index into the array of cached things, or NULL
706
+	 *                                                     if you intend to use $clear_all = TRUE, or the relation only
707
+	 *                                                     has 1 object anyways (ie, it's a BelongsToRelation)
708
+	 * @param bool   $clear_all                            This flags clearing the entire cache relation property if
709
+	 *                                                     this is HasMany or HABTM.
710
+	 * @throws EE_Error
711
+	 * @return EE_Base_Class | boolean from which was cleared from the cache, or true if we requested to remove a
712
+	 *                       relation from all
713
+	 */
714
+	public function clear_cache($relationName, $object_to_remove_or_index_into_array = null, $clear_all = false)
715
+	{
716
+		$relationship_to_model = $this->get_model()->related_settings_for($relationName);
717
+		$index_in_cache = '';
718
+		if ( ! $relationship_to_model) {
719
+			throw new EE_Error(
720
+				sprintf(
721
+					__("There is no relationship to %s on a %s. Cannot clear that cache", 'event_espresso'),
722
+					$relationName,
723
+					get_class($this)
724
+				)
725
+			);
726
+		}
727
+		if ($clear_all) {
728
+			$obj_removed = true;
729
+			$this->_model_relations[$relationName] = null;
730
+		} elseif ($relationship_to_model instanceof EE_Belongs_To_Relation) {
731
+			$obj_removed = $this->_model_relations[$relationName];
732
+			$this->_model_relations[$relationName] = null;
733
+		} else {
734
+			if ($object_to_remove_or_index_into_array instanceof EE_Base_Class
735
+				&& $object_to_remove_or_index_into_array->ID()
736
+			) {
737
+				$index_in_cache = $object_to_remove_or_index_into_array->ID();
738
+				if (is_array($this->_model_relations[$relationName])
739
+					&& ! isset($this->_model_relations[$relationName][$index_in_cache])
740
+				) {
741
+					$index_found_at = null;
742
+					//find this object in the array even though it has a different key
743
+					foreach ($this->_model_relations[$relationName] as $index => $obj) {
744
+						if (
745
+							$obj instanceof EE_Base_Class
746
+							&& (
747
+								$obj == $object_to_remove_or_index_into_array
748
+								|| $obj->ID() === $object_to_remove_or_index_into_array->ID()
749
+							)
750
+						) {
751
+							$index_found_at = $index;
752
+							break;
753
+						}
754
+					}
755
+					if ($index_found_at) {
756
+						$index_in_cache = $index_found_at;
757
+					} else {
758
+						//it wasn't found. huh. well obviously it doesn't need to be removed from teh cache
759
+						//if it wasn't in it to begin with. So we're done
760
+						return $object_to_remove_or_index_into_array;
761
+					}
762
+				}
763
+			} elseif ($object_to_remove_or_index_into_array instanceof EE_Base_Class) {
764
+				//so they provided a model object, but it's not yet saved to the DB... so let's go hunting for it!
765
+				foreach ($this->get_all_from_cache($relationName) as $index => $potentially_obj_we_want) {
766
+					if ($potentially_obj_we_want == $object_to_remove_or_index_into_array) {
767
+						$index_in_cache = $index;
768
+					}
769
+				}
770
+			} else {
771
+				$index_in_cache = $object_to_remove_or_index_into_array;
772
+			}
773
+			//supposedly we've found it. But it could just be that the client code
774
+			//provided a bad index/object
775
+			if (
776
+			isset(
777
+				$this->_model_relations[$relationName],
778
+				$this->_model_relations[$relationName][$index_in_cache]
779
+			)
780
+			) {
781
+				$obj_removed = $this->_model_relations[$relationName][$index_in_cache];
782
+				unset($this->_model_relations[$relationName][$index_in_cache]);
783
+			} else {
784
+				//that thing was never cached anyways.
785
+				$obj_removed = null;
786
+			}
787
+		}
788
+		return $obj_removed;
789
+	}
790
+
791
+
792
+
793
+	/**
794
+	 * update_cache_after_object_save
795
+	 * Allows a cached item to have it's cache ID (within the array of cached items) reset using the new ID it has
796
+	 * obtained after being saved to the db
797
+	 *
798
+	 * @param string         $relationName       - the type of object that is cached
799
+	 * @param \EE_Base_Class $newly_saved_object - the newly saved object to be re-cached
800
+	 * @param string         $current_cache_id   - the ID that was used when originally caching the object
801
+	 * @return boolean TRUE on success, FALSE on fail
802
+	 * @throws \EE_Error
803
+	 */
804
+	public function update_cache_after_object_save(
805
+		$relationName,
806
+		EE_Base_Class $newly_saved_object,
807
+		$current_cache_id = ''
808
+	) {
809
+		// verify that incoming object is of the correct type
810
+		$obj_class = 'EE_' . $relationName;
811
+		if ($newly_saved_object instanceof $obj_class) {
812
+			/* @type EE_Base_Class $newly_saved_object */
813
+			// now get the type of relation
814
+			$relationship_to_model = $this->get_model()->related_settings_for($relationName);
815
+			// if this is a 1:1 relationship
816
+			if ($relationship_to_model instanceof EE_Belongs_To_Relation) {
817
+				// then just replace the cached object with the newly saved object
818
+				$this->_model_relations[$relationName] = $newly_saved_object;
819
+				return true;
820
+				// or if it's some kind of sordid feral polyamorous relationship...
821
+			} elseif (is_array($this->_model_relations[$relationName])
822
+					  && isset($this->_model_relations[$relationName][$current_cache_id])
823
+			) {
824
+				// then remove the current cached item
825
+				unset($this->_model_relations[$relationName][$current_cache_id]);
826
+				// and cache the newly saved object using it's new ID
827
+				$this->_model_relations[$relationName][$newly_saved_object->ID()] = $newly_saved_object;
828
+				return true;
829
+			}
830
+		}
831
+		return false;
832
+	}
833
+
834
+
835
+
836
+	/**
837
+	 * Fetches a single EE_Base_Class on that relation. (If the relation is of type
838
+	 * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
839
+	 *
840
+	 * @param string $relationName
841
+	 * @return EE_Base_Class
842
+	 */
843
+	public function get_one_from_cache($relationName)
844
+	{
845
+		$cached_array_or_object = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName]
846
+			: null;
847
+		if (is_array($cached_array_or_object)) {
848
+			return array_shift($cached_array_or_object);
849
+		} else {
850
+			return $cached_array_or_object;
851
+		}
852
+	}
853
+
854
+
855
+
856
+	/**
857
+	 * Fetches a single EE_Base_Class on that relation. (If the relation is of type
858
+	 * BelongsTo, it will only ever have 1 object. However, other relations could have an array of objects)
859
+	 *
860
+	 * @param string $relationName
861
+	 * @throws \EE_Error
862
+	 * @return EE_Base_Class[] NOT necessarily indexed by primary keys
863
+	 */
864
+	public function get_all_from_cache($relationName)
865
+	{
866
+		$objects = isset($this->_model_relations[$relationName]) ? $this->_model_relations[$relationName] : array();
867
+		// if the result is not an array, but exists, make it an array
868
+		$objects = is_array($objects) ? $objects : array($objects);
869
+		//bugfix for https://events.codebasehq.com/projects/event-espresso/tickets/7143
870
+		//basically, if this model object was stored in the session, and these cached model objects
871
+		//already have IDs, let's make sure they're in their model's entity mapper
872
+		//otherwise we will have duplicates next time we call
873
+		// EE_Registry::instance()->load_model( $relationName )->get_one_by_ID( $result->ID() );
874
+		$model = EE_Registry::instance()->load_model($relationName);
875
+		foreach ($objects as $model_object) {
876
+			if ($model instanceof EEM_Base && $model_object instanceof EE_Base_Class) {
877
+				//ensure its in the map if it has an ID; otherwise it will be added to the map when its saved
878
+				if ($model_object->ID()) {
879
+					$model->add_to_entity_map($model_object);
880
+				}
881
+			} else {
882
+				throw new EE_Error(
883
+					sprintf(
884
+						__(
885
+							'Error retrieving related model objects. Either $1%s is not a model or $2%s is not a model object',
886
+							'event_espresso'
887
+						),
888
+						$relationName,
889
+						gettype($model_object)
890
+					)
891
+				);
892
+			}
893
+		}
894
+		return $objects;
895
+	}
896
+
897
+
898
+
899
+	/**
900
+	 * Returns the next x number of EE_Base_Class objects in sequence from this object as found in the database
901
+	 * matching the given query conditions.
902
+	 *
903
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
904
+	 * @param int   $limit              How many objects to return.
905
+	 * @param array $query_params       Any additional conditions on the query.
906
+	 * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
907
+	 *                                  you can indicate just the columns you want returned
908
+	 * @return array|EE_Base_Class[]
909
+	 * @throws \EE_Error
910
+	 */
911
+	public function next_x($field_to_order_by = null, $limit = 1, $query_params = array(), $columns_to_select = null)
912
+	{
913
+		$field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
914
+			? $this->get_model()->get_primary_key_field()->get_name()
915
+			: $field_to_order_by;
916
+		$current_value = ! empty($field) ? $this->get($field) : null;
917
+		if (empty($field) || empty($current_value)) {
918
+			return array();
919
+		}
920
+		return $this->get_model()->next_x($current_value, $field, $limit, $query_params, $columns_to_select);
921
+	}
922
+
923
+
924
+
925
+	/**
926
+	 * Returns the previous x number of EE_Base_Class objects in sequence from this object as found in the database
927
+	 * matching the given query conditions.
928
+	 *
929
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
930
+	 * @param int   $limit              How many objects to return.
931
+	 * @param array $query_params       Any additional conditions on the query.
932
+	 * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
933
+	 *                                  you can indicate just the columns you want returned
934
+	 * @return array|EE_Base_Class[]
935
+	 * @throws \EE_Error
936
+	 */
937
+	public function previous_x(
938
+		$field_to_order_by = null,
939
+		$limit = 1,
940
+		$query_params = array(),
941
+		$columns_to_select = null
942
+	) {
943
+		$field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
944
+			? $this->get_model()->get_primary_key_field()->get_name()
945
+			: $field_to_order_by;
946
+		$current_value = ! empty($field) ? $this->get($field) : null;
947
+		if (empty($field) || empty($current_value)) {
948
+			return array();
949
+		}
950
+		return $this->get_model()->previous_x($current_value, $field, $limit, $query_params, $columns_to_select);
951
+	}
952
+
953
+
954
+
955
+	/**
956
+	 * Returns the next EE_Base_Class object in sequence from this object as found in the database
957
+	 * matching the given query conditions.
958
+	 *
959
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
960
+	 * @param array $query_params       Any additional conditions on the query.
961
+	 * @param null  $columns_to_select  If left null, then an array of EE_Base_Class objects is returned, otherwise
962
+	 *                                  you can indicate just the columns you want returned
963
+	 * @return array|EE_Base_Class
964
+	 * @throws \EE_Error
965
+	 */
966
+	public function next($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
967
+	{
968
+		$field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
969
+			? $this->get_model()->get_primary_key_field()->get_name()
970
+			: $field_to_order_by;
971
+		$current_value = ! empty($field) ? $this->get($field) : null;
972
+		if (empty($field) || empty($current_value)) {
973
+			return array();
974
+		}
975
+		return $this->get_model()->next($current_value, $field, $query_params, $columns_to_select);
976
+	}
977
+
978
+
979
+
980
+	/**
981
+	 * Returns the previous EE_Base_Class object in sequence from this object as found in the database
982
+	 * matching the given query conditions.
983
+	 *
984
+	 * @param null  $field_to_order_by  What field is being used as the reference point.
985
+	 * @param array $query_params       Any additional conditions on the query.
986
+	 * @param null  $columns_to_select  If left null, then an EE_Base_Class object is returned, otherwise
987
+	 *                                  you can indicate just the column you want returned
988
+	 * @return array|EE_Base_Class
989
+	 * @throws \EE_Error
990
+	 */
991
+	public function previous($field_to_order_by = null, $query_params = array(), $columns_to_select = null)
992
+	{
993
+		$field = empty($field_to_order_by) && $this->get_model()->has_primary_key_field()
994
+			? $this->get_model()->get_primary_key_field()->get_name()
995
+			: $field_to_order_by;
996
+		$current_value = ! empty($field) ? $this->get($field) : null;
997
+		if (empty($field) || empty($current_value)) {
998
+			return array();
999
+		}
1000
+		return $this->get_model()->previous($current_value, $field, $query_params, $columns_to_select);
1001
+	}
1002
+
1003
+
1004
+
1005
+	/**
1006
+	 * Overrides parent because parent expects old models.
1007
+	 * This also doesn't do any validation, and won't work for serialized arrays
1008
+	 *
1009
+	 * @param string $field_name
1010
+	 * @param mixed  $field_value_from_db
1011
+	 * @throws \EE_Error
1012
+	 */
1013
+	public function set_from_db($field_name, $field_value_from_db)
1014
+	{
1015
+		$field_obj = $this->get_model()->field_settings_for($field_name);
1016
+		if ($field_obj instanceof EE_Model_Field_Base) {
1017
+			//you would think the DB has no NULLs for non-null label fields right? wrong!
1018
+			//eg, a CPT model object could have an entry in the posts table, but no
1019
+			//entry in the meta table. Meaning that all its columns in the meta table
1020
+			//are null! yikes! so when we find one like that, use defaults for its meta columns
1021
+			if ($field_value_from_db === null) {
1022
+				if ($field_obj->is_nullable()) {
1023
+					//if the field allows nulls, then let it be null
1024
+					$field_value = null;
1025
+				} else {
1026
+					$field_value = $field_obj->get_default_value();
1027
+				}
1028
+			} else {
1029
+				$field_value = $field_obj->prepare_for_set_from_db($field_value_from_db);
1030
+			}
1031
+			$this->_fields[$field_name] = $field_value;
1032
+			$this->_clear_cached_property($field_name);
1033
+		}
1034
+	}
1035
+
1036
+
1037
+
1038
+	/**
1039
+	 * verifies that the specified field is of the correct type
1040
+	 *
1041
+	 * @param string $field_name
1042
+	 * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1043
+	 *                                (in cases where the same property may be used for different outputs
1044
+	 *                                - i.e. datetime, money etc.)
1045
+	 * @return mixed
1046
+	 * @throws \EE_Error
1047
+	 */
1048
+	public function get($field_name, $extra_cache_ref = null)
1049
+	{
1050
+		return $this->_get_cached_property($field_name, false, $extra_cache_ref);
1051
+	}
1052
+
1053
+
1054
+
1055
+	/**
1056
+	 * This method simply returns the RAW unprocessed value for the given property in this class
1057
+	 *
1058
+	 * @param  string $field_name A valid fieldname
1059
+	 * @return mixed              Whatever the raw value stored on the property is.
1060
+	 * @throws EE_Error if fieldSettings is misconfigured or the field doesn't exist.
1061
+	 */
1062
+	public function get_raw($field_name)
1063
+	{
1064
+		$field_settings = $this->get_model()->field_settings_for($field_name);
1065
+		return $field_settings instanceof EE_Datetime_Field && $this->_fields[$field_name] instanceof DateTime
1066
+			? $this->_fields[$field_name]->format('U')
1067
+			: $this->_fields[$field_name];
1068
+	}
1069
+
1070
+
1071
+
1072
+	/**
1073
+	 * This is used to return the internal DateTime object used for a field that is a
1074
+	 * EE_Datetime_Field.
1075
+	 *
1076
+	 * @param string $field_name               The field name retrieving the DateTime object.
1077
+	 * @return mixed null | false | DateTime  If the requested field is NOT a EE_Datetime_Field then
1078
+	 * @throws \EE_Error
1079
+	 *                                         an error is set and false returned.  If the field IS an
1080
+	 *                                         EE_Datetime_Field and but the field value is null, then
1081
+	 *                                         just null is returned (because that indicates that likely
1082
+	 *                                         this field is nullable).
1083
+	 */
1084
+	public function get_DateTime_object($field_name)
1085
+	{
1086
+		$field_settings = $this->get_model()->field_settings_for($field_name);
1087
+		if ( ! $field_settings instanceof EE_Datetime_Field) {
1088
+			EE_Error::add_error(
1089
+				sprintf(
1090
+					__(
1091
+						'The field %s is not an EE_Datetime_Field field.  There is no DateTime object stored on this field type.',
1092
+						'event_espresso'
1093
+					),
1094
+					$field_name
1095
+				),
1096
+				__FILE__,
1097
+				__FUNCTION__,
1098
+				__LINE__
1099
+			);
1100
+			return false;
1101
+		}
1102
+		return $this->_fields[$field_name];
1103
+	}
1104
+
1105
+
1106
+
1107
+	/**
1108
+	 * To be used in template to immediately echo out the value, and format it for output.
1109
+	 * Eg, should call stripslashes and whatnot before echoing
1110
+	 *
1111
+	 * @param string $field_name      the name of the field as it appears in the DB
1112
+	 * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1113
+	 *                                (in cases where the same property may be used for different outputs
1114
+	 *                                - i.e. datetime, money etc.)
1115
+	 * @return void
1116
+	 * @throws \EE_Error
1117
+	 */
1118
+	public function e($field_name, $extra_cache_ref = null)
1119
+	{
1120
+		echo $this->get_pretty($field_name, $extra_cache_ref);
1121
+	}
1122
+
1123
+
1124
+
1125
+	/**
1126
+	 * Exactly like e(), echoes out the field, but sets its schema to 'form_input', so that it
1127
+	 * can be easily used as the value of form input.
1128
+	 *
1129
+	 * @param string $field_name
1130
+	 * @return void
1131
+	 * @throws \EE_Error
1132
+	 */
1133
+	public function f($field_name)
1134
+	{
1135
+		$this->e($field_name, 'form_input');
1136
+	}
1137
+
1138
+
1139
+
1140
+	/**
1141
+	 * Gets a pretty view of the field's value. $extra_cache_ref can specify different formats for this.
1142
+	 * The $extra_cache_ref will be passed to the model field's prepare_for_pretty_echoing, so consult the field's class
1143
+	 * to see what options are available.
1144
+	 * @param string $field_name
1145
+	 * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
1146
+	 *                                (in cases where the same property may be used for different outputs
1147
+	 *                                - i.e. datetime, money etc.)
1148
+	 * @return mixed
1149
+	 * @throws \EE_Error
1150
+	 */
1151
+	public function get_pretty($field_name, $extra_cache_ref = null)
1152
+	{
1153
+		return $this->_get_cached_property($field_name, true, $extra_cache_ref);
1154
+	}
1155
+
1156
+
1157
+
1158
+	/**
1159
+	 * This simply returns the datetime for the given field name
1160
+	 * Note: this protected function is called by the wrapper get_date or get_time or get_datetime functions
1161
+	 * (and the equivalent e_date, e_time, e_datetime).
1162
+	 *
1163
+	 * @access   protected
1164
+	 * @param string   $field_name   Field on the instantiated EE_Base_Class child object
1165
+	 * @param string   $dt_frmt      valid datetime format used for date
1166
+	 *                               (if '' then we just use the default on the field,
1167
+	 *                               if NULL we use the last-used format)
1168
+	 * @param string   $tm_frmt      Same as above except this is for time format
1169
+	 * @param string   $date_or_time if NULL then both are returned, otherwise "D" = only date and "T" = only time.
1170
+	 * @param  boolean $echo         Whether the dtt is echoing using pretty echoing or just returned using vanilla get
1171
+	 * @return string|bool|EE_Error string on success, FALSE on fail, or EE_Error Exception is thrown
1172
+	 *                               if field is not a valid dtt field, or void if echoing
1173
+	 * @throws \EE_Error
1174
+	 */
1175
+	protected function _get_datetime($field_name, $dt_frmt = '', $tm_frmt = '', $date_or_time = '', $echo = false)
1176
+	{
1177
+		// clear cached property
1178
+		$this->_clear_cached_property($field_name);
1179
+		//reset format properties because they are used in get()
1180
+		$this->_dt_frmt = $dt_frmt !== '' ? $dt_frmt : $this->_dt_frmt;
1181
+		$this->_tm_frmt = $tm_frmt !== '' ? $tm_frmt : $this->_tm_frmt;
1182
+		if ($echo) {
1183
+			$this->e($field_name, $date_or_time);
1184
+			return '';
1185
+		}
1186
+		return $this->get($field_name, $date_or_time);
1187
+	}
1188
+
1189
+
1190
+
1191
+	/**
1192
+	 * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the date
1193
+	 * portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1194
+	 * other echoes the pretty value for dtt)
1195
+	 *
1196
+	 * @param  string $field_name name of model object datetime field holding the value
1197
+	 * @param  string $format     format for the date returned (if NULL we use default in dt_frmt property)
1198
+	 * @return string            datetime value formatted
1199
+	 * @throws \EE_Error
1200
+	 */
1201
+	public function get_date($field_name, $format = '')
1202
+	{
1203
+		return $this->_get_datetime($field_name, $format, null, 'D');
1204
+	}
1205
+
1206
+
1207
+
1208
+	/**
1209
+	 * @param      $field_name
1210
+	 * @param string $format
1211
+	 * @throws \EE_Error
1212
+	 */
1213
+	public function e_date($field_name, $format = '')
1214
+	{
1215
+		$this->_get_datetime($field_name, $format, null, 'D', true);
1216
+	}
1217
+
1218
+
1219
+
1220
+	/**
1221
+	 * below are wrapper functions for the various datetime outputs that can be obtained for JUST returning the time
1222
+	 * portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1223
+	 * other echoes the pretty value for dtt)
1224
+	 *
1225
+	 * @param  string $field_name name of model object datetime field holding the value
1226
+	 * @param  string $format     format for the time returned ( if NULL we use default in tm_frmt property)
1227
+	 * @return string             datetime value formatted
1228
+	 * @throws \EE_Error
1229
+	 */
1230
+	public function get_time($field_name, $format = '')
1231
+	{
1232
+		return $this->_get_datetime($field_name, null, $format, 'T');
1233
+	}
1234
+
1235
+
1236
+
1237
+	/**
1238
+	 * @param      $field_name
1239
+	 * @param string $format
1240
+	 * @throws \EE_Error
1241
+	 */
1242
+	public function e_time($field_name, $format = '')
1243
+	{
1244
+		$this->_get_datetime($field_name, null, $format, 'T', true);
1245
+	}
1246
+
1247
+
1248
+
1249
+	/**
1250
+	 * below are wrapper functions for the various datetime outputs that can be obtained for returning the date AND
1251
+	 * time portion of a datetime value. (note the only difference between get_ and e_ is one returns the value and the
1252
+	 * other echoes the pretty value for dtt)
1253
+	 *
1254
+	 * @param  string $field_name name of model object datetime field holding the value
1255
+	 * @param  string $dt_frmt    format for the date returned (if NULL we use default in dt_frmt property)
1256
+	 * @param  string $tm_frmt    format for the time returned (if NULL we use default in tm_frmt property)
1257
+	 * @return string             datetime value formatted
1258
+	 * @throws \EE_Error
1259
+	 */
1260
+	public function get_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1261
+	{
1262
+		return $this->_get_datetime($field_name, $dt_frmt, $tm_frmt);
1263
+	}
1264
+
1265
+
1266
+
1267
+	/**
1268
+	 * @param string $field_name
1269
+	 * @param string $dt_frmt
1270
+	 * @param string $tm_frmt
1271
+	 * @throws \EE_Error
1272
+	 */
1273
+	public function e_datetime($field_name, $dt_frmt = '', $tm_frmt = '')
1274
+	{
1275
+		$this->_get_datetime($field_name, $dt_frmt, $tm_frmt, null, true);
1276
+	}
1277
+
1278
+
1279
+
1280
+	/**
1281
+	 * Get the i8ln value for a date using the WordPress @see date_i18n function.
1282
+	 *
1283
+	 * @param string $field_name The EE_Datetime_Field reference for the date being retrieved.
1284
+	 * @param string $format     PHP valid date/time string format.  If none is provided then the internal set format
1285
+	 *                           on the object will be used.
1286
+	 * @return string Date and time string in set locale or false if no field exists for the given
1287
+	 * @throws \EE_Error
1288
+	 *                           field name.
1289
+	 */
1290
+	public function get_i18n_datetime($field_name, $format = '')
1291
+	{
1292
+		$format = empty($format) ? $this->_dt_frmt . ' ' . $this->_tm_frmt : $format;
1293
+		return date_i18n(
1294
+			$format,
1295
+			EEH_DTT_Helper::get_timestamp_with_offset($this->get_raw($field_name), $this->_timezone)
1296
+		);
1297
+	}
1298
+
1299
+
1300
+
1301
+	/**
1302
+	 * This method validates whether the given field name is a valid field on the model object as well as it is of a
1303
+	 * type EE_Datetime_Field.  On success there will be returned the field settings.  On fail an EE_Error exception is
1304
+	 * thrown.
1305
+	 *
1306
+	 * @param  string $field_name The field name being checked
1307
+	 * @throws EE_Error
1308
+	 * @return EE_Datetime_Field
1309
+	 */
1310
+	protected function _get_dtt_field_settings($field_name)
1311
+	{
1312
+		$field = $this->get_model()->field_settings_for($field_name);
1313
+		//check if field is dtt
1314
+		if ($field instanceof EE_Datetime_Field) {
1315
+			return $field;
1316
+		} else {
1317
+			throw new EE_Error(sprintf(__('The field name "%s" has been requested for the EE_Base_Class datetime functions and it is not a valid EE_Datetime_Field.  Please check the spelling of the field and make sure it has been setup as a EE_Datetime_Field in the %s model constructor',
1318
+				'event_espresso'), $field_name, self::_get_model_classname(get_class($this))));
1319
+		}
1320
+	}
1321
+
1322
+
1323
+
1324
+
1325
+	/**
1326
+	 * NOTE ABOUT BELOW:
1327
+	 * These convenience date and time setters are for setting date and time independently.  In other words you might
1328
+	 * want to change the time on a datetime_field but leave the date the same (or vice versa). IF on the other hand
1329
+	 * you want to set both date and time at the same time, you can just use the models default set($fieldname,$value)
1330
+	 * method and make sure you send the entire datetime value for setting.
1331
+	 */
1332
+	/**
1333
+	 * sets the time on a datetime property
1334
+	 *
1335
+	 * @access protected
1336
+	 * @param string|Datetime $time      a valid time string for php datetime functions (or DateTime object)
1337
+	 * @param string          $fieldname the name of the field the time is being set on (must match a EE_Datetime_Field)
1338
+	 * @throws \EE_Error
1339
+	 */
1340
+	protected function _set_time_for($time, $fieldname)
1341
+	{
1342
+		$this->_set_date_time('T', $time, $fieldname);
1343
+	}
1344
+
1345
+
1346
+
1347
+	/**
1348
+	 * sets the date on a datetime property
1349
+	 *
1350
+	 * @access protected
1351
+	 * @param string|DateTime $date      a valid date string for php datetime functions ( or DateTime object)
1352
+	 * @param string          $fieldname the name of the field the date is being set on (must match a EE_Datetime_Field)
1353
+	 * @throws \EE_Error
1354
+	 */
1355
+	protected function _set_date_for($date, $fieldname)
1356
+	{
1357
+		$this->_set_date_time('D', $date, $fieldname);
1358
+	}
1359
+
1360
+
1361
+
1362
+	/**
1363
+	 * This takes care of setting a date or time independently on a given model object property. This method also
1364
+	 * verifies that the given fieldname matches a model object property and is for a EE_Datetime_Field field
1365
+	 *
1366
+	 * @access protected
1367
+	 * @param string          $what           "T" for time, 'B' for both, 'D' for Date.
1368
+	 * @param string|DateTime $datetime_value A valid Date or Time string (or DateTime object)
1369
+	 * @param string          $fieldname      the name of the field the date OR time is being set on (must match a
1370
+	 *                                        EE_Datetime_Field property)
1371
+	 * @throws \EE_Error
1372
+	 */
1373
+	protected function _set_date_time($what = 'T', $datetime_value, $fieldname)
1374
+	{
1375
+		$field = $this->_get_dtt_field_settings($fieldname);
1376
+		$field->set_timezone($this->_timezone);
1377
+		$field->set_date_format($this->_dt_frmt);
1378
+		$field->set_time_format($this->_tm_frmt);
1379
+		switch ($what) {
1380
+			case 'T' :
1381
+				$this->_fields[$fieldname] = $field->prepare_for_set_with_new_time(
1382
+					$datetime_value,
1383
+					$this->_fields[$fieldname]
1384
+				);
1385
+				break;
1386
+			case 'D' :
1387
+				$this->_fields[$fieldname] = $field->prepare_for_set_with_new_date(
1388
+					$datetime_value,
1389
+					$this->_fields[$fieldname]
1390
+				);
1391
+				break;
1392
+			case 'B' :
1393
+				$this->_fields[$fieldname] = $field->prepare_for_set($datetime_value);
1394
+				break;
1395
+		}
1396
+		$this->_clear_cached_property($fieldname);
1397
+	}
1398
+
1399
+
1400
+
1401
+	/**
1402
+	 * This will return a timestamp for the website timezone but ONLY when the current website timezone is different
1403
+	 * than the timezone set for the website. NOTE, this currently only works well with methods that return values.  If
1404
+	 * you use it with methods that echo values the $_timestamp property may not get reset to its original value and
1405
+	 * that could lead to some unexpected results!
1406
+	 *
1407
+	 * @access public
1408
+	 * @param string               $field_name This is the name of the field on the object that contains the date/time
1409
+	 *                                         value being returned.
1410
+	 * @param string               $callback   must match a valid method in this class (defaults to get_datetime)
1411
+	 * @param mixed (array|string) $args       This is the arguments that will be passed to the callback.
1412
+	 * @param string               $prepend    You can include something to prepend on the timestamp
1413
+	 * @param string               $append     You can include something to append on the timestamp
1414
+	 * @throws EE_Error
1415
+	 * @return string timestamp
1416
+	 */
1417
+	public function display_in_my_timezone(
1418
+		$field_name,
1419
+		$callback = 'get_datetime',
1420
+		$args = null,
1421
+		$prepend = '',
1422
+		$append = ''
1423
+	) {
1424
+		$timezone = EEH_DTT_Helper::get_timezone();
1425
+		if ($timezone === $this->_timezone) {
1426
+			return '';
1427
+		}
1428
+		$original_timezone = $this->_timezone;
1429
+		$this->set_timezone($timezone);
1430
+		$fn = (array)$field_name;
1431
+		$args = array_merge($fn, (array)$args);
1432
+		if ( ! method_exists($this, $callback)) {
1433
+			throw new EE_Error(
1434
+				sprintf(
1435
+					__(
1436
+						'The method named "%s" given as the callback param in "display_in_my_timezone" does not exist.  Please check your spelling',
1437
+						'event_espresso'
1438
+					),
1439
+					$callback
1440
+				)
1441
+			);
1442
+		}
1443
+		$args = (array)$args;
1444
+		$return = $prepend . call_user_func_array(array($this, $callback), $args) . $append;
1445
+		$this->set_timezone($original_timezone);
1446
+		return $return;
1447
+	}
1448
+
1449
+
1450
+
1451
+	/**
1452
+	 * Deletes this model object.
1453
+	 * This calls the `EE_Base_Class::_delete` method.  Child classes wishing to change default behaviour should
1454
+	 * override
1455
+	 * `EE_Base_Class::_delete` NOT this class.
1456
+	 *
1457
+	 * @return boolean | int
1458
+	 * @throws \EE_Error
1459
+	 */
1460
+	public function delete()
1461
+	{
1462
+		/**
1463
+		 * Called just before the `EE_Base_Class::_delete` method call.
1464
+		 * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1465
+		 * should be aware that `_delete` may not always result in a permanent delete.  For example, `EE_Soft_Delete_Base_Class::_delete`
1466
+		 * soft deletes (trash) the object and does not permanently delete it.
1467
+		 *
1468
+		 * @param EE_Base_Class $model_object about to be 'deleted'
1469
+		 */
1470
+		do_action('AHEE__EE_Base_Class__delete__before', $this);
1471
+		$result = $this->_delete();
1472
+		/**
1473
+		 * Called just after the `EE_Base_Class::_delete` method call.
1474
+		 * Note: `EE_Base_Class::_delete` might be overridden by child classes so any client code hooking into these actions
1475
+		 * should be aware that `_delete` may not always result in a permanent delete.  For example `EE_Soft_Base_Class::_delete`
1476
+		 * soft deletes (trash) the object and does not permanently delete it.
1477
+		 *
1478
+		 * @param EE_Base_Class $model_object that was just 'deleted'
1479
+		 * @param boolean       $result
1480
+		 */
1481
+		do_action('AHEE__EE_Base_Class__delete__end', $this, $result);
1482
+		return $result;
1483
+	}
1484
+
1485
+
1486
+
1487
+	/**
1488
+	 * Calls the specific delete method for the instantiated class.
1489
+	 * This method is called by the public `EE_Base_Class::delete` method.  Any child classes desiring to override
1490
+	 * default functionality for "delete" (which is to call `permanently_delete`) should override this method NOT
1491
+	 * `EE_Base_Class::delete`
1492
+	 *
1493
+	 * @return bool|int
1494
+	 * @throws \EE_Error
1495
+	 */
1496
+	protected function _delete()
1497
+	{
1498
+		return $this->delete_permanently();
1499
+	}
1500
+
1501
+
1502
+
1503
+	/**
1504
+	 * Deletes this model object permanently from db (but keep in mind related models my block the delete and return an
1505
+	 * error)
1506
+	 *
1507
+	 * @return bool | int
1508
+	 * @throws \EE_Error
1509
+	 */
1510
+	public function delete_permanently()
1511
+	{
1512
+		/**
1513
+		 * Called just before HARD deleting a model object
1514
+		 *
1515
+		 * @param EE_Base_Class $model_object about to be 'deleted'
1516
+		 */
1517
+		do_action('AHEE__EE_Base_Class__delete_permanently__before', $this);
1518
+		$model = $this->get_model();
1519
+		$result = $model->delete_permanently_by_ID($this->ID());
1520
+		$this->refresh_cache_of_related_objects();
1521
+		/**
1522
+		 * Called just after HARD deleting a model object
1523
+		 *
1524
+		 * @param EE_Base_Class $model_object that was just 'deleted'
1525
+		 * @param boolean       $result
1526
+		 */
1527
+		do_action('AHEE__EE_Base_Class__delete_permanently__end', $this, $result);
1528
+		return $result;
1529
+	}
1530
+
1531
+
1532
+
1533
+	/**
1534
+	 * When this model object is deleted, it may still be cached on related model objects. This clears the cache of
1535
+	 * related model objects
1536
+	 *
1537
+	 * @throws \EE_Error
1538
+	 */
1539
+	public function refresh_cache_of_related_objects()
1540
+	{
1541
+		foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
1542
+			if ( ! empty($this->_model_relations[$relation_name])) {
1543
+				$related_objects = $this->_model_relations[$relation_name];
1544
+				if ($relation_obj instanceof EE_Belongs_To_Relation) {
1545
+					//this relation only stores a single model object, not an array
1546
+					//but let's make it consistent
1547
+					$related_objects = array($related_objects);
1548
+				}
1549
+				foreach ($related_objects as $related_object) {
1550
+					//only refresh their cache if they're in memory
1551
+					if ($related_object instanceof EE_Base_Class) {
1552
+						$related_object->clear_cache($this->get_model()->get_this_model_name(), $this);
1553
+					}
1554
+				}
1555
+			}
1556
+		}
1557
+	}
1558
+
1559
+
1560
+
1561
+	/**
1562
+	 *        Saves this object to the database. An array may be supplied to set some values on this
1563
+	 * object just before saving.
1564
+	 *
1565
+	 * @access public
1566
+	 * @param array $set_cols_n_values keys are field names, values are their new values,
1567
+	 *                                 if provided during the save() method (often client code will change the fields'
1568
+	 *                                 values before calling save)
1569
+	 * @throws \EE_Error
1570
+	 * @return int , 1 on a successful update, the ID of the new entry on insert; 0 on failure or if the model object
1571
+	 *                                 isn't allowed to persist (as determined by EE_Base_Class::allow_persist())
1572
+	 */
1573
+	public function save($set_cols_n_values = array())
1574
+	{
1575
+		/**
1576
+		 * Filters the fields we're about to save on the model object
1577
+		 *
1578
+		 * @param array         $set_cols_n_values
1579
+		 * @param EE_Base_Class $model_object
1580
+		 */
1581
+		$set_cols_n_values = (array)apply_filters('FHEE__EE_Base_Class__save__set_cols_n_values', $set_cols_n_values,
1582
+			$this);
1583
+		//set attributes as provided in $set_cols_n_values
1584
+		foreach ($set_cols_n_values as $column => $value) {
1585
+			$this->set($column, $value);
1586
+		}
1587
+		// no changes ? then don't do anything
1588
+		if (! $this->_has_changes && $this->ID() && $this->get_model()->get_primary_key_field()->is_auto_increment()) {
1589
+			return 0;
1590
+		}
1591
+		/**
1592
+		 * Saving a model object.
1593
+		 * Before we perform a save, this action is fired.
1594
+		 *
1595
+		 * @param EE_Base_Class $model_object the model object about to be saved.
1596
+		 */
1597
+		do_action('AHEE__EE_Base_Class__save__begin', $this);
1598
+		if ( ! $this->allow_persist()) {
1599
+			return 0;
1600
+		}
1601
+		//now get current attribute values
1602
+		$save_cols_n_values = $this->_fields;
1603
+		//if the object already has an ID, update it. Otherwise, insert it
1604
+		//also: change the assumption about values passed to the model NOT being prepare dby the model object. They have been
1605
+		$old_assumption_concerning_value_preparation = $this->get_model()
1606
+															->get_assumption_concerning_values_already_prepared_by_model_object();
1607
+		$this->get_model()->assume_values_already_prepared_by_model_object(true);
1608
+		//does this model have an autoincrement PK?
1609
+		if ($this->get_model()->has_primary_key_field()) {
1610
+			if ($this->get_model()->get_primary_key_field()->is_auto_increment()) {
1611
+				//ok check if it's set, if so: update; if not, insert
1612
+				if ( ! empty($save_cols_n_values[self::_get_primary_key_name(get_class($this))])) {
1613
+					$results = $this->get_model()->update_by_ID($save_cols_n_values, $this->ID());
1614
+				} else {
1615
+					unset($save_cols_n_values[self::_get_primary_key_name(get_class($this))]);
1616
+					$results = $this->get_model()->insert($save_cols_n_values);
1617
+					if ($results) {
1618
+						//if successful, set the primary key
1619
+						//but don't use the normal SET method, because it will check if
1620
+						//an item with the same ID exists in the mapper & db, then
1621
+						//will find it in the db (because we just added it) and THAT object
1622
+						//will get added to the mapper before we can add this one!
1623
+						//but if we just avoid using the SET method, all that headache can be avoided
1624
+						$pk_field_name = self::_get_primary_key_name(get_class($this));
1625
+						$this->_fields[$pk_field_name] = $results;
1626
+						$this->_clear_cached_property($pk_field_name);
1627
+						$this->get_model()->add_to_entity_map($this);
1628
+						$this->_update_cached_related_model_objs_fks();
1629
+					}
1630
+				}
1631
+			} else {//PK is NOT auto-increment
1632
+				//so check if one like it already exists in the db
1633
+				if ($this->get_model()->exists_by_ID($this->ID())) {
1634
+					if (WP_DEBUG && ! $this->in_entity_map()) {
1635
+						throw new EE_Error(
1636
+							sprintf(
1637
+								__('Using a model object %1$s that is NOT in the entity map, can lead to unexpected errors. You should either: %4$s 1. Put it in the entity mapper by calling %2$s %4$s 2. Discard this model object and use what is in the entity mapper %4$s 3. Fetch from the database using %3$s',
1638
+									'event_espresso'),
1639
+								get_class($this),
1640
+								get_class($this->get_model()) . '::instance()->add_to_entity_map()',
1641
+								get_class($this->get_model()) . '::instance()->get_one_by_ID()',
1642
+								'<br />'
1643
+							)
1644
+						);
1645
+					}
1646
+					$results = $this->get_model()->update_by_ID($save_cols_n_values, $this->ID());
1647
+				} else {
1648
+					$results = $this->get_model()->insert($save_cols_n_values);
1649
+					$this->_update_cached_related_model_objs_fks();
1650
+				}
1651
+			}
1652
+		} else {//there is NO primary key
1653
+			$already_in_db = false;
1654
+			foreach ($this->get_model()->unique_indexes() as $index) {
1655
+				$uniqueness_where_params = array_intersect_key($save_cols_n_values, $index->fields());
1656
+				if ($this->get_model()->exists(array($uniqueness_where_params))) {
1657
+					$already_in_db = true;
1658
+				}
1659
+			}
1660
+			if ($already_in_db) {
1661
+				$combined_pk_fields_n_values = array_intersect_key($save_cols_n_values,
1662
+					$this->get_model()->get_combined_primary_key_fields());
1663
+				$results = $this->get_model()->update($save_cols_n_values, $combined_pk_fields_n_values);
1664
+			} else {
1665
+				$results = $this->get_model()->insert($save_cols_n_values);
1666
+			}
1667
+		}
1668
+		//restore the old assumption about values being prepared by the model object
1669
+		$this->get_model()
1670
+			 ->assume_values_already_prepared_by_model_object($old_assumption_concerning_value_preparation);
1671
+		/**
1672
+		 * After saving the model object this action is called
1673
+		 *
1674
+		 * @param EE_Base_Class $model_object which was just saved
1675
+		 * @param boolean|int   $results      if it were updated, TRUE or FALSE; if it were newly inserted
1676
+		 *                                    the new ID (or 0 if an error occurred and it wasn't updated)
1677
+		 */
1678
+		do_action('AHEE__EE_Base_Class__save__end', $this, $results);
1679
+		$this->_has_changes = false;
1680
+		return $results;
1681
+	}
1682
+
1683
+
1684
+
1685
+	/**
1686
+	 * Updates the foreign key on related models objects pointing to this to have this model object's ID
1687
+	 * as their foreign key.  If the cached related model objects already exist in the db, saves them (so that the DB
1688
+	 * is consistent) Especially useful in case we JUST added this model object ot the database and we want to let its
1689
+	 * cached relations with foreign keys to it know about that change. Eg: we've created a transaction but haven't
1690
+	 * saved it to the db. We also create a registration and don't save it to the DB, but we DO cache it on the
1691
+	 * transaction. Now, when we save the transaction, the registration's TXN_ID will be automatically updated, whether
1692
+	 * or not they exist in the DB (if they do, their DB records will be automatically updated)
1693
+	 *
1694
+	 * @return void
1695
+	 * @throws \EE_Error
1696
+	 */
1697
+	protected function _update_cached_related_model_objs_fks()
1698
+	{
1699
+		foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
1700
+			if ($relation_obj instanceof EE_Has_Many_Relation) {
1701
+				foreach ($this->get_all_from_cache($relation_name) as $related_model_obj_in_cache) {
1702
+					$fk_to_this = $related_model_obj_in_cache->get_model()->get_foreign_key_to(
1703
+						$this->get_model()->get_this_model_name()
1704
+					);
1705
+					$related_model_obj_in_cache->set($fk_to_this->get_name(), $this->ID());
1706
+					if ($related_model_obj_in_cache->ID()) {
1707
+						$related_model_obj_in_cache->save();
1708
+					}
1709
+				}
1710
+			}
1711
+		}
1712
+	}
1713
+
1714
+
1715
+
1716
+	/**
1717
+	 * Saves this model object and its NEW cached relations to the database.
1718
+	 * (Meaning, for now, IT DOES NOT WORK if the cached items already exist in the DB.
1719
+	 * In order for that to work, we would need to mark model objects as dirty/clean...
1720
+	 * because otherwise, there's a potential for infinite looping of saving
1721
+	 * Saves the cached related model objects, and ensures the relation between them
1722
+	 * and this object and properly setup
1723
+	 *
1724
+	 * @return int ID of new model object on save; 0 on failure+
1725
+	 * @throws \EE_Error
1726
+	 */
1727
+	public function save_new_cached_related_model_objs()
1728
+	{
1729
+		//make sure this has been saved
1730
+		if ( ! $this->ID()) {
1731
+			$id = $this->save();
1732
+		} else {
1733
+			$id = $this->ID();
1734
+		}
1735
+		//now save all the NEW cached model objects  (ie they don't exist in the DB)
1736
+		foreach ($this->get_model()->relation_settings() as $relationName => $relationObj) {
1737
+			if ($this->_model_relations[$relationName]) {
1738
+				//is this a relation where we should expect just ONE related object (ie, EE_Belongs_To_relation)
1739
+				//or MANY related objects (ie, EE_HABTM_Relation or EE_Has_Many_Relation)?
1740
+				if ($relationObj instanceof EE_Belongs_To_Relation) {
1741
+					//add a relation to that relation type (which saves the appropriate thing in the process)
1742
+					//but ONLY if it DOES NOT exist in the DB
1743
+					/* @var $related_model_obj EE_Base_Class */
1744
+					$related_model_obj = $this->_model_relations[$relationName];
1745
+					//					if( ! $related_model_obj->ID()){
1746
+					$this->_add_relation_to($related_model_obj, $relationName);
1747
+					$related_model_obj->save_new_cached_related_model_objs();
1748
+					//					}
1749
+				} else {
1750
+					foreach ($this->_model_relations[$relationName] as $related_model_obj) {
1751
+						//add a relation to that relation type (which saves the appropriate thing in the process)
1752
+						//but ONLY if it DOES NOT exist in the DB
1753
+						//						if( ! $related_model_obj->ID()){
1754
+						$this->_add_relation_to($related_model_obj, $relationName);
1755
+						$related_model_obj->save_new_cached_related_model_objs();
1756
+						//						}
1757
+					}
1758
+				}
1759
+			}
1760
+		}
1761
+		return $id;
1762
+	}
1763
+
1764
+
1765
+
1766
+	/**
1767
+	 * for getting a model while instantiated.
1768
+	 *
1769
+	 * @return \EEM_Base | \EEM_CPT_Base
1770
+	 */
1771
+	public function get_model()
1772
+	{
1773
+		$modelName = self::_get_model_classname(get_class($this));
1774
+		return self::_get_model_instance_with_name($modelName, $this->_timezone);
1775
+	}
1776
+
1777
+
1778
+
1779
+	/**
1780
+	 * @param $props_n_values
1781
+	 * @param $classname
1782
+	 * @return mixed bool|EE_Base_Class|EEM_CPT_Base
1783
+	 * @throws \EE_Error
1784
+	 */
1785
+	protected static function _get_object_from_entity_mapper($props_n_values, $classname)
1786
+	{
1787
+		//TODO: will not work for Term_Relationships because they have no PK!
1788
+		$primary_id_ref = self::_get_primary_key_name($classname);
1789
+		if (array_key_exists($primary_id_ref, $props_n_values) && ! empty($props_n_values[$primary_id_ref])) {
1790
+			$id = $props_n_values[$primary_id_ref];
1791
+			return self::_get_model($classname)->get_from_entity_map($id);
1792
+		}
1793
+		return false;
1794
+	}
1795
+
1796
+
1797
+
1798
+	/**
1799
+	 * This is called by child static "new_instance" method and we'll check to see if there is an existing db entry for
1800
+	 * the primary key (if present in incoming values). If there is a key in the incoming array that matches the
1801
+	 * primary key for the model AND it is not null, then we check the db. If there's a an object we return it.  If not
1802
+	 * we return false.
1803
+	 *
1804
+	 * @param  array  $props_n_values   incoming array of properties and their values
1805
+	 * @param  string $classname        the classname of the child class
1806
+	 * @param null    $timezone
1807
+	 * @param array   $date_formats     incoming date_formats in an array where the first value is the
1808
+	 *                                  date_format and the second value is the time format
1809
+	 * @return mixed (EE_Base_Class|bool)
1810
+	 * @throws \EE_Error
1811
+	 */
1812
+	protected static function _check_for_object($props_n_values, $classname, $timezone = null, $date_formats = array())
1813
+	{
1814
+		$existing = null;
1815
+		if (self::_get_model($classname)->has_primary_key_field()) {
1816
+			$primary_id_ref = self::_get_primary_key_name($classname);
1817
+			if (array_key_exists($primary_id_ref, $props_n_values)
1818
+				&& ! empty($props_n_values[$primary_id_ref])
1819
+			) {
1820
+				$existing = self::_get_model($classname, $timezone)->get_one_by_ID(
1821
+					$props_n_values[$primary_id_ref]
1822
+				);
1823
+			}
1824
+		} elseif (self::_get_model($classname, $timezone)->has_all_combined_primary_key_fields($props_n_values)) {
1825
+			//no primary key on this model, but there's still a matching item in the DB
1826
+			$existing = self::_get_model($classname, $timezone)->get_one_by_ID(
1827
+				self::_get_model($classname, $timezone)->get_index_primary_key_string($props_n_values)
1828
+			);
1829
+		}
1830
+		if ($existing) {
1831
+			//set date formats if present before setting values
1832
+			if ( ! empty($date_formats) && is_array($date_formats)) {
1833
+				$existing->set_date_format($date_formats[0]);
1834
+				$existing->set_time_format($date_formats[1]);
1835
+			} else {
1836
+				//set default formats for date and time
1837
+				$existing->set_date_format(get_option('date_format'));
1838
+				$existing->set_time_format(get_option('time_format'));
1839
+			}
1840
+			foreach ($props_n_values as $property => $field_value) {
1841
+				$existing->set($property, $field_value);
1842
+			}
1843
+			return $existing;
1844
+		} else {
1845
+			return false;
1846
+		}
1847
+	}
1848
+
1849
+
1850
+
1851
+	/**
1852
+	 * Gets the EEM_*_Model for this class
1853
+	 *
1854
+	 * @access public now, as this is more convenient
1855
+	 * @param      $classname
1856
+	 * @param null $timezone
1857
+	 * @throws EE_Error
1858
+	 * @return EEM_Base
1859
+	 */
1860
+	protected static function _get_model($classname, $timezone = null)
1861
+	{
1862
+		//find model for this class
1863
+		if ( ! $classname) {
1864
+			throw new EE_Error(
1865
+				sprintf(
1866
+					__(
1867
+						"What were you thinking calling _get_model(%s)?? You need to specify the class name",
1868
+						"event_espresso"
1869
+					),
1870
+					$classname
1871
+				)
1872
+			);
1873
+		}
1874
+		$modelName = self::_get_model_classname($classname);
1875
+		return self::_get_model_instance_with_name($modelName, $timezone);
1876
+	}
1877
+
1878
+
1879
+
1880
+	/**
1881
+	 * Gets the model instance (eg instance of EEM_Attendee) given its classname (eg EE_Attendee)
1882
+	 *
1883
+	 * @param string $model_classname
1884
+	 * @param null   $timezone
1885
+	 * @return EEM_Base
1886
+	 */
1887
+	protected static function _get_model_instance_with_name($model_classname, $timezone = null)
1888
+	{
1889
+		$model_classname = str_replace('EEM_', '', $model_classname);
1890
+		$model = EE_Registry::instance()->load_model($model_classname);
1891
+		$model->set_timezone($timezone);
1892
+		return $model;
1893
+	}
1894
+
1895
+
1896
+
1897
+	/**
1898
+	 * If a model name is provided (eg Registration), gets the model classname for that model.
1899
+	 * Also works if a model class's classname is provided (eg EE_Registration).
1900
+	 *
1901
+	 * @param null $model_name
1902
+	 * @return string like EEM_Attendee
1903
+	 */
1904
+	private static function _get_model_classname($model_name = null)
1905
+	{
1906
+		if (strpos($model_name, "EE_") === 0) {
1907
+			$model_classname = str_replace("EE_", "EEM_", $model_name);
1908
+		} else {
1909
+			$model_classname = "EEM_" . $model_name;
1910
+		}
1911
+		return $model_classname;
1912
+	}
1913
+
1914
+
1915
+
1916
+	/**
1917
+	 * returns the name of the primary key attribute
1918
+	 *
1919
+	 * @param null $classname
1920
+	 * @throws EE_Error
1921
+	 * @return string
1922
+	 */
1923
+	protected static function _get_primary_key_name($classname = null)
1924
+	{
1925
+		if ( ! $classname) {
1926
+			throw new EE_Error(
1927
+				sprintf(
1928
+					__("What were you thinking calling _get_primary_key_name(%s)", "event_espresso"),
1929
+					$classname
1930
+				)
1931
+			);
1932
+		}
1933
+		return self::_get_model($classname)->get_primary_key_field()->get_name();
1934
+	}
1935
+
1936
+
1937
+
1938
+	/**
1939
+	 * Gets the value of the primary key.
1940
+	 * If the object hasn't yet been saved, it should be whatever the model field's default was
1941
+	 * (eg, if this were the EE_Event class, look at the primary key field on EEM_Event and see what its default value
1942
+	 * is. Usually defaults for integer primary keys are 0; string primary keys are usually NULL).
1943
+	 *
1944
+	 * @return mixed, if the primary key is of type INT it'll be an int. Otherwise it could be a string
1945
+	 * @throws \EE_Error
1946
+	 */
1947
+	public function ID()
1948
+	{
1949
+		//now that we know the name of the variable, use a variable variable to get its value and return its
1950
+		if ($this->get_model()->has_primary_key_field()) {
1951
+			return $this->_fields[self::_get_primary_key_name(get_class($this))];
1952
+		} else {
1953
+			return $this->get_model()->get_index_primary_key_string($this->_fields);
1954
+		}
1955
+	}
1956
+
1957
+
1958
+
1959
+	/**
1960
+	 * Adds a relationship to the specified EE_Base_Class object, given the relationship's name. Eg, if the current
1961
+	 * model is related to a group of events, the $relationName should be 'Event', and should be a key in the EE
1962
+	 * Model's $_model_relations array. If this model object doesn't exist in the DB, just caches the related thing
1963
+	 *
1964
+	 * @param mixed  $otherObjectModelObjectOrID       EE_Base_Class or the ID of the other object
1965
+	 * @param string $relationName                     eg 'Events','Question',etc.
1966
+	 *                                                 an attendee to a group, you also want to specify which role they
1967
+	 *                                                 will have in that group. So you would use this parameter to
1968
+	 *                                                 specify array('role-column-name'=>'role-id')
1969
+	 * @param array  $extra_join_model_fields_n_values You can optionally include an array of key=>value pairs that
1970
+	 *                                                 allow you to further constrict the relation to being added.
1971
+	 *                                                 However, keep in mind that the columns (keys) given must match a
1972
+	 *                                                 column on the JOIN table and currently only the HABTM models
1973
+	 *                                                 accept these additional conditions.  Also remember that if an
1974
+	 *                                                 exact match isn't found for these extra cols/val pairs, then a
1975
+	 *                                                 NEW row is created in the join table.
1976
+	 * @param null   $cache_id
1977
+	 * @throws EE_Error
1978
+	 * @return EE_Base_Class the object the relation was added to
1979
+	 */
1980
+	public function _add_relation_to(
1981
+		$otherObjectModelObjectOrID,
1982
+		$relationName,
1983
+		$extra_join_model_fields_n_values = array(),
1984
+		$cache_id = null
1985
+	) {
1986
+		//if this thing exists in the DB, save the relation to the DB
1987
+		if ($this->ID()) {
1988
+			$otherObject = $this->get_model()
1989
+								->add_relationship_to($this, $otherObjectModelObjectOrID, $relationName,
1990
+									$extra_join_model_fields_n_values);
1991
+			//clear cache so future get_many_related and get_first_related() return new results.
1992
+			$this->clear_cache($relationName, $otherObject, true);
1993
+			if ($otherObject instanceof EE_Base_Class) {
1994
+				$otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
1995
+			}
1996
+		} else {
1997
+			//this thing doesn't exist in the DB,  so just cache it
1998
+			if ( ! $otherObjectModelObjectOrID instanceof EE_Base_Class) {
1999
+				throw new EE_Error(sprintf(
2000
+					__('Before a model object is saved to the database, calls to _add_relation_to must be passed an actual object, not just an ID. You provided %s as the model object to a %s',
2001
+						'event_espresso'),
2002
+					$otherObjectModelObjectOrID,
2003
+					get_class($this)
2004
+				));
2005
+			} else {
2006
+				$otherObject = $otherObjectModelObjectOrID;
2007
+			}
2008
+			$this->cache($relationName, $otherObjectModelObjectOrID, $cache_id);
2009
+		}
2010
+		if ($otherObject instanceof EE_Base_Class) {
2011
+			//fix the reciprocal relation too
2012
+			if ($otherObject->ID()) {
2013
+				//its saved so assumed relations exist in the DB, so we can just
2014
+				//clear the cache so future queries use the updated info in the DB
2015
+				$otherObject->clear_cache($this->get_model()->get_this_model_name(), null, true);
2016
+			} else {
2017
+				//it's not saved, so it caches relations like this
2018
+				$otherObject->cache($this->get_model()->get_this_model_name(), $this);
2019
+			}
2020
+		}
2021
+		return $otherObject;
2022
+	}
2023
+
2024
+
2025
+
2026
+	/**
2027
+	 * Removes a relationship to the specified EE_Base_Class object, given the relationships' name. Eg, if the current
2028
+	 * model is related to a group of events, the $relationName should be 'Events', and should be a key in the EE
2029
+	 * Model's $_model_relations array. If this model object doesn't exist in the DB, just removes the related thing
2030
+	 * from the cache
2031
+	 *
2032
+	 * @param mixed  $otherObjectModelObjectOrID
2033
+	 *                EE_Base_Class or the ID of the other object, OR an array key into the cache if this isn't saved
2034
+	 *                to the DB yet
2035
+	 * @param string $relationName
2036
+	 * @param array  $where_query
2037
+	 *                You can optionally include an array of key=>value pairs that allow you to further constrict the
2038
+	 *                relation to being added. However, keep in mind that the columns (keys) given must match a column
2039
+	 *                on the JOIN table and currently only the HABTM models accept these additional conditions. Also
2040
+	 *                remember that if an exact match isn't found for these extra cols/val pairs, then a NEW row is
2041
+	 *                created in the join table.
2042
+	 * @return EE_Base_Class the relation was removed from
2043
+	 * @throws \EE_Error
2044
+	 */
2045
+	public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = array())
2046
+	{
2047
+		if ($this->ID()) {
2048
+			//if this exists in the DB, save the relation change to the DB too
2049
+			$otherObject = $this->get_model()
2050
+								->remove_relationship_to($this, $otherObjectModelObjectOrID, $relationName,
2051
+									$where_query);
2052
+			$this->clear_cache($relationName, $otherObject);
2053
+		} else {
2054
+			//this doesn't exist in the DB, just remove it from the cache
2055
+			$otherObject = $this->clear_cache($relationName, $otherObjectModelObjectOrID);
2056
+		}
2057
+		if ($otherObject instanceof EE_Base_Class) {
2058
+			$otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
2059
+		}
2060
+		return $otherObject;
2061
+	}
2062
+
2063
+
2064
+
2065
+	/**
2066
+	 * Removes ALL the related things for the $relationName.
2067
+	 *
2068
+	 * @param string $relationName
2069
+	 * @param array  $where_query_params like EEM_Base::get_all's $query_params[0] (where conditions)
2070
+	 * @return EE_Base_Class
2071
+	 * @throws \EE_Error
2072
+	 */
2073
+	public function _remove_relations($relationName, $where_query_params = array())
2074
+	{
2075
+		if ($this->ID()) {
2076
+			//if this exists in the DB, save the relation change to the DB too
2077
+			$otherObjects = $this->get_model()->remove_relations($this, $relationName, $where_query_params);
2078
+			$this->clear_cache($relationName, null, true);
2079
+		} else {
2080
+			//this doesn't exist in the DB, just remove it from the cache
2081
+			$otherObjects = $this->clear_cache($relationName, null, true);
2082
+		}
2083
+		if (is_array($otherObjects)) {
2084
+			foreach ($otherObjects as $otherObject) {
2085
+				$otherObject->clear_cache($this->get_model()->get_this_model_name(), $this);
2086
+			}
2087
+		}
2088
+		return $otherObjects;
2089
+	}
2090
+
2091
+
2092
+
2093
+	/**
2094
+	 * Gets all the related model objects of the specified type. Eg, if the current class if
2095
+	 * EE_Event, you could call $this->get_many_related('Registration') to get an array of all the
2096
+	 * EE_Registration objects which related to this event. Note: by default, we remove the "default query params"
2097
+	 * because we want to get even deleted items etc.
2098
+	 *
2099
+	 * @param string $relationName key in the model's _model_relations array
2100
+	 * @param array  $query_params like EEM_Base::get_all
2101
+	 * @return EE_Base_Class[] Results not necessarily indexed by IDs, because some results might not have primary keys
2102
+	 * @throws \EE_Error
2103
+	 *                             or might not be saved yet. Consider using EEM_Base::get_IDs() on these results if
2104
+	 *                             you want IDs
2105
+	 */
2106
+	public function get_many_related($relationName, $query_params = array())
2107
+	{
2108
+		if ($this->ID()) {
2109
+			//this exists in the DB, so get the related things from either the cache or the DB
2110
+			//if there are query parameters, forget about caching the related model objects.
2111
+			if ($query_params) {
2112
+				$related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
2113
+			} else {
2114
+				//did we already cache the result of this query?
2115
+				$cached_results = $this->get_all_from_cache($relationName);
2116
+				if ( ! $cached_results) {
2117
+					$related_model_objects = $this->get_model()->get_all_related($this, $relationName, $query_params);
2118
+					//if no query parameters were passed, then we got all the related model objects
2119
+					//for that relation. We can cache them then.
2120
+					foreach ($related_model_objects as $related_model_object) {
2121
+						$this->cache($relationName, $related_model_object);
2122
+					}
2123
+				} else {
2124
+					$related_model_objects = $cached_results;
2125
+				}
2126
+			}
2127
+		} else {
2128
+			//this doesn't exist in the DB, so just get the related things from the cache
2129
+			$related_model_objects = $this->get_all_from_cache($relationName);
2130
+		}
2131
+		return $related_model_objects;
2132
+	}
2133
+
2134
+
2135
+
2136
+	/**
2137
+	 * Instead of getting the related model objects, simply counts them. Ignores default_where_conditions by default,
2138
+	 * unless otherwise specified in the $query_params
2139
+	 *
2140
+	 * @param string $relation_name  model_name like 'Event', or 'Registration'
2141
+	 * @param array  $query_params   like EEM_Base::get_all's
2142
+	 * @param string $field_to_count name of field to count by. By default, uses primary key
2143
+	 * @param bool   $distinct       if we want to only count the distinct values for the column then you can trigger
2144
+	 *                               that by the setting $distinct to TRUE;
2145
+	 * @return int
2146
+	 */
2147
+	public function count_related($relation_name, $query_params = array(), $field_to_count = null, $distinct = false)
2148
+	{
2149
+		return $this->get_model()->count_related($this, $relation_name, $query_params, $field_to_count, $distinct);
2150
+	}
2151
+
2152
+
2153
+
2154
+	/**
2155
+	 * Instead of getting the related model objects, simply sums up the values of the specified field.
2156
+	 * Note: ignores default_where_conditions by default, unless otherwise specified in the $query_params
2157
+	 *
2158
+	 * @param string $relation_name model_name like 'Event', or 'Registration'
2159
+	 * @param array  $query_params  like EEM_Base::get_all's
2160
+	 * @param string $field_to_sum  name of field to count by.
2161
+	 *                              By default, uses primary key (which doesn't make much sense, so you should probably
2162
+	 *                              change it)
2163
+	 * @return int
2164
+	 */
2165
+	public function sum_related($relation_name, $query_params = array(), $field_to_sum = null)
2166
+	{
2167
+		return $this->get_model()->sum_related($this, $relation_name, $query_params, $field_to_sum);
2168
+	}
2169
+
2170
+
2171
+
2172
+	/**
2173
+	 * Gets the first (ie, one) related model object of the specified type.
2174
+	 *
2175
+	 * @param string $relationName key in the model's _model_relations array
2176
+	 * @param array  $query_params like EEM_Base::get_all
2177
+	 * @return EE_Base_Class (not an array, a single object)
2178
+	 * @throws \EE_Error
2179
+	 */
2180
+	public function get_first_related($relationName, $query_params = array())
2181
+	{
2182
+		if ($this->ID()) {//this exists in the DB, get from the cache OR the DB
2183
+			//if they've provided some query parameters, don't bother trying to cache the result
2184
+			//also make sure we're not caching the result of get_first_related
2185
+			//on a relation which should have an array of objects (because the cache might have an array of objects)
2186
+			if ($query_params
2187
+				|| ! $this->get_model()->related_settings_for($relationName)
2188
+					 instanceof
2189
+					 EE_Belongs_To_Relation
2190
+			) {
2191
+				$related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2192
+			} else {
2193
+				//first, check if we've already cached the result of this query
2194
+				$cached_result = $this->get_one_from_cache($relationName);
2195
+				if ( ! $cached_result) {
2196
+					$related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2197
+					$this->cache($relationName, $related_model_object);
2198
+				} else {
2199
+					$related_model_object = $cached_result;
2200
+				}
2201
+			}
2202
+		} else {
2203
+			$related_model_object = null;
2204
+			//this doesn't exist in the Db, but maybe the relation is of type belongs to, and so the related thing might
2205
+			if ($this->get_model()->related_settings_for($relationName) instanceof EE_Belongs_To_Relation) {
2206
+				$related_model_object = $this->get_model()->get_first_related($this, $relationName, $query_params);
2207
+			}
2208
+			//this doesn't exist in the DB and apparently the thing it belongs to doesn't either, just get what's cached on this object
2209
+			if ( ! $related_model_object) {
2210
+				$related_model_object = $this->get_one_from_cache($relationName);
2211
+			}
2212
+		}
2213
+		return $related_model_object;
2214
+	}
2215
+
2216
+
2217
+
2218
+	/**
2219
+	 * Does a delete on all related objects of type $relationName and removes
2220
+	 * the current model object's relation to them. If they can't be deleted (because
2221
+	 * of blocking related model objects) does nothing. If the related model objects are
2222
+	 * soft-deletable, they will be soft-deleted regardless of related blocking model objects.
2223
+	 * If this model object doesn't exist yet in the DB, just removes its related things
2224
+	 *
2225
+	 * @param string $relationName
2226
+	 * @param array  $query_params like EEM_Base::get_all's
2227
+	 * @return int how many deleted
2228
+	 * @throws \EE_Error
2229
+	 */
2230
+	public function delete_related($relationName, $query_params = array())
2231
+	{
2232
+		if ($this->ID()) {
2233
+			$count = $this->get_model()->delete_related($this, $relationName, $query_params);
2234
+		} else {
2235
+			$count = count($this->get_all_from_cache($relationName));
2236
+			$this->clear_cache($relationName, null, true);
2237
+		}
2238
+		return $count;
2239
+	}
2240
+
2241
+
2242
+
2243
+	/**
2244
+	 * Does a hard delete (ie, removes the DB row) on all related objects of type $relationName and removes
2245
+	 * the current model object's relation to them. If they can't be deleted (because
2246
+	 * of blocking related model objects) just does a soft delete on it instead, if possible.
2247
+	 * If the related thing isn't a soft-deletable model object, this function is identical
2248
+	 * to delete_related(). If this model object doesn't exist in the DB, just remove its related things
2249
+	 *
2250
+	 * @param string $relationName
2251
+	 * @param array  $query_params like EEM_Base::get_all's
2252
+	 * @return int how many deleted (including those soft deleted)
2253
+	 * @throws \EE_Error
2254
+	 */
2255
+	public function delete_related_permanently($relationName, $query_params = array())
2256
+	{
2257
+		if ($this->ID()) {
2258
+			$count = $this->get_model()->delete_related_permanently($this, $relationName, $query_params);
2259
+		} else {
2260
+			$count = count($this->get_all_from_cache($relationName));
2261
+		}
2262
+		$this->clear_cache($relationName, null, true);
2263
+		return $count;
2264
+	}
2265
+
2266
+
2267
+
2268
+	/**
2269
+	 * is_set
2270
+	 * Just a simple utility function children can use for checking if property exists
2271
+	 *
2272
+	 * @access  public
2273
+	 * @param  string $field_name property to check
2274
+	 * @return bool                              TRUE if existing,FALSE if not.
2275
+	 */
2276
+	public function is_set($field_name)
2277
+	{
2278
+		return isset($this->_fields[$field_name]);
2279
+	}
2280
+
2281
+
2282
+
2283
+	/**
2284
+	 * Just a simple utility function children can use for checking if property (or properties) exists and throwing an
2285
+	 * EE_Error exception if they don't
2286
+	 *
2287
+	 * @param  mixed (string|array) $properties properties to check
2288
+	 * @throws EE_Error
2289
+	 * @return bool                              TRUE if existing, throw EE_Error if not.
2290
+	 */
2291
+	protected function _property_exists($properties)
2292
+	{
2293
+		foreach ((array)$properties as $property_name) {
2294
+			//first make sure this property exists
2295
+			if ( ! $this->_fields[$property_name]) {
2296
+				throw new EE_Error(
2297
+					sprintf(
2298
+						__(
2299
+							'Trying to retrieve a non-existent property (%s).  Double check the spelling please',
2300
+							'event_espresso'
2301
+						),
2302
+						$property_name
2303
+					)
2304
+				);
2305
+			}
2306
+		}
2307
+		return true;
2308
+	}
2309
+
2310
+
2311
+
2312
+	/**
2313
+	 * This simply returns an array of model fields for this object
2314
+	 *
2315
+	 * @return array
2316
+	 * @throws \EE_Error
2317
+	 */
2318
+	public function model_field_array()
2319
+	{
2320
+		$fields = $this->get_model()->field_settings(false);
2321
+		$properties = array();
2322
+		//remove prepended underscore
2323
+		foreach ($fields as $field_name => $settings) {
2324
+			$properties[$field_name] = $this->get($field_name);
2325
+		}
2326
+		return $properties;
2327
+	}
2328
+
2329
+
2330
+
2331
+	/**
2332
+	 * Very handy general function to allow for plugins to extend any child of EE_Base_Class.
2333
+	 * If a method is called on a child of EE_Base_Class that doesn't exist, this function is called
2334
+	 * (http://www.garfieldtech.com/blog/php-magic-call) and passed the method's name and arguments. Instead of
2335
+	 * requiring a plugin to extend the EE_Base_Class (which works fine is there's only 1 plugin, but when will that
2336
+	 * happen?) they can add a hook onto 'filters_hook_espresso__{className}__{methodName}' (eg,
2337
+	 * filters_hook_espresso__EE_Answer__my_great_function) and accepts 2 arguments: the object on which the function
2338
+	 * was called, and an array of the original arguments passed to the function. Whatever their callback function
2339
+	 * returns will be returned by this function. Example: in functions.php (or in a plugin):
2340
+	 * add_filter('FHEE__EE_Answer__my_callback','my_callback',10,3); function
2341
+	 * my_callback($previousReturnValue,EE_Base_Class $object,$argsArray){
2342
+	 * $returnString= "you called my_callback! and passed args:".implode(",",$argsArray);
2343
+	 *        return $previousReturnValue.$returnString;
2344
+	 * }
2345
+	 * require('EE_Answer.class.php');
2346
+	 * $answer= EE_Answer::new_instance(array('REG_ID' => 2,'QST_ID' => 3,'ANS_value' => The answer is 42'));
2347
+	 * echo $answer->my_callback('monkeys',100);
2348
+	 * //will output "you called my_callback! and passed args:monkeys,100"
2349
+	 *
2350
+	 * @param string $methodName name of method which was called on a child of EE_Base_Class, but which
2351
+	 * @param array  $args       array of original arguments passed to the function
2352
+	 * @throws EE_Error
2353
+	 * @return mixed whatever the plugin which calls add_filter decides
2354
+	 */
2355
+	public function __call($methodName, $args)
2356
+	{
2357
+		$className = get_class($this);
2358
+		$tagName = "FHEE__{$className}__{$methodName}";
2359
+		if ( ! has_filter($tagName)) {
2360
+			throw new EE_Error(
2361
+				sprintf(
2362
+					__(
2363
+						"Method %s on class %s does not exist! You can create one with the following code in functions.php or in a plugin: add_filter('%s','my_callback',10,3);function my_callback(\$previousReturnValue,EE_Base_Class \$object, \$argsArray){/*function body*/return \$whatever;}",
2364
+						"event_espresso"
2365
+					),
2366
+					$methodName,
2367
+					$className,
2368
+					$tagName
2369
+				)
2370
+			);
2371
+		}
2372
+		return apply_filters($tagName, null, $this, $args);
2373
+	}
2374
+
2375
+
2376
+
2377
+	/**
2378
+	 * Similar to insert_post_meta, adds a record in the Extra_Meta model's table with the given key and value.
2379
+	 * A $previous_value can be specified in case there are many meta rows with the same key
2380
+	 *
2381
+	 * @param string $meta_key
2382
+	 * @param mixed  $meta_value
2383
+	 * @param mixed  $previous_value
2384
+	 * @return bool|int # of records updated (or BOOLEAN if we actually ended up inserting the extra meta row)
2385
+	 * @throws \EE_Error
2386
+	 * NOTE: if the values haven't changed, returns 0
2387
+	 */
2388
+	public function update_extra_meta($meta_key, $meta_value, $previous_value = null)
2389
+	{
2390
+		$query_params = array(
2391
+			array(
2392
+				'EXM_key'  => $meta_key,
2393
+				'OBJ_ID'   => $this->ID(),
2394
+				'EXM_type' => $this->get_model()->get_this_model_name(),
2395
+			),
2396
+		);
2397
+		if ($previous_value !== null) {
2398
+			$query_params[0]['EXM_value'] = $meta_value;
2399
+		}
2400
+		$existing_rows_like_that = EEM_Extra_Meta::instance()->get_all($query_params);
2401
+		if ( ! $existing_rows_like_that) {
2402
+			return $this->add_extra_meta($meta_key, $meta_value);
2403
+		}
2404
+		foreach ($existing_rows_like_that as $existing_row) {
2405
+			$existing_row->save(array('EXM_value' => $meta_value));
2406
+		}
2407
+		return count($existing_rows_like_that);
2408
+	}
2409
+
2410
+
2411
+
2412
+	/**
2413
+	 * Adds a new extra meta record. If $unique is set to TRUE, we'll first double-check
2414
+	 * no other extra meta for this model object have the same key. Returns TRUE if the
2415
+	 * extra meta row was entered, false if not
2416
+	 *
2417
+	 * @param string  $meta_key
2418
+	 * @param string  $meta_value
2419
+	 * @param boolean $unique
2420
+	 * @return boolean
2421
+	 * @throws \EE_Error
2422
+	 */
2423
+	public function add_extra_meta($meta_key, $meta_value, $unique = false)
2424
+	{
2425
+		if ($unique) {
2426
+			$existing_extra_meta = EEM_Extra_Meta::instance()->get_one(
2427
+				array(
2428
+					array(
2429
+						'EXM_key'  => $meta_key,
2430
+						'OBJ_ID'   => $this->ID(),
2431
+						'EXM_type' => $this->get_model()->get_this_model_name(),
2432
+					),
2433
+				)
2434
+			);
2435
+			if ($existing_extra_meta) {
2436
+				return false;
2437
+			}
2438
+		}
2439
+		$new_extra_meta = EE_Extra_Meta::new_instance(
2440
+			array(
2441
+				'EXM_key'   => $meta_key,
2442
+				'EXM_value' => $meta_value,
2443
+				'OBJ_ID'    => $this->ID(),
2444
+				'EXM_type'  => $this->get_model()->get_this_model_name(),
2445
+			)
2446
+		);
2447
+		$new_extra_meta->save();
2448
+		return true;
2449
+	}
2450
+
2451
+
2452
+
2453
+	/**
2454
+	 * Deletes all the extra meta rows for this record as specified by key. If $meta_value
2455
+	 * is specified, only deletes extra meta records with that value.
2456
+	 *
2457
+	 * @param string $meta_key
2458
+	 * @param string $meta_value
2459
+	 * @return int number of extra meta rows deleted
2460
+	 * @throws \EE_Error
2461
+	 */
2462
+	public function delete_extra_meta($meta_key, $meta_value = null)
2463
+	{
2464
+		$query_params = array(
2465
+			array(
2466
+				'EXM_key'  => $meta_key,
2467
+				'OBJ_ID'   => $this->ID(),
2468
+				'EXM_type' => $this->get_model()->get_this_model_name(),
2469
+			),
2470
+		);
2471
+		if ($meta_value !== null) {
2472
+			$query_params[0]['EXM_value'] = $meta_value;
2473
+		}
2474
+		return EEM_Extra_Meta::instance()->delete($query_params);
2475
+	}
2476
+
2477
+
2478
+
2479
+	/**
2480
+	 * Gets the extra meta with the given meta key. If you specify "single" we just return 1, otherwise
2481
+	 * an array of everything found. Requires that this model actually have a relation of type EE_Has_Many_Any_Relation.
2482
+	 * You can specify $default is case you haven't found the extra meta
2483
+	 *
2484
+	 * @param string  $meta_key
2485
+	 * @param boolean $single
2486
+	 * @param mixed   $default if we don't find anything, what should we return?
2487
+	 * @return mixed single value if $single; array if ! $single
2488
+	 * @throws \EE_Error
2489
+	 */
2490
+	public function get_extra_meta($meta_key, $single = false, $default = null)
2491
+	{
2492
+		if ($single) {
2493
+			$result = $this->get_first_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2494
+			if ($result instanceof EE_Extra_Meta) {
2495
+				return $result->value();
2496
+			} else {
2497
+				return $default;
2498
+			}
2499
+		} else {
2500
+			$results = $this->get_many_related('Extra_Meta', array(array('EXM_key' => $meta_key)));
2501
+			if ($results) {
2502
+				$values = array();
2503
+				foreach ($results as $result) {
2504
+					if ($result instanceof EE_Extra_Meta) {
2505
+						$values[$result->ID()] = $result->value();
2506
+					}
2507
+				}
2508
+				return $values;
2509
+			} else {
2510
+				return $default;
2511
+			}
2512
+		}
2513
+	}
2514
+
2515
+
2516
+
2517
+	/**
2518
+	 * Returns a simple array of all the extra meta associated with this model object.
2519
+	 * If $one_of_each_key is true (Default), it will be an array of simple key-value pairs, keys being the
2520
+	 * extra meta's key, and teh value being its value. However, if there are duplicate extra meta rows with
2521
+	 * the same key, only one will be used. (eg array('foo'=>'bar','monkey'=>123))
2522
+	 * If $one_of_each_key is false, it will return an array with the top-level keys being
2523
+	 * the extra meta keys, but their values are also arrays, which have the extra-meta's ID as their sub-key, and
2524
+	 * finally the extra meta's value as each sub-value. (eg
2525
+	 * array('foo'=>array(1=>'bar',2=>'bill'),'monkey'=>array(3=>123)))
2526
+	 *
2527
+	 * @param boolean $one_of_each_key
2528
+	 * @return array
2529
+	 * @throws \EE_Error
2530
+	 */
2531
+	public function all_extra_meta_array($one_of_each_key = true)
2532
+	{
2533
+		$return_array = array();
2534
+		if ($one_of_each_key) {
2535
+			$extra_meta_objs = $this->get_many_related('Extra_Meta', array('group_by' => 'EXM_key'));
2536
+			foreach ($extra_meta_objs as $extra_meta_obj) {
2537
+				if ($extra_meta_obj instanceof EE_Extra_Meta) {
2538
+					$return_array[$extra_meta_obj->key()] = $extra_meta_obj->value();
2539
+				}
2540
+			}
2541
+		} else {
2542
+			$extra_meta_objs = $this->get_many_related('Extra_Meta');
2543
+			foreach ($extra_meta_objs as $extra_meta_obj) {
2544
+				if ($extra_meta_obj instanceof EE_Extra_Meta) {
2545
+					if ( ! isset($return_array[$extra_meta_obj->key()])) {
2546
+						$return_array[$extra_meta_obj->key()] = array();
2547
+					}
2548
+					$return_array[$extra_meta_obj->key()][$extra_meta_obj->ID()] = $extra_meta_obj->value();
2549
+				}
2550
+			}
2551
+		}
2552
+		return $return_array;
2553
+	}
2554
+
2555
+
2556
+
2557
+	/**
2558
+	 * Gets a pretty nice displayable nice for this model object. Often overridden
2559
+	 *
2560
+	 * @return string
2561
+	 * @throws \EE_Error
2562
+	 */
2563
+	public function name()
2564
+	{
2565
+		//find a field that's not a text field
2566
+		$field_we_can_use = $this->get_model()->get_a_field_of_type('EE_Text_Field_Base');
2567
+		if ($field_we_can_use) {
2568
+			return $this->get($field_we_can_use->get_name());
2569
+		} else {
2570
+			$first_few_properties = $this->model_field_array();
2571
+			$first_few_properties = array_slice($first_few_properties, 0, 3);
2572
+			$name_parts = array();
2573
+			foreach ($first_few_properties as $name => $value) {
2574
+				$name_parts[] = "$name:$value";
2575
+			}
2576
+			return implode(",", $name_parts);
2577
+		}
2578
+	}
2579
+
2580
+
2581
+
2582
+	/**
2583
+	 * in_entity_map
2584
+	 * Checks if this model object has been proven to already be in the entity map
2585
+	 *
2586
+	 * @return boolean
2587
+	 * @throws \EE_Error
2588
+	 */
2589
+	public function in_entity_map()
2590
+	{
2591
+		if ($this->ID() && $this->get_model()->get_from_entity_map($this->ID()) === $this) {
2592
+			//well, if we looked, did we find it in the entity map?
2593
+			return true;
2594
+		} else {
2595
+			return false;
2596
+		}
2597
+	}
2598
+
2599
+
2600
+
2601
+	/**
2602
+	 * refresh_from_db
2603
+	 * Makes sure the fields and values on this model object are in-sync with what's in the database.
2604
+	 *
2605
+	 * @throws EE_Error if this model object isn't in the entity mapper (because then you should
2606
+	 * just use what's in the entity mapper and refresh it) and WP_DEBUG is TRUE
2607
+	 */
2608
+	public function refresh_from_db()
2609
+	{
2610
+		if ($this->ID() && $this->in_entity_map()) {
2611
+			$this->get_model()->refresh_entity_map_from_db($this->ID());
2612
+		} else {
2613
+			//if it doesn't have ID, you shouldn't be asking to refresh it from teh database (because its not in the database)
2614
+			//if it has an ID but it's not in the map, and you're asking me to refresh it
2615
+			//that's kinda dangerous. You should just use what's in the entity map, or add this to the entity map if there's
2616
+			//absolutely nothing in it for this ID
2617
+			if (WP_DEBUG) {
2618
+				throw new EE_Error(
2619
+					sprintf(
2620
+						__('Trying to refresh a model object with ID "%1$s" that\'s not in the entity map? First off: you should put it in the entity map by calling %2$s. Second off, if you want what\'s in the database right now, you should just call %3$s yourself and discard this model object.',
2621
+							'event_espresso'),
2622
+						$this->ID(),
2623
+						get_class($this->get_model()) . '::instance()->add_to_entity_map()',
2624
+						get_class($this->get_model()) . '::instance()->refresh_entity_map()'
2625
+					)
2626
+				);
2627
+			}
2628
+		}
2629
+	}
2630
+
2631
+
2632
+
2633
+	/**
2634
+	 * Because some other plugins, like Advanced Cron Manager, expect all objects to have this method
2635
+	 * (probably a bad assumption they have made, oh well)
2636
+	 *
2637
+	 * @return string
2638
+	 */
2639
+	public function __toString()
2640
+	{
2641
+		try {
2642
+			return sprintf('%s (%s)', $this->name(), $this->ID());
2643
+		} catch (Exception $e) {
2644
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
2645
+			return '';
2646
+		}
2647
+	}
2648
+
2649
+
2650
+
2651
+	/**
2652
+	 * Clear related model objects if they're already in the DB, because otherwise when we
2653
+	 * UN-serialize this model object we'll need to be careful to add them to the entity map.
2654
+	 * This means if we have made changes to those related model objects, and want to unserialize
2655
+	 * the this model object on a subsequent request, changes to those related model objects will be lost.
2656
+	 * Instead, those related model objects should be directly serialized and stored.
2657
+	 * Eg, the following won't work:
2658
+	 * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2659
+	 * $att = $reg->attendee();
2660
+	 * $att->set( 'ATT_fname', 'Dirk' );
2661
+	 * update_option( 'my_option', serialize( $reg ) );
2662
+	 * //END REQUEST
2663
+	 * //START NEXT REQUEST
2664
+	 * $reg = get_option( 'my_option' );
2665
+	 * $reg->attendee()->save();
2666
+	 * And would need to be replace with:
2667
+	 * $reg = EEM_Registration::instance()->get_one_by_ID( 123 );
2668
+	 * $att = $reg->attendee();
2669
+	 * $att->set( 'ATT_fname', 'Dirk' );
2670
+	 * update_option( 'my_option', serialize( $reg ) );
2671
+	 * //END REQUEST
2672
+	 * //START NEXT REQUEST
2673
+	 * $att = get_option( 'my_option' );
2674
+	 * $att->save();
2675
+	 *
2676
+	 * @return array
2677
+	 * @throws \EE_Error
2678
+	 */
2679
+	public function __sleep()
2680
+	{
2681
+		foreach ($this->get_model()->relation_settings() as $relation_name => $relation_obj) {
2682
+			if ($relation_obj instanceof EE_Belongs_To_Relation) {
2683
+				$classname = 'EE_' . $this->get_model()->get_this_model_name();
2684
+				if (
2685
+					$this->get_one_from_cache($relation_name) instanceof $classname
2686
+					&& $this->get_one_from_cache($relation_name)->ID()
2687
+				) {
2688
+					$this->clear_cache($relation_name, $this->get_one_from_cache($relation_name)->ID());
2689
+				}
2690
+			}
2691
+		}
2692
+		$this->_props_n_values_provided_in_constructor = array();
2693
+		return array_keys(get_object_vars($this));
2694
+	}
2695
+
2696
+
2697
+
2698
+	/**
2699
+	 * restore _props_n_values_provided_in_constructor
2700
+	 * PLZ NOTE: this will reset the array to whatever fields values were present prior to serialization,
2701
+	 * and therefore should NOT be used to determine if state change has occurred since initial construction.
2702
+	 * At best, you would only be able to detect if state change has occurred during THIS request.
2703
+	 */
2704
+	public function __wakeup()
2705
+	{
2706
+		$this->_props_n_values_provided_in_constructor = $this->_fields;
2707
+	}
2708 2708
 
2709 2709
 
2710 2710
 
Please login to merge, or discard this patch.
core/EE_Request_Handler.core.php 1 patch
Spacing   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\interfaces\InterminableInterface;
2 2
 
3
-if ( ! defined( 'EVENT_ESPRESSO_VERSION')) {exit('No direct script access allowed');}
3
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {exit('No direct script access allowed'); }
4 4
 /**
5 5
  * class EE_Request_Handler
6 6
  *
@@ -51,13 +51,13 @@  discard block
 block discarded – undo
51 51
 	 * @access public
52 52
 	 * @param  EE_Request $request
53 53
 	 */
54
-	public function __construct( EE_Request $request ) {
54
+	public function __construct(EE_Request $request) {
55 55
 		// grab request vars
56 56
 		$this->_params = $request->params();
57 57
 		// AJAX ???
58
-		$this->ajax = defined( 'DOING_AJAX' ) && DOING_AJAX ? true : false;
59
-		$this->front_ajax = defined( 'EE_FRONT_AJAX' ) && EE_FRONT_AJAX ? true : false;
60
-		do_action( 'AHEE__EE_Request_Handler__construct__complete' );
58
+		$this->ajax = defined('DOING_AJAX') && DOING_AJAX ? true : false;
59
+		$this->front_ajax = defined('EE_FRONT_AJAX') && EE_FRONT_AJAX ? true : false;
60
+		do_action('AHEE__EE_Request_Handler__construct__complete');
61 61
 	}
62 62
 
63 63
 
@@ -69,12 +69,12 @@  discard block
 block discarded – undo
69 69
 	 * @param WP $wp
70 70
 	 * @return void
71 71
 	 */
72
-	public function parse_request( $wp = null ) {
72
+	public function parse_request($wp = null) {
73 73
 		//if somebody forgot to provide us with WP, that's ok because its global
74
-		if ( ! $wp instanceof WP ) {
74
+		if ( ! $wp instanceof WP) {
75 75
 			global $wp;
76 76
 		}
77
-		$this->set_request_vars( $wp );
77
+		$this->set_request_vars($wp);
78 78
 	}
79 79
 
80 80
 
@@ -86,14 +86,14 @@  discard block
 block discarded – undo
86 86
 	 * @param WP $wp
87 87
 	 * @return void
88 88
 	 */
89
-	public function set_request_vars( $wp = null ) {
90
-		if ( ! is_admin() ) {
89
+	public function set_request_vars($wp = null) {
90
+		if ( ! is_admin()) {
91 91
 			// set request post_id
92
-			$this->set( 'post_id', $this->get_post_id_from_request( $wp ));
92
+			$this->set('post_id', $this->get_post_id_from_request($wp));
93 93
 			// set request post name
94
-			$this->set( 'post_name', $this->get_post_name_from_request( $wp ));
94
+			$this->set('post_name', $this->get_post_name_from_request($wp));
95 95
 			// set request post_type
96
-			$this->set( 'post_type', $this->get_post_type_from_request( $wp ));
96
+			$this->set('post_type', $this->get_post_type_from_request($wp));
97 97
 			// true or false ? is this page being used by EE ?
98 98
 			$this->set_espresso_page();
99 99
 		}
@@ -108,19 +108,19 @@  discard block
 block discarded – undo
108 108
 	 * @param WP $wp
109 109
 	 * @return int
110 110
 	 */
111
-	public function get_post_id_from_request( $wp = null ) {
112
-		if ( ! $wp instanceof WP ){
111
+	public function get_post_id_from_request($wp = null) {
112
+		if ( ! $wp instanceof WP) {
113 113
 			global $wp;
114 114
 		}
115 115
 		$post_id = null;
116
-		if ( isset( $wp->query_vars['p'] )) {
116
+		if (isset($wp->query_vars['p'])) {
117 117
 			$post_id = $wp->query_vars['p'];
118 118
 		}
119
-		if ( ! $post_id && isset( $wp->query_vars['page_id'] )) {
119
+		if ( ! $post_id && isset($wp->query_vars['page_id'])) {
120 120
 			$post_id = $wp->query_vars['page_id'];
121 121
 		}
122
-		if ( ! $post_id && isset( $wp->request ) && is_numeric( basename( $wp->request ))) {
123
-			$post_id = basename( $wp->request );
122
+		if ( ! $post_id && isset($wp->request) && is_numeric(basename($wp->request))) {
123
+			$post_id = basename($wp->request);
124 124
 		}
125 125
 		return $post_id;
126 126
 	}
@@ -134,35 +134,35 @@  discard block
 block discarded – undo
134 134
 	 * @param WP $wp
135 135
 	 * @return string
136 136
 	 */
137
-	public function get_post_name_from_request( $wp = null ) {
138
-		if ( ! $wp instanceof WP ){
137
+	public function get_post_name_from_request($wp = null) {
138
+		if ( ! $wp instanceof WP) {
139 139
 			global $wp;
140 140
 		}
141 141
 		$post_name = null;
142
-		if ( isset( $wp->query_vars['name'] ) && ! empty( $wp->query_vars['name'] )) {
142
+		if (isset($wp->query_vars['name']) && ! empty($wp->query_vars['name'])) {
143 143
 			$post_name = $wp->query_vars['name'];
144 144
 		}
145
-		if ( ! $post_name && isset( $wp->query_vars['pagename'] ) && ! empty( $wp->query_vars['pagename'] )) {
145
+		if ( ! $post_name && isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
146 146
 			$post_name = $wp->query_vars['pagename'];
147 147
 		}
148
-		if ( ! $post_name && isset( $wp->request ) && ! empty( $wp->request )) {
149
-			$possible_post_name = basename( $wp->request );
150
-			if ( ! is_numeric( $possible_post_name )) {
148
+		if ( ! $post_name && isset($wp->request) && ! empty($wp->request)) {
149
+			$possible_post_name = basename($wp->request);
150
+			if ( ! is_numeric($possible_post_name)) {
151 151
 				/** @type WPDB $wpdb */
152 152
 				global $wpdb;
153 153
 				$SQL = "SELECT ID from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s";
154
-				$possible_post_name = $wpdb->get_var( $wpdb->prepare( $SQL, $possible_post_name ));
155
-				if ( $possible_post_name ) {
154
+				$possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $possible_post_name));
155
+				if ($possible_post_name) {
156 156
 					$post_name = $possible_post_name;
157 157
 				}
158 158
 			}
159 159
 		}
160
-		if ( ! $post_name && $this->get( 'post_id' )) {
160
+		if ( ! $post_name && $this->get('post_id')) {
161 161
 			/** @type WPDB $wpdb */
162 162
 			global $wpdb;
163 163
 			$SQL = "SELECT post_name from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d";
164
-			$possible_post_name = $wpdb->get_var( $wpdb->prepare( $SQL, $this->get( 'post_id' )));
165
-			if( $possible_post_name ) {
164
+			$possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $this->get('post_id')));
165
+			if ($possible_post_name) {
166 166
 				$post_name = $possible_post_name;
167 167
 			}
168 168
 		}
@@ -178,11 +178,11 @@  discard block
 block discarded – undo
178 178
 	 * @param WP $wp
179 179
 	 * @return mixed
180 180
 	 */
181
-	public function get_post_type_from_request( $wp = null ) {
182
-		if ( ! $wp instanceof WP ){
181
+	public function get_post_type_from_request($wp = null) {
182
+		if ( ! $wp instanceof WP) {
183 183
 			global $wp;
184 184
 		}
185
-		return isset( $wp->query_vars['post_type'] ) ? $wp->query_vars['post_type'] : null;
185
+		return isset($wp->query_vars['post_type']) ? $wp->query_vars['post_type'] : null;
186 186
 	}
187 187
 
188 188
 
@@ -192,18 +192,18 @@  discard block
 block discarded – undo
192 192
 	 * @param  WP $wp
193 193
 	 * @return string
194 194
 	 */
195
-	public function get_current_page_permalink( $wp = null ) {
196
-		$post_id = $this->get_post_id_from_request( $wp );
197
-		if ( $post_id ) {
198
-			$current_page_permalink = get_permalink( $post_id );
195
+	public function get_current_page_permalink($wp = null) {
196
+		$post_id = $this->get_post_id_from_request($wp);
197
+		if ($post_id) {
198
+			$current_page_permalink = get_permalink($post_id);
199 199
 		} else {
200
-			if ( ! $wp instanceof WP ) {
200
+			if ( ! $wp instanceof WP) {
201 201
 				global $wp;
202 202
 			}
203
-			if ( $wp->request ) {
204
-				$current_page_permalink = site_url( $wp->request );
203
+			if ($wp->request) {
204
+				$current_page_permalink = site_url($wp->request);
205 205
 			} else {
206
-				$current_page_permalink = esc_url( site_url( $_SERVER[ 'REQUEST_URI' ] ) );
206
+				$current_page_permalink = esc_url(site_url($_SERVER['REQUEST_URI']));
207 207
 			}
208 208
 		}
209 209
 		return $current_page_permalink;
@@ -220,31 +220,31 @@  discard block
 block discarded – undo
220 220
 	public function test_for_espresso_page() {
221 221
 		global $wp;
222 222
 		/** @type EE_CPT_Strategy $EE_CPT_Strategy */
223
-		$EE_CPT_Strategy = EE_Registry::instance()->load_core( 'CPT_Strategy' );
223
+		$EE_CPT_Strategy = EE_Registry::instance()->load_core('CPT_Strategy');
224 224
 		$espresso_CPT_taxonomies = $EE_CPT_Strategy->get_CPT_taxonomies();
225
-		if ( is_array( $espresso_CPT_taxonomies ) ) {
226
-			foreach ( $espresso_CPT_taxonomies as $espresso_CPT_taxonomy =>$details ) {
227
-				if ( isset( $wp->query_vars, $wp->query_vars[ $espresso_CPT_taxonomy ] ) ) {
225
+		if (is_array($espresso_CPT_taxonomies)) {
226
+			foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy =>$details) {
227
+				if (isset($wp->query_vars, $wp->query_vars[$espresso_CPT_taxonomy])) {
228 228
 					return true;
229 229
 				}
230 230
 			}
231 231
 		}
232 232
 		// load espresso CPT endpoints
233 233
 		$espresso_CPT_endpoints = $EE_CPT_Strategy->get_CPT_endpoints();
234
-		$post_type_CPT_endpoints = array_flip( $espresso_CPT_endpoints );
235
-		$post_types = (array)$this->get( 'post_type' );
236
-		foreach ( $post_types as $post_type ) {
234
+		$post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints);
235
+		$post_types = (array) $this->get('post_type');
236
+		foreach ($post_types as $post_type) {
237 237
 			// was a post name passed ?
238
-			if ( isset( $post_type_CPT_endpoints[ $post_type ] ) ) {
238
+			if (isset($post_type_CPT_endpoints[$post_type])) {
239 239
 				// kk we know this is an espresso page, but is it a specific post ?
240
-				if ( ! $this->get( 'post_name' ) ) {
240
+				if ( ! $this->get('post_name')) {
241 241
 					// there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events
242
-					$post_name = isset( $post_type_CPT_endpoints[ $this->get( 'post_type' ) ] )
243
-                        ? $post_type_CPT_endpoints[ $this->get( 'post_type' ) ]
242
+					$post_name = isset($post_type_CPT_endpoints[$this->get('post_type')])
243
+                        ? $post_type_CPT_endpoints[$this->get('post_type')]
244 244
                         : '';
245 245
 					// if the post type matches on of our then set the endpoint
246
-					if ( $post_name ) {
247
-						$this->set( 'post_name', $post_name );
246
+					if ($post_name) {
247
+						$this->set('post_name', $post_name);
248 248
 					}
249 249
 				}
250 250
 				return true;
@@ -262,7 +262,7 @@  discard block
 block discarded – undo
262 262
 	 * @param null|bool $value
263 263
 	 * @return    void
264 264
 	 */
265
-	public function set_espresso_page( $value = null ) {
265
+	public function set_espresso_page($value = null) {
266 266
         $this->_params['is_espresso_page'] = ! empty($value) ? $value : $this->test_for_espresso_page();
267 267
 	}
268 268
 
@@ -275,7 +275,7 @@  discard block
 block discarded – undo
275 275
 	 *  @return 	mixed
276 276
 	 */
277 277
 	public function is_espresso_page() {
278
-		return isset( $this->_params['is_espresso_page'] ) ? $this->_params['is_espresso_page'] : false;
278
+		return isset($this->_params['is_espresso_page']) ? $this->_params['is_espresso_page'] : false;
279 279
 	}
280 280
 
281 281
 
@@ -299,14 +299,14 @@  discard block
 block discarded – undo
299 299
 	 * @param bool $override_ee
300 300
 	 * @return    void
301 301
 	 */
302
-	public function set( $key, $value, $override_ee = false ) {
302
+	public function set($key, $value, $override_ee = false) {
303 303
 		// don't allow "ee" to be overwritten unless explicitly instructed to do so
304 304
 		if (
305 305
 			$key !== 'ee' ||
306
-			( $key === 'ee' && empty( $this->_params['ee'] ))
307
-			|| ( $key === 'ee' && ! empty( $this->_params['ee'] ) && $override_ee )
306
+			($key === 'ee' && empty($this->_params['ee']))
307
+			|| ($key === 'ee' && ! empty($this->_params['ee']) && $override_ee)
308 308
 		) {
309
-			$this->_params[ $key ] = $value;
309
+			$this->_params[$key] = $value;
310 310
 		}
311 311
 	}
312 312
 
@@ -320,8 +320,8 @@  discard block
 block discarded – undo
320 320
 	 * @param null $default
321 321
 	 * @return    mixed
322 322
 	 */
323
-	public function get( $key, $default = null ) {
324
-		return isset( $this->_params[ $key ] ) ? $this->_params[ $key ] : $default;
323
+	public function get($key, $default = null) {
324
+		return isset($this->_params[$key]) ? $this->_params[$key] : $default;
325 325
 	}
326 326
 
327 327
 
@@ -333,8 +333,8 @@  discard block
 block discarded – undo
333 333
 	 * @param $key
334 334
 	 * @return    boolean
335 335
 	 */
336
-	public function is_set( $key ) {
337
-		return isset( $this->_params[ $key ] ) ? true : false;
336
+	public function is_set($key) {
337
+		return isset($this->_params[$key]) ? true : false;
338 338
 	}
339 339
 
340 340
 
@@ -346,8 +346,8 @@  discard block
 block discarded – undo
346 346
 	 * @param $key
347 347
 	 * @return    void
348 348
 	 */
349
-	public function un_set( $key ) {
350
-		unset( $this->_params[ $key ] );
349
+	public function un_set($key) {
350
+		unset($this->_params[$key]);
351 351
 	}
352 352
 
353 353
 
@@ -360,8 +360,8 @@  discard block
 block discarded – undo
360 360
 	 * @param $value
361 361
 	 * @return    void
362 362
 	 */
363
-	public function set_notice( $key, $value ) {
364
-		$this->_notice[ $key ] = $value;
363
+	public function set_notice($key, $value) {
364
+		$this->_notice[$key] = $value;
365 365
 	}
366 366
 
367 367
 
@@ -373,8 +373,8 @@  discard block
 block discarded – undo
373 373
 	 * @param $key
374 374
 	 * @return    mixed
375 375
 	 */
376
-	public function get_notice( $key ) {
377
-		return isset( $this->_notice[ $key ] ) ? $this->_notice[ $key ] : null;
376
+	public function get_notice($key) {
377
+		return isset($this->_notice[$key]) ? $this->_notice[$key] : null;
378 378
 	}
379 379
 
380 380
 
@@ -386,7 +386,7 @@  discard block
 block discarded – undo
386 386
 	 * @param $string
387 387
 	 * @return    void
388 388
 	 */
389
-	public function add_output( $string ) {
389
+	public function add_output($string) {
390 390
 		$this->_output .= $string;
391 391
 	}
392 392
 
@@ -408,8 +408,8 @@  discard block
 block discarded – undo
408 408
 	 * @param $item
409 409
 	 * @param $key
410 410
 	 */
411
-	public function sanitize_text_field_for_array_walk( &$item, &$key ) {
412
-		$item = strpos( $item, 'email' ) !== false ? sanitize_email( $item ) : sanitize_text_field( $item );
411
+	public function sanitize_text_field_for_array_walk(&$item, &$key) {
412
+		$item = strpos($item, 'email') !== false ? sanitize_email($item) : sanitize_text_field($item);
413 413
 	}
414 414
 
415 415
 
@@ -419,7 +419,7 @@  discard block
 block discarded – undo
419 419
 	 * @param $b
420 420
 	 * @return bool
421 421
 	 */
422
-	public function __set($a,$b) { return false; }
422
+	public function __set($a, $b) { return false; }
423 423
 
424 424
 
425 425
 
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +219 added lines, -219 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('ABSPATH')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 /*
5 5
   Plugin Name:		Event Espresso
@@ -40,243 +40,243 @@  discard block
 block discarded – undo
40 40
  * @since            4.0
41 41
  */
42 42
 if (function_exists('espresso_version')) {
43
-    /**
44
-     *    espresso_duplicate_plugin_error
45
-     *    displays if more than one version of EE is activated at the same time
46
-     */
47
-    function espresso_duplicate_plugin_error()
48
-    {
49
-        ?>
43
+	/**
44
+	 *    espresso_duplicate_plugin_error
45
+	 *    displays if more than one version of EE is activated at the same time
46
+	 */
47
+	function espresso_duplicate_plugin_error()
48
+	{
49
+		?>
50 50
         <div class="error">
51 51
             <p>
52 52
                 <?php echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                ); ?>
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+				); ?>
56 56
             </p>
57 57
         </div>
58 58
         <?php
59
-        espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-    }
59
+		espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+	}
61 61
 
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
-    if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
+	if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                            esc_html__(
79
-                                    'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                                    'event_espresso'
81
-                            ),
82
-                            EE_MIN_PHP_VER_REQUIRED,
83
-                            PHP_VERSION,
84
-                            '<br/>',
85
-                            '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+							esc_html__(
79
+									'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+									'event_espresso'
81
+							),
82
+							EE_MIN_PHP_VER_REQUIRED,
83
+							PHP_VERSION,
84
+							'<br/>',
85
+							'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        /**
97
-         * espresso_version
98
-         * Returns the plugin version
99
-         *
100
-         * @return string
101
-         */
102
-        function espresso_version()
103
-        {
104
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.46.rc.005');
105
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		/**
97
+		 * espresso_version
98
+		 * Returns the plugin version
99
+		 *
100
+		 * @return string
101
+		 */
102
+		function espresso_version()
103
+		{
104
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.46.rc.005');
105
+		}
106 106
 
107
-        // define versions
108
-        define('EVENT_ESPRESSO_VERSION', espresso_version());
109
-        define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
-        define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
-        define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
-        //used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
-        if ( ! defined('DS')) {
115
-            define('DS', '/');
116
-        }
117
-        if ( ! defined('PS')) {
118
-            define('PS', PATH_SEPARATOR);
119
-        }
120
-        if ( ! defined('SP')) {
121
-            define('SP', ' ');
122
-        }
123
-        if ( ! defined('EENL')) {
124
-            define('EENL', "\n");
125
-        }
126
-        define('EE_SUPPORT_EMAIL', '[email protected]');
127
-        // define the plugin directory and URL
128
-        define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
-        define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
-        define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
-        // main root folder paths
132
-        define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
-        define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
-        define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
-        define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
-        define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
-        define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
-        define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
-        define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
-        // core system paths
141
-        define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
-        define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
-        define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
-        define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
-        define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
-        define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
-        define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
-        define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
-        define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
-        define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
-        define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
-        define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
-        // gateways
154
-        define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
-        define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
-        // asset URL paths
157
-        define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
-        define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
-        define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
-        define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
-        define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
-        define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
-        // define upload paths
164
-        $uploads = wp_upload_dir();
165
-        // define the uploads directory and URL
166
-        define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
-        define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
-        // define the templates directory and URL
169
-        define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
-        define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
-        // define the gateway directory and URL
172
-        define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
-        define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
-        // languages folder/path
175
-        define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
-        define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
-        //check for dompdf fonts in uploads
178
-        if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
-            define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
-        }
181
-        //ajax constants
182
-        define(
183
-                'EE_FRONT_AJAX',
184
-                isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
-        );
186
-        define(
187
-                'EE_ADMIN_AJAX',
188
-                isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
-        );
190
-        //just a handy constant occasionally needed for finding values representing infinity in the DB
191
-        //you're better to use this than its straight value (currently -1) in case you ever
192
-        //want to change its default value! or find when -1 means infinity
193
-        define('EE_INF_IN_DB', -1);
194
-        define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
-        define('EE_DEBUG', false);
196
-        // for older WP versions
197
-        if ( ! defined('MONTH_IN_SECONDS')) {
198
-            define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30);
199
-        }
200
-        /**
201
-         *    espresso_plugin_activation
202
-         *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
203
-         */
204
-        function espresso_plugin_activation()
205
-        {
206
-            update_option('ee_espresso_activation', true);
207
-        }
107
+		// define versions
108
+		define('EVENT_ESPRESSO_VERSION', espresso_version());
109
+		define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
+		define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
+		define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
+		//used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
+		if ( ! defined('DS')) {
115
+			define('DS', '/');
116
+		}
117
+		if ( ! defined('PS')) {
118
+			define('PS', PATH_SEPARATOR);
119
+		}
120
+		if ( ! defined('SP')) {
121
+			define('SP', ' ');
122
+		}
123
+		if ( ! defined('EENL')) {
124
+			define('EENL', "\n");
125
+		}
126
+		define('EE_SUPPORT_EMAIL', '[email protected]');
127
+		// define the plugin directory and URL
128
+		define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
+		define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
+		define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
+		// main root folder paths
132
+		define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
+		define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
+		define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
+		define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
+		define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
+		define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
+		define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
+		define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
+		// core system paths
141
+		define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
+		define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
+		define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
+		define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
+		define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
+		define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
+		define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
+		define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
+		define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
+		define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
+		define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
+		define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
+		// gateways
154
+		define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
+		define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
+		// asset URL paths
157
+		define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
+		define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
+		define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
+		define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
+		define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
+		define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
+		// define upload paths
164
+		$uploads = wp_upload_dir();
165
+		// define the uploads directory and URL
166
+		define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
+		define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
+		// define the templates directory and URL
169
+		define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
+		define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
+		// define the gateway directory and URL
172
+		define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
+		define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
+		// languages folder/path
175
+		define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
+		define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
+		//check for dompdf fonts in uploads
178
+		if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
+			define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
+		}
181
+		//ajax constants
182
+		define(
183
+				'EE_FRONT_AJAX',
184
+				isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
+		);
186
+		define(
187
+				'EE_ADMIN_AJAX',
188
+				isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
+		);
190
+		//just a handy constant occasionally needed for finding values representing infinity in the DB
191
+		//you're better to use this than its straight value (currently -1) in case you ever
192
+		//want to change its default value! or find when -1 means infinity
193
+		define('EE_INF_IN_DB', -1);
194
+		define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
+		define('EE_DEBUG', false);
196
+		// for older WP versions
197
+		if ( ! defined('MONTH_IN_SECONDS')) {
198
+			define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30);
199
+		}
200
+		/**
201
+		 *    espresso_plugin_activation
202
+		 *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
203
+		 */
204
+		function espresso_plugin_activation()
205
+		{
206
+			update_option('ee_espresso_activation', true);
207
+		}
208 208
 
209
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
210
-        /**
211
-         *    espresso_load_error_handling
212
-         *    this function loads EE's class for handling exceptions and errors
213
-         */
214
-        function espresso_load_error_handling()
215
-        {
216
-            // load debugging tools
217
-            if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
218
-                require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
219
-                EEH_Debug_Tools::instance();
220
-            }
221
-            // load error handling
222
-            if (is_readable(EE_CORE . 'EE_Error.core.php')) {
223
-                require_once(EE_CORE . 'EE_Error.core.php');
224
-            } else {
225
-                wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
226
-            }
227
-        }
209
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
210
+		/**
211
+		 *    espresso_load_error_handling
212
+		 *    this function loads EE's class for handling exceptions and errors
213
+		 */
214
+		function espresso_load_error_handling()
215
+		{
216
+			// load debugging tools
217
+			if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
218
+				require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
219
+				EEH_Debug_Tools::instance();
220
+			}
221
+			// load error handling
222
+			if (is_readable(EE_CORE . 'EE_Error.core.php')) {
223
+				require_once(EE_CORE . 'EE_Error.core.php');
224
+			} else {
225
+				wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
226
+			}
227
+		}
228 228
 
229
-        /**
230
-         *    espresso_load_required
231
-         *    given a class name and path, this function will load that file or throw an exception
232
-         *
233
-         * @param    string $classname
234
-         * @param    string $full_path_to_file
235
-         * @throws    EE_Error
236
-         */
237
-        function espresso_load_required($classname, $full_path_to_file)
238
-        {
239
-            static $error_handling_loaded = false;
240
-            if ( ! $error_handling_loaded) {
241
-                espresso_load_error_handling();
242
-                $error_handling_loaded = true;
243
-            }
244
-            if (is_readable($full_path_to_file)) {
245
-                require_once($full_path_to_file);
246
-            } else {
247
-                throw new EE_Error (
248
-                        sprintf(
249
-                                esc_html__(
250
-                                        'The %s class file could not be located or is not readable due to file permissions.',
251
-                                        'event_espresso'
252
-                                ),
253
-                                $classname
254
-                        )
255
-                );
256
-            }
257
-        }
229
+		/**
230
+		 *    espresso_load_required
231
+		 *    given a class name and path, this function will load that file or throw an exception
232
+		 *
233
+		 * @param    string $classname
234
+		 * @param    string $full_path_to_file
235
+		 * @throws    EE_Error
236
+		 */
237
+		function espresso_load_required($classname, $full_path_to_file)
238
+		{
239
+			static $error_handling_loaded = false;
240
+			if ( ! $error_handling_loaded) {
241
+				espresso_load_error_handling();
242
+				$error_handling_loaded = true;
243
+			}
244
+			if (is_readable($full_path_to_file)) {
245
+				require_once($full_path_to_file);
246
+			} else {
247
+				throw new EE_Error (
248
+						sprintf(
249
+								esc_html__(
250
+										'The %s class file could not be located or is not readable due to file permissions.',
251
+										'event_espresso'
252
+								),
253
+								$classname
254
+						)
255
+				);
256
+			}
257
+		}
258 258
 
259
-        espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
260
-        espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
261
-        espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
262
-        new EE_Bootstrap();
263
-    }
259
+		espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
260
+		espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
261
+		espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
262
+		new EE_Bootstrap();
263
+	}
264 264
 }
265 265
 if ( ! function_exists('espresso_deactivate_plugin')) {
266
-    /**
267
-     *    deactivate_plugin
268
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
269
-     *
270
-     * @access public
271
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
272
-     * @return    void
273
-     */
274
-    function espresso_deactivate_plugin($plugin_basename = '')
275
-    {
276
-        if ( ! function_exists('deactivate_plugins')) {
277
-            require_once(ABSPATH . 'wp-admin/includes/plugin.php');
278
-        }
279
-        unset($_GET['activate'], $_REQUEST['activate']);
280
-        deactivate_plugins($plugin_basename);
281
-    }
266
+	/**
267
+	 *    deactivate_plugin
268
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
269
+	 *
270
+	 * @access public
271
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
272
+	 * @return    void
273
+	 */
274
+	function espresso_deactivate_plugin($plugin_basename = '')
275
+	{
276
+		if ( ! function_exists('deactivate_plugins')) {
277
+			require_once(ABSPATH . 'wp-admin/includes/plugin.php');
278
+		}
279
+		unset($_GET['activate'], $_REQUEST['activate']);
280
+		deactivate_plugins($plugin_basename);
281
+	}
282 282
 }
283 283
\ No newline at end of file
Please login to merge, or discard this patch.
core/EE_Module_Request_Router.core.php 2 patches
Indentation   +307 added lines, -307 removed lines patch added patch discarded remove patch
@@ -17,316 +17,316 @@
 block discarded – undo
17 17
 final class EE_Module_Request_Router implements InterminableInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @var array $_previous_routes
22
-     */
23
-    private static $_previous_routes = array();
24
-
25
-    /**
26
-     * @var WP_Query $WP_Query
27
-     */
28
-    public $WP_Query;
29
-
30
-
31
-
32
-    /**
33
-     * EE_Module_Request_Router constructor.
34
-     */
35
-    public function __construct()
36
-    {
37
-    }
38
-
39
-
40
-
41
-    /**
42
-     * on the first call  to this method, it checks the EE_Request_Handler for a "route"
43
-     * on subsequent calls to this method,
44
-     * instead of checking the EE_Request_Handler for a route, it checks the previous routes array,
45
-     * and checks if the last called route has any forwarding routes registered for it
46
-     *
47
-     * @param WP_Query $WP_Query
48
-     * @return NULL|string
49
-     * @throws EE_Error
50
-     * @throws ReflectionException
51
-     */
52
-    public function get_route(WP_Query $WP_Query)
53
-    {
54
-        $this->WP_Query = $WP_Query;
55
-        // assume this if first route being called
56
-        $previous_route = false;
57
-        // but is it really ???
58
-        if (! empty(self::$_previous_routes)) {
59
-            // get last run route
60
-            $previous_routes = array_values(self::$_previous_routes);
61
-            $previous_route = array_pop($previous_routes);
62
-        }
63
-        //  has another route already been run ?
64
-        if ($previous_route) {
65
-            // check if  forwarding has been set
66
-            $current_route = $this->get_forward($previous_route);
67
-            try {
68
-                //check for recursive forwarding
69
-                if (isset(self::$_previous_routes[$current_route])) {
70
-                    throw new EE_Error(
71
-                        sprintf(
72
-                            __(
73
-                                'An error occurred. The %s route has already been called, and therefore can not be forwarded to, because an infinite loop would be created and break the interweb.',
74
-                                'event_espresso'
75
-                            ),
76
-                            $current_route
77
-                        )
78
-                    );
79
-                }
80
-            } catch (EE_Error $e) {
81
-                $e->get_error();
82
-                return null;
83
-            }
84
-        } else {
85
-            // first route called
86
-            $current_route = null;
87
-            // grab all routes
88
-            $routes = EE_Config::get_routes();
89
-            //d( $routes );
90
-            foreach ($routes as $key => $route) {
91
-                // check request for module route
92
-                if (EE_Registry::instance()->REQ->is_set($key)) {
93
-                    //echo '<b style="color:#2EA2CC;">key : <span style="color:#E76700">' . $key . '</span></b><br />';
94
-                    $current_route = sanitize_text_field(EE_Registry::instance()->REQ->get($key));
95
-                    if ($current_route) {
96
-                        $current_route = array($key, $current_route);
97
-                        //echo '<b style="color:#2EA2CC;">current_route : <span style="color:#E76700">' . $current_route . '</span></b><br />';
98
-                        break;
99
-                    }
100
-                }
101
-            }
102
-        }
103
-        // sorry, but I can't read what you route !
104
-        if (empty($current_route)) {
105
-            return null;
106
-        }
107
-        //add route to previous routes array
108
-        self::$_previous_routes[] = $current_route;
109
-        return $current_route;
110
-    }
111
-
112
-
113
-
114
-    /**
115
-     * this method simply takes a valid route, and resolves what module class method the route points to
116
-     *
117
-     * @param string $key
118
-     * @param string $current_route
119
-     * @return mixed EED_Module | boolean
120
-     * @throws EE_Error
121
-     * @throws ReflectionException
122
-     */
123
-    public function resolve_route($key, $current_route)
124
-    {
125
-        // get module method that route has been mapped to
126
-        $module_method = EE_Config::get_route($current_route, $key);
127
-        //EEH_Debug_Tools::printr( $module_method, '$module_method  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
128
-        // verify result was returned
129
-        if (empty($module_method)) {
130
-            $msg = sprintf(
131
-                __('The requested route %s could not be mapped to any registered modules.', 'event_espresso'),
132
-                $current_route
133
-            );
134
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
135
-            return false;
136
-        }
137
-        // verify that result is an array
138
-        if (! is_array($module_method)) {
139
-            $msg = sprintf(__('The %s  route has not been properly registered.', 'event_espresso'), $current_route);
140
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
141
-            return false;
142
-        }
143
-        // grab module name
144
-        $module_name = $module_method[0];
145
-        // verify that a class method was registered properly
146
-        if (! isset($module_method[1])) {
147
-            $msg = sprintf(
148
-                __('A class method for the %s  route has not been properly registered.', 'event_espresso'),
149
-                $current_route
150
-            );
151
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
152
-            return false;
153
-        }
154
-        // grab method
155
-        $method = $module_method[1];
156
-        // verify that class exists
157
-        if (! class_exists($module_name)) {
158
-            $msg = sprintf(__('The requested %s class could not be found.', 'event_espresso'), $module_name);
159
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
160
-            return false;
161
-        }
162
-        // verify that method exists
163
-        if (! method_exists($module_name, $method)) {
164
-            $msg = sprintf(
165
-                __('The class method %s for the %s route is in invalid.', 'event_espresso'), $method, $current_route
166
-            );
167
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
168
-            return false;
169
-        }
170
-        // instantiate module and call route method
171
-        return $this->_module_router($module_name, $method);
172
-    }
173
-
174
-
175
-
176
-    /**
177
-     * this method instantiates modules and calls the method that was defined when the route was registered
178
-     *
179
-     * @param string $module_name
180
-     * @return EED_Module|object|null
181
-     * @throws ReflectionException
182
-     */
183
-    public static function module_factory($module_name)
184
-    {
185
-        if ($module_name === 'EED_Module') {
186
-            EE_Error::add_error(
187
-                sprintf(
188
-                    __(
189
-                        'EED_Module is an abstract parent class an can not be instantiated. Please provide a proper module name.',
190
-                        'event_espresso'
191
-                    ), $module_name
192
-                ), __FILE__, __FUNCTION__, __LINE__
193
-            );
194
-            return null;
195
-        }
196
-        // let's pause to reflect on this...
197
-        $mod_reflector = new ReflectionClass($module_name);
198
-        // ensure that class is actually a module
199
-        if (! $mod_reflector->isSubclassOf('EED_Module')) {
200
-            EE_Error::add_error(
201
-                sprintf(__('The requested %s module is not of the class EED_Module.', 'event_espresso'), $module_name),
202
-                __FILE__, __FUNCTION__, __LINE__
203
-            );
204
-            return null;
205
-        }
206
-        // instantiate and return module class
207
-        return $mod_reflector->newInstance();
208
-    }
209
-
210
-
211
-
212
-    /**
213
-     * this method instantiates modules and calls the method that was defined when the route was registered
214
-     *
215
-     * @param string $module_name
216
-     * @param string $method
217
-     * @return EED_Module|null
218
-     * @throws EE_Error
219
-     * @throws ReflectionException
220
-     */
221
-    private function _module_router($module_name, $method)
222
-    {
223
-        // instantiate module class
224
-        $module = EE_Module_Request_Router::module_factory($module_name);
225
-        if ($module instanceof EED_Module) {
226
-            // and call whatever action the route was for
227
-            try {
228
-                call_user_func(array($module, $method), $this->WP_Query);
229
-            } catch (EE_Error $e) {
230
-                $e->get_error();
231
-                return null;
232
-            }
233
-        }
234
-        return $module;
235
-    }
236
-
237
-
238
-
239
-    /**
240
-     * @param $current_route
241
-     * @return string
242
-     */
243
-    public function get_forward($current_route)
244
-    {
245
-        return EE_Config::get_forward($current_route);
246
-    }
247
-
248
-
249
-
250
-    /**
251
-     * @param $current_route
252
-     * @return string
253
-     */
254
-    public function get_view($current_route)
255
-    {
256
-        return EE_Config::get_view($current_route);
257
-    }
258
-
259
-
260
-
261
-    /**
262
-     * @param $a
263
-     * @param $b
264
-     * @return bool
265
-     */
266
-    public function __set($a, $b)
267
-    {
268
-        return false;
269
-    }
270
-
271
-
272
-
273
-    /**
274
-     * @param $a
275
-     * @return bool
276
-     */
277
-    public function __get($a)
278
-    {
279
-        return false;
280
-    }
281
-
282
-
283
-
284
-    /**
285
-     * @param $a
286
-     * @return bool
287
-     */
288
-    public function __isset($a)
289
-    {
290
-        return false;
291
-    }
292
-
293
-
294
-
295
-    /**
296
-     * @param $a
297
-     * @return bool
298
-     */
299
-    public function __unset($a)
300
-    {
301
-        return false;
302
-    }
303
-
304
-
305
-
306
-    /**
307
-     * @return void
308
-     */
309
-    public function __clone()
310
-    {
311
-    }
312
-
313
-
314
-
315
-    /**
316
-     * @return void
317
-     */
318
-    public function __wakeup()
319
-    {
320
-    }
20
+	/**
21
+	 * @var array $_previous_routes
22
+	 */
23
+	private static $_previous_routes = array();
24
+
25
+	/**
26
+	 * @var WP_Query $WP_Query
27
+	 */
28
+	public $WP_Query;
29
+
30
+
31
+
32
+	/**
33
+	 * EE_Module_Request_Router constructor.
34
+	 */
35
+	public function __construct()
36
+	{
37
+	}
38
+
39
+
40
+
41
+	/**
42
+	 * on the first call  to this method, it checks the EE_Request_Handler for a "route"
43
+	 * on subsequent calls to this method,
44
+	 * instead of checking the EE_Request_Handler for a route, it checks the previous routes array,
45
+	 * and checks if the last called route has any forwarding routes registered for it
46
+	 *
47
+	 * @param WP_Query $WP_Query
48
+	 * @return NULL|string
49
+	 * @throws EE_Error
50
+	 * @throws ReflectionException
51
+	 */
52
+	public function get_route(WP_Query $WP_Query)
53
+	{
54
+		$this->WP_Query = $WP_Query;
55
+		// assume this if first route being called
56
+		$previous_route = false;
57
+		// but is it really ???
58
+		if (! empty(self::$_previous_routes)) {
59
+			// get last run route
60
+			$previous_routes = array_values(self::$_previous_routes);
61
+			$previous_route = array_pop($previous_routes);
62
+		}
63
+		//  has another route already been run ?
64
+		if ($previous_route) {
65
+			// check if  forwarding has been set
66
+			$current_route = $this->get_forward($previous_route);
67
+			try {
68
+				//check for recursive forwarding
69
+				if (isset(self::$_previous_routes[$current_route])) {
70
+					throw new EE_Error(
71
+						sprintf(
72
+							__(
73
+								'An error occurred. The %s route has already been called, and therefore can not be forwarded to, because an infinite loop would be created and break the interweb.',
74
+								'event_espresso'
75
+							),
76
+							$current_route
77
+						)
78
+					);
79
+				}
80
+			} catch (EE_Error $e) {
81
+				$e->get_error();
82
+				return null;
83
+			}
84
+		} else {
85
+			// first route called
86
+			$current_route = null;
87
+			// grab all routes
88
+			$routes = EE_Config::get_routes();
89
+			//d( $routes );
90
+			foreach ($routes as $key => $route) {
91
+				// check request for module route
92
+				if (EE_Registry::instance()->REQ->is_set($key)) {
93
+					//echo '<b style="color:#2EA2CC;">key : <span style="color:#E76700">' . $key . '</span></b><br />';
94
+					$current_route = sanitize_text_field(EE_Registry::instance()->REQ->get($key));
95
+					if ($current_route) {
96
+						$current_route = array($key, $current_route);
97
+						//echo '<b style="color:#2EA2CC;">current_route : <span style="color:#E76700">' . $current_route . '</span></b><br />';
98
+						break;
99
+					}
100
+				}
101
+			}
102
+		}
103
+		// sorry, but I can't read what you route !
104
+		if (empty($current_route)) {
105
+			return null;
106
+		}
107
+		//add route to previous routes array
108
+		self::$_previous_routes[] = $current_route;
109
+		return $current_route;
110
+	}
111
+
112
+
113
+
114
+	/**
115
+	 * this method simply takes a valid route, and resolves what module class method the route points to
116
+	 *
117
+	 * @param string $key
118
+	 * @param string $current_route
119
+	 * @return mixed EED_Module | boolean
120
+	 * @throws EE_Error
121
+	 * @throws ReflectionException
122
+	 */
123
+	public function resolve_route($key, $current_route)
124
+	{
125
+		// get module method that route has been mapped to
126
+		$module_method = EE_Config::get_route($current_route, $key);
127
+		//EEH_Debug_Tools::printr( $module_method, '$module_method  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
128
+		// verify result was returned
129
+		if (empty($module_method)) {
130
+			$msg = sprintf(
131
+				__('The requested route %s could not be mapped to any registered modules.', 'event_espresso'),
132
+				$current_route
133
+			);
134
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
135
+			return false;
136
+		}
137
+		// verify that result is an array
138
+		if (! is_array($module_method)) {
139
+			$msg = sprintf(__('The %s  route has not been properly registered.', 'event_espresso'), $current_route);
140
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
141
+			return false;
142
+		}
143
+		// grab module name
144
+		$module_name = $module_method[0];
145
+		// verify that a class method was registered properly
146
+		if (! isset($module_method[1])) {
147
+			$msg = sprintf(
148
+				__('A class method for the %s  route has not been properly registered.', 'event_espresso'),
149
+				$current_route
150
+			);
151
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
152
+			return false;
153
+		}
154
+		// grab method
155
+		$method = $module_method[1];
156
+		// verify that class exists
157
+		if (! class_exists($module_name)) {
158
+			$msg = sprintf(__('The requested %s class could not be found.', 'event_espresso'), $module_name);
159
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
160
+			return false;
161
+		}
162
+		// verify that method exists
163
+		if (! method_exists($module_name, $method)) {
164
+			$msg = sprintf(
165
+				__('The class method %s for the %s route is in invalid.', 'event_espresso'), $method, $current_route
166
+			);
167
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
168
+			return false;
169
+		}
170
+		// instantiate module and call route method
171
+		return $this->_module_router($module_name, $method);
172
+	}
173
+
174
+
175
+
176
+	/**
177
+	 * this method instantiates modules and calls the method that was defined when the route was registered
178
+	 *
179
+	 * @param string $module_name
180
+	 * @return EED_Module|object|null
181
+	 * @throws ReflectionException
182
+	 */
183
+	public static function module_factory($module_name)
184
+	{
185
+		if ($module_name === 'EED_Module') {
186
+			EE_Error::add_error(
187
+				sprintf(
188
+					__(
189
+						'EED_Module is an abstract parent class an can not be instantiated. Please provide a proper module name.',
190
+						'event_espresso'
191
+					), $module_name
192
+				), __FILE__, __FUNCTION__, __LINE__
193
+			);
194
+			return null;
195
+		}
196
+		// let's pause to reflect on this...
197
+		$mod_reflector = new ReflectionClass($module_name);
198
+		// ensure that class is actually a module
199
+		if (! $mod_reflector->isSubclassOf('EED_Module')) {
200
+			EE_Error::add_error(
201
+				sprintf(__('The requested %s module is not of the class EED_Module.', 'event_espresso'), $module_name),
202
+				__FILE__, __FUNCTION__, __LINE__
203
+			);
204
+			return null;
205
+		}
206
+		// instantiate and return module class
207
+		return $mod_reflector->newInstance();
208
+	}
209
+
210
+
211
+
212
+	/**
213
+	 * this method instantiates modules and calls the method that was defined when the route was registered
214
+	 *
215
+	 * @param string $module_name
216
+	 * @param string $method
217
+	 * @return EED_Module|null
218
+	 * @throws EE_Error
219
+	 * @throws ReflectionException
220
+	 */
221
+	private function _module_router($module_name, $method)
222
+	{
223
+		// instantiate module class
224
+		$module = EE_Module_Request_Router::module_factory($module_name);
225
+		if ($module instanceof EED_Module) {
226
+			// and call whatever action the route was for
227
+			try {
228
+				call_user_func(array($module, $method), $this->WP_Query);
229
+			} catch (EE_Error $e) {
230
+				$e->get_error();
231
+				return null;
232
+			}
233
+		}
234
+		return $module;
235
+	}
236
+
237
+
238
+
239
+	/**
240
+	 * @param $current_route
241
+	 * @return string
242
+	 */
243
+	public function get_forward($current_route)
244
+	{
245
+		return EE_Config::get_forward($current_route);
246
+	}
247
+
248
+
249
+
250
+	/**
251
+	 * @param $current_route
252
+	 * @return string
253
+	 */
254
+	public function get_view($current_route)
255
+	{
256
+		return EE_Config::get_view($current_route);
257
+	}
258
+
259
+
260
+
261
+	/**
262
+	 * @param $a
263
+	 * @param $b
264
+	 * @return bool
265
+	 */
266
+	public function __set($a, $b)
267
+	{
268
+		return false;
269
+	}
270
+
271
+
272
+
273
+	/**
274
+	 * @param $a
275
+	 * @return bool
276
+	 */
277
+	public function __get($a)
278
+	{
279
+		return false;
280
+	}
281
+
282
+
283
+
284
+	/**
285
+	 * @param $a
286
+	 * @return bool
287
+	 */
288
+	public function __isset($a)
289
+	{
290
+		return false;
291
+	}
292
+
293
+
294
+
295
+	/**
296
+	 * @param $a
297
+	 * @return bool
298
+	 */
299
+	public function __unset($a)
300
+	{
301
+		return false;
302
+	}
303
+
304
+
305
+
306
+	/**
307
+	 * @return void
308
+	 */
309
+	public function __clone()
310
+	{
311
+	}
312
+
313
+
314
+
315
+	/**
316
+	 * @return void
317
+	 */
318
+	public function __wakeup()
319
+	{
320
+	}
321 321
 
322 322
 
323 323
 
324
-    /**
325
-     *
326
-     */
327
-    public function __destruct()
328
-    {
329
-    }
324
+	/**
325
+	 *
326
+	 */
327
+	public function __destruct()
328
+	{
329
+	}
330 330
 
331 331
 }
332 332
 // End of file EE_Module_Request_Router.core.php
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -55,7 +55,7 @@  discard block
 block discarded – undo
55 55
         // assume this if first route being called
56 56
         $previous_route = false;
57 57
         // but is it really ???
58
-        if (! empty(self::$_previous_routes)) {
58
+        if ( ! empty(self::$_previous_routes)) {
59 59
             // get last run route
60 60
             $previous_routes = array_values(self::$_previous_routes);
61 61
             $previous_route = array_pop($previous_routes);
@@ -135,36 +135,36 @@  discard block
 block discarded – undo
135 135
             return false;
136 136
         }
137 137
         // verify that result is an array
138
-        if (! is_array($module_method)) {
138
+        if ( ! is_array($module_method)) {
139 139
             $msg = sprintf(__('The %s  route has not been properly registered.', 'event_espresso'), $current_route);
140
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
140
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
141 141
             return false;
142 142
         }
143 143
         // grab module name
144 144
         $module_name = $module_method[0];
145 145
         // verify that a class method was registered properly
146
-        if (! isset($module_method[1])) {
146
+        if ( ! isset($module_method[1])) {
147 147
             $msg = sprintf(
148 148
                 __('A class method for the %s  route has not been properly registered.', 'event_espresso'),
149 149
                 $current_route
150 150
             );
151
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
151
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
152 152
             return false;
153 153
         }
154 154
         // grab method
155 155
         $method = $module_method[1];
156 156
         // verify that class exists
157
-        if (! class_exists($module_name)) {
157
+        if ( ! class_exists($module_name)) {
158 158
             $msg = sprintf(__('The requested %s class could not be found.', 'event_espresso'), $module_name);
159 159
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
160 160
             return false;
161 161
         }
162 162
         // verify that method exists
163
-        if (! method_exists($module_name, $method)) {
163
+        if ( ! method_exists($module_name, $method)) {
164 164
             $msg = sprintf(
165 165
                 __('The class method %s for the %s route is in invalid.', 'event_espresso'), $method, $current_route
166 166
             );
167
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
167
+            EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
168 168
             return false;
169 169
         }
170 170
         // instantiate module and call route method
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
         // let's pause to reflect on this...
197 197
         $mod_reflector = new ReflectionClass($module_name);
198 198
         // ensure that class is actually a module
199
-        if (! $mod_reflector->isSubclassOf('EED_Module')) {
199
+        if ( ! $mod_reflector->isSubclassOf('EED_Module')) {
200 200
             EE_Error::add_error(
201 201
                 sprintf(__('The requested %s module is not of the class EED_Module.', 'event_espresso'), $module_name),
202 202
                 __FILE__, __FUNCTION__, __LINE__
Please login to merge, or discard this patch.
form_sections/strategies/display/EE_Number_Input_Display_Strategy.php 2 patches
Doc Comments   +3 added lines patch added patch discarded remove patch
@@ -64,6 +64,9 @@
 block discarded – undo
64 64
     }
65 65
 
66 66
 
67
+    /**
68
+     * @param string $argument_label
69
+     */
67 70
     private function throwValidationException($argument_label, $argument_value)
68 71
     {
69 72
         throw new InvalidArgumentException(
Please login to merge, or discard this patch.
Indentation   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -14,111 +14,111 @@
 block discarded – undo
14 14
 class EE_Number_Input_Display_Strategy extends EE_Display_Strategy_Base
15 15
 {
16 16
 
17
-    /**
18
-     * minimum value for number field
19
-     *
20
-     * @var int|null $min
21
-     */
22
-    protected $min;
23
-
24
-    /**
25
-     * maximum value for number field
26
-     *
27
-     * @var int|null $max
28
-     */
29
-    protected $max;
30
-
31
-
32
-    /**
33
-     * This is used to set the "step" attribute for the html5 number input.
34
-     * Controls the increments on the input when incrementing or decrementing the value.
35
-     * Note:  Although the step attribute allows for the string "any" to be used, Firefox and Chrome will interpret that
36
-     * to increment by 1.  So although "any" is accepted as a value, it is converted to 1.
37
-     * @var float
38
-     */
39
-    protected $step;
40
-
41
-
42
-    /**
43
-     * EE_Number_Input_Display_Strategy constructor.
44
-     * Null is the default value for the incoming arguments because 0 is a valid value.  So we use null
45
-     * to indicate NOT setting this attribute.
46
-     *
47
-     * @param int|null $min
48
-     * @param int|null $max
49
-     * @param int|null $step
50
-     * @throws InvalidArgumentException
51
-     */
52
-    public function __construct($min = null, $max = null, $step = null)
53
-    {
54
-        $this->min = is_numeric($min) || $min === null
55
-            ? $min
56
-            : $this->throwValidationException('min', $min);
57
-        $this->max = is_numeric($max) || $max === null
58
-            ? $max
59
-            : $this->throwValidationException('max', $max);
60
-        $step = $step === 'any' ? 1 : $step;
61
-        $this->step = is_numeric($step) || $step === null
62
-            ? $step
63
-            : $this->throwValidationException('step', $step);
64
-    }
65
-
66
-
67
-    private function throwValidationException($argument_label, $argument_value)
68
-    {
69
-        throw new InvalidArgumentException(
70
-            sprintf(
71
-                esc_html__(
72
-                    'The %1$s parameter value for %2$s must be numeric or null, %3$s was passed into the constructor.',
73
-                    'event_espresso'
74
-                ),
75
-                $argument_label,
76
-                __CLASS__,
77
-                $argument_value
78
-            )
79
-        );
80
-    }
81
-
82
-
83
-
84
-    /**
85
-     * @return string of html to display the field
86
-     */
87
-    public function display()
88
-    {
89
-        $input = $this->_opening_tag('input');
90
-        $input .= $this->_attributes_string(
91
-            array_merge(
92
-                $this->_standard_attributes_array(),
93
-                $this->getNumberInputAttributes()
94
-            )
95
-        );
96
-        $input .= $this->_close_tag();
97
-        return $input;
98
-    }
99
-
100
-
101
-    /**
102
-     * Return the attributes specific to this display strategy
103
-     * @return array
104
-     */
105
-    private function getNumberInputAttributes()
106
-    {
107
-        $attributes = array(
108
-            'type' => 'number',
109
-            'value' => $this->_input->raw_value_in_form()
110
-        );
111
-        if ($this->min !== null) {
112
-            $attributes['min'] = $this->min;
113
-        }
114
-        if ($this->max !== null) {
115
-            $attributes['max'] = $this->max;
116
-        }
117
-        if ($this->step !== null) {
118
-            $attributes['step'] = $this->step;
119
-        }
120
-        return $attributes;
121
-    }
17
+	/**
18
+	 * minimum value for number field
19
+	 *
20
+	 * @var int|null $min
21
+	 */
22
+	protected $min;
23
+
24
+	/**
25
+	 * maximum value for number field
26
+	 *
27
+	 * @var int|null $max
28
+	 */
29
+	protected $max;
30
+
31
+
32
+	/**
33
+	 * This is used to set the "step" attribute for the html5 number input.
34
+	 * Controls the increments on the input when incrementing or decrementing the value.
35
+	 * Note:  Although the step attribute allows for the string "any" to be used, Firefox and Chrome will interpret that
36
+	 * to increment by 1.  So although "any" is accepted as a value, it is converted to 1.
37
+	 * @var float
38
+	 */
39
+	protected $step;
40
+
41
+
42
+	/**
43
+	 * EE_Number_Input_Display_Strategy constructor.
44
+	 * Null is the default value for the incoming arguments because 0 is a valid value.  So we use null
45
+	 * to indicate NOT setting this attribute.
46
+	 *
47
+	 * @param int|null $min
48
+	 * @param int|null $max
49
+	 * @param int|null $step
50
+	 * @throws InvalidArgumentException
51
+	 */
52
+	public function __construct($min = null, $max = null, $step = null)
53
+	{
54
+		$this->min = is_numeric($min) || $min === null
55
+			? $min
56
+			: $this->throwValidationException('min', $min);
57
+		$this->max = is_numeric($max) || $max === null
58
+			? $max
59
+			: $this->throwValidationException('max', $max);
60
+		$step = $step === 'any' ? 1 : $step;
61
+		$this->step = is_numeric($step) || $step === null
62
+			? $step
63
+			: $this->throwValidationException('step', $step);
64
+	}
65
+
66
+
67
+	private function throwValidationException($argument_label, $argument_value)
68
+	{
69
+		throw new InvalidArgumentException(
70
+			sprintf(
71
+				esc_html__(
72
+					'The %1$s parameter value for %2$s must be numeric or null, %3$s was passed into the constructor.',
73
+					'event_espresso'
74
+				),
75
+				$argument_label,
76
+				__CLASS__,
77
+				$argument_value
78
+			)
79
+		);
80
+	}
81
+
82
+
83
+
84
+	/**
85
+	 * @return string of html to display the field
86
+	 */
87
+	public function display()
88
+	{
89
+		$input = $this->_opening_tag('input');
90
+		$input .= $this->_attributes_string(
91
+			array_merge(
92
+				$this->_standard_attributes_array(),
93
+				$this->getNumberInputAttributes()
94
+			)
95
+		);
96
+		$input .= $this->_close_tag();
97
+		return $input;
98
+	}
99
+
100
+
101
+	/**
102
+	 * Return the attributes specific to this display strategy
103
+	 * @return array
104
+	 */
105
+	private function getNumberInputAttributes()
106
+	{
107
+		$attributes = array(
108
+			'type' => 'number',
109
+			'value' => $this->_input->raw_value_in_form()
110
+		);
111
+		if ($this->min !== null) {
112
+			$attributes['min'] = $this->min;
113
+		}
114
+		if ($this->max !== null) {
115
+			$attributes['max'] = $this->max;
116
+		}
117
+		if ($this->step !== null) {
118
+			$attributes['step'] = $this->step;
119
+		}
120
+		return $attributes;
121
+	}
122 122
 
123 123
 }
124 124
 // End of file EE_Number_Input_Display_Strategy.php
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Float_Input.input.php 1 patch
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -11,33 +11,33 @@
 block discarded – undo
11 11
 class EE_Float_Input extends EE_Form_Input_Base
12 12
 {
13 13
 
14
-    /**
15
-     * @param array $input_settings
16
-     * @throws InvalidArgumentException
17
-     */
18
-    public function __construct($input_settings = array())
19
-    {
20
-        $this->_set_display_strategy(
21
-            new EE_Number_Input_Display_Strategy(
22
-                isset($input_settings['min_value'])
23
-                    ? $input_settings['min_value']
24
-                    : null,
25
-                isset($input_settings['max_value'])
26
-                    ? $input_settings['max_value']
27
-                    : null,
28
-                isset($input_settings['step_value'])
29
-                    ? $input_settings['step_value']
30
-                    : null
31
-            )
32
-        );
33
-        $this->_set_normalization_strategy(new EE_Float_Normalization());
34
-        $this->_add_validation_strategy(
35
-            new EE_Float_Validation_Strategy(
36
-                isset($input_settings['validation_error_message'])
37
-                    ? $input_settings['validation_error_message']
38
-                    : null
39
-            )
40
-        );
41
-        parent::__construct($input_settings);
42
-    }
14
+	/**
15
+	 * @param array $input_settings
16
+	 * @throws InvalidArgumentException
17
+	 */
18
+	public function __construct($input_settings = array())
19
+	{
20
+		$this->_set_display_strategy(
21
+			new EE_Number_Input_Display_Strategy(
22
+				isset($input_settings['min_value'])
23
+					? $input_settings['min_value']
24
+					: null,
25
+				isset($input_settings['max_value'])
26
+					? $input_settings['max_value']
27
+					: null,
28
+				isset($input_settings['step_value'])
29
+					? $input_settings['step_value']
30
+					: null
31
+			)
32
+		);
33
+		$this->_set_normalization_strategy(new EE_Float_Normalization());
34
+		$this->_add_validation_strategy(
35
+			new EE_Float_Validation_Strategy(
36
+				isset($input_settings['validation_error_message'])
37
+					? $input_settings['validation_error_message']
38
+					: null
39
+			)
40
+		);
41
+		parent::__construct($input_settings);
42
+	}
43 43
 }
Please login to merge, or discard this patch.