@@ -116,7 +116,7 @@ discard block |
||
116 | 116 | $attributes['limit'] = (int) $attributes['limit']; |
117 | 117 | $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN); |
118 | 118 | // don't display on archives unless 'display_on_archives' is true |
119 | - if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) { |
|
119 | + if ($attributes['limit'] === 0 || ( ! $display_on_archives && is_archive())) { |
|
120 | 120 | return ''; |
121 | 121 | } |
122 | 122 | try { |
@@ -317,7 +317,7 @@ discard block |
||
317 | 317 | */ |
318 | 318 | private function getDatetime(array $attributes) |
319 | 319 | { |
320 | - if (! empty($attributes['datetime_id'])) { |
|
320 | + if ( ! empty($attributes['datetime_id'])) { |
|
321 | 321 | $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']); |
322 | 322 | if ($datetime instanceof EE_Datetime) { |
323 | 323 | return $datetime; |
@@ -337,7 +337,7 @@ discard block |
||
337 | 337 | */ |
338 | 338 | private function getTicket(array $attributes) |
339 | 339 | { |
340 | - if (! empty($attributes['ticket_id'])) { |
|
340 | + if ( ! empty($attributes['ticket_id'])) { |
|
341 | 341 | $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']); |
342 | 342 | if ($ticket instanceof EE_Ticket) { |
343 | 343 | return $ticket; |
@@ -354,7 +354,7 @@ discard block |
||
354 | 354 | private function setAdditionalQueryParams(array $attributes) |
355 | 355 | { |
356 | 356 | $reg_status_array = EEM_Registration::reg_status_array(); |
357 | - if (isset($reg_status_array[ $attributes['status'] ])) { |
|
357 | + if (isset($reg_status_array[$attributes['status']])) { |
|
358 | 358 | $this->query_params[0]['Registration.STS_ID'] = $attributes['status']; |
359 | 359 | } |
360 | 360 | if (absint($attributes['limit'])) { |
@@ -32,342 +32,342 @@ |
||
32 | 32 | */ |
33 | 33 | class EspressoEventAttendees extends EspressoShortcode |
34 | 34 | { |
35 | - private $query_params = array( |
|
36 | - 0 => array(), |
|
37 | - ); |
|
35 | + private $query_params = array( |
|
36 | + 0 => array(), |
|
37 | + ); |
|
38 | 38 | |
39 | - private $template_args = array( |
|
40 | - 'contacts' => array(), |
|
41 | - 'event' => null, |
|
42 | - 'datetime' => null, |
|
43 | - 'ticket' => null, |
|
44 | - ); |
|
39 | + private $template_args = array( |
|
40 | + 'contacts' => array(), |
|
41 | + 'event' => null, |
|
42 | + 'datetime' => null, |
|
43 | + 'ticket' => null, |
|
44 | + ); |
|
45 | 45 | |
46 | - /** |
|
47 | - * the actual shortcode tag that gets registered with WordPress |
|
48 | - * |
|
49 | - * @return string |
|
50 | - */ |
|
51 | - public function getTag() |
|
52 | - { |
|
53 | - return 'ESPRESSO_EVENT_ATTENDEES'; |
|
54 | - } |
|
46 | + /** |
|
47 | + * the actual shortcode tag that gets registered with WordPress |
|
48 | + * |
|
49 | + * @return string |
|
50 | + */ |
|
51 | + public function getTag() |
|
52 | + { |
|
53 | + return 'ESPRESSO_EVENT_ATTENDEES'; |
|
54 | + } |
|
55 | 55 | |
56 | 56 | |
57 | - /** |
|
58 | - * the time in seconds to cache the results of the processShortcode() method |
|
59 | - * 0 means the processShortcode() results will NOT be cached at all |
|
60 | - * |
|
61 | - * @return int |
|
62 | - */ |
|
63 | - public function cacheExpiration() |
|
64 | - { |
|
65 | - return 0; |
|
66 | - } |
|
57 | + /** |
|
58 | + * the time in seconds to cache the results of the processShortcode() method |
|
59 | + * 0 means the processShortcode() results will NOT be cached at all |
|
60 | + * |
|
61 | + * @return int |
|
62 | + */ |
|
63 | + public function cacheExpiration() |
|
64 | + { |
|
65 | + return 0; |
|
66 | + } |
|
67 | 67 | |
68 | 68 | |
69 | - /** |
|
70 | - * a place for adding any initialization code that needs to run prior to wp_header(). |
|
71 | - * this may be required for shortcodes that utilize a corresponding module, |
|
72 | - * and need to enqueue assets for that module |
|
73 | - * |
|
74 | - * @return void |
|
75 | - */ |
|
76 | - public function initializeShortcode() |
|
77 | - { |
|
78 | - $this->shortcodeHasBeenInitialized(); |
|
79 | - } |
|
69 | + /** |
|
70 | + * a place for adding any initialization code that needs to run prior to wp_header(). |
|
71 | + * this may be required for shortcodes that utilize a corresponding module, |
|
72 | + * and need to enqueue assets for that module |
|
73 | + * |
|
74 | + * @return void |
|
75 | + */ |
|
76 | + public function initializeShortcode() |
|
77 | + { |
|
78 | + $this->shortcodeHasBeenInitialized(); |
|
79 | + } |
|
80 | 80 | |
81 | 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 | - * [ESPRESSO_EVENT_ATTENDEES event_id=123] |
|
87 | - * - attendees for specific event. |
|
88 | - * [ESPRESSO_EVENT_ATTENDEES datetime_id=245] |
|
89 | - * - attendees for a specific datetime. |
|
90 | - * [ESPRESSO_EVENT_ATTENDEES ticket_id=123] |
|
91 | - * - attendees for a specific ticket. |
|
92 | - * [ESPRESSO_EVENT_ATTENDEES status=all] |
|
93 | - * - specific registration status (use status id) or all for all attendees regardless of status. |
|
94 | - * Note default is to only return approved attendees |
|
95 | - * [ESPRESSO_EVENT_ATTENDEES show_gravatar=true] |
|
96 | - * - default is to not return gravatar. Otherwise if this is set then return gravatar for email address given. |
|
97 | - * [ESPRESSO_EVENT_ATTENDEES display_on_archives=true] |
|
98 | - * - default is to not display attendees list on archive pages. |
|
99 | - * Note: because of the relationship between event_id, ticket_id, and datetime_id: |
|
100 | - * If more than one of those params is included, then preference is given to the following: |
|
101 | - * - event_id is used whenever its present and any others are ignored. |
|
102 | - * - if no event_id then datetime is used whenever its present and any others are ignored. |
|
103 | - * - otherwise ticket_id is used if present. |
|
104 | - * |
|
105 | - * @param array|string $attributes |
|
106 | - * @return string |
|
107 | - * @throws EE_Error |
|
108 | - * @throws InvalidDataTypeException |
|
109 | - * @throws InvalidInterfaceException |
|
110 | - * @throws InvalidArgumentException |
|
111 | - * @throws DomainException |
|
112 | - * @throws ReflectionException |
|
113 | - */ |
|
114 | - public function processShortcode($attributes = array()) |
|
115 | - { |
|
116 | - // grab attributes and merge with defaults |
|
117 | - $attributes = $this->getAttributes((array) $attributes); |
|
118 | - $attributes['limit'] = (int) $attributes['limit']; |
|
119 | - $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN); |
|
120 | - // don't display on archives unless 'display_on_archives' is true |
|
121 | - if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) { |
|
122 | - return ''; |
|
123 | - } |
|
124 | - try { |
|
125 | - $this->setBaseTemplateArguments($attributes); |
|
126 | - $this->validateEntities($attributes); |
|
127 | - $this->setBaseQueryParams(); |
|
128 | - } catch (EntityNotFoundException $e) { |
|
129 | - if (WP_DEBUG) { |
|
130 | - return '<div class="important-notice ee-error">' |
|
131 | - . $e->getMessage() |
|
132 | - . '</div>'; |
|
133 | - } |
|
134 | - return ''; |
|
135 | - } |
|
136 | - $this->setAdditionalQueryParams($attributes); |
|
137 | - // get contacts! |
|
138 | - $this->template_args['contacts'] = EEM_Attendee::instance()->get_all($this->query_params); |
|
139 | - // all set let's load up the template and return. |
|
140 | - return EEH_Template::locate_template( |
|
141 | - 'loop-espresso_event_attendees.php', |
|
142 | - $this->template_args |
|
143 | - ); |
|
144 | - } |
|
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 | + * [ESPRESSO_EVENT_ATTENDEES event_id=123] |
|
87 | + * - attendees for specific event. |
|
88 | + * [ESPRESSO_EVENT_ATTENDEES datetime_id=245] |
|
89 | + * - attendees for a specific datetime. |
|
90 | + * [ESPRESSO_EVENT_ATTENDEES ticket_id=123] |
|
91 | + * - attendees for a specific ticket. |
|
92 | + * [ESPRESSO_EVENT_ATTENDEES status=all] |
|
93 | + * - specific registration status (use status id) or all for all attendees regardless of status. |
|
94 | + * Note default is to only return approved attendees |
|
95 | + * [ESPRESSO_EVENT_ATTENDEES show_gravatar=true] |
|
96 | + * - default is to not return gravatar. Otherwise if this is set then return gravatar for email address given. |
|
97 | + * [ESPRESSO_EVENT_ATTENDEES display_on_archives=true] |
|
98 | + * - default is to not display attendees list on archive pages. |
|
99 | + * Note: because of the relationship between event_id, ticket_id, and datetime_id: |
|
100 | + * If more than one of those params is included, then preference is given to the following: |
|
101 | + * - event_id is used whenever its present and any others are ignored. |
|
102 | + * - if no event_id then datetime is used whenever its present and any others are ignored. |
|
103 | + * - otherwise ticket_id is used if present. |
|
104 | + * |
|
105 | + * @param array|string $attributes |
|
106 | + * @return string |
|
107 | + * @throws EE_Error |
|
108 | + * @throws InvalidDataTypeException |
|
109 | + * @throws InvalidInterfaceException |
|
110 | + * @throws InvalidArgumentException |
|
111 | + * @throws DomainException |
|
112 | + * @throws ReflectionException |
|
113 | + */ |
|
114 | + public function processShortcode($attributes = array()) |
|
115 | + { |
|
116 | + // grab attributes and merge with defaults |
|
117 | + $attributes = $this->getAttributes((array) $attributes); |
|
118 | + $attributes['limit'] = (int) $attributes['limit']; |
|
119 | + $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN); |
|
120 | + // don't display on archives unless 'display_on_archives' is true |
|
121 | + if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) { |
|
122 | + return ''; |
|
123 | + } |
|
124 | + try { |
|
125 | + $this->setBaseTemplateArguments($attributes); |
|
126 | + $this->validateEntities($attributes); |
|
127 | + $this->setBaseQueryParams(); |
|
128 | + } catch (EntityNotFoundException $e) { |
|
129 | + if (WP_DEBUG) { |
|
130 | + return '<div class="important-notice ee-error">' |
|
131 | + . $e->getMessage() |
|
132 | + . '</div>'; |
|
133 | + } |
|
134 | + return ''; |
|
135 | + } |
|
136 | + $this->setAdditionalQueryParams($attributes); |
|
137 | + // get contacts! |
|
138 | + $this->template_args['contacts'] = EEM_Attendee::instance()->get_all($this->query_params); |
|
139 | + // all set let's load up the template and return. |
|
140 | + return EEH_Template::locate_template( |
|
141 | + 'loop-espresso_event_attendees.php', |
|
142 | + $this->template_args |
|
143 | + ); |
|
144 | + } |
|
145 | 145 | |
146 | 146 | |
147 | - /** |
|
148 | - * merge incoming attributes with filtered defaults |
|
149 | - * |
|
150 | - * @param array $attributes |
|
151 | - * @return array |
|
152 | - */ |
|
153 | - private function getAttributes(array $attributes) |
|
154 | - { |
|
155 | - return (array) apply_filters( |
|
156 | - 'EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts', |
|
157 | - $attributes + array( |
|
158 | - 'event_id' => null, |
|
159 | - 'datetime_id' => null, |
|
160 | - 'ticket_id' => null, |
|
161 | - 'status' => EEM_Registration::status_id_approved, |
|
162 | - 'show_gravatar' => false, |
|
163 | - 'display_on_archives' => false, |
|
164 | - 'limit' => 999, |
|
165 | - ) |
|
166 | - ); |
|
167 | - } |
|
147 | + /** |
|
148 | + * merge incoming attributes with filtered defaults |
|
149 | + * |
|
150 | + * @param array $attributes |
|
151 | + * @return array |
|
152 | + */ |
|
153 | + private function getAttributes(array $attributes) |
|
154 | + { |
|
155 | + return (array) apply_filters( |
|
156 | + 'EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts', |
|
157 | + $attributes + array( |
|
158 | + 'event_id' => null, |
|
159 | + 'datetime_id' => null, |
|
160 | + 'ticket_id' => null, |
|
161 | + 'status' => EEM_Registration::status_id_approved, |
|
162 | + 'show_gravatar' => false, |
|
163 | + 'display_on_archives' => false, |
|
164 | + 'limit' => 999, |
|
165 | + ) |
|
166 | + ); |
|
167 | + } |
|
168 | 168 | |
169 | 169 | |
170 | - /** |
|
171 | - * Set all the base template arguments from the incoming attributes. |
|
172 | - * * Note: because of the relationship between event_id, ticket_id, and datetime_id: |
|
173 | - * If more than one of those params is included, then preference is given to the following: |
|
174 | - * - event_id is used whenever its present and any others are ignored. |
|
175 | - * - if no event_id then datetime is used whenever its present and any others are ignored. |
|
176 | - * - otherwise ticket_id is used if present. |
|
177 | - * |
|
178 | - * @param array $attributes |
|
179 | - * @throws EE_Error |
|
180 | - * @throws InvalidDataTypeException |
|
181 | - * @throws InvalidInterfaceException |
|
182 | - * @throws InvalidArgumentException |
|
183 | - * @throws ReflectionException |
|
184 | - */ |
|
185 | - private function setBaseTemplateArguments(array $attributes) |
|
186 | - { |
|
187 | - $this->template_args['show_gravatar'] = $attributes['show_gravatar']; |
|
188 | - $this->template_args['event'] = $this->getEvent($attributes); |
|
189 | - $this->template_args['datetime'] = empty($attributes['event_id']) |
|
190 | - ? $this->getDatetime($attributes) |
|
191 | - : null; |
|
192 | - $this->template_args['ticket'] = empty($attributes['datetime_id']) && empty($attributes['event_id']) |
|
193 | - ? $this->getTicket($attributes) |
|
194 | - : null; |
|
195 | - } |
|
170 | + /** |
|
171 | + * Set all the base template arguments from the incoming attributes. |
|
172 | + * * Note: because of the relationship between event_id, ticket_id, and datetime_id: |
|
173 | + * If more than one of those params is included, then preference is given to the following: |
|
174 | + * - event_id is used whenever its present and any others are ignored. |
|
175 | + * - if no event_id then datetime is used whenever its present and any others are ignored. |
|
176 | + * - otherwise ticket_id is used if present. |
|
177 | + * |
|
178 | + * @param array $attributes |
|
179 | + * @throws EE_Error |
|
180 | + * @throws InvalidDataTypeException |
|
181 | + * @throws InvalidInterfaceException |
|
182 | + * @throws InvalidArgumentException |
|
183 | + * @throws ReflectionException |
|
184 | + */ |
|
185 | + private function setBaseTemplateArguments(array $attributes) |
|
186 | + { |
|
187 | + $this->template_args['show_gravatar'] = $attributes['show_gravatar']; |
|
188 | + $this->template_args['event'] = $this->getEvent($attributes); |
|
189 | + $this->template_args['datetime'] = empty($attributes['event_id']) |
|
190 | + ? $this->getDatetime($attributes) |
|
191 | + : null; |
|
192 | + $this->template_args['ticket'] = empty($attributes['datetime_id']) && empty($attributes['event_id']) |
|
193 | + ? $this->getTicket($attributes) |
|
194 | + : null; |
|
195 | + } |
|
196 | 196 | |
197 | 197 | |
198 | - /** |
|
199 | - * Validates the presence of entities for the given attribute values. |
|
200 | - * |
|
201 | - * @param array $attributes |
|
202 | - * @throws EntityNotFoundException |
|
203 | - */ |
|
204 | - private function validateEntities(array $attributes) |
|
205 | - { |
|
206 | - if ( |
|
207 | - ! $this->template_args['event'] instanceof EE_Event |
|
208 | - || ( |
|
209 | - empty($attributes['event_id']) |
|
210 | - && $attributes['datetime_id'] |
|
211 | - && ! $this->template_args['datetime'] instanceof EE_Datetime |
|
212 | - ) |
|
213 | - || ( |
|
214 | - empty($attributes['event_id']) |
|
215 | - && empty($attributes['datetime_id']) |
|
216 | - && $attributes['ticket_id'] |
|
217 | - && ! $this->template_args['ticket'] instanceof EE_Ticket |
|
218 | - ) |
|
219 | - ) { |
|
220 | - throw new EntityNotFoundException( |
|
221 | - '', |
|
222 | - '', |
|
223 | - esc_html__( |
|
224 | - '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.', |
|
225 | - 'event_espresso' |
|
226 | - ) |
|
227 | - ); |
|
228 | - } |
|
229 | - } |
|
198 | + /** |
|
199 | + * Validates the presence of entities for the given attribute values. |
|
200 | + * |
|
201 | + * @param array $attributes |
|
202 | + * @throws EntityNotFoundException |
|
203 | + */ |
|
204 | + private function validateEntities(array $attributes) |
|
205 | + { |
|
206 | + if ( |
|
207 | + ! $this->template_args['event'] instanceof EE_Event |
|
208 | + || ( |
|
209 | + empty($attributes['event_id']) |
|
210 | + && $attributes['datetime_id'] |
|
211 | + && ! $this->template_args['datetime'] instanceof EE_Datetime |
|
212 | + ) |
|
213 | + || ( |
|
214 | + empty($attributes['event_id']) |
|
215 | + && empty($attributes['datetime_id']) |
|
216 | + && $attributes['ticket_id'] |
|
217 | + && ! $this->template_args['ticket'] instanceof EE_Ticket |
|
218 | + ) |
|
219 | + ) { |
|
220 | + throw new EntityNotFoundException( |
|
221 | + '', |
|
222 | + '', |
|
223 | + esc_html__( |
|
224 | + '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.', |
|
225 | + 'event_espresso' |
|
226 | + ) |
|
227 | + ); |
|
228 | + } |
|
229 | + } |
|
230 | 230 | |
231 | 231 | |
232 | - /** |
|
233 | - * Sets the query params for the base query elements. |
|
234 | - */ |
|
235 | - private function setBaseQueryParams() |
|
236 | - { |
|
237 | - switch (true) { |
|
238 | - case $this->template_args['datetime'] instanceof EE_Datetime: |
|
239 | - $this->query_params = array( |
|
240 | - 0 => array( |
|
241 | - 'Registration.Ticket.Datetime.DTT_ID' => $this->template_args['datetime']->ID(), |
|
242 | - ), |
|
243 | - 'default_where_conditions' => 'this_model_only', |
|
244 | - ); |
|
245 | - break; |
|
246 | - case $this->template_args['ticket'] instanceof EE_Ticket: |
|
247 | - $this->query_params[0] = array( |
|
248 | - 'Registration.TKT_ID' => $this->template_args['ticket']->ID(), |
|
249 | - ); |
|
250 | - break; |
|
251 | - case $this->template_args['event'] instanceof EE_Event: |
|
252 | - $this->query_params[0] = array( |
|
253 | - 'Registration.EVT_ID' => $this->template_args['event']->ID(), |
|
254 | - ); |
|
255 | - break; |
|
256 | - } |
|
257 | - } |
|
232 | + /** |
|
233 | + * Sets the query params for the base query elements. |
|
234 | + */ |
|
235 | + private function setBaseQueryParams() |
|
236 | + { |
|
237 | + switch (true) { |
|
238 | + case $this->template_args['datetime'] instanceof EE_Datetime: |
|
239 | + $this->query_params = array( |
|
240 | + 0 => array( |
|
241 | + 'Registration.Ticket.Datetime.DTT_ID' => $this->template_args['datetime']->ID(), |
|
242 | + ), |
|
243 | + 'default_where_conditions' => 'this_model_only', |
|
244 | + ); |
|
245 | + break; |
|
246 | + case $this->template_args['ticket'] instanceof EE_Ticket: |
|
247 | + $this->query_params[0] = array( |
|
248 | + 'Registration.TKT_ID' => $this->template_args['ticket']->ID(), |
|
249 | + ); |
|
250 | + break; |
|
251 | + case $this->template_args['event'] instanceof EE_Event: |
|
252 | + $this->query_params[0] = array( |
|
253 | + 'Registration.EVT_ID' => $this->template_args['event']->ID(), |
|
254 | + ); |
|
255 | + break; |
|
256 | + } |
|
257 | + } |
|
258 | 258 | |
259 | 259 | |
260 | - /** |
|
261 | - * @param array $attributes |
|
262 | - * @return EE_Event|null |
|
263 | - * @throws EE_Error |
|
264 | - * @throws InvalidDataTypeException |
|
265 | - * @throws InvalidInterfaceException |
|
266 | - * @throws InvalidArgumentException |
|
267 | - * @throws ReflectionException |
|
268 | - */ |
|
269 | - private function getEvent(array $attributes) |
|
270 | - { |
|
271 | - switch (true) { |
|
272 | - case ! empty($attributes['event_id']): |
|
273 | - $event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']); |
|
274 | - break; |
|
275 | - case ! empty($attributes['datetime_id']): |
|
276 | - $event = EEM_Event::instance()->get_one(array( |
|
277 | - array( |
|
278 | - 'Datetime.DTT_ID' => $attributes['datetime_id'], |
|
279 | - ), |
|
280 | - )); |
|
281 | - break; |
|
282 | - case ! empty($attributes['ticket_id']): |
|
283 | - $event = EEM_Event::instance()->get_one(array( |
|
284 | - array( |
|
285 | - 'Datetime.Ticket.TKT_ID' => $attributes['ticket_id'], |
|
286 | - ), |
|
287 | - 'default_where_conditions' => 'none' |
|
288 | - )); |
|
289 | - break; |
|
290 | - case is_espresso_event(): |
|
291 | - $event = EEH_Event_View::get_event(); |
|
292 | - break; |
|
293 | - default: |
|
294 | - // one last shot... |
|
295 | - // try getting the earliest active event |
|
296 | - $events = EEM_Event::instance()->get_active_events(array( |
|
297 | - 'limit' => 1, |
|
298 | - 'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'), |
|
299 | - )); |
|
300 | - // if none then get the next upcoming |
|
301 | - $events = empty($events) |
|
302 | - ? EEM_Event::instance()->get_upcoming_events(array( |
|
303 | - 'limit' => 1, |
|
304 | - 'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'), |
|
305 | - )) |
|
306 | - : $events; |
|
307 | - $event = reset($events); |
|
308 | - } |
|
260 | + /** |
|
261 | + * @param array $attributes |
|
262 | + * @return EE_Event|null |
|
263 | + * @throws EE_Error |
|
264 | + * @throws InvalidDataTypeException |
|
265 | + * @throws InvalidInterfaceException |
|
266 | + * @throws InvalidArgumentException |
|
267 | + * @throws ReflectionException |
|
268 | + */ |
|
269 | + private function getEvent(array $attributes) |
|
270 | + { |
|
271 | + switch (true) { |
|
272 | + case ! empty($attributes['event_id']): |
|
273 | + $event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']); |
|
274 | + break; |
|
275 | + case ! empty($attributes['datetime_id']): |
|
276 | + $event = EEM_Event::instance()->get_one(array( |
|
277 | + array( |
|
278 | + 'Datetime.DTT_ID' => $attributes['datetime_id'], |
|
279 | + ), |
|
280 | + )); |
|
281 | + break; |
|
282 | + case ! empty($attributes['ticket_id']): |
|
283 | + $event = EEM_Event::instance()->get_one(array( |
|
284 | + array( |
|
285 | + 'Datetime.Ticket.TKT_ID' => $attributes['ticket_id'], |
|
286 | + ), |
|
287 | + 'default_where_conditions' => 'none' |
|
288 | + )); |
|
289 | + break; |
|
290 | + case is_espresso_event(): |
|
291 | + $event = EEH_Event_View::get_event(); |
|
292 | + break; |
|
293 | + default: |
|
294 | + // one last shot... |
|
295 | + // try getting the earliest active event |
|
296 | + $events = EEM_Event::instance()->get_active_events(array( |
|
297 | + 'limit' => 1, |
|
298 | + 'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'), |
|
299 | + )); |
|
300 | + // if none then get the next upcoming |
|
301 | + $events = empty($events) |
|
302 | + ? EEM_Event::instance()->get_upcoming_events(array( |
|
303 | + 'limit' => 1, |
|
304 | + 'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'), |
|
305 | + )) |
|
306 | + : $events; |
|
307 | + $event = reset($events); |
|
308 | + } |
|
309 | 309 | |
310 | - return $event instanceof EE_Event ? $event : null; |
|
311 | - } |
|
310 | + return $event instanceof EE_Event ? $event : null; |
|
311 | + } |
|
312 | 312 | |
313 | 313 | |
314 | - /** |
|
315 | - * @param array $attributes |
|
316 | - * @return EE_Datetime|null |
|
317 | - * @throws EE_Error |
|
318 | - * @throws InvalidDataTypeException |
|
319 | - * @throws InvalidInterfaceException |
|
320 | - * @throws InvalidArgumentException |
|
321 | - */ |
|
322 | - private function getDatetime(array $attributes) |
|
323 | - { |
|
324 | - if (! empty($attributes['datetime_id'])) { |
|
325 | - $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']); |
|
326 | - if ($datetime instanceof EE_Datetime) { |
|
327 | - return $datetime; |
|
328 | - } |
|
329 | - } |
|
330 | - return null; |
|
331 | - } |
|
314 | + /** |
|
315 | + * @param array $attributes |
|
316 | + * @return EE_Datetime|null |
|
317 | + * @throws EE_Error |
|
318 | + * @throws InvalidDataTypeException |
|
319 | + * @throws InvalidInterfaceException |
|
320 | + * @throws InvalidArgumentException |
|
321 | + */ |
|
322 | + private function getDatetime(array $attributes) |
|
323 | + { |
|
324 | + if (! empty($attributes['datetime_id'])) { |
|
325 | + $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']); |
|
326 | + if ($datetime instanceof EE_Datetime) { |
|
327 | + return $datetime; |
|
328 | + } |
|
329 | + } |
|
330 | + return null; |
|
331 | + } |
|
332 | 332 | |
333 | 333 | |
334 | - /** |
|
335 | - * @param array $attributes |
|
336 | - * @return EE_Base_Class|EE_Ticket|null |
|
337 | - * @throws EE_Error |
|
338 | - * @throws InvalidDataTypeException |
|
339 | - * @throws InvalidInterfaceException |
|
340 | - * @throws InvalidArgumentException |
|
341 | - */ |
|
342 | - private function getTicket(array $attributes) |
|
343 | - { |
|
344 | - if (! empty($attributes['ticket_id'])) { |
|
345 | - $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']); |
|
346 | - if ($ticket instanceof EE_Ticket) { |
|
347 | - return $ticket; |
|
348 | - } |
|
349 | - } |
|
350 | - return null; |
|
351 | - } |
|
334 | + /** |
|
335 | + * @param array $attributes |
|
336 | + * @return EE_Base_Class|EE_Ticket|null |
|
337 | + * @throws EE_Error |
|
338 | + * @throws InvalidDataTypeException |
|
339 | + * @throws InvalidInterfaceException |
|
340 | + * @throws InvalidArgumentException |
|
341 | + */ |
|
342 | + private function getTicket(array $attributes) |
|
343 | + { |
|
344 | + if (! empty($attributes['ticket_id'])) { |
|
345 | + $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']); |
|
346 | + if ($ticket instanceof EE_Ticket) { |
|
347 | + return $ticket; |
|
348 | + } |
|
349 | + } |
|
350 | + return null; |
|
351 | + } |
|
352 | 352 | |
353 | 353 | |
354 | - /** |
|
355 | - * @param array $attributes |
|
356 | - * @throws EE_Error |
|
357 | - */ |
|
358 | - private function setAdditionalQueryParams(array $attributes) |
|
359 | - { |
|
360 | - $reg_status_array = EEM_Registration::reg_status_array(); |
|
361 | - if (isset($reg_status_array[ $attributes['status'] ])) { |
|
362 | - $this->query_params[0]['Registration.STS_ID'] = $attributes['status']; |
|
363 | - } |
|
364 | - if (absint($attributes['limit'])) { |
|
365 | - $this->query_params['limit'] = $attributes['limit']; |
|
366 | - } |
|
367 | - $this->query_params['group_by'] = array('ATT_ID'); |
|
368 | - $this->query_params['order_by'] = (array) apply_filters( |
|
369 | - 'FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by', |
|
370 | - array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC') |
|
371 | - ); |
|
372 | - } |
|
354 | + /** |
|
355 | + * @param array $attributes |
|
356 | + * @throws EE_Error |
|
357 | + */ |
|
358 | + private function setAdditionalQueryParams(array $attributes) |
|
359 | + { |
|
360 | + $reg_status_array = EEM_Registration::reg_status_array(); |
|
361 | + if (isset($reg_status_array[ $attributes['status'] ])) { |
|
362 | + $this->query_params[0]['Registration.STS_ID'] = $attributes['status']; |
|
363 | + } |
|
364 | + if (absint($attributes['limit'])) { |
|
365 | + $this->query_params['limit'] = $attributes['limit']; |
|
366 | + } |
|
367 | + $this->query_params['group_by'] = array('ATT_ID'); |
|
368 | + $this->query_params['order_by'] = (array) apply_filters( |
|
369 | + 'FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by', |
|
370 | + array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC') |
|
371 | + ); |
|
372 | + } |
|
373 | 373 | } |
@@ -128,7 +128,7 @@ discard block |
||
128 | 128 | if (is_array($this->_CPTs)) { |
129 | 129 | foreach ($this->_CPTs as $CPT_type => $CPT) { |
130 | 130 | if (isset($CPT['plural_slug'])) { |
131 | - $_CPT_endpoints [ (string) $CPT['plural_slug'] ] = $CPT_type; |
|
131 | + $_CPT_endpoints [(string) $CPT['plural_slug']] = $CPT_type; |
|
132 | 132 | } |
133 | 133 | } |
134 | 134 | } |
@@ -151,7 +151,7 @@ discard block |
||
151 | 151 | public function pre_get_posts($WP_Query) |
152 | 152 | { |
153 | 153 | // check that post-type is set |
154 | - if (! $WP_Query instanceof WP_Query) { |
|
154 | + if ( ! $WP_Query instanceof WP_Query) { |
|
155 | 155 | return; |
156 | 156 | } |
157 | 157 | // add our conditionals |
@@ -195,7 +195,7 @@ discard block |
||
195 | 195 | $terms = EEM_Term::instance()->get_all_CPT_post_tags(); |
196 | 196 | foreach ($terms as $term) { |
197 | 197 | if ($term instanceof EE_Term) { |
198 | - $this->_CPT_terms[ $term->slug() ] = $term; |
|
198 | + $this->_CPT_terms[$term->slug()] = $term; |
|
199 | 199 | } |
200 | 200 | } |
201 | 201 | } |
@@ -260,7 +260,7 @@ discard block |
||
260 | 260 | // loop thru our taxonomies |
261 | 261 | foreach ($this->_CPT_taxonomies as $CPT_taxonomy => $CPT_taxonomy_details) { |
262 | 262 | // check if one of our taxonomies is set as a query var |
263 | - if (isset($WP_Query->query[ $CPT_taxonomy ])) { |
|
263 | + if (isset($WP_Query->query[$CPT_taxonomy])) { |
|
264 | 264 | // but which CPT does that correspond to??? hmmm... guess we gotta go looping |
265 | 265 | foreach ($this->_CPTs as $post_type => $CPT) { |
266 | 266 | // verify our CPT has args, is public and has taxonomies set |
@@ -284,7 +284,7 @@ discard block |
||
284 | 284 | break; |
285 | 285 | default: |
286 | 286 | do_action( |
287 | - 'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_' . $post_type . '_post_type', |
|
287 | + 'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_'.$post_type.'_post_type', |
|
288 | 288 | $WP_Query, |
289 | 289 | $this |
290 | 290 | ); |
@@ -309,11 +309,11 @@ discard block |
||
309 | 309 | // loop thru post_types as array |
310 | 310 | foreach ((array) $WP_Query->query_vars['post_type'] as $post_type) { |
311 | 311 | // is current query for an EE CPT ? |
312 | - if (isset($this->_CPTs[ $post_type ])) { |
|
312 | + if (isset($this->_CPTs[$post_type])) { |
|
313 | 313 | // is EE on or off ? |
314 | 314 | if (EE_Maintenance_Mode::instance()->level()) { |
315 | 315 | // reroute CPT template view to maintenance_mode.template.php |
316 | - if (! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) { |
|
316 | + if ( ! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) { |
|
317 | 317 | add_filter('template_include', array('EE_Maintenance_Mode', 'template_include'), 99999); |
318 | 318 | } |
319 | 319 | if (has_filter('the_content', array(EE_Maintenance_Mode::instance(), 'the_content'))) { |
@@ -341,7 +341,7 @@ discard block |
||
341 | 341 | 'EventEspresso\core\CPTs\CptQueryModifier', |
342 | 342 | array( |
343 | 343 | $post_type, |
344 | - $this->_CPTs[ $post_type ], |
|
344 | + $this->_CPTs[$post_type], |
|
345 | 345 | $WP_Query, |
346 | 346 | ) |
347 | 347 | ); |
@@ -16,449 +16,449 @@ |
||
16 | 16 | */ |
17 | 17 | class EE_CPT_Strategy extends EE_Base |
18 | 18 | { |
19 | - /** |
|
20 | - * @var EE_CPT_Strategy $_instance |
|
21 | - */ |
|
22 | - private static $_instance; |
|
23 | - |
|
24 | - /** |
|
25 | - * the current page, if it utilizes CPTs |
|
26 | - * |
|
27 | - * @var array $CPT |
|
28 | - */ |
|
29 | - protected $CPT; |
|
30 | - |
|
31 | - /** |
|
32 | - * return value from CustomPostTypeDefinitions::getDefinitions() |
|
33 | - * |
|
34 | - * @var array $_CPTs |
|
35 | - */ |
|
36 | - protected $_CPTs = array(); |
|
37 | - |
|
38 | - /** |
|
39 | - * @var array $_CPT_taxonomies |
|
40 | - */ |
|
41 | - protected $_CPT_taxonomies = array(); |
|
42 | - |
|
43 | - /** |
|
44 | - * @var array $_CPT_terms |
|
45 | - */ |
|
46 | - protected $_CPT_terms = array(); |
|
47 | - |
|
48 | - /** |
|
49 | - * @var array $_CPT_endpoints |
|
50 | - */ |
|
51 | - protected $_CPT_endpoints = array(); |
|
52 | - |
|
53 | - /** |
|
54 | - * @var EEM_Base $CPT_model |
|
55 | - */ |
|
56 | - protected $CPT_model; |
|
57 | - |
|
58 | - /** |
|
59 | - * @var CptQueryModifier $query_modifier |
|
60 | - */ |
|
61 | - protected $query_modifier; |
|
62 | - |
|
63 | - |
|
64 | - /** |
|
65 | - * @singleton method used to instantiate class object |
|
66 | - * @param CustomPostTypeDefinitions|null $custom_post_types |
|
67 | - * @param CustomTaxonomyDefinitions|null $taxonomies |
|
68 | - * @return EE_CPT_Strategy |
|
69 | - */ |
|
70 | - public static function instance( |
|
71 | - $custom_post_types = null, |
|
72 | - $taxonomies = null |
|
73 | - ) { |
|
74 | - // check if class object is instantiated |
|
75 | - if ( |
|
76 | - ! self::$_instance instanceof EE_CPT_Strategy |
|
77 | - && $custom_post_types instanceof CustomPostTypeDefinitions |
|
78 | - && $taxonomies instanceof CustomTaxonomyDefinitions |
|
79 | - ) { |
|
80 | - self::$_instance = new self($custom_post_types, $taxonomies); |
|
81 | - } |
|
82 | - return self::$_instance; |
|
83 | - } |
|
84 | - |
|
85 | - |
|
86 | - /** |
|
87 | - * @param CustomPostTypeDefinitions $custom_post_types |
|
88 | - * @param CustomTaxonomyDefinitions $taxonomies |
|
89 | - */ |
|
90 | - protected function __construct( |
|
91 | - CustomPostTypeDefinitions $custom_post_types, |
|
92 | - CustomTaxonomyDefinitions $taxonomies |
|
93 | - ) { |
|
94 | - // get CPT data |
|
95 | - $this->_CPTs = $custom_post_types->getDefinitions(); |
|
96 | - $this->_CPT_endpoints = $this->_set_CPT_endpoints(); |
|
97 | - $this->_CPT_taxonomies = $taxonomies->getCustomTaxonomyDefinitions(); |
|
98 | - add_action('pre_get_posts', array($this, 'pre_get_posts'), 5); |
|
99 | - } |
|
100 | - |
|
101 | - |
|
102 | - /** |
|
103 | - * @return array |
|
104 | - */ |
|
105 | - public function get_CPT_endpoints() |
|
106 | - { |
|
107 | - return $this->_CPT_endpoints; |
|
108 | - } |
|
109 | - |
|
110 | - |
|
111 | - /** |
|
112 | - * @return array |
|
113 | - */ |
|
114 | - public function get_CPT_taxonomies() |
|
115 | - { |
|
116 | - return $this->_CPT_taxonomies; |
|
117 | - } |
|
118 | - |
|
119 | - |
|
120 | - /** |
|
121 | - * add CPT "slugs" to array of default espresso "pages" |
|
122 | - * |
|
123 | - * @return array |
|
124 | - */ |
|
125 | - private function _set_CPT_endpoints() |
|
126 | - { |
|
127 | - $_CPT_endpoints = array(); |
|
128 | - if (is_array($this->_CPTs)) { |
|
129 | - foreach ($this->_CPTs as $CPT_type => $CPT) { |
|
130 | - if (isset($CPT['plural_slug'])) { |
|
131 | - $_CPT_endpoints [ (string) $CPT['plural_slug'] ] = $CPT_type; |
|
132 | - } |
|
133 | - } |
|
134 | - } |
|
135 | - return $_CPT_endpoints; |
|
136 | - } |
|
137 | - |
|
138 | - |
|
139 | - /** |
|
140 | - * If this query (not just "main" queries (ie, for WP's infamous "loop")) is for an EE CPT, then we want to |
|
141 | - * supercharge the get_posts query to add our EE stuff (like joining to our tables, selecting extra columns, and |
|
142 | - * adding EE objects to the post to facilitate further querying of related data etc) |
|
143 | - * |
|
144 | - * @param WP_Query $WP_Query |
|
145 | - * @return void |
|
146 | - * @throws EE_Error |
|
147 | - * @throws InvalidArgumentException |
|
148 | - * @throws InvalidInterfaceException |
|
149 | - * @throws InvalidDataTypeException |
|
150 | - */ |
|
151 | - public function pre_get_posts($WP_Query) |
|
152 | - { |
|
153 | - // check that post-type is set |
|
154 | - if (! $WP_Query instanceof WP_Query) { |
|
155 | - return; |
|
156 | - } |
|
157 | - // add our conditionals |
|
158 | - $this->_set_EE_tags_on_WP_Query($WP_Query); |
|
159 | - // check for terms |
|
160 | - $this->_set_post_type_for_terms($WP_Query); |
|
161 | - // make sure paging is always set |
|
162 | - $this->_set_paging($WP_Query); |
|
163 | - // is a taxonomy set ? |
|
164 | - $this->_set_CPT_taxonomies_on_WP_Query($WP_Query); |
|
165 | - // loop thru post_types if set |
|
166 | - $this->_process_WP_Query_post_types($WP_Query); |
|
167 | - } |
|
168 | - |
|
169 | - |
|
170 | - /** |
|
171 | - * @param WP_Query $WP_Query |
|
172 | - * @return void |
|
173 | - */ |
|
174 | - private function _set_EE_tags_on_WP_Query(WP_Query $WP_Query) |
|
175 | - { |
|
176 | - $WP_Query->is_espresso_event_single = false; |
|
177 | - $WP_Query->is_espresso_event_archive = false; |
|
178 | - $WP_Query->is_espresso_event_taxonomy = false; |
|
179 | - $WP_Query->is_espresso_venue_single = false; |
|
180 | - $WP_Query->is_espresso_venue_archive = false; |
|
181 | - $WP_Query->is_espresso_venue_taxonomy = false; |
|
182 | - } |
|
183 | - |
|
184 | - |
|
185 | - /** |
|
186 | - * @return void |
|
187 | - * @throws EE_Error |
|
188 | - * @throws InvalidArgumentException |
|
189 | - * @throws InvalidDataTypeException |
|
190 | - * @throws InvalidInterfaceException |
|
191 | - */ |
|
192 | - private function _set_CPT_terms() |
|
193 | - { |
|
194 | - if (empty($this->_CPT_terms)) { |
|
195 | - $terms = EEM_Term::instance()->get_all_CPT_post_tags(); |
|
196 | - foreach ($terms as $term) { |
|
197 | - if ($term instanceof EE_Term) { |
|
198 | - $this->_CPT_terms[ $term->slug() ] = $term; |
|
199 | - } |
|
200 | - } |
|
201 | - } |
|
202 | - } |
|
203 | - |
|
204 | - |
|
205 | - /** |
|
206 | - * @param WP_Query $WP_Query |
|
207 | - * @return void |
|
208 | - * @throws EE_Error |
|
209 | - * @throws InvalidArgumentException |
|
210 | - * @throws InvalidDataTypeException |
|
211 | - * @throws InvalidInterfaceException |
|
212 | - */ |
|
213 | - private function _set_post_type_for_terms(WP_Query $WP_Query) |
|
214 | - { |
|
215 | - // is a tag set ? |
|
216 | - if (isset($WP_Query->query['tag'])) { |
|
217 | - // get term for tag |
|
218 | - $term = EEM_Term::instance()->get_post_tag_for_event_or_venue($WP_Query->query['tag']); |
|
219 | - // verify the term |
|
220 | - if ($term instanceof EE_Term) { |
|
221 | - $term->post_type = array_merge(array('post', 'page'), (array) $term->post_type); |
|
222 | - $term->post_type = apply_filters( |
|
223 | - 'FHEE__EE_CPT_Strategy___set_post_type_for_terms__term_post_type', |
|
224 | - $term->post_type, |
|
225 | - $term |
|
226 | - ); |
|
227 | - // if a post type is already set |
|
228 | - if (isset($WP_Query->query_vars['post_type'])) { |
|
229 | - // add to existing array |
|
230 | - $term->post_type = array_merge((array) $WP_Query->query_vars['post_type'], $term->post_type); |
|
231 | - } |
|
232 | - // just set post_type to our CPT |
|
233 | - $WP_Query->set('post_type', array_unique($term->post_type)); |
|
234 | - } |
|
235 | - } |
|
236 | - } |
|
237 | - |
|
238 | - |
|
239 | - /** |
|
240 | - * @param WP_Query $WP_Query |
|
241 | - * @return void |
|
242 | - */ |
|
243 | - public function _set_paging($WP_Query) |
|
244 | - { |
|
245 | - if ($WP_Query->is_main_query() && apply_filters('FHEE__EE_CPT_Strategy___set_paging', true)) { |
|
246 | - $page = get_query_var('page') ? get_query_var('page') : null; |
|
247 | - $paged = get_query_var('paged') ? get_query_var('paged') : $page; |
|
248 | - $WP_Query->set('paged', $paged); |
|
249 | - } |
|
250 | - } |
|
251 | - |
|
252 | - |
|
253 | - /** |
|
254 | - * @param \WP_Query $WP_Query |
|
255 | - */ |
|
256 | - protected function _set_CPT_taxonomies_on_WP_Query($WP_Query) |
|
257 | - { |
|
258 | - // is a taxonomy set ? |
|
259 | - if ($WP_Query->is_tax) { |
|
260 | - // loop thru our taxonomies |
|
261 | - foreach ($this->_CPT_taxonomies as $CPT_taxonomy => $CPT_taxonomy_details) { |
|
262 | - // check if one of our taxonomies is set as a query var |
|
263 | - if (isset($WP_Query->query[ $CPT_taxonomy ])) { |
|
264 | - // but which CPT does that correspond to??? hmmm... guess we gotta go looping |
|
265 | - foreach ($this->_CPTs as $post_type => $CPT) { |
|
266 | - // verify our CPT has args, is public and has taxonomies set |
|
267 | - if ( |
|
268 | - isset($CPT['args']['public']) |
|
269 | - && $CPT['args']['public'] |
|
270 | - && ! empty($CPT['args']['taxonomies']) |
|
271 | - && in_array($CPT_taxonomy, $CPT['args']['taxonomies'], true) |
|
272 | - ) { |
|
273 | - // if so, then add this CPT post_type to the current query's array of post_types' |
|
274 | - $WP_Query->query_vars['post_type'] = isset($WP_Query->query_vars['post_type']) |
|
275 | - ? (array) $WP_Query->query_vars['post_type'] |
|
276 | - : array(); |
|
277 | - $WP_Query->query_vars['post_type'][] = $post_type; |
|
278 | - switch ($post_type) { |
|
279 | - case 'espresso_events': |
|
280 | - $WP_Query->is_espresso_event_taxonomy = true; |
|
281 | - break; |
|
282 | - case 'espresso_venues': |
|
283 | - $WP_Query->is_espresso_venue_taxonomy = true; |
|
284 | - break; |
|
285 | - default: |
|
286 | - do_action( |
|
287 | - 'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_' . $post_type . '_post_type', |
|
288 | - $WP_Query, |
|
289 | - $this |
|
290 | - ); |
|
291 | - } |
|
292 | - } |
|
293 | - } |
|
294 | - } |
|
295 | - } |
|
296 | - } |
|
297 | - } |
|
298 | - |
|
299 | - |
|
300 | - /** |
|
301 | - * @param \WP_Query $WP_Query |
|
302 | - * @throws InvalidArgumentException |
|
303 | - * @throws InvalidDataTypeException |
|
304 | - * @throws InvalidInterfaceException |
|
305 | - */ |
|
306 | - protected function _process_WP_Query_post_types($WP_Query) |
|
307 | - { |
|
308 | - if (isset($WP_Query->query_vars['post_type'])) { |
|
309 | - // loop thru post_types as array |
|
310 | - foreach ((array) $WP_Query->query_vars['post_type'] as $post_type) { |
|
311 | - // is current query for an EE CPT ? |
|
312 | - if (isset($this->_CPTs[ $post_type ])) { |
|
313 | - // is EE on or off ? |
|
314 | - if (EE_Maintenance_Mode::instance()->level()) { |
|
315 | - // reroute CPT template view to maintenance_mode.template.php |
|
316 | - if (! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) { |
|
317 | - add_filter('template_include', array('EE_Maintenance_Mode', 'template_include'), 99999); |
|
318 | - } |
|
319 | - if (has_filter('the_content', array(EE_Maintenance_Mode::instance(), 'the_content'))) { |
|
320 | - add_filter('the_content', array($this, 'inject_EE_shortcode_placeholder'), 1); |
|
321 | - } |
|
322 | - return; |
|
323 | - } |
|
324 | - $this->_generate_CptQueryModifier($WP_Query, $post_type); |
|
325 | - } |
|
326 | - } |
|
327 | - } |
|
328 | - } |
|
329 | - |
|
330 | - |
|
331 | - /** |
|
332 | - * @param \WP_Query $WP_Query |
|
333 | - * @param string $post_type |
|
334 | - * @throws InvalidArgumentException |
|
335 | - * @throws InvalidDataTypeException |
|
336 | - * @throws InvalidInterfaceException |
|
337 | - */ |
|
338 | - protected function _generate_CptQueryModifier($WP_Query, $post_type) |
|
339 | - { |
|
340 | - $this->query_modifier = LoaderFactory::getLoader()->getShared( |
|
341 | - 'EventEspresso\core\CPTs\CptQueryModifier', |
|
342 | - array( |
|
343 | - $post_type, |
|
344 | - $this->_CPTs[ $post_type ], |
|
345 | - $WP_Query, |
|
346 | - ) |
|
347 | - ); |
|
348 | - $this->_CPT_taxonomies = $this->query_modifier->taxonomies(); |
|
349 | - } |
|
350 | - |
|
351 | - |
|
352 | - /** |
|
353 | - * inject_EE_shortcode_placeholder |
|
354 | - * in order to display the M-Mode notice on our CPT routes, |
|
355 | - * we need to first inject what looks like one of our shortcodes, |
|
356 | - * so that it can be replaced with the actual M-Mode notice |
|
357 | - * |
|
358 | - * @return string |
|
359 | - */ |
|
360 | - public function inject_EE_shortcode_placeholder() |
|
361 | - { |
|
362 | - return '[ESPRESSO_'; |
|
363 | - } |
|
364 | - |
|
365 | - |
|
366 | - /** |
|
367 | - * @deprecated |
|
368 | - * @since 4.8.41 |
|
369 | - * @return void |
|
370 | - */ |
|
371 | - public function _possibly_set_ee_request_var() |
|
372 | - { |
|
373 | - $this->query_modifier->setRequestVarsIfCpt(); |
|
374 | - } |
|
375 | - |
|
376 | - |
|
377 | - /** |
|
378 | - * @deprecated |
|
379 | - * @since 4.8.41 |
|
380 | - * @param $SQL |
|
381 | - * @return string |
|
382 | - */ |
|
383 | - public function posts_fields($SQL) |
|
384 | - { |
|
385 | - if ($this->query_modifier instanceof CptQueryModifier) { |
|
386 | - return $this->query_modifier->postsFields($SQL); |
|
387 | - } |
|
388 | - return $SQL; |
|
389 | - } |
|
390 | - |
|
391 | - |
|
392 | - /** |
|
393 | - * @deprecated |
|
394 | - * @since 4.8.41 |
|
395 | - * @param $SQL |
|
396 | - * @return string |
|
397 | - */ |
|
398 | - public function posts_join($SQL) |
|
399 | - { |
|
400 | - if ($this->query_modifier instanceof CptQueryModifier) { |
|
401 | - return $this->query_modifier->postsJoin($SQL); |
|
402 | - } |
|
403 | - return $SQL; |
|
404 | - } |
|
405 | - |
|
406 | - |
|
407 | - /** |
|
408 | - * @deprecated |
|
409 | - * @since 4.8.41 |
|
410 | - * @param \WP_Post[] $posts |
|
411 | - * @return \WP_Post[] |
|
412 | - */ |
|
413 | - public function the_posts($posts) |
|
414 | - { |
|
415 | - if ($this->query_modifier instanceof CptQueryModifier) { |
|
416 | - $this->query_modifier->thePosts($posts); |
|
417 | - } |
|
418 | - return $posts; |
|
419 | - } |
|
420 | - |
|
421 | - |
|
422 | - /** |
|
423 | - * @deprecated |
|
424 | - * @since 4.8.41 |
|
425 | - * @param $url |
|
426 | - * @param $ID |
|
427 | - * @return string |
|
428 | - */ |
|
429 | - public function get_edit_post_link($url, $ID) |
|
430 | - { |
|
431 | - if ($this->query_modifier instanceof CptQueryModifier) { |
|
432 | - return $this->query_modifier->getEditPostLink($url, $ID); |
|
433 | - } |
|
434 | - return ''; |
|
435 | - } |
|
436 | - |
|
437 | - |
|
438 | - /** |
|
439 | - * @deprecated |
|
440 | - * @since 4.8.41 |
|
441 | - * @param null $WP_Query |
|
442 | - */ |
|
443 | - protected function _do_template_filters($WP_Query = null) |
|
444 | - { |
|
445 | - if ($this->query_modifier instanceof CptQueryModifier) { |
|
446 | - $this->query_modifier->addTemplateFilters(); |
|
447 | - } |
|
448 | - } |
|
449 | - |
|
450 | - |
|
451 | - /** |
|
452 | - * @deprecated |
|
453 | - * @since 4.8.41 |
|
454 | - * @param string $current_template Existing default template path derived for this page call. |
|
455 | - * @return string the path to the full template file. |
|
456 | - */ |
|
457 | - public function single_cpt_template($current_template) |
|
458 | - { |
|
459 | - if ($this->query_modifier instanceof CptQueryModifier) { |
|
460 | - return $this->query_modifier->singleCptTemplate($current_template); |
|
461 | - } |
|
462 | - return $current_template; |
|
463 | - } |
|
19 | + /** |
|
20 | + * @var EE_CPT_Strategy $_instance |
|
21 | + */ |
|
22 | + private static $_instance; |
|
23 | + |
|
24 | + /** |
|
25 | + * the current page, if it utilizes CPTs |
|
26 | + * |
|
27 | + * @var array $CPT |
|
28 | + */ |
|
29 | + protected $CPT; |
|
30 | + |
|
31 | + /** |
|
32 | + * return value from CustomPostTypeDefinitions::getDefinitions() |
|
33 | + * |
|
34 | + * @var array $_CPTs |
|
35 | + */ |
|
36 | + protected $_CPTs = array(); |
|
37 | + |
|
38 | + /** |
|
39 | + * @var array $_CPT_taxonomies |
|
40 | + */ |
|
41 | + protected $_CPT_taxonomies = array(); |
|
42 | + |
|
43 | + /** |
|
44 | + * @var array $_CPT_terms |
|
45 | + */ |
|
46 | + protected $_CPT_terms = array(); |
|
47 | + |
|
48 | + /** |
|
49 | + * @var array $_CPT_endpoints |
|
50 | + */ |
|
51 | + protected $_CPT_endpoints = array(); |
|
52 | + |
|
53 | + /** |
|
54 | + * @var EEM_Base $CPT_model |
|
55 | + */ |
|
56 | + protected $CPT_model; |
|
57 | + |
|
58 | + /** |
|
59 | + * @var CptQueryModifier $query_modifier |
|
60 | + */ |
|
61 | + protected $query_modifier; |
|
62 | + |
|
63 | + |
|
64 | + /** |
|
65 | + * @singleton method used to instantiate class object |
|
66 | + * @param CustomPostTypeDefinitions|null $custom_post_types |
|
67 | + * @param CustomTaxonomyDefinitions|null $taxonomies |
|
68 | + * @return EE_CPT_Strategy |
|
69 | + */ |
|
70 | + public static function instance( |
|
71 | + $custom_post_types = null, |
|
72 | + $taxonomies = null |
|
73 | + ) { |
|
74 | + // check if class object is instantiated |
|
75 | + if ( |
|
76 | + ! self::$_instance instanceof EE_CPT_Strategy |
|
77 | + && $custom_post_types instanceof CustomPostTypeDefinitions |
|
78 | + && $taxonomies instanceof CustomTaxonomyDefinitions |
|
79 | + ) { |
|
80 | + self::$_instance = new self($custom_post_types, $taxonomies); |
|
81 | + } |
|
82 | + return self::$_instance; |
|
83 | + } |
|
84 | + |
|
85 | + |
|
86 | + /** |
|
87 | + * @param CustomPostTypeDefinitions $custom_post_types |
|
88 | + * @param CustomTaxonomyDefinitions $taxonomies |
|
89 | + */ |
|
90 | + protected function __construct( |
|
91 | + CustomPostTypeDefinitions $custom_post_types, |
|
92 | + CustomTaxonomyDefinitions $taxonomies |
|
93 | + ) { |
|
94 | + // get CPT data |
|
95 | + $this->_CPTs = $custom_post_types->getDefinitions(); |
|
96 | + $this->_CPT_endpoints = $this->_set_CPT_endpoints(); |
|
97 | + $this->_CPT_taxonomies = $taxonomies->getCustomTaxonomyDefinitions(); |
|
98 | + add_action('pre_get_posts', array($this, 'pre_get_posts'), 5); |
|
99 | + } |
|
100 | + |
|
101 | + |
|
102 | + /** |
|
103 | + * @return array |
|
104 | + */ |
|
105 | + public function get_CPT_endpoints() |
|
106 | + { |
|
107 | + return $this->_CPT_endpoints; |
|
108 | + } |
|
109 | + |
|
110 | + |
|
111 | + /** |
|
112 | + * @return array |
|
113 | + */ |
|
114 | + public function get_CPT_taxonomies() |
|
115 | + { |
|
116 | + return $this->_CPT_taxonomies; |
|
117 | + } |
|
118 | + |
|
119 | + |
|
120 | + /** |
|
121 | + * add CPT "slugs" to array of default espresso "pages" |
|
122 | + * |
|
123 | + * @return array |
|
124 | + */ |
|
125 | + private function _set_CPT_endpoints() |
|
126 | + { |
|
127 | + $_CPT_endpoints = array(); |
|
128 | + if (is_array($this->_CPTs)) { |
|
129 | + foreach ($this->_CPTs as $CPT_type => $CPT) { |
|
130 | + if (isset($CPT['plural_slug'])) { |
|
131 | + $_CPT_endpoints [ (string) $CPT['plural_slug'] ] = $CPT_type; |
|
132 | + } |
|
133 | + } |
|
134 | + } |
|
135 | + return $_CPT_endpoints; |
|
136 | + } |
|
137 | + |
|
138 | + |
|
139 | + /** |
|
140 | + * If this query (not just "main" queries (ie, for WP's infamous "loop")) is for an EE CPT, then we want to |
|
141 | + * supercharge the get_posts query to add our EE stuff (like joining to our tables, selecting extra columns, and |
|
142 | + * adding EE objects to the post to facilitate further querying of related data etc) |
|
143 | + * |
|
144 | + * @param WP_Query $WP_Query |
|
145 | + * @return void |
|
146 | + * @throws EE_Error |
|
147 | + * @throws InvalidArgumentException |
|
148 | + * @throws InvalidInterfaceException |
|
149 | + * @throws InvalidDataTypeException |
|
150 | + */ |
|
151 | + public function pre_get_posts($WP_Query) |
|
152 | + { |
|
153 | + // check that post-type is set |
|
154 | + if (! $WP_Query instanceof WP_Query) { |
|
155 | + return; |
|
156 | + } |
|
157 | + // add our conditionals |
|
158 | + $this->_set_EE_tags_on_WP_Query($WP_Query); |
|
159 | + // check for terms |
|
160 | + $this->_set_post_type_for_terms($WP_Query); |
|
161 | + // make sure paging is always set |
|
162 | + $this->_set_paging($WP_Query); |
|
163 | + // is a taxonomy set ? |
|
164 | + $this->_set_CPT_taxonomies_on_WP_Query($WP_Query); |
|
165 | + // loop thru post_types if set |
|
166 | + $this->_process_WP_Query_post_types($WP_Query); |
|
167 | + } |
|
168 | + |
|
169 | + |
|
170 | + /** |
|
171 | + * @param WP_Query $WP_Query |
|
172 | + * @return void |
|
173 | + */ |
|
174 | + private function _set_EE_tags_on_WP_Query(WP_Query $WP_Query) |
|
175 | + { |
|
176 | + $WP_Query->is_espresso_event_single = false; |
|
177 | + $WP_Query->is_espresso_event_archive = false; |
|
178 | + $WP_Query->is_espresso_event_taxonomy = false; |
|
179 | + $WP_Query->is_espresso_venue_single = false; |
|
180 | + $WP_Query->is_espresso_venue_archive = false; |
|
181 | + $WP_Query->is_espresso_venue_taxonomy = false; |
|
182 | + } |
|
183 | + |
|
184 | + |
|
185 | + /** |
|
186 | + * @return void |
|
187 | + * @throws EE_Error |
|
188 | + * @throws InvalidArgumentException |
|
189 | + * @throws InvalidDataTypeException |
|
190 | + * @throws InvalidInterfaceException |
|
191 | + */ |
|
192 | + private function _set_CPT_terms() |
|
193 | + { |
|
194 | + if (empty($this->_CPT_terms)) { |
|
195 | + $terms = EEM_Term::instance()->get_all_CPT_post_tags(); |
|
196 | + foreach ($terms as $term) { |
|
197 | + if ($term instanceof EE_Term) { |
|
198 | + $this->_CPT_terms[ $term->slug() ] = $term; |
|
199 | + } |
|
200 | + } |
|
201 | + } |
|
202 | + } |
|
203 | + |
|
204 | + |
|
205 | + /** |
|
206 | + * @param WP_Query $WP_Query |
|
207 | + * @return void |
|
208 | + * @throws EE_Error |
|
209 | + * @throws InvalidArgumentException |
|
210 | + * @throws InvalidDataTypeException |
|
211 | + * @throws InvalidInterfaceException |
|
212 | + */ |
|
213 | + private function _set_post_type_for_terms(WP_Query $WP_Query) |
|
214 | + { |
|
215 | + // is a tag set ? |
|
216 | + if (isset($WP_Query->query['tag'])) { |
|
217 | + // get term for tag |
|
218 | + $term = EEM_Term::instance()->get_post_tag_for_event_or_venue($WP_Query->query['tag']); |
|
219 | + // verify the term |
|
220 | + if ($term instanceof EE_Term) { |
|
221 | + $term->post_type = array_merge(array('post', 'page'), (array) $term->post_type); |
|
222 | + $term->post_type = apply_filters( |
|
223 | + 'FHEE__EE_CPT_Strategy___set_post_type_for_terms__term_post_type', |
|
224 | + $term->post_type, |
|
225 | + $term |
|
226 | + ); |
|
227 | + // if a post type is already set |
|
228 | + if (isset($WP_Query->query_vars['post_type'])) { |
|
229 | + // add to existing array |
|
230 | + $term->post_type = array_merge((array) $WP_Query->query_vars['post_type'], $term->post_type); |
|
231 | + } |
|
232 | + // just set post_type to our CPT |
|
233 | + $WP_Query->set('post_type', array_unique($term->post_type)); |
|
234 | + } |
|
235 | + } |
|
236 | + } |
|
237 | + |
|
238 | + |
|
239 | + /** |
|
240 | + * @param WP_Query $WP_Query |
|
241 | + * @return void |
|
242 | + */ |
|
243 | + public function _set_paging($WP_Query) |
|
244 | + { |
|
245 | + if ($WP_Query->is_main_query() && apply_filters('FHEE__EE_CPT_Strategy___set_paging', true)) { |
|
246 | + $page = get_query_var('page') ? get_query_var('page') : null; |
|
247 | + $paged = get_query_var('paged') ? get_query_var('paged') : $page; |
|
248 | + $WP_Query->set('paged', $paged); |
|
249 | + } |
|
250 | + } |
|
251 | + |
|
252 | + |
|
253 | + /** |
|
254 | + * @param \WP_Query $WP_Query |
|
255 | + */ |
|
256 | + protected function _set_CPT_taxonomies_on_WP_Query($WP_Query) |
|
257 | + { |
|
258 | + // is a taxonomy set ? |
|
259 | + if ($WP_Query->is_tax) { |
|
260 | + // loop thru our taxonomies |
|
261 | + foreach ($this->_CPT_taxonomies as $CPT_taxonomy => $CPT_taxonomy_details) { |
|
262 | + // check if one of our taxonomies is set as a query var |
|
263 | + if (isset($WP_Query->query[ $CPT_taxonomy ])) { |
|
264 | + // but which CPT does that correspond to??? hmmm... guess we gotta go looping |
|
265 | + foreach ($this->_CPTs as $post_type => $CPT) { |
|
266 | + // verify our CPT has args, is public and has taxonomies set |
|
267 | + if ( |
|
268 | + isset($CPT['args']['public']) |
|
269 | + && $CPT['args']['public'] |
|
270 | + && ! empty($CPT['args']['taxonomies']) |
|
271 | + && in_array($CPT_taxonomy, $CPT['args']['taxonomies'], true) |
|
272 | + ) { |
|
273 | + // if so, then add this CPT post_type to the current query's array of post_types' |
|
274 | + $WP_Query->query_vars['post_type'] = isset($WP_Query->query_vars['post_type']) |
|
275 | + ? (array) $WP_Query->query_vars['post_type'] |
|
276 | + : array(); |
|
277 | + $WP_Query->query_vars['post_type'][] = $post_type; |
|
278 | + switch ($post_type) { |
|
279 | + case 'espresso_events': |
|
280 | + $WP_Query->is_espresso_event_taxonomy = true; |
|
281 | + break; |
|
282 | + case 'espresso_venues': |
|
283 | + $WP_Query->is_espresso_venue_taxonomy = true; |
|
284 | + break; |
|
285 | + default: |
|
286 | + do_action( |
|
287 | + 'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_' . $post_type . '_post_type', |
|
288 | + $WP_Query, |
|
289 | + $this |
|
290 | + ); |
|
291 | + } |
|
292 | + } |
|
293 | + } |
|
294 | + } |
|
295 | + } |
|
296 | + } |
|
297 | + } |
|
298 | + |
|
299 | + |
|
300 | + /** |
|
301 | + * @param \WP_Query $WP_Query |
|
302 | + * @throws InvalidArgumentException |
|
303 | + * @throws InvalidDataTypeException |
|
304 | + * @throws InvalidInterfaceException |
|
305 | + */ |
|
306 | + protected function _process_WP_Query_post_types($WP_Query) |
|
307 | + { |
|
308 | + if (isset($WP_Query->query_vars['post_type'])) { |
|
309 | + // loop thru post_types as array |
|
310 | + foreach ((array) $WP_Query->query_vars['post_type'] as $post_type) { |
|
311 | + // is current query for an EE CPT ? |
|
312 | + if (isset($this->_CPTs[ $post_type ])) { |
|
313 | + // is EE on or off ? |
|
314 | + if (EE_Maintenance_Mode::instance()->level()) { |
|
315 | + // reroute CPT template view to maintenance_mode.template.php |
|
316 | + if (! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) { |
|
317 | + add_filter('template_include', array('EE_Maintenance_Mode', 'template_include'), 99999); |
|
318 | + } |
|
319 | + if (has_filter('the_content', array(EE_Maintenance_Mode::instance(), 'the_content'))) { |
|
320 | + add_filter('the_content', array($this, 'inject_EE_shortcode_placeholder'), 1); |
|
321 | + } |
|
322 | + return; |
|
323 | + } |
|
324 | + $this->_generate_CptQueryModifier($WP_Query, $post_type); |
|
325 | + } |
|
326 | + } |
|
327 | + } |
|
328 | + } |
|
329 | + |
|
330 | + |
|
331 | + /** |
|
332 | + * @param \WP_Query $WP_Query |
|
333 | + * @param string $post_type |
|
334 | + * @throws InvalidArgumentException |
|
335 | + * @throws InvalidDataTypeException |
|
336 | + * @throws InvalidInterfaceException |
|
337 | + */ |
|
338 | + protected function _generate_CptQueryModifier($WP_Query, $post_type) |
|
339 | + { |
|
340 | + $this->query_modifier = LoaderFactory::getLoader()->getShared( |
|
341 | + 'EventEspresso\core\CPTs\CptQueryModifier', |
|
342 | + array( |
|
343 | + $post_type, |
|
344 | + $this->_CPTs[ $post_type ], |
|
345 | + $WP_Query, |
|
346 | + ) |
|
347 | + ); |
|
348 | + $this->_CPT_taxonomies = $this->query_modifier->taxonomies(); |
|
349 | + } |
|
350 | + |
|
351 | + |
|
352 | + /** |
|
353 | + * inject_EE_shortcode_placeholder |
|
354 | + * in order to display the M-Mode notice on our CPT routes, |
|
355 | + * we need to first inject what looks like one of our shortcodes, |
|
356 | + * so that it can be replaced with the actual M-Mode notice |
|
357 | + * |
|
358 | + * @return string |
|
359 | + */ |
|
360 | + public function inject_EE_shortcode_placeholder() |
|
361 | + { |
|
362 | + return '[ESPRESSO_'; |
|
363 | + } |
|
364 | + |
|
365 | + |
|
366 | + /** |
|
367 | + * @deprecated |
|
368 | + * @since 4.8.41 |
|
369 | + * @return void |
|
370 | + */ |
|
371 | + public function _possibly_set_ee_request_var() |
|
372 | + { |
|
373 | + $this->query_modifier->setRequestVarsIfCpt(); |
|
374 | + } |
|
375 | + |
|
376 | + |
|
377 | + /** |
|
378 | + * @deprecated |
|
379 | + * @since 4.8.41 |
|
380 | + * @param $SQL |
|
381 | + * @return string |
|
382 | + */ |
|
383 | + public function posts_fields($SQL) |
|
384 | + { |
|
385 | + if ($this->query_modifier instanceof CptQueryModifier) { |
|
386 | + return $this->query_modifier->postsFields($SQL); |
|
387 | + } |
|
388 | + return $SQL; |
|
389 | + } |
|
390 | + |
|
391 | + |
|
392 | + /** |
|
393 | + * @deprecated |
|
394 | + * @since 4.8.41 |
|
395 | + * @param $SQL |
|
396 | + * @return string |
|
397 | + */ |
|
398 | + public function posts_join($SQL) |
|
399 | + { |
|
400 | + if ($this->query_modifier instanceof CptQueryModifier) { |
|
401 | + return $this->query_modifier->postsJoin($SQL); |
|
402 | + } |
|
403 | + return $SQL; |
|
404 | + } |
|
405 | + |
|
406 | + |
|
407 | + /** |
|
408 | + * @deprecated |
|
409 | + * @since 4.8.41 |
|
410 | + * @param \WP_Post[] $posts |
|
411 | + * @return \WP_Post[] |
|
412 | + */ |
|
413 | + public function the_posts($posts) |
|
414 | + { |
|
415 | + if ($this->query_modifier instanceof CptQueryModifier) { |
|
416 | + $this->query_modifier->thePosts($posts); |
|
417 | + } |
|
418 | + return $posts; |
|
419 | + } |
|
420 | + |
|
421 | + |
|
422 | + /** |
|
423 | + * @deprecated |
|
424 | + * @since 4.8.41 |
|
425 | + * @param $url |
|
426 | + * @param $ID |
|
427 | + * @return string |
|
428 | + */ |
|
429 | + public function get_edit_post_link($url, $ID) |
|
430 | + { |
|
431 | + if ($this->query_modifier instanceof CptQueryModifier) { |
|
432 | + return $this->query_modifier->getEditPostLink($url, $ID); |
|
433 | + } |
|
434 | + return ''; |
|
435 | + } |
|
436 | + |
|
437 | + |
|
438 | + /** |
|
439 | + * @deprecated |
|
440 | + * @since 4.8.41 |
|
441 | + * @param null $WP_Query |
|
442 | + */ |
|
443 | + protected function _do_template_filters($WP_Query = null) |
|
444 | + { |
|
445 | + if ($this->query_modifier instanceof CptQueryModifier) { |
|
446 | + $this->query_modifier->addTemplateFilters(); |
|
447 | + } |
|
448 | + } |
|
449 | + |
|
450 | + |
|
451 | + /** |
|
452 | + * @deprecated |
|
453 | + * @since 4.8.41 |
|
454 | + * @param string $current_template Existing default template path derived for this page call. |
|
455 | + * @return string the path to the full template file. |
|
456 | + */ |
|
457 | + public function single_cpt_template($current_template) |
|
458 | + { |
|
459 | + if ($this->query_modifier instanceof CptQueryModifier) { |
|
460 | + return $this->query_modifier->singleCptTemplate($current_template); |
|
461 | + } |
|
462 | + return $current_template; |
|
463 | + } |
|
464 | 464 | } |
@@ -122,13 +122,13 @@ discard block |
||
122 | 122 | ) |
123 | 123 | ) { |
124 | 124 | // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement |
125 | - $SQL .= ', ' . EEM_Datetime::instance()->table() . '.* '; |
|
125 | + $SQL .= ', '.EEM_Datetime::instance()->table().'.* '; |
|
126 | 126 | if ($wp_query->is_espresso_event_archive || $wp_query->is_espresso_event_taxonomy) { |
127 | 127 | // because we only want to retrieve the next upcoming datetime for each event: |
128 | 128 | // add something like: |
129 | 129 | // ", MIN( wp_esp_datetime.DTT_EVT_start ) as event_start_date " |
130 | 130 | // to WP Query SELECT statement |
131 | - $SQL .= ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date '; |
|
131 | + $SQL .= ', MIN( '.EEM_Datetime::instance()->table().'.DTT_EVT_start ) as event_start_date '; |
|
132 | 132 | } |
133 | 133 | } |
134 | 134 | return $SQL; |
@@ -158,9 +158,9 @@ discard block |
||
158 | 158 | // adds something like: |
159 | 159 | // " LEFT JOIN wp_esp_datetime ON ( wp_esp_datetime.EVT_ID = wp_posts.ID ) " |
160 | 160 | // to WP Query JOIN statement |
161 | - $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . EEM_Event::instance()->table() |
|
162 | - . '.ID = ' . EEM_Datetime::instance()->table() . '.' |
|
163 | - . EEM_Event::instance()->primary_key_name() . ' ) '; |
|
161 | + $SQL .= ' INNER JOIN '.EEM_Datetime::instance()->table().' ON ( '.EEM_Event::instance()->table() |
|
162 | + . '.ID = '.EEM_Datetime::instance()->table().'.' |
|
163 | + . EEM_Event::instance()->primary_key_name().' ) '; |
|
164 | 164 | } |
165 | 165 | return $SQL; |
166 | 166 | } |
@@ -190,8 +190,8 @@ discard block |
||
190 | 190 | || ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events) |
191 | 191 | || ! EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events |
192 | 192 | ) { |
193 | - $SQL .= ' AND ' . EEM_Datetime::instance()->table() . ".DTT_EVT_end > '" |
|
194 | - . current_time('mysql', true) . "' "; |
|
193 | + $SQL .= ' AND '.EEM_Datetime::instance()->table().".DTT_EVT_end > '" |
|
194 | + . current_time('mysql', true)."' "; |
|
195 | 195 | } |
196 | 196 | } |
197 | 197 | return $SQL; |
@@ -239,7 +239,7 @@ discard block |
||
239 | 239 | // but we want to only show each event only once |
240 | 240 | // (whereas if we didn't group them by the post's ID, then we would end up with many repeats) |
241 | 241 | global $wpdb; |
242 | - $SQL = $wpdb->posts . '.ID '; |
|
242 | + $SQL = $wpdb->posts.'.ID '; |
|
243 | 243 | } |
244 | 244 | return $SQL; |
245 | 245 | } |
@@ -9,244 +9,244 @@ |
||
9 | 9 | */ |
10 | 10 | class EE_CPT_Event_Strategy |
11 | 11 | { |
12 | - /** |
|
13 | - * the current page, if it utilizes CPTs |
|
14 | - * |
|
15 | - * @var object $CPT |
|
16 | - */ |
|
17 | - protected $CPT; |
|
18 | - |
|
19 | - |
|
20 | - /** |
|
21 | - * @param array|WP_Query|null $wp_query |
|
22 | - * @param array $CPT |
|
23 | - */ |
|
24 | - public function __construct($wp_query, array $CPT = []) |
|
25 | - { |
|
26 | - if ($wp_query instanceof WP_Query) { |
|
27 | - $WP_Query = $wp_query; |
|
28 | - $this->CPT = $CPT; |
|
29 | - } else { |
|
30 | - $WP_Query = isset($wp_query['WP_Query']) ? $wp_query['WP_Query'] : null; |
|
31 | - $this->CPT = isset($wp_query['CPT']) ? $wp_query['CPT'] : null; |
|
32 | - } |
|
33 | - // !!!!!!!!!! IMPORTANT !!!!!!!!!!!! |
|
34 | - // here's the list of available filters in the WP_Query object |
|
35 | - // 'posts_where' |
|
36 | - // 'posts_where_paged' |
|
37 | - // 'posts_groupby' |
|
38 | - // 'posts_join_paged' |
|
39 | - // 'posts_orderby' |
|
40 | - // 'posts_distinct' |
|
41 | - // 'post_limits' |
|
42 | - // 'posts_fields' |
|
43 | - // 'posts_join' |
|
44 | - $this->_add_filters(); |
|
45 | - if ($WP_Query instanceof WP_Query) { |
|
46 | - $WP_Query->is_espresso_event_single = is_singular() |
|
47 | - && isset($WP_Query->query->post_type) |
|
48 | - && $WP_Query->query->post_type === 'espresso_events'; |
|
49 | - $WP_Query->is_espresso_event_archive = is_post_type_archive('espresso_events'); |
|
50 | - $WP_Query->is_espresso_event_taxonomy = is_tax('espresso_event_categories'); |
|
51 | - } |
|
52 | - } |
|
53 | - |
|
54 | - |
|
55 | - /** |
|
56 | - * When an instance of this class is created, we add our filters |
|
57 | - * (which will get removed in case the next call to get_posts ISN'T |
|
58 | - * for event CPTs) |
|
59 | - */ |
|
60 | - protected function _add_filters() |
|
61 | - { |
|
62 | - add_filter('posts_fields', [$this, 'posts_fields'], 1, 2); |
|
63 | - add_filter('posts_join', [$this, 'posts_join'], 1, 2); |
|
64 | - add_filter('posts_where', [$this, 'posts_where'], 10, 2); |
|
65 | - // add_filter( 'the_posts', array( $this, 'the_posts' ), 1, 2 ); |
|
66 | - add_filter('posts_orderby', [$this, 'posts_orderby'], 1, 2); |
|
67 | - add_filter('posts_groupby', [$this, 'posts_groupby'], 1, 2); |
|
68 | - add_action('posts_selection', [$this, 'remove_filters']); |
|
69 | - } |
|
70 | - |
|
71 | - |
|
72 | - /** |
|
73 | - * public access to _remove_filters() |
|
74 | - * |
|
75 | - * @since 4.9.63.p |
|
76 | - */ |
|
77 | - public function remove_filters() |
|
78 | - { |
|
79 | - $this->_remove_filters(); |
|
80 | - } |
|
81 | - |
|
82 | - |
|
83 | - /** |
|
84 | - * Should eb called when the last filter or hook is fired for this CPT strategy. |
|
85 | - * This is to avoid applying this CPT strategy for other posts or CPTs (eg, |
|
86 | - * we don't want to join to the datetime table when querying for venues, do we!?) |
|
87 | - */ |
|
88 | - protected function _remove_filters() |
|
89 | - { |
|
90 | - remove_filter('posts_fields', [$this, 'posts_fields'], 1); |
|
91 | - remove_filter('posts_join', [$this, 'posts_join'], 1); |
|
92 | - remove_filter('posts_where', [$this, 'posts_where']); |
|
93 | - // remove_filter( 'the_posts', array( $this, 'the_posts' ), 1 ); |
|
94 | - remove_filter('posts_orderby', [$this, 'posts_orderby'], 1); |
|
95 | - remove_filter('posts_groupby', [$this, 'posts_groupby'], 1); |
|
96 | - remove_action('posts_selection', [$this, 'remove_filters']); |
|
97 | - } |
|
98 | - |
|
99 | - |
|
100 | - /** |
|
101 | - * @param string $SQL |
|
102 | - * @param WP_Query|null $wp_query |
|
103 | - * @return string |
|
104 | - * @throws EE_Error |
|
105 | - */ |
|
106 | - public function posts_fields($SQL, $wp_query) |
|
107 | - { |
|
108 | - if ( |
|
109 | - $wp_query instanceof WP_Query |
|
110 | - && ( |
|
111 | - $wp_query->is_espresso_event_single |
|
112 | - || $wp_query->is_espresso_event_archive |
|
113 | - || $wp_query->is_espresso_event_taxonomy |
|
114 | - ) |
|
115 | - ) { |
|
116 | - // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement |
|
117 | - $SQL .= ', ' . EEM_Datetime::instance()->table() . '.* '; |
|
118 | - if ($wp_query->is_espresso_event_archive || $wp_query->is_espresso_event_taxonomy) { |
|
119 | - // because we only want to retrieve the next upcoming datetime for each event: |
|
120 | - // add something like: |
|
121 | - // ", MIN( wp_esp_datetime.DTT_EVT_start ) as event_start_date " |
|
122 | - // to WP Query SELECT statement |
|
123 | - $SQL .= ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date '; |
|
124 | - } |
|
125 | - } |
|
126 | - return $SQL; |
|
127 | - } |
|
128 | - |
|
129 | - |
|
130 | - /** |
|
131 | - * @param string $SQL |
|
132 | - * @param WP_Query|null $wp_query |
|
133 | - * @return string |
|
134 | - * @throws EE_Error |
|
135 | - */ |
|
136 | - public function posts_join($SQL, $wp_query) |
|
137 | - { |
|
138 | - if ( |
|
139 | - $wp_query instanceof WP_Query |
|
140 | - && ( |
|
141 | - $wp_query->is_espresso_event_single |
|
142 | - || $wp_query->is_espresso_event_archive |
|
143 | - || $wp_query->is_espresso_event_taxonomy |
|
144 | - ) |
|
145 | - ) { |
|
146 | - // adds something like: |
|
147 | - // " LEFT JOIN wp_esp_datetime ON ( wp_esp_datetime.EVT_ID = wp_posts.ID ) " |
|
148 | - // to WP Query JOIN statement |
|
149 | - $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . EEM_Event::instance()->table() |
|
150 | - . '.ID = ' . EEM_Datetime::instance()->table() . '.' |
|
151 | - . EEM_Event::instance()->primary_key_name() . ' ) '; |
|
152 | - } |
|
153 | - return $SQL; |
|
154 | - } |
|
155 | - |
|
156 | - |
|
157 | - /** |
|
158 | - * @param string $SQL |
|
159 | - * @param WP_Query|null $wp_query |
|
160 | - * @return string |
|
161 | - * @throws EE_Error |
|
162 | - */ |
|
163 | - public function posts_where($SQL, $wp_query) |
|
164 | - { |
|
165 | - if ( |
|
166 | - $wp_query instanceof WP_Query |
|
167 | - && ( |
|
168 | - $wp_query->is_espresso_event_archive |
|
169 | - || $wp_query->is_espresso_event_taxonomy |
|
170 | - ) |
|
171 | - ) { |
|
172 | - if ( |
|
173 | - ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive) |
|
174 | - || ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events) |
|
175 | - || ! EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events |
|
176 | - ) { |
|
177 | - $SQL .= ' AND ' . EEM_Datetime::instance()->table() . ".DTT_EVT_end > '" |
|
178 | - . current_time('mysql', true) . "' "; |
|
179 | - } |
|
180 | - } |
|
181 | - return $SQL; |
|
182 | - } |
|
183 | - |
|
184 | - |
|
185 | - /** |
|
186 | - * @param string $SQL |
|
187 | - * @param WP_Query|null $wp_query |
|
188 | - * @return string |
|
189 | - */ |
|
190 | - public function posts_orderby($SQL, $wp_query) |
|
191 | - { |
|
192 | - if ( |
|
193 | - $wp_query instanceof WP_Query |
|
194 | - && ( |
|
195 | - $wp_query->is_espresso_event_archive |
|
196 | - || $wp_query->is_espresso_event_taxonomy |
|
197 | - ) |
|
198 | - ) { |
|
199 | - $SQL = ' event_start_date ASC '; |
|
200 | - } |
|
201 | - return $SQL; |
|
202 | - } |
|
203 | - |
|
204 | - |
|
205 | - /** |
|
206 | - * @param string $SQL |
|
207 | - * @param WP_Query|null $wp_query |
|
208 | - * @return string |
|
209 | - */ |
|
210 | - public function posts_groupby($SQL, $wp_query) |
|
211 | - { |
|
212 | - if ( |
|
213 | - $wp_query instanceof WP_Query |
|
214 | - && ( |
|
215 | - $wp_query->is_espresso_event_archive |
|
216 | - || $wp_query->is_espresso_event_taxonomy |
|
217 | - ) |
|
218 | - ) { |
|
219 | - // TODO: add event list option for displaying ALL datetimes in event list or only primary datetime (default) |
|
220 | - // we're joining to the datetimes table, where there can be MANY datetimes for a single event, |
|
221 | - // but we want to only show each event only once |
|
222 | - // (whereas if we didn't group them by the post's ID, then we would end up with many repeats) |
|
223 | - global $wpdb; |
|
224 | - $SQL = $wpdb->posts . '.ID '; |
|
225 | - } |
|
226 | - return $SQL; |
|
227 | - } |
|
228 | - |
|
229 | - |
|
230 | - /** |
|
231 | - * @param array $posts |
|
232 | - * @param WP_Query|null $wp_query |
|
233 | - * @return array |
|
234 | - */ |
|
235 | - public function the_posts($posts, $wp_query) |
|
236 | - { |
|
237 | - return $posts; |
|
238 | - } |
|
239 | - |
|
240 | - |
|
241 | - /** |
|
242 | - * @param mixed $meta_value |
|
243 | - * @param int|string $post_id |
|
244 | - * @param int|string $meta_key |
|
245 | - * @param bool|int|string $single |
|
246 | - * @return mixed |
|
247 | - */ |
|
248 | - public function get_EE_post_type_metadata($meta_value, $post_id, $meta_key, $single) |
|
249 | - { |
|
250 | - return $meta_value; |
|
251 | - } |
|
12 | + /** |
|
13 | + * the current page, if it utilizes CPTs |
|
14 | + * |
|
15 | + * @var object $CPT |
|
16 | + */ |
|
17 | + protected $CPT; |
|
18 | + |
|
19 | + |
|
20 | + /** |
|
21 | + * @param array|WP_Query|null $wp_query |
|
22 | + * @param array $CPT |
|
23 | + */ |
|
24 | + public function __construct($wp_query, array $CPT = []) |
|
25 | + { |
|
26 | + if ($wp_query instanceof WP_Query) { |
|
27 | + $WP_Query = $wp_query; |
|
28 | + $this->CPT = $CPT; |
|
29 | + } else { |
|
30 | + $WP_Query = isset($wp_query['WP_Query']) ? $wp_query['WP_Query'] : null; |
|
31 | + $this->CPT = isset($wp_query['CPT']) ? $wp_query['CPT'] : null; |
|
32 | + } |
|
33 | + // !!!!!!!!!! IMPORTANT !!!!!!!!!!!! |
|
34 | + // here's the list of available filters in the WP_Query object |
|
35 | + // 'posts_where' |
|
36 | + // 'posts_where_paged' |
|
37 | + // 'posts_groupby' |
|
38 | + // 'posts_join_paged' |
|
39 | + // 'posts_orderby' |
|
40 | + // 'posts_distinct' |
|
41 | + // 'post_limits' |
|
42 | + // 'posts_fields' |
|
43 | + // 'posts_join' |
|
44 | + $this->_add_filters(); |
|
45 | + if ($WP_Query instanceof WP_Query) { |
|
46 | + $WP_Query->is_espresso_event_single = is_singular() |
|
47 | + && isset($WP_Query->query->post_type) |
|
48 | + && $WP_Query->query->post_type === 'espresso_events'; |
|
49 | + $WP_Query->is_espresso_event_archive = is_post_type_archive('espresso_events'); |
|
50 | + $WP_Query->is_espresso_event_taxonomy = is_tax('espresso_event_categories'); |
|
51 | + } |
|
52 | + } |
|
53 | + |
|
54 | + |
|
55 | + /** |
|
56 | + * When an instance of this class is created, we add our filters |
|
57 | + * (which will get removed in case the next call to get_posts ISN'T |
|
58 | + * for event CPTs) |
|
59 | + */ |
|
60 | + protected function _add_filters() |
|
61 | + { |
|
62 | + add_filter('posts_fields', [$this, 'posts_fields'], 1, 2); |
|
63 | + add_filter('posts_join', [$this, 'posts_join'], 1, 2); |
|
64 | + add_filter('posts_where', [$this, 'posts_where'], 10, 2); |
|
65 | + // add_filter( 'the_posts', array( $this, 'the_posts' ), 1, 2 ); |
|
66 | + add_filter('posts_orderby', [$this, 'posts_orderby'], 1, 2); |
|
67 | + add_filter('posts_groupby', [$this, 'posts_groupby'], 1, 2); |
|
68 | + add_action('posts_selection', [$this, 'remove_filters']); |
|
69 | + } |
|
70 | + |
|
71 | + |
|
72 | + /** |
|
73 | + * public access to _remove_filters() |
|
74 | + * |
|
75 | + * @since 4.9.63.p |
|
76 | + */ |
|
77 | + public function remove_filters() |
|
78 | + { |
|
79 | + $this->_remove_filters(); |
|
80 | + } |
|
81 | + |
|
82 | + |
|
83 | + /** |
|
84 | + * Should eb called when the last filter or hook is fired for this CPT strategy. |
|
85 | + * This is to avoid applying this CPT strategy for other posts or CPTs (eg, |
|
86 | + * we don't want to join to the datetime table when querying for venues, do we!?) |
|
87 | + */ |
|
88 | + protected function _remove_filters() |
|
89 | + { |
|
90 | + remove_filter('posts_fields', [$this, 'posts_fields'], 1); |
|
91 | + remove_filter('posts_join', [$this, 'posts_join'], 1); |
|
92 | + remove_filter('posts_where', [$this, 'posts_where']); |
|
93 | + // remove_filter( 'the_posts', array( $this, 'the_posts' ), 1 ); |
|
94 | + remove_filter('posts_orderby', [$this, 'posts_orderby'], 1); |
|
95 | + remove_filter('posts_groupby', [$this, 'posts_groupby'], 1); |
|
96 | + remove_action('posts_selection', [$this, 'remove_filters']); |
|
97 | + } |
|
98 | + |
|
99 | + |
|
100 | + /** |
|
101 | + * @param string $SQL |
|
102 | + * @param WP_Query|null $wp_query |
|
103 | + * @return string |
|
104 | + * @throws EE_Error |
|
105 | + */ |
|
106 | + public function posts_fields($SQL, $wp_query) |
|
107 | + { |
|
108 | + if ( |
|
109 | + $wp_query instanceof WP_Query |
|
110 | + && ( |
|
111 | + $wp_query->is_espresso_event_single |
|
112 | + || $wp_query->is_espresso_event_archive |
|
113 | + || $wp_query->is_espresso_event_taxonomy |
|
114 | + ) |
|
115 | + ) { |
|
116 | + // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement |
|
117 | + $SQL .= ', ' . EEM_Datetime::instance()->table() . '.* '; |
|
118 | + if ($wp_query->is_espresso_event_archive || $wp_query->is_espresso_event_taxonomy) { |
|
119 | + // because we only want to retrieve the next upcoming datetime for each event: |
|
120 | + // add something like: |
|
121 | + // ", MIN( wp_esp_datetime.DTT_EVT_start ) as event_start_date " |
|
122 | + // to WP Query SELECT statement |
|
123 | + $SQL .= ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date '; |
|
124 | + } |
|
125 | + } |
|
126 | + return $SQL; |
|
127 | + } |
|
128 | + |
|
129 | + |
|
130 | + /** |
|
131 | + * @param string $SQL |
|
132 | + * @param WP_Query|null $wp_query |
|
133 | + * @return string |
|
134 | + * @throws EE_Error |
|
135 | + */ |
|
136 | + public function posts_join($SQL, $wp_query) |
|
137 | + { |
|
138 | + if ( |
|
139 | + $wp_query instanceof WP_Query |
|
140 | + && ( |
|
141 | + $wp_query->is_espresso_event_single |
|
142 | + || $wp_query->is_espresso_event_archive |
|
143 | + || $wp_query->is_espresso_event_taxonomy |
|
144 | + ) |
|
145 | + ) { |
|
146 | + // adds something like: |
|
147 | + // " LEFT JOIN wp_esp_datetime ON ( wp_esp_datetime.EVT_ID = wp_posts.ID ) " |
|
148 | + // to WP Query JOIN statement |
|
149 | + $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . EEM_Event::instance()->table() |
|
150 | + . '.ID = ' . EEM_Datetime::instance()->table() . '.' |
|
151 | + . EEM_Event::instance()->primary_key_name() . ' ) '; |
|
152 | + } |
|
153 | + return $SQL; |
|
154 | + } |
|
155 | + |
|
156 | + |
|
157 | + /** |
|
158 | + * @param string $SQL |
|
159 | + * @param WP_Query|null $wp_query |
|
160 | + * @return string |
|
161 | + * @throws EE_Error |
|
162 | + */ |
|
163 | + public function posts_where($SQL, $wp_query) |
|
164 | + { |
|
165 | + if ( |
|
166 | + $wp_query instanceof WP_Query |
|
167 | + && ( |
|
168 | + $wp_query->is_espresso_event_archive |
|
169 | + || $wp_query->is_espresso_event_taxonomy |
|
170 | + ) |
|
171 | + ) { |
|
172 | + if ( |
|
173 | + ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive) |
|
174 | + || ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events) |
|
175 | + || ! EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events |
|
176 | + ) { |
|
177 | + $SQL .= ' AND ' . EEM_Datetime::instance()->table() . ".DTT_EVT_end > '" |
|
178 | + . current_time('mysql', true) . "' "; |
|
179 | + } |
|
180 | + } |
|
181 | + return $SQL; |
|
182 | + } |
|
183 | + |
|
184 | + |
|
185 | + /** |
|
186 | + * @param string $SQL |
|
187 | + * @param WP_Query|null $wp_query |
|
188 | + * @return string |
|
189 | + */ |
|
190 | + public function posts_orderby($SQL, $wp_query) |
|
191 | + { |
|
192 | + if ( |
|
193 | + $wp_query instanceof WP_Query |
|
194 | + && ( |
|
195 | + $wp_query->is_espresso_event_archive |
|
196 | + || $wp_query->is_espresso_event_taxonomy |
|
197 | + ) |
|
198 | + ) { |
|
199 | + $SQL = ' event_start_date ASC '; |
|
200 | + } |
|
201 | + return $SQL; |
|
202 | + } |
|
203 | + |
|
204 | + |
|
205 | + /** |
|
206 | + * @param string $SQL |
|
207 | + * @param WP_Query|null $wp_query |
|
208 | + * @return string |
|
209 | + */ |
|
210 | + public function posts_groupby($SQL, $wp_query) |
|
211 | + { |
|
212 | + if ( |
|
213 | + $wp_query instanceof WP_Query |
|
214 | + && ( |
|
215 | + $wp_query->is_espresso_event_archive |
|
216 | + || $wp_query->is_espresso_event_taxonomy |
|
217 | + ) |
|
218 | + ) { |
|
219 | + // TODO: add event list option for displaying ALL datetimes in event list or only primary datetime (default) |
|
220 | + // we're joining to the datetimes table, where there can be MANY datetimes for a single event, |
|
221 | + // but we want to only show each event only once |
|
222 | + // (whereas if we didn't group them by the post's ID, then we would end up with many repeats) |
|
223 | + global $wpdb; |
|
224 | + $SQL = $wpdb->posts . '.ID '; |
|
225 | + } |
|
226 | + return $SQL; |
|
227 | + } |
|
228 | + |
|
229 | + |
|
230 | + /** |
|
231 | + * @param array $posts |
|
232 | + * @param WP_Query|null $wp_query |
|
233 | + * @return array |
|
234 | + */ |
|
235 | + public function the_posts($posts, $wp_query) |
|
236 | + { |
|
237 | + return $posts; |
|
238 | + } |
|
239 | + |
|
240 | + |
|
241 | + /** |
|
242 | + * @param mixed $meta_value |
|
243 | + * @param int|string $post_id |
|
244 | + * @param int|string $meta_key |
|
245 | + * @param bool|int|string $single |
|
246 | + * @return mixed |
|
247 | + */ |
|
248 | + public function get_EE_post_type_metadata($meta_value, $post_id, $meta_key, $single) |
|
249 | + { |
|
250 | + return $meta_value; |
|
251 | + } |
|
252 | 252 | } |
@@ -80,7 +80,7 @@ discard block |
||
80 | 80 | $data = []; |
81 | 81 | if (empty($this->countries)) { |
82 | 82 | $this->data_version = $this->getCountrySubRegionDataVersion(); |
83 | - $data = $this->retrieveJsonData(self::REPO_URL . 'countries.json'); |
|
83 | + $data = $this->retrieveJsonData(self::REPO_URL.'countries.json'); |
|
84 | 84 | } |
85 | 85 | if (empty($data)) { |
86 | 86 | EE_Error::add_error( |
@@ -144,7 +144,7 @@ discard block |
||
144 | 144 | */ |
145 | 145 | private function processCountryData($CNT_ISO, $countries = array()) |
146 | 146 | { |
147 | - if (! empty($countries)) { |
|
147 | + if ( ! empty($countries)) { |
|
148 | 148 | foreach ($countries as $key => $country) { |
149 | 149 | if ( |
150 | 150 | $country instanceof stdClass |
@@ -153,7 +153,7 @@ discard block |
||
153 | 153 | && ! empty($country->filename) |
154 | 154 | ) { |
155 | 155 | $country->sub_regions = $this->retrieveJsonData( |
156 | - self::REPO_URL . 'countries/' . $country->filename . '.json' |
|
156 | + self::REPO_URL.'countries/'.$country->filename.'.json' |
|
157 | 157 | ); |
158 | 158 | return $this->saveSubRegionData($country, $country->sub_regions); |
159 | 159 | } |
@@ -215,7 +215,7 @@ discard block |
||
215 | 215 | foreach ($sub_regions as $sub_region) { |
216 | 216 | // remove country code from sub region code |
217 | 217 | $abbrev = str_replace( |
218 | - $country->code . '-', |
|
218 | + $country->code.'-', |
|
219 | 219 | '', |
220 | 220 | sanitize_text_field($sub_region->code) |
221 | 221 | ); |
@@ -25,252 +25,252 @@ |
||
25 | 25 | */ |
26 | 26 | class CountrySubRegionDao |
27 | 27 | { |
28 | - const REPO_URL = 'https://raw.githubusercontent.com/eventespresso/countries-and-subregions/master/'; |
|
28 | + const REPO_URL = 'https://raw.githubusercontent.com/eventespresso/countries-and-subregions/master/'; |
|
29 | 29 | |
30 | - const OPTION_NAME_COUNTRY_DATA_VERSION = 'espresso-country-sub-region-data-version'; |
|
30 | + const OPTION_NAME_COUNTRY_DATA_VERSION = 'espresso-country-sub-region-data-version'; |
|
31 | 31 | |
32 | - /** |
|
33 | - * @var EEM_State $state_model |
|
34 | - */ |
|
35 | - private $state_model; |
|
32 | + /** |
|
33 | + * @var EEM_State $state_model |
|
34 | + */ |
|
35 | + private $state_model; |
|
36 | 36 | |
37 | - /** |
|
38 | - * @var JsonValidator $json_validator |
|
39 | - */ |
|
40 | - private $json_validator; |
|
37 | + /** |
|
38 | + * @var JsonValidator $json_validator |
|
39 | + */ |
|
40 | + private $json_validator; |
|
41 | 41 | |
42 | - /** |
|
43 | - * @var string $data_version |
|
44 | - */ |
|
45 | - private $data_version; |
|
42 | + /** |
|
43 | + * @var string $data_version |
|
44 | + */ |
|
45 | + private $data_version; |
|
46 | 46 | |
47 | - /** |
|
48 | - * @var array $countries |
|
49 | - */ |
|
50 | - private $countries = array(); |
|
47 | + /** |
|
48 | + * @var array $countries |
|
49 | + */ |
|
50 | + private $countries = array(); |
|
51 | 51 | |
52 | 52 | |
53 | - /** |
|
54 | - * CountrySubRegionDao constructor. |
|
55 | - * |
|
56 | - * @param EEM_State $state_model |
|
57 | - * @param JsonValidator $json_validator |
|
58 | - */ |
|
59 | - public function __construct(EEM_State $state_model, JsonValidator $json_validator) |
|
60 | - { |
|
61 | - $this->state_model = $state_model; |
|
62 | - $this->json_validator = $json_validator; |
|
63 | - } |
|
53 | + /** |
|
54 | + * CountrySubRegionDao constructor. |
|
55 | + * |
|
56 | + * @param EEM_State $state_model |
|
57 | + * @param JsonValidator $json_validator |
|
58 | + */ |
|
59 | + public function __construct(EEM_State $state_model, JsonValidator $json_validator) |
|
60 | + { |
|
61 | + $this->state_model = $state_model; |
|
62 | + $this->json_validator = $json_validator; |
|
63 | + } |
|
64 | 64 | |
65 | 65 | |
66 | - /** |
|
67 | - * @param EE_Country $country_object |
|
68 | - * @return bool |
|
69 | - * @throws EE_Error |
|
70 | - * @throws InvalidArgumentException |
|
71 | - * @throws InvalidDataTypeException |
|
72 | - * @throws InvalidInterfaceException |
|
73 | - * @throws ReflectionException |
|
74 | - */ |
|
75 | - public function saveCountrySubRegions($country_object) |
|
76 | - { |
|
77 | - $CNT_ISO = $country_object->ID(); |
|
78 | - $has_sub_regions = $this->state_model->count(array(array('Country.CNT_ISO' => $CNT_ISO))); |
|
79 | - $data = []; |
|
80 | - if (empty($this->countries)) { |
|
81 | - $this->data_version = $this->getCountrySubRegionDataVersion(); |
|
82 | - $data = $this->retrieveJsonData(self::REPO_URL . 'countries.json'); |
|
83 | - } |
|
84 | - if (empty($data)) { |
|
85 | - EE_Error::add_error( |
|
86 | - 'Country Subregion Data could not be retrieved', |
|
87 | - __FILE__, |
|
88 | - __METHOD__, |
|
89 | - __LINE__ |
|
90 | - ); |
|
91 | - } |
|
92 | - if ( |
|
93 | - ! $has_sub_regions |
|
94 | - || (isset($data->version) && version_compare($data->version, $this->data_version)) |
|
95 | - ) { |
|
96 | - if ( |
|
97 | - isset($data->countries) |
|
98 | - && $this->processCountryData($CNT_ISO, $data->countries) > 0 |
|
99 | - ) { |
|
100 | - $this->countries = $data->countries; |
|
101 | - $this->updateCountrySubRegionDataVersion($data->version); |
|
102 | - return true; |
|
103 | - } |
|
104 | - } |
|
105 | - return false; |
|
106 | - } |
|
66 | + /** |
|
67 | + * @param EE_Country $country_object |
|
68 | + * @return bool |
|
69 | + * @throws EE_Error |
|
70 | + * @throws InvalidArgumentException |
|
71 | + * @throws InvalidDataTypeException |
|
72 | + * @throws InvalidInterfaceException |
|
73 | + * @throws ReflectionException |
|
74 | + */ |
|
75 | + public function saveCountrySubRegions($country_object) |
|
76 | + { |
|
77 | + $CNT_ISO = $country_object->ID(); |
|
78 | + $has_sub_regions = $this->state_model->count(array(array('Country.CNT_ISO' => $CNT_ISO))); |
|
79 | + $data = []; |
|
80 | + if (empty($this->countries)) { |
|
81 | + $this->data_version = $this->getCountrySubRegionDataVersion(); |
|
82 | + $data = $this->retrieveJsonData(self::REPO_URL . 'countries.json'); |
|
83 | + } |
|
84 | + if (empty($data)) { |
|
85 | + EE_Error::add_error( |
|
86 | + 'Country Subregion Data could not be retrieved', |
|
87 | + __FILE__, |
|
88 | + __METHOD__, |
|
89 | + __LINE__ |
|
90 | + ); |
|
91 | + } |
|
92 | + if ( |
|
93 | + ! $has_sub_regions |
|
94 | + || (isset($data->version) && version_compare($data->version, $this->data_version)) |
|
95 | + ) { |
|
96 | + if ( |
|
97 | + isset($data->countries) |
|
98 | + && $this->processCountryData($CNT_ISO, $data->countries) > 0 |
|
99 | + ) { |
|
100 | + $this->countries = $data->countries; |
|
101 | + $this->updateCountrySubRegionDataVersion($data->version); |
|
102 | + return true; |
|
103 | + } |
|
104 | + } |
|
105 | + return false; |
|
106 | + } |
|
107 | 107 | |
108 | 108 | |
109 | - /** |
|
110 | - * @since 4.9.70.p |
|
111 | - * @return string |
|
112 | - */ |
|
113 | - private function getCountrySubRegionDataVersion() |
|
114 | - { |
|
115 | - return get_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, null); |
|
116 | - } |
|
109 | + /** |
|
110 | + * @since 4.9.70.p |
|
111 | + * @return string |
|
112 | + */ |
|
113 | + private function getCountrySubRegionDataVersion() |
|
114 | + { |
|
115 | + return get_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, null); |
|
116 | + } |
|
117 | 117 | |
118 | 118 | |
119 | - /** |
|
120 | - * @param string $version |
|
121 | - */ |
|
122 | - private function updateCountrySubRegionDataVersion($version = '') |
|
123 | - { |
|
124 | - // add version option if it has never been added before, or update existing |
|
125 | - if ($this->data_version === null) { |
|
126 | - add_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version, '', false); |
|
127 | - } else { |
|
128 | - update_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version); |
|
129 | - } |
|
130 | - } |
|
119 | + /** |
|
120 | + * @param string $version |
|
121 | + */ |
|
122 | + private function updateCountrySubRegionDataVersion($version = '') |
|
123 | + { |
|
124 | + // add version option if it has never been added before, or update existing |
|
125 | + if ($this->data_version === null) { |
|
126 | + add_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version, '', false); |
|
127 | + } else { |
|
128 | + update_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version); |
|
129 | + } |
|
130 | + } |
|
131 | 131 | |
132 | 132 | |
133 | - /** |
|
134 | - * @param string $CNT_ISO |
|
135 | - * @param array $countries |
|
136 | - * @return int |
|
137 | - * @throws EE_Error |
|
138 | - * @throws InvalidArgumentException |
|
139 | - * @throws InvalidDataTypeException |
|
140 | - * @throws InvalidInterfaceException |
|
141 | - * @throws ReflectionException |
|
142 | - * @since 4.9.70.p |
|
143 | - */ |
|
144 | - private function processCountryData($CNT_ISO, $countries = array()) |
|
145 | - { |
|
146 | - if (! empty($countries)) { |
|
147 | - foreach ($countries as $key => $country) { |
|
148 | - if ( |
|
149 | - $country instanceof stdClass |
|
150 | - && $country->code === $CNT_ISO |
|
151 | - && empty($country->sub_regions) |
|
152 | - && ! empty($country->filename) |
|
153 | - ) { |
|
154 | - $country->sub_regions = $this->retrieveJsonData( |
|
155 | - self::REPO_URL . 'countries/' . $country->filename . '.json' |
|
156 | - ); |
|
157 | - return $this->saveSubRegionData($country, $country->sub_regions); |
|
158 | - } |
|
159 | - } |
|
160 | - } |
|
161 | - return 0; |
|
162 | - } |
|
133 | + /** |
|
134 | + * @param string $CNT_ISO |
|
135 | + * @param array $countries |
|
136 | + * @return int |
|
137 | + * @throws EE_Error |
|
138 | + * @throws InvalidArgumentException |
|
139 | + * @throws InvalidDataTypeException |
|
140 | + * @throws InvalidInterfaceException |
|
141 | + * @throws ReflectionException |
|
142 | + * @since 4.9.70.p |
|
143 | + */ |
|
144 | + private function processCountryData($CNT_ISO, $countries = array()) |
|
145 | + { |
|
146 | + if (! empty($countries)) { |
|
147 | + foreach ($countries as $key => $country) { |
|
148 | + if ( |
|
149 | + $country instanceof stdClass |
|
150 | + && $country->code === $CNT_ISO |
|
151 | + && empty($country->sub_regions) |
|
152 | + && ! empty($country->filename) |
|
153 | + ) { |
|
154 | + $country->sub_regions = $this->retrieveJsonData( |
|
155 | + self::REPO_URL . 'countries/' . $country->filename . '.json' |
|
156 | + ); |
|
157 | + return $this->saveSubRegionData($country, $country->sub_regions); |
|
158 | + } |
|
159 | + } |
|
160 | + } |
|
161 | + return 0; |
|
162 | + } |
|
163 | 163 | |
164 | 164 | |
165 | - /** |
|
166 | - * @param string $url |
|
167 | - * @return array |
|
168 | - */ |
|
169 | - private function retrieveJsonData($url) |
|
170 | - { |
|
171 | - if (empty($url)) { |
|
172 | - EE_Error::add_error( |
|
173 | - 'No URL was provided!', |
|
174 | - __FILE__, |
|
175 | - __METHOD__, |
|
176 | - __LINE__ |
|
177 | - ); |
|
178 | - return array(); |
|
179 | - } |
|
180 | - $request = wp_safe_remote_get($url); |
|
181 | - if ($request instanceof WP_Error) { |
|
182 | - EE_Error::add_error( |
|
183 | - $request->get_error_message(), |
|
184 | - __FILE__, |
|
185 | - __METHOD__, |
|
186 | - __LINE__ |
|
187 | - ); |
|
188 | - return array(); |
|
189 | - } |
|
190 | - $body = wp_remote_retrieve_body($request); |
|
191 | - $json = json_decode($body); |
|
192 | - if ($this->json_validator->isValid(__FILE__, __METHOD__, __LINE__)) { |
|
193 | - return $json; |
|
194 | - } |
|
195 | - return array(); |
|
196 | - } |
|
165 | + /** |
|
166 | + * @param string $url |
|
167 | + * @return array |
|
168 | + */ |
|
169 | + private function retrieveJsonData($url) |
|
170 | + { |
|
171 | + if (empty($url)) { |
|
172 | + EE_Error::add_error( |
|
173 | + 'No URL was provided!', |
|
174 | + __FILE__, |
|
175 | + __METHOD__, |
|
176 | + __LINE__ |
|
177 | + ); |
|
178 | + return array(); |
|
179 | + } |
|
180 | + $request = wp_safe_remote_get($url); |
|
181 | + if ($request instanceof WP_Error) { |
|
182 | + EE_Error::add_error( |
|
183 | + $request->get_error_message(), |
|
184 | + __FILE__, |
|
185 | + __METHOD__, |
|
186 | + __LINE__ |
|
187 | + ); |
|
188 | + return array(); |
|
189 | + } |
|
190 | + $body = wp_remote_retrieve_body($request); |
|
191 | + $json = json_decode($body); |
|
192 | + if ($this->json_validator->isValid(__FILE__, __METHOD__, __LINE__)) { |
|
193 | + return $json; |
|
194 | + } |
|
195 | + return array(); |
|
196 | + } |
|
197 | 197 | |
198 | 198 | |
199 | - /** |
|
200 | - * @param stdClass $country |
|
201 | - * @param array $sub_regions |
|
202 | - * @return int |
|
203 | - * @throws EE_Error |
|
204 | - * @throws InvalidArgumentException |
|
205 | - * @throws InvalidDataTypeException |
|
206 | - * @throws InvalidInterfaceException |
|
207 | - * @throws ReflectionException |
|
208 | - */ |
|
209 | - private function saveSubRegionData(stdClass $country, $sub_regions = array()) |
|
210 | - { |
|
211 | - $results = 0; |
|
212 | - if (is_array($sub_regions)) { |
|
213 | - $existing_sub_regions = $this->getExistingStateAbbreviations($country->code); |
|
214 | - foreach ($sub_regions as $sub_region) { |
|
215 | - // remove country code from sub region code |
|
216 | - $abbrev = str_replace( |
|
217 | - $country->code . '-', |
|
218 | - '', |
|
219 | - sanitize_text_field($sub_region->code) |
|
220 | - ); |
|
221 | - // but NOT if sub region code results in only a number |
|
222 | - if (absint($abbrev) !== 0) { |
|
223 | - $abbrev = sanitize_text_field($sub_region->code); |
|
224 | - } |
|
225 | - if ( |
|
226 | - ! in_array($abbrev, $existing_sub_regions, true) |
|
227 | - && $this->state_model->insert( |
|
228 | - [ |
|
229 | - // STA_ID CNT_ISO STA_abbrev STA_name STA_active |
|
230 | - 'CNT_ISO' => $country->code, |
|
231 | - 'STA_abbrev' => $abbrev, |
|
232 | - 'STA_name' => sanitize_text_field($sub_region->name), |
|
233 | - 'STA_active' => 1, |
|
234 | - ] |
|
235 | - ) |
|
236 | - ) { |
|
237 | - $results++; |
|
238 | - } |
|
239 | - } |
|
240 | - } |
|
241 | - return $results; |
|
242 | - } |
|
199 | + /** |
|
200 | + * @param stdClass $country |
|
201 | + * @param array $sub_regions |
|
202 | + * @return int |
|
203 | + * @throws EE_Error |
|
204 | + * @throws InvalidArgumentException |
|
205 | + * @throws InvalidDataTypeException |
|
206 | + * @throws InvalidInterfaceException |
|
207 | + * @throws ReflectionException |
|
208 | + */ |
|
209 | + private function saveSubRegionData(stdClass $country, $sub_regions = array()) |
|
210 | + { |
|
211 | + $results = 0; |
|
212 | + if (is_array($sub_regions)) { |
|
213 | + $existing_sub_regions = $this->getExistingStateAbbreviations($country->code); |
|
214 | + foreach ($sub_regions as $sub_region) { |
|
215 | + // remove country code from sub region code |
|
216 | + $abbrev = str_replace( |
|
217 | + $country->code . '-', |
|
218 | + '', |
|
219 | + sanitize_text_field($sub_region->code) |
|
220 | + ); |
|
221 | + // but NOT if sub region code results in only a number |
|
222 | + if (absint($abbrev) !== 0) { |
|
223 | + $abbrev = sanitize_text_field($sub_region->code); |
|
224 | + } |
|
225 | + if ( |
|
226 | + ! in_array($abbrev, $existing_sub_regions, true) |
|
227 | + && $this->state_model->insert( |
|
228 | + [ |
|
229 | + // STA_ID CNT_ISO STA_abbrev STA_name STA_active |
|
230 | + 'CNT_ISO' => $country->code, |
|
231 | + 'STA_abbrev' => $abbrev, |
|
232 | + 'STA_name' => sanitize_text_field($sub_region->name), |
|
233 | + 'STA_active' => 1, |
|
234 | + ] |
|
235 | + ) |
|
236 | + ) { |
|
237 | + $results++; |
|
238 | + } |
|
239 | + } |
|
240 | + } |
|
241 | + return $results; |
|
242 | + } |
|
243 | 243 | |
244 | 244 | |
245 | - /** |
|
246 | - * @param string $CNT_ISO |
|
247 | - * @since 4.9.76.p |
|
248 | - * @return array |
|
249 | - * @throws EE_Error |
|
250 | - * @throws InvalidArgumentException |
|
251 | - * @throws InvalidDataTypeException |
|
252 | - * @throws InvalidInterfaceException |
|
253 | - * @throws ReflectionException |
|
254 | - */ |
|
255 | - private function getExistingStateAbbreviations($CNT_ISO) |
|
256 | - { |
|
257 | - $existing_sub_region_IDs = []; |
|
258 | - $existing_sub_regions = $this->state_model->get_all(array( |
|
259 | - array( |
|
260 | - 'Country.CNT_ISO' => array( |
|
261 | - 'IN', |
|
262 | - [$CNT_ISO] |
|
263 | - ) |
|
264 | - ), |
|
265 | - 'order_by' => array('Country.CNT_name' => 'ASC', 'STA_name' => 'ASC') |
|
266 | - )); |
|
267 | - if (is_array($existing_sub_regions)) { |
|
268 | - foreach ($existing_sub_regions as $existing_sub_region) { |
|
269 | - if ($existing_sub_region instanceof EE_State) { |
|
270 | - $existing_sub_region_IDs[] = $existing_sub_region->abbrev(); |
|
271 | - } |
|
272 | - } |
|
273 | - } |
|
274 | - return $existing_sub_region_IDs; |
|
275 | - } |
|
245 | + /** |
|
246 | + * @param string $CNT_ISO |
|
247 | + * @since 4.9.76.p |
|
248 | + * @return array |
|
249 | + * @throws EE_Error |
|
250 | + * @throws InvalidArgumentException |
|
251 | + * @throws InvalidDataTypeException |
|
252 | + * @throws InvalidInterfaceException |
|
253 | + * @throws ReflectionException |
|
254 | + */ |
|
255 | + private function getExistingStateAbbreviations($CNT_ISO) |
|
256 | + { |
|
257 | + $existing_sub_region_IDs = []; |
|
258 | + $existing_sub_regions = $this->state_model->get_all(array( |
|
259 | + array( |
|
260 | + 'Country.CNT_ISO' => array( |
|
261 | + 'IN', |
|
262 | + [$CNT_ISO] |
|
263 | + ) |
|
264 | + ), |
|
265 | + 'order_by' => array('Country.CNT_name' => 'ASC', 'STA_name' => 'ASC') |
|
266 | + )); |
|
267 | + if (is_array($existing_sub_regions)) { |
|
268 | + foreach ($existing_sub_regions as $existing_sub_region) { |
|
269 | + if ($existing_sub_region instanceof EE_State) { |
|
270 | + $existing_sub_region_IDs[] = $existing_sub_region->abbrev(); |
|
271 | + } |
|
272 | + } |
|
273 | + } |
|
274 | + return $existing_sub_region_IDs; |
|
275 | + } |
|
276 | 276 | } |
@@ -20,202 +20,202 @@ |
||
20 | 20 | */ |
21 | 21 | class PayPalSettingsForm extends EE_Payment_Method_Form |
22 | 22 | { |
23 | - /** |
|
24 | - * @var string of HTML being the help tab link |
|
25 | - */ |
|
26 | - protected $helpTabLink; |
|
23 | + /** |
|
24 | + * @var string of HTML being the help tab link |
|
25 | + */ |
|
26 | + protected $helpTabLink; |
|
27 | 27 | |
28 | - public function __construct(array $options_array = array(), $help_tab_link = '') |
|
29 | - { |
|
30 | - $this->helpTabLink = $help_tab_link; |
|
31 | - $options_array = array_replace_recursive( |
|
32 | - array( |
|
33 | - 'extra_meta_inputs' => array( |
|
34 | - 'api_username' => new EE_Text_Input( |
|
35 | - array( |
|
36 | - 'html_label_text' => sprintf( |
|
37 | - // translators: %s link to help doc |
|
38 | - esc_html__('API Username %s', 'event_espresso'), |
|
39 | - $help_tab_link |
|
40 | - ), |
|
41 | - 'required' => true, |
|
42 | - ) |
|
43 | - ), |
|
44 | - 'api_password' => new EE_Text_Input( |
|
45 | - array( |
|
46 | - 'html_label_text' => sprintf( |
|
47 | - // translators: %s link to help doc |
|
48 | - esc_html__('API Password %s', 'event_espresso'), |
|
49 | - $help_tab_link |
|
50 | - ), |
|
51 | - 'required' => true, |
|
52 | - ) |
|
53 | - ), |
|
54 | - 'api_signature' => new EE_Text_Input( |
|
55 | - array( |
|
56 | - 'html_label_text' => sprintf( |
|
57 | - // translators: %s link to help doc |
|
58 | - esc_html__('API Signature %s', 'event_espresso'), |
|
59 | - $help_tab_link |
|
60 | - ), |
|
61 | - 'required' => true, |
|
62 | - ) |
|
63 | - ), |
|
64 | - ) |
|
65 | - ), |
|
66 | - $options_array |
|
67 | - ); |
|
68 | - parent::__construct($options_array); |
|
69 | - } |
|
28 | + public function __construct(array $options_array = array(), $help_tab_link = '') |
|
29 | + { |
|
30 | + $this->helpTabLink = $help_tab_link; |
|
31 | + $options_array = array_replace_recursive( |
|
32 | + array( |
|
33 | + 'extra_meta_inputs' => array( |
|
34 | + 'api_username' => new EE_Text_Input( |
|
35 | + array( |
|
36 | + 'html_label_text' => sprintf( |
|
37 | + // translators: %s link to help doc |
|
38 | + esc_html__('API Username %s', 'event_espresso'), |
|
39 | + $help_tab_link |
|
40 | + ), |
|
41 | + 'required' => true, |
|
42 | + ) |
|
43 | + ), |
|
44 | + 'api_password' => new EE_Text_Input( |
|
45 | + array( |
|
46 | + 'html_label_text' => sprintf( |
|
47 | + // translators: %s link to help doc |
|
48 | + esc_html__('API Password %s', 'event_espresso'), |
|
49 | + $help_tab_link |
|
50 | + ), |
|
51 | + 'required' => true, |
|
52 | + ) |
|
53 | + ), |
|
54 | + 'api_signature' => new EE_Text_Input( |
|
55 | + array( |
|
56 | + 'html_label_text' => sprintf( |
|
57 | + // translators: %s link to help doc |
|
58 | + esc_html__('API Signature %s', 'event_espresso'), |
|
59 | + $help_tab_link |
|
60 | + ), |
|
61 | + 'required' => true, |
|
62 | + ) |
|
63 | + ), |
|
64 | + ) |
|
65 | + ), |
|
66 | + $options_array |
|
67 | + ); |
|
68 | + parent::__construct($options_array); |
|
69 | + } |
|
70 | 70 | |
71 | - /** |
|
72 | - * Tests the the PayPal API credentials work ok |
|
73 | - * @return string of an error using the credentials, otherwise, if the credentials work, returns a blank string |
|
74 | - * @throws EE_Error |
|
75 | - */ |
|
76 | - protected function checkForCredentialsErrors() |
|
77 | - { |
|
78 | - $request_params = array( |
|
79 | - 'METHOD' => 'GetBalance', |
|
80 | - 'VERSION' => '204.0', |
|
81 | - 'USER' => $this->get_input_value('api_username'), |
|
82 | - 'PWD' => $this->get_input_value('api_password'), |
|
83 | - 'SIGNATURE' => $this->get_input_value('api_signature'), |
|
84 | - ); |
|
85 | - $gateway_url = $this->get_input_value('PMD_debug_mode') |
|
86 | - ? 'https://api-3t.sandbox.paypal.com/nvp' |
|
87 | - : 'https://api-3t.paypal.com/nvp'; |
|
88 | - // Request Customer Details. |
|
89 | - $response = wp_remote_post( |
|
90 | - $gateway_url, |
|
91 | - array( |
|
92 | - 'method' => 'POST', |
|
93 | - 'timeout' => 45, |
|
94 | - 'httpversion' => '1.1', |
|
95 | - 'cookies' => array(), |
|
96 | - 'headers' => array(), |
|
97 | - 'body' => http_build_query($request_params, '', '&'), |
|
98 | - ) |
|
99 | - ); |
|
100 | - if (is_wp_error($response) || empty($response['body'])) { |
|
101 | - // If we got here then there was an error in this request. |
|
102 | - // maybe is turned off. We don't know the credentials are invalid |
|
103 | - EE_Error::add_error( |
|
104 | - sprintf( |
|
105 | - // translators: %1$s Error message received from PayPal |
|
106 | - esc_html__( |
|
107 | - // @codingStandardsIgnoreStart |
|
108 | - 'Your PayPal credentials could not be verified. The following error occurred while communicating with PayPal: %1$s', |
|
109 | - // @codingStandardsIgnoreEnd |
|
110 | - 'event_espresso' |
|
111 | - ), |
|
112 | - $response->get_error_message() |
|
113 | - ), |
|
114 | - __FILE__, |
|
115 | - __FUNCTION__, |
|
116 | - __LINE__ |
|
117 | - ); |
|
118 | - } |
|
119 | - $response_args = array(); |
|
120 | - parse_str(urldecode($response['body']), $response_args); |
|
71 | + /** |
|
72 | + * Tests the the PayPal API credentials work ok |
|
73 | + * @return string of an error using the credentials, otherwise, if the credentials work, returns a blank string |
|
74 | + * @throws EE_Error |
|
75 | + */ |
|
76 | + protected function checkForCredentialsErrors() |
|
77 | + { |
|
78 | + $request_params = array( |
|
79 | + 'METHOD' => 'GetBalance', |
|
80 | + 'VERSION' => '204.0', |
|
81 | + 'USER' => $this->get_input_value('api_username'), |
|
82 | + 'PWD' => $this->get_input_value('api_password'), |
|
83 | + 'SIGNATURE' => $this->get_input_value('api_signature'), |
|
84 | + ); |
|
85 | + $gateway_url = $this->get_input_value('PMD_debug_mode') |
|
86 | + ? 'https://api-3t.sandbox.paypal.com/nvp' |
|
87 | + : 'https://api-3t.paypal.com/nvp'; |
|
88 | + // Request Customer Details. |
|
89 | + $response = wp_remote_post( |
|
90 | + $gateway_url, |
|
91 | + array( |
|
92 | + 'method' => 'POST', |
|
93 | + 'timeout' => 45, |
|
94 | + 'httpversion' => '1.1', |
|
95 | + 'cookies' => array(), |
|
96 | + 'headers' => array(), |
|
97 | + 'body' => http_build_query($request_params, '', '&'), |
|
98 | + ) |
|
99 | + ); |
|
100 | + if (is_wp_error($response) || empty($response['body'])) { |
|
101 | + // If we got here then there was an error in this request. |
|
102 | + // maybe is turned off. We don't know the credentials are invalid |
|
103 | + EE_Error::add_error( |
|
104 | + sprintf( |
|
105 | + // translators: %1$s Error message received from PayPal |
|
106 | + esc_html__( |
|
107 | + // @codingStandardsIgnoreStart |
|
108 | + 'Your PayPal credentials could not be verified. The following error occurred while communicating with PayPal: %1$s', |
|
109 | + // @codingStandardsIgnoreEnd |
|
110 | + 'event_espresso' |
|
111 | + ), |
|
112 | + $response->get_error_message() |
|
113 | + ), |
|
114 | + __FILE__, |
|
115 | + __FUNCTION__, |
|
116 | + __LINE__ |
|
117 | + ); |
|
118 | + } |
|
119 | + $response_args = array(); |
|
120 | + parse_str(urldecode($response['body']), $response_args); |
|
121 | 121 | |
122 | - if (empty($response_args['ACK'])) { |
|
123 | - EE_Error::add_error( |
|
124 | - esc_html__( |
|
125 | - 'Your PayPal credentials could not be verified. Part of their response was missing.', |
|
126 | - 'event_espresso' |
|
127 | - ), |
|
128 | - __FILE__, |
|
129 | - __FUNCTION__, |
|
130 | - __LINE__ |
|
131 | - ); |
|
132 | - } |
|
133 | - if ( |
|
134 | - in_array( |
|
135 | - $response_args['ACK'], |
|
136 | - array( |
|
137 | - 'Success', |
|
138 | - 'SuccessWithWarning' |
|
139 | - ), |
|
140 | - true |
|
141 | - ) |
|
142 | - ) { |
|
143 | - return ''; |
|
144 | - } else { |
|
145 | - return sprintf( |
|
146 | - // translators: %1$s: PayPal response message, %2$s: PayPal response code |
|
147 | - esc_html__( |
|
148 | - // @codingStandardsIgnoreStart |
|
149 | - 'Your PayPal API credentials appear to be invalid. PayPal said "%1$s (%2$s)". Please see tips below.', |
|
150 | - // @codingStandardsIgnoreEnd |
|
151 | - 'event_espresso' |
|
152 | - ), |
|
153 | - isset($response_args['L_LONGMESSAGE0']) |
|
154 | - ? $response_args['L_LONGMESSAGE0'] |
|
155 | - : esc_html__('No error message received from PayPal', 'event_espresso'), |
|
156 | - isset($response_args['L_ERRORCODE0']) ? $response_args['L_ERRORCODE0'] : 0 |
|
157 | - ); |
|
158 | - } |
|
159 | - } |
|
122 | + if (empty($response_args['ACK'])) { |
|
123 | + EE_Error::add_error( |
|
124 | + esc_html__( |
|
125 | + 'Your PayPal credentials could not be verified. Part of their response was missing.', |
|
126 | + 'event_espresso' |
|
127 | + ), |
|
128 | + __FILE__, |
|
129 | + __FUNCTION__, |
|
130 | + __LINE__ |
|
131 | + ); |
|
132 | + } |
|
133 | + if ( |
|
134 | + in_array( |
|
135 | + $response_args['ACK'], |
|
136 | + array( |
|
137 | + 'Success', |
|
138 | + 'SuccessWithWarning' |
|
139 | + ), |
|
140 | + true |
|
141 | + ) |
|
142 | + ) { |
|
143 | + return ''; |
|
144 | + } else { |
|
145 | + return sprintf( |
|
146 | + // translators: %1$s: PayPal response message, %2$s: PayPal response code |
|
147 | + esc_html__( |
|
148 | + // @codingStandardsIgnoreStart |
|
149 | + 'Your PayPal API credentials appear to be invalid. PayPal said "%1$s (%2$s)". Please see tips below.', |
|
150 | + // @codingStandardsIgnoreEnd |
|
151 | + 'event_espresso' |
|
152 | + ), |
|
153 | + isset($response_args['L_LONGMESSAGE0']) |
|
154 | + ? $response_args['L_LONGMESSAGE0'] |
|
155 | + : esc_html__('No error message received from PayPal', 'event_espresso'), |
|
156 | + isset($response_args['L_ERRORCODE0']) ? $response_args['L_ERRORCODE0'] : 0 |
|
157 | + ); |
|
158 | + } |
|
159 | + } |
|
160 | 160 | |
161 | - /** |
|
162 | - * Gets the HTML to show the link to the help tab |
|
163 | - * @return string |
|
164 | - */ |
|
165 | - protected function helpTabLink() |
|
166 | - { |
|
167 | - return $this->helpTabLink; |
|
168 | - } |
|
161 | + /** |
|
162 | + * Gets the HTML to show the link to the help tab |
|
163 | + * @return string |
|
164 | + */ |
|
165 | + protected function helpTabLink() |
|
166 | + { |
|
167 | + return $this->helpTabLink; |
|
168 | + } |
|
169 | 169 | |
170 | - /** |
|
171 | - * Does the normal validation, but also verifies the PayPal API credentials work. |
|
172 | - * If they don't, sets a validation error on the entire form, and adds validation errors (which are really more |
|
173 | - * tips) on each of the inputs that could be the cause of the problem. |
|
174 | - * @throws EE_Error |
|
175 | - */ |
|
176 | - public function _validate() |
|
177 | - { |
|
178 | - parent::_validate(); |
|
179 | - $credentials_message = $this->checkForCredentialsErrors(); |
|
180 | - if ($credentials_message !== '') { |
|
181 | - $this->add_validation_error($credentials_message); |
|
182 | - $this->get_input('PMD_debug_mode')->add_validation_error( |
|
183 | - esc_html__( |
|
184 | - // @codingStandardsIgnoreStart |
|
185 | - 'If you are using PayPal Sandbox (test) credentials, Debug mode should be set to "Yes". Otherwise, if you are using live PayPal credentials, set this to "No".', |
|
186 | - // @codingStandardsIgnoreEnd |
|
187 | - 'event_espresso' |
|
188 | - ) |
|
189 | - ); |
|
190 | - $this->get_input('api_username')->add_validation_error( |
|
191 | - sprintf( |
|
192 | - // translators: $1$s HTML for a link to the help tab |
|
193 | - esc_html__( |
|
194 | - 'Are you sure this is your API username, not your login username? %1$s', |
|
195 | - 'event_espresso' |
|
196 | - ), |
|
197 | - $this->helpTabLink() |
|
198 | - ) |
|
199 | - ); |
|
200 | - $this->get_input('api_password')->add_validation_error( |
|
201 | - sprintf( |
|
202 | - // translators: $1$s HTML for a link to the help tab |
|
203 | - esc_html__( |
|
204 | - 'Are you sure this is your API password, not your login password? %1$s', |
|
205 | - 'event_espresso' |
|
206 | - ), |
|
207 | - $this->helpTabLink() |
|
208 | - ) |
|
209 | - ); |
|
210 | - $this->get_input('api_signature')->add_validation_error( |
|
211 | - sprintf( |
|
212 | - // translators: $1$s HTML for a link to the help tab |
|
213 | - esc_html__('Please verify your API signature is correct. %1$s', 'event_espresso'), |
|
214 | - $this->helpTabLink() |
|
215 | - ) |
|
216 | - ); |
|
217 | - } |
|
218 | - } |
|
170 | + /** |
|
171 | + * Does the normal validation, but also verifies the PayPal API credentials work. |
|
172 | + * If they don't, sets a validation error on the entire form, and adds validation errors (which are really more |
|
173 | + * tips) on each of the inputs that could be the cause of the problem. |
|
174 | + * @throws EE_Error |
|
175 | + */ |
|
176 | + public function _validate() |
|
177 | + { |
|
178 | + parent::_validate(); |
|
179 | + $credentials_message = $this->checkForCredentialsErrors(); |
|
180 | + if ($credentials_message !== '') { |
|
181 | + $this->add_validation_error($credentials_message); |
|
182 | + $this->get_input('PMD_debug_mode')->add_validation_error( |
|
183 | + esc_html__( |
|
184 | + // @codingStandardsIgnoreStart |
|
185 | + 'If you are using PayPal Sandbox (test) credentials, Debug mode should be set to "Yes". Otherwise, if you are using live PayPal credentials, set this to "No".', |
|
186 | + // @codingStandardsIgnoreEnd |
|
187 | + 'event_espresso' |
|
188 | + ) |
|
189 | + ); |
|
190 | + $this->get_input('api_username')->add_validation_error( |
|
191 | + sprintf( |
|
192 | + // translators: $1$s HTML for a link to the help tab |
|
193 | + esc_html__( |
|
194 | + 'Are you sure this is your API username, not your login username? %1$s', |
|
195 | + 'event_espresso' |
|
196 | + ), |
|
197 | + $this->helpTabLink() |
|
198 | + ) |
|
199 | + ); |
|
200 | + $this->get_input('api_password')->add_validation_error( |
|
201 | + sprintf( |
|
202 | + // translators: $1$s HTML for a link to the help tab |
|
203 | + esc_html__( |
|
204 | + 'Are you sure this is your API password, not your login password? %1$s', |
|
205 | + 'event_espresso' |
|
206 | + ), |
|
207 | + $this->helpTabLink() |
|
208 | + ) |
|
209 | + ); |
|
210 | + $this->get_input('api_signature')->add_validation_error( |
|
211 | + sprintf( |
|
212 | + // translators: $1$s HTML for a link to the help tab |
|
213 | + esc_html__('Please verify your API signature is correct. %1$s', 'event_espresso'), |
|
214 | + $this->helpTabLink() |
|
215 | + ) |
|
216 | + ); |
|
217 | + } |
|
218 | + } |
|
219 | 219 | } |
220 | 220 | // End of file PayPalSettingsForm.php |
221 | 221 | // Location: ${NAMESPACE}/PayPalSettingsForm.php |
@@ -193,7 +193,7 @@ discard block |
||
193 | 193 | */ |
194 | 194 | protected function setCollectionInterface($collection_interface) |
195 | 195 | { |
196 | - if (! (interface_exists($collection_interface) || class_exists($collection_interface))) { |
|
196 | + if ( ! (interface_exists($collection_interface) || class_exists($collection_interface))) { |
|
197 | 197 | throw new InvalidInterfaceException($collection_interface); |
198 | 198 | } |
199 | 199 | $this->collection_interface = $collection_interface; |
@@ -221,7 +221,7 @@ discard block |
||
221 | 221 | */ |
222 | 222 | protected function setCollectionName($collection_name) |
223 | 223 | { |
224 | - if (! is_string($collection_name)) { |
|
224 | + if ( ! is_string($collection_name)) { |
|
225 | 225 | throw new InvalidDataTypeException('$collection_name', $collection_name, 'string'); |
226 | 226 | } |
227 | 227 | $this->collection_name = str_replace( |
@@ -281,7 +281,7 @@ discard block |
||
281 | 281 | */ |
282 | 282 | protected function setIdentifierCallback($identifier_callback = 'identifier') |
283 | 283 | { |
284 | - if (! is_string($identifier_callback)) { |
|
284 | + if ( ! is_string($identifier_callback)) { |
|
285 | 285 | throw new InvalidDataTypeException('$identifier_callback', $identifier_callback, 'string'); |
286 | 286 | } |
287 | 287 | $this->identifier_callback = $identifier_callback; |
@@ -311,7 +311,7 @@ discard block |
||
311 | 311 | $this->file_mask = ! empty($file_mask) ? $file_mask : '*.php'; |
312 | 312 | // we know our default is a string, so if it's not a string now, |
313 | 313 | // then that means the incoming parameter was something else |
314 | - if (! is_string($this->file_mask)) { |
|
314 | + if ( ! is_string($this->file_mask)) { |
|
315 | 315 | throw new InvalidDataTypeException('$file_mask', $this->file_mask, 'string'); |
316 | 316 | } |
317 | 317 | } |
@@ -336,7 +336,7 @@ discard block |
||
336 | 336 | public function setCollectionFQCNs($collection_FQCNs) |
337 | 337 | { |
338 | 338 | foreach ((array) $collection_FQCNs as $collection_FQCN) { |
339 | - if (! empty($collection_FQCN)) { |
|
339 | + if ( ! empty($collection_FQCN)) { |
|
340 | 340 | if (class_exists($collection_FQCN)) { |
341 | 341 | $this->collection_FQCNs[] = $collection_FQCN; |
342 | 342 | } else { |
@@ -358,7 +358,7 @@ discard block |
||
358 | 358 | */ |
359 | 359 | protected function getFQCNsFromPartialNamespace($partial_FQCN) |
360 | 360 | { |
361 | - if (! $this->file_locator instanceof FqcnLocator) { |
|
361 | + if ( ! $this->file_locator instanceof FqcnLocator) { |
|
362 | 362 | $this->file_locator = new FqcnLocator(); |
363 | 363 | } |
364 | 364 | $this->file_locator->locate($partial_FQCN); |
@@ -384,8 +384,8 @@ discard block |
||
384 | 384 | public function setCollectionPaths($collection_paths) |
385 | 385 | { |
386 | 386 | foreach ((array) $collection_paths as $collection_path) { |
387 | - if (! empty($collection_path)) { |
|
388 | - if (! is_readable($collection_path)) { |
|
387 | + if ( ! empty($collection_path)) { |
|
388 | + if ( ! is_readable($collection_path)) { |
|
389 | 389 | throw new InvalidFilePathException($collection_path); |
390 | 390 | } |
391 | 391 | $this->collection_paths[] = $collection_path; |
@@ -43,353 +43,353 @@ |
||
43 | 43 | */ |
44 | 44 | class CollectionDetails implements CollectionDetailsInterface |
45 | 45 | { |
46 | - /** |
|
47 | - * if $identifier_type is set to this, |
|
48 | - * then the collection will use each object's spl_object_hash() as it's identifier |
|
49 | - */ |
|
50 | - const ID_OBJECT_HASH = 'identifier-uses-spl-object-hash'; |
|
51 | - |
|
52 | - /** |
|
53 | - * if $identifier_type is set to this, |
|
54 | - * then the collection will use each object's class name as it's identifier |
|
55 | - */ |
|
56 | - const ID_CLASS_NAME = 'identifier-uses-object-class-name'; |
|
57 | - |
|
58 | - /** |
|
59 | - * if $identifier_type is set to this, |
|
60 | - * then the collection will use the return value from a specified callback method on each object |
|
61 | - */ |
|
62 | - const ID_CALLBACK_METHOD = 'identifier-uses-callback-method'; |
|
63 | - |
|
64 | - /** |
|
65 | - * The interface used for controlling what gets added to the collection |
|
66 | - * |
|
67 | - * @var string $collection_interface |
|
68 | - */ |
|
69 | - protected $collection_interface = ''; |
|
70 | - |
|
71 | - /** |
|
72 | - * a unique name used to identify the collection in filter names |
|
73 | - * supplied value is run through sanitize_title_with_dashes(), |
|
74 | - * but then also converts dashes to underscores |
|
75 | - * |
|
76 | - * @var string $collection_name |
|
77 | - */ |
|
78 | - protected $collection_name = ''; |
|
79 | - |
|
80 | - /** |
|
81 | - * what the collection uses for the object identifier. |
|
82 | - * corresponds to one of the class constants above. |
|
83 | - * CollectionDetails::ID_OBJECT_HASH will use spl_object_hash( object ) for the identifier |
|
84 | - * CollectionDetails::ID_CLASS_NAME will use get_class( object ) for the identifier |
|
85 | - * CollectionDetails::ID_CALLBACK_METHOD will use a callback for the identifier |
|
86 | - * defaults to using spl_object_hash() so that multiple objects of the same class can be added |
|
87 | - * |
|
88 | - * @var string $identifier_type |
|
89 | - */ |
|
90 | - protected $identifier_type = CollectionDetails::ID_OBJECT_HASH; |
|
91 | - |
|
92 | - /** |
|
93 | - * the pattern applied to paths when searching for class files to add to the collection |
|
94 | - * ie: "My_Awesome_*.class.php" |
|
95 | - * defaults to "*.php" |
|
96 | - * |
|
97 | - * @var string $file_mask |
|
98 | - */ |
|
99 | - protected $file_mask = ''; |
|
100 | - |
|
101 | - /** |
|
102 | - * if the $identifier_type above is set to CollectionDetails::ID_CALLBACK_METHOD, |
|
103 | - * then this specifies the method to use on each entity. |
|
104 | - * If the callback method does not exist, then an exception will be thrown |
|
105 | - * |
|
106 | - * @var string $identifier_callback |
|
107 | - */ |
|
108 | - protected $identifier_callback = ''; |
|
109 | - |
|
110 | - /** |
|
111 | - * an array of Fully Qualified Class Names |
|
112 | - * for example: |
|
113 | - * $FQCNs = array( |
|
114 | - * '/Fully/Qualified/ClassNameA' |
|
115 | - * '/Fully/Qualified/Other/ClassNameB' |
|
116 | - * ); |
|
117 | - * |
|
118 | - * @var array $collection_FQCNs |
|
119 | - */ |
|
120 | - protected $collection_FQCNs = array(); |
|
121 | - |
|
122 | - /** |
|
123 | - * an array of full server paths to folders containing files to be loaded into collection |
|
124 | - * for example: |
|
125 | - * $paths = array( |
|
126 | - * '/full/server/path/to/ClassNameA.ext.php' // for class ClassNameA |
|
127 | - * '/full/server/path/to/other/ClassNameB.php' // for class ClassNameB |
|
128 | - * ); |
|
129 | - * |
|
130 | - * @var array $collection_paths |
|
131 | - */ |
|
132 | - protected $collection_paths = array(); |
|
133 | - |
|
134 | - /** |
|
135 | - * @var LocatorInterface $file_locator |
|
136 | - */ |
|
137 | - protected $file_locator; |
|
138 | - |
|
139 | - |
|
140 | - /** |
|
141 | - * CollectionDetails constructor. |
|
142 | - * |
|
143 | - * @access public |
|
144 | - * @param string $collection_name |
|
145 | - * @param string $collection_interface |
|
146 | - * @param array $collection_FQCNs |
|
147 | - * @param array $collection_paths |
|
148 | - * @param string $file_mask |
|
149 | - * @param string $identifier_type |
|
150 | - * @param string $identifier_callback |
|
151 | - * @param LocatorInterface $file_locator |
|
152 | - * @throws CollectionDetailsException |
|
153 | - */ |
|
154 | - public function __construct( |
|
155 | - $collection_name, |
|
156 | - $collection_interface, |
|
157 | - array $collection_FQCNs = array(), |
|
158 | - array $collection_paths = array(), |
|
159 | - $file_mask = '', |
|
160 | - $identifier_type = CollectionDetails::ID_OBJECT_HASH, |
|
161 | - $identifier_callback = '', |
|
162 | - LocatorInterface $file_locator = null |
|
163 | - ) { |
|
164 | - try { |
|
165 | - $this->setCollectionName($collection_name); |
|
166 | - $this->setCollectionInterface($collection_interface); |
|
167 | - $this->setCollectionFQCNs($collection_FQCNs); |
|
168 | - $this->setCollectionPaths($collection_paths); |
|
169 | - $this->setFileMasks($file_mask); |
|
170 | - $this->setIdentifierType($identifier_type); |
|
171 | - $this->setIdentifierCallback($identifier_callback); |
|
172 | - $this->file_locator = $file_locator; |
|
173 | - } catch (Exception $exception) { |
|
174 | - throw new CollectionDetailsException($exception); |
|
175 | - } |
|
176 | - } |
|
177 | - |
|
178 | - |
|
179 | - /** |
|
180 | - * @access public |
|
181 | - * @return mixed |
|
182 | - */ |
|
183 | - public function getCollectionInterface() |
|
184 | - { |
|
185 | - return $this->collection_interface; |
|
186 | - } |
|
187 | - |
|
188 | - |
|
189 | - /** |
|
190 | - * @access protected |
|
191 | - * @param string $collection_interface |
|
192 | - * @throws InvalidInterfaceException |
|
193 | - */ |
|
194 | - protected function setCollectionInterface($collection_interface) |
|
195 | - { |
|
196 | - if (! (interface_exists($collection_interface) || class_exists($collection_interface))) { |
|
197 | - throw new InvalidInterfaceException($collection_interface); |
|
198 | - } |
|
199 | - $this->collection_interface = $collection_interface; |
|
200 | - } |
|
201 | - |
|
202 | - |
|
203 | - /** |
|
204 | - * the collection name will be used for creating dynamic filters |
|
205 | - * |
|
206 | - * @access public |
|
207 | - * @return string |
|
208 | - */ |
|
209 | - public function collectionName() |
|
210 | - { |
|
211 | - return $this->collection_name; |
|
212 | - } |
|
213 | - |
|
214 | - |
|
215 | - /** |
|
216 | - * sanitizes collection name and converts spaces and dashes to underscores |
|
217 | - * |
|
218 | - * @access protected |
|
219 | - * @param string $collection_name |
|
220 | - * @throws InvalidDataTypeException |
|
221 | - */ |
|
222 | - protected function setCollectionName($collection_name) |
|
223 | - { |
|
224 | - if (! is_string($collection_name)) { |
|
225 | - throw new InvalidDataTypeException('$collection_name', $collection_name, 'string'); |
|
226 | - } |
|
227 | - $this->collection_name = str_replace( |
|
228 | - '-', |
|
229 | - '_', |
|
230 | - sanitize_title_with_dashes($collection_name, '', 'save') |
|
231 | - ); |
|
232 | - } |
|
233 | - |
|
234 | - |
|
235 | - /** |
|
236 | - * @access public |
|
237 | - * @return string |
|
238 | - */ |
|
239 | - public function identifierType() |
|
240 | - { |
|
241 | - return $this->identifier_type; |
|
242 | - } |
|
243 | - |
|
244 | - |
|
245 | - /** |
|
246 | - * @access protected |
|
247 | - * @param string $identifier_type |
|
248 | - * @throws InvalidIdentifierException |
|
249 | - */ |
|
250 | - protected function setIdentifierType($identifier_type) |
|
251 | - { |
|
252 | - if ( |
|
253 | - ! ($identifier_type === CollectionDetails::ID_CLASS_NAME |
|
254 | - || $identifier_type === CollectionDetails::ID_OBJECT_HASH |
|
255 | - || $identifier_type === CollectionDetails::ID_CALLBACK_METHOD |
|
256 | - ) |
|
257 | - ) { |
|
258 | - throw new InvalidIdentifierException( |
|
259 | - $identifier_type, |
|
260 | - 'CollectionDetails::ID_CLASS_NAME or CollectionDetails::ID_OBJECT_HASH or CollectionDetails::ID_CALLBACK_METHOD' |
|
261 | - ); |
|
262 | - } |
|
263 | - $this->identifier_type = $identifier_type; |
|
264 | - } |
|
265 | - |
|
266 | - |
|
267 | - /** |
|
268 | - * @access public |
|
269 | - * @return string |
|
270 | - */ |
|
271 | - public function identifierCallback() |
|
272 | - { |
|
273 | - return $this->identifier_callback; |
|
274 | - } |
|
275 | - |
|
276 | - |
|
277 | - /** |
|
278 | - * @access protected |
|
279 | - * @param string $identifier_callback |
|
280 | - * @throws InvalidDataTypeException |
|
281 | - */ |
|
282 | - protected function setIdentifierCallback($identifier_callback = 'identifier') |
|
283 | - { |
|
284 | - if (! is_string($identifier_callback)) { |
|
285 | - throw new InvalidDataTypeException('$identifier_callback', $identifier_callback, 'string'); |
|
286 | - } |
|
287 | - $this->identifier_callback = $identifier_callback; |
|
288 | - } |
|
289 | - |
|
290 | - |
|
291 | - /** |
|
292 | - * @access public |
|
293 | - * @return string |
|
294 | - */ |
|
295 | - public function getFileMask() |
|
296 | - { |
|
297 | - return $this->file_mask; |
|
298 | - } |
|
299 | - |
|
300 | - |
|
301 | - /** |
|
302 | - * sets the file mask which is then used to filter what files get loaded |
|
303 | - * when searching for classes to add to the collection. Defaults to '*.php' |
|
304 | - * |
|
305 | - * @access protected |
|
306 | - * @param string $file_mask |
|
307 | - * @throws InvalidDataTypeException |
|
308 | - */ |
|
309 | - protected function setFileMasks($file_mask) |
|
310 | - { |
|
311 | - $this->file_mask = ! empty($file_mask) ? $file_mask : '*.php'; |
|
312 | - // we know our default is a string, so if it's not a string now, |
|
313 | - // then that means the incoming parameter was something else |
|
314 | - if (! is_string($this->file_mask)) { |
|
315 | - throw new InvalidDataTypeException('$file_mask', $this->file_mask, 'string'); |
|
316 | - } |
|
317 | - } |
|
318 | - |
|
319 | - |
|
320 | - /** |
|
321 | - * @access public |
|
322 | - * @return array |
|
323 | - */ |
|
324 | - public function getCollectionFQCNs() |
|
325 | - { |
|
326 | - return $this->collection_FQCNs; |
|
327 | - } |
|
328 | - |
|
329 | - |
|
330 | - /** |
|
331 | - * @access public |
|
332 | - * @param string|array $collection_FQCNs |
|
333 | - * @throws InvalidClassException |
|
334 | - * @throws InvalidDataTypeException |
|
335 | - */ |
|
336 | - public function setCollectionFQCNs($collection_FQCNs) |
|
337 | - { |
|
338 | - foreach ((array) $collection_FQCNs as $collection_FQCN) { |
|
339 | - if (! empty($collection_FQCN)) { |
|
340 | - if (class_exists($collection_FQCN)) { |
|
341 | - $this->collection_FQCNs[] = $collection_FQCN; |
|
342 | - } else { |
|
343 | - foreach ($this->getFQCNsFromPartialNamespace($collection_FQCN) as $FQCN) { |
|
344 | - $this->collection_FQCNs[] = $FQCN; |
|
345 | - } |
|
346 | - } |
|
347 | - } |
|
348 | - } |
|
349 | - } |
|
350 | - |
|
351 | - |
|
352 | - /** |
|
353 | - * @access protected |
|
354 | - * @param string $partial_FQCN |
|
355 | - * @return array |
|
356 | - * @throws InvalidDataTypeException |
|
357 | - * @throws InvalidClassException |
|
358 | - */ |
|
359 | - protected function getFQCNsFromPartialNamespace($partial_FQCN) |
|
360 | - { |
|
361 | - if (! $this->file_locator instanceof FqcnLocator) { |
|
362 | - $this->file_locator = new FqcnLocator(); |
|
363 | - } |
|
364 | - $this->file_locator->locate($partial_FQCN); |
|
365 | - return $this->file_locator->getFQCNs(); |
|
366 | - } |
|
367 | - |
|
368 | - |
|
369 | - /** |
|
370 | - * @access public |
|
371 | - * @return array |
|
372 | - */ |
|
373 | - public function getCollectionPaths() |
|
374 | - { |
|
375 | - return $this->collection_paths; |
|
376 | - } |
|
377 | - |
|
378 | - |
|
379 | - /** |
|
380 | - * @access public |
|
381 | - * @param string|array $collection_paths |
|
382 | - * @throws InvalidFilePathException |
|
383 | - */ |
|
384 | - public function setCollectionPaths($collection_paths) |
|
385 | - { |
|
386 | - foreach ((array) $collection_paths as $collection_path) { |
|
387 | - if (! empty($collection_path)) { |
|
388 | - if (! is_readable($collection_path)) { |
|
389 | - throw new InvalidFilePathException($collection_path); |
|
390 | - } |
|
391 | - $this->collection_paths[] = $collection_path; |
|
392 | - } |
|
393 | - } |
|
394 | - } |
|
46 | + /** |
|
47 | + * if $identifier_type is set to this, |
|
48 | + * then the collection will use each object's spl_object_hash() as it's identifier |
|
49 | + */ |
|
50 | + const ID_OBJECT_HASH = 'identifier-uses-spl-object-hash'; |
|
51 | + |
|
52 | + /** |
|
53 | + * if $identifier_type is set to this, |
|
54 | + * then the collection will use each object's class name as it's identifier |
|
55 | + */ |
|
56 | + const ID_CLASS_NAME = 'identifier-uses-object-class-name'; |
|
57 | + |
|
58 | + /** |
|
59 | + * if $identifier_type is set to this, |
|
60 | + * then the collection will use the return value from a specified callback method on each object |
|
61 | + */ |
|
62 | + const ID_CALLBACK_METHOD = 'identifier-uses-callback-method'; |
|
63 | + |
|
64 | + /** |
|
65 | + * The interface used for controlling what gets added to the collection |
|
66 | + * |
|
67 | + * @var string $collection_interface |
|
68 | + */ |
|
69 | + protected $collection_interface = ''; |
|
70 | + |
|
71 | + /** |
|
72 | + * a unique name used to identify the collection in filter names |
|
73 | + * supplied value is run through sanitize_title_with_dashes(), |
|
74 | + * but then also converts dashes to underscores |
|
75 | + * |
|
76 | + * @var string $collection_name |
|
77 | + */ |
|
78 | + protected $collection_name = ''; |
|
79 | + |
|
80 | + /** |
|
81 | + * what the collection uses for the object identifier. |
|
82 | + * corresponds to one of the class constants above. |
|
83 | + * CollectionDetails::ID_OBJECT_HASH will use spl_object_hash( object ) for the identifier |
|
84 | + * CollectionDetails::ID_CLASS_NAME will use get_class( object ) for the identifier |
|
85 | + * CollectionDetails::ID_CALLBACK_METHOD will use a callback for the identifier |
|
86 | + * defaults to using spl_object_hash() so that multiple objects of the same class can be added |
|
87 | + * |
|
88 | + * @var string $identifier_type |
|
89 | + */ |
|
90 | + protected $identifier_type = CollectionDetails::ID_OBJECT_HASH; |
|
91 | + |
|
92 | + /** |
|
93 | + * the pattern applied to paths when searching for class files to add to the collection |
|
94 | + * ie: "My_Awesome_*.class.php" |
|
95 | + * defaults to "*.php" |
|
96 | + * |
|
97 | + * @var string $file_mask |
|
98 | + */ |
|
99 | + protected $file_mask = ''; |
|
100 | + |
|
101 | + /** |
|
102 | + * if the $identifier_type above is set to CollectionDetails::ID_CALLBACK_METHOD, |
|
103 | + * then this specifies the method to use on each entity. |
|
104 | + * If the callback method does not exist, then an exception will be thrown |
|
105 | + * |
|
106 | + * @var string $identifier_callback |
|
107 | + */ |
|
108 | + protected $identifier_callback = ''; |
|
109 | + |
|
110 | + /** |
|
111 | + * an array of Fully Qualified Class Names |
|
112 | + * for example: |
|
113 | + * $FQCNs = array( |
|
114 | + * '/Fully/Qualified/ClassNameA' |
|
115 | + * '/Fully/Qualified/Other/ClassNameB' |
|
116 | + * ); |
|
117 | + * |
|
118 | + * @var array $collection_FQCNs |
|
119 | + */ |
|
120 | + protected $collection_FQCNs = array(); |
|
121 | + |
|
122 | + /** |
|
123 | + * an array of full server paths to folders containing files to be loaded into collection |
|
124 | + * for example: |
|
125 | + * $paths = array( |
|
126 | + * '/full/server/path/to/ClassNameA.ext.php' // for class ClassNameA |
|
127 | + * '/full/server/path/to/other/ClassNameB.php' // for class ClassNameB |
|
128 | + * ); |
|
129 | + * |
|
130 | + * @var array $collection_paths |
|
131 | + */ |
|
132 | + protected $collection_paths = array(); |
|
133 | + |
|
134 | + /** |
|
135 | + * @var LocatorInterface $file_locator |
|
136 | + */ |
|
137 | + protected $file_locator; |
|
138 | + |
|
139 | + |
|
140 | + /** |
|
141 | + * CollectionDetails constructor. |
|
142 | + * |
|
143 | + * @access public |
|
144 | + * @param string $collection_name |
|
145 | + * @param string $collection_interface |
|
146 | + * @param array $collection_FQCNs |
|
147 | + * @param array $collection_paths |
|
148 | + * @param string $file_mask |
|
149 | + * @param string $identifier_type |
|
150 | + * @param string $identifier_callback |
|
151 | + * @param LocatorInterface $file_locator |
|
152 | + * @throws CollectionDetailsException |
|
153 | + */ |
|
154 | + public function __construct( |
|
155 | + $collection_name, |
|
156 | + $collection_interface, |
|
157 | + array $collection_FQCNs = array(), |
|
158 | + array $collection_paths = array(), |
|
159 | + $file_mask = '', |
|
160 | + $identifier_type = CollectionDetails::ID_OBJECT_HASH, |
|
161 | + $identifier_callback = '', |
|
162 | + LocatorInterface $file_locator = null |
|
163 | + ) { |
|
164 | + try { |
|
165 | + $this->setCollectionName($collection_name); |
|
166 | + $this->setCollectionInterface($collection_interface); |
|
167 | + $this->setCollectionFQCNs($collection_FQCNs); |
|
168 | + $this->setCollectionPaths($collection_paths); |
|
169 | + $this->setFileMasks($file_mask); |
|
170 | + $this->setIdentifierType($identifier_type); |
|
171 | + $this->setIdentifierCallback($identifier_callback); |
|
172 | + $this->file_locator = $file_locator; |
|
173 | + } catch (Exception $exception) { |
|
174 | + throw new CollectionDetailsException($exception); |
|
175 | + } |
|
176 | + } |
|
177 | + |
|
178 | + |
|
179 | + /** |
|
180 | + * @access public |
|
181 | + * @return mixed |
|
182 | + */ |
|
183 | + public function getCollectionInterface() |
|
184 | + { |
|
185 | + return $this->collection_interface; |
|
186 | + } |
|
187 | + |
|
188 | + |
|
189 | + /** |
|
190 | + * @access protected |
|
191 | + * @param string $collection_interface |
|
192 | + * @throws InvalidInterfaceException |
|
193 | + */ |
|
194 | + protected function setCollectionInterface($collection_interface) |
|
195 | + { |
|
196 | + if (! (interface_exists($collection_interface) || class_exists($collection_interface))) { |
|
197 | + throw new InvalidInterfaceException($collection_interface); |
|
198 | + } |
|
199 | + $this->collection_interface = $collection_interface; |
|
200 | + } |
|
201 | + |
|
202 | + |
|
203 | + /** |
|
204 | + * the collection name will be used for creating dynamic filters |
|
205 | + * |
|
206 | + * @access public |
|
207 | + * @return string |
|
208 | + */ |
|
209 | + public function collectionName() |
|
210 | + { |
|
211 | + return $this->collection_name; |
|
212 | + } |
|
213 | + |
|
214 | + |
|
215 | + /** |
|
216 | + * sanitizes collection name and converts spaces and dashes to underscores |
|
217 | + * |
|
218 | + * @access protected |
|
219 | + * @param string $collection_name |
|
220 | + * @throws InvalidDataTypeException |
|
221 | + */ |
|
222 | + protected function setCollectionName($collection_name) |
|
223 | + { |
|
224 | + if (! is_string($collection_name)) { |
|
225 | + throw new InvalidDataTypeException('$collection_name', $collection_name, 'string'); |
|
226 | + } |
|
227 | + $this->collection_name = str_replace( |
|
228 | + '-', |
|
229 | + '_', |
|
230 | + sanitize_title_with_dashes($collection_name, '', 'save') |
|
231 | + ); |
|
232 | + } |
|
233 | + |
|
234 | + |
|
235 | + /** |
|
236 | + * @access public |
|
237 | + * @return string |
|
238 | + */ |
|
239 | + public function identifierType() |
|
240 | + { |
|
241 | + return $this->identifier_type; |
|
242 | + } |
|
243 | + |
|
244 | + |
|
245 | + /** |
|
246 | + * @access protected |
|
247 | + * @param string $identifier_type |
|
248 | + * @throws InvalidIdentifierException |
|
249 | + */ |
|
250 | + protected function setIdentifierType($identifier_type) |
|
251 | + { |
|
252 | + if ( |
|
253 | + ! ($identifier_type === CollectionDetails::ID_CLASS_NAME |
|
254 | + || $identifier_type === CollectionDetails::ID_OBJECT_HASH |
|
255 | + || $identifier_type === CollectionDetails::ID_CALLBACK_METHOD |
|
256 | + ) |
|
257 | + ) { |
|
258 | + throw new InvalidIdentifierException( |
|
259 | + $identifier_type, |
|
260 | + 'CollectionDetails::ID_CLASS_NAME or CollectionDetails::ID_OBJECT_HASH or CollectionDetails::ID_CALLBACK_METHOD' |
|
261 | + ); |
|
262 | + } |
|
263 | + $this->identifier_type = $identifier_type; |
|
264 | + } |
|
265 | + |
|
266 | + |
|
267 | + /** |
|
268 | + * @access public |
|
269 | + * @return string |
|
270 | + */ |
|
271 | + public function identifierCallback() |
|
272 | + { |
|
273 | + return $this->identifier_callback; |
|
274 | + } |
|
275 | + |
|
276 | + |
|
277 | + /** |
|
278 | + * @access protected |
|
279 | + * @param string $identifier_callback |
|
280 | + * @throws InvalidDataTypeException |
|
281 | + */ |
|
282 | + protected function setIdentifierCallback($identifier_callback = 'identifier') |
|
283 | + { |
|
284 | + if (! is_string($identifier_callback)) { |
|
285 | + throw new InvalidDataTypeException('$identifier_callback', $identifier_callback, 'string'); |
|
286 | + } |
|
287 | + $this->identifier_callback = $identifier_callback; |
|
288 | + } |
|
289 | + |
|
290 | + |
|
291 | + /** |
|
292 | + * @access public |
|
293 | + * @return string |
|
294 | + */ |
|
295 | + public function getFileMask() |
|
296 | + { |
|
297 | + return $this->file_mask; |
|
298 | + } |
|
299 | + |
|
300 | + |
|
301 | + /** |
|
302 | + * sets the file mask which is then used to filter what files get loaded |
|
303 | + * when searching for classes to add to the collection. Defaults to '*.php' |
|
304 | + * |
|
305 | + * @access protected |
|
306 | + * @param string $file_mask |
|
307 | + * @throws InvalidDataTypeException |
|
308 | + */ |
|
309 | + protected function setFileMasks($file_mask) |
|
310 | + { |
|
311 | + $this->file_mask = ! empty($file_mask) ? $file_mask : '*.php'; |
|
312 | + // we know our default is a string, so if it's not a string now, |
|
313 | + // then that means the incoming parameter was something else |
|
314 | + if (! is_string($this->file_mask)) { |
|
315 | + throw new InvalidDataTypeException('$file_mask', $this->file_mask, 'string'); |
|
316 | + } |
|
317 | + } |
|
318 | + |
|
319 | + |
|
320 | + /** |
|
321 | + * @access public |
|
322 | + * @return array |
|
323 | + */ |
|
324 | + public function getCollectionFQCNs() |
|
325 | + { |
|
326 | + return $this->collection_FQCNs; |
|
327 | + } |
|
328 | + |
|
329 | + |
|
330 | + /** |
|
331 | + * @access public |
|
332 | + * @param string|array $collection_FQCNs |
|
333 | + * @throws InvalidClassException |
|
334 | + * @throws InvalidDataTypeException |
|
335 | + */ |
|
336 | + public function setCollectionFQCNs($collection_FQCNs) |
|
337 | + { |
|
338 | + foreach ((array) $collection_FQCNs as $collection_FQCN) { |
|
339 | + if (! empty($collection_FQCN)) { |
|
340 | + if (class_exists($collection_FQCN)) { |
|
341 | + $this->collection_FQCNs[] = $collection_FQCN; |
|
342 | + } else { |
|
343 | + foreach ($this->getFQCNsFromPartialNamespace($collection_FQCN) as $FQCN) { |
|
344 | + $this->collection_FQCNs[] = $FQCN; |
|
345 | + } |
|
346 | + } |
|
347 | + } |
|
348 | + } |
|
349 | + } |
|
350 | + |
|
351 | + |
|
352 | + /** |
|
353 | + * @access protected |
|
354 | + * @param string $partial_FQCN |
|
355 | + * @return array |
|
356 | + * @throws InvalidDataTypeException |
|
357 | + * @throws InvalidClassException |
|
358 | + */ |
|
359 | + protected function getFQCNsFromPartialNamespace($partial_FQCN) |
|
360 | + { |
|
361 | + if (! $this->file_locator instanceof FqcnLocator) { |
|
362 | + $this->file_locator = new FqcnLocator(); |
|
363 | + } |
|
364 | + $this->file_locator->locate($partial_FQCN); |
|
365 | + return $this->file_locator->getFQCNs(); |
|
366 | + } |
|
367 | + |
|
368 | + |
|
369 | + /** |
|
370 | + * @access public |
|
371 | + * @return array |
|
372 | + */ |
|
373 | + public function getCollectionPaths() |
|
374 | + { |
|
375 | + return $this->collection_paths; |
|
376 | + } |
|
377 | + |
|
378 | + |
|
379 | + /** |
|
380 | + * @access public |
|
381 | + * @param string|array $collection_paths |
|
382 | + * @throws InvalidFilePathException |
|
383 | + */ |
|
384 | + public function setCollectionPaths($collection_paths) |
|
385 | + { |
|
386 | + foreach ((array) $collection_paths as $collection_path) { |
|
387 | + if (! empty($collection_path)) { |
|
388 | + if (! is_readable($collection_path)) { |
|
389 | + throw new InvalidFilePathException($collection_path); |
|
390 | + } |
|
391 | + $this->collection_paths[] = $collection_path; |
|
392 | + } |
|
393 | + } |
|
394 | + } |
|
395 | 395 | } |
@@ -85,7 +85,7 @@ discard block |
||
85 | 85 | */ |
86 | 86 | public function setReturnUrl($return_url) |
87 | 87 | { |
88 | - if (! is_string($return_url)) { |
|
88 | + if ( ! is_string($return_url)) { |
|
89 | 89 | throw new InvalidDataTypeException('$return_url', $return_url, 'string'); |
90 | 90 | } |
91 | 91 | $this->return_url = $return_url; |
@@ -102,7 +102,7 @@ discard block |
||
102 | 102 | */ |
103 | 103 | protected function getPersistentAdminNoticeCollection() |
104 | 104 | { |
105 | - if (! $this->notice_collection instanceof Collection) { |
|
105 | + if ( ! $this->notice_collection instanceof Collection) { |
|
106 | 106 | $this->notice_collection = new Collection( |
107 | 107 | 'EventEspresso\core\domain\entities\notifications\PersistentAdminNotice' |
108 | 108 | ); |
@@ -125,7 +125,7 @@ discard block |
||
125 | 125 | protected function retrieveStoredNotices() |
126 | 126 | { |
127 | 127 | $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array()); |
128 | - if (! empty($persistent_admin_notices)) { |
|
128 | + if ( ! empty($persistent_admin_notices)) { |
|
129 | 129 | foreach ($persistent_admin_notices as $name => $details) { |
130 | 130 | if (is_array($details)) { |
131 | 131 | if ( |
@@ -247,14 +247,14 @@ discard block |
||
247 | 247 | { |
248 | 248 | wp_register_script( |
249 | 249 | 'espresso_core', |
250 | - EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js', |
|
250 | + EE_GLOBAL_ASSETS_URL.'scripts/espresso_core.js', |
|
251 | 251 | array('jquery'), |
252 | 252 | EVENT_ESPRESSO_VERSION, |
253 | 253 | true |
254 | 254 | ); |
255 | 255 | wp_register_script( |
256 | 256 | 'ee_error_js', |
257 | - EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js', |
|
257 | + EE_GLOBAL_ASSETS_URL.'scripts/EE_Error.js', |
|
258 | 258 | array('espresso_core'), |
259 | 259 | EVENT_ESPRESSO_VERSION, |
260 | 260 | true |
@@ -285,7 +285,7 @@ discard block |
||
285 | 285 | // used in template |
286 | 286 | $persistent_admin_notice_name = $persistent_admin_notice->getName(); |
287 | 287 | $persistent_admin_notice_message = $persistent_admin_notice->getMessage(); |
288 | - require EE_TEMPLATES . '/notifications/persistent_admin_notice.template.php'; |
|
288 | + require EE_TEMPLATES.'/notifications/persistent_admin_notice.template.php'; |
|
289 | 289 | } |
290 | 290 | |
291 | 291 | |
@@ -310,7 +310,7 @@ discard block |
||
310 | 310 | { |
311 | 311 | $pan_name = $this->request->getRequestParam('ee_nag_notice', $pan_name); |
312 | 312 | $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
313 | - if (! empty($pan_name) && $this->notice_collection->has($pan_name)) { |
|
313 | + if ( ! empty($pan_name) && $this->notice_collection->has($pan_name)) { |
|
314 | 314 | /** @var PersistentAdminNotice $persistent_admin_notice */ |
315 | 315 | $persistent_admin_notice = $this->notice_collection->get($pan_name); |
316 | 316 | $persistent_admin_notice->setDismissed(true); |
@@ -360,10 +360,10 @@ discard block |
||
360 | 360 | foreach ($this->notice_collection as $persistent_admin_notice) { |
361 | 361 | // are we deleting this notice ? |
362 | 362 | if ($persistent_admin_notice->getPurge()) { |
363 | - unset($persistent_admin_notices[ $persistent_admin_notice->getName() ]); |
|
363 | + unset($persistent_admin_notices[$persistent_admin_notice->getName()]); |
|
364 | 364 | } else { |
365 | 365 | /** @var PersistentAdminNotice $persistent_admin_notice */ |
366 | - $persistent_admin_notices[ $persistent_admin_notice->getName() ] = array( |
|
366 | + $persistent_admin_notices[$persistent_admin_notice->getName()] = array( |
|
367 | 367 | 'message' => $persistent_admin_notice->getMessage(), |
368 | 368 | 'capability' => $persistent_admin_notice->getCapability(), |
369 | 369 | 'cap_context' => $persistent_admin_notice->getCapContext(), |
@@ -30,393 +30,393 @@ |
||
30 | 30 | */ |
31 | 31 | class PersistentAdminNoticeManager |
32 | 32 | { |
33 | - const WP_OPTION_KEY = 'ee_pers_admin_notices'; |
|
34 | - |
|
35 | - /** |
|
36 | - * @var Collection|PersistentAdminNotice[] $notice_collection |
|
37 | - */ |
|
38 | - private $notice_collection; |
|
39 | - |
|
40 | - /** |
|
41 | - * if AJAX is not enabled, then the return URL will be used for redirecting back to the admin page where the |
|
42 | - * persistent admin notice was displayed, and ultimately dismissed from. |
|
43 | - * |
|
44 | - * @var string $return_url |
|
45 | - */ |
|
46 | - private $return_url; |
|
47 | - |
|
48 | - /** |
|
49 | - * @var CapabilitiesChecker $capabilities_checker |
|
50 | - */ |
|
51 | - private $capabilities_checker; |
|
52 | - |
|
53 | - /** |
|
54 | - * @var RequestInterface $request |
|
55 | - */ |
|
56 | - private $request; |
|
57 | - |
|
58 | - |
|
59 | - /** |
|
60 | - * PersistentAdminNoticeManager constructor |
|
61 | - * |
|
62 | - * @param CapabilitiesChecker $capabilities_checker |
|
63 | - * @param RequestInterface $request |
|
64 | - * @param string $return_url where to redirect to after dismissing notices |
|
65 | - * @throws InvalidDataTypeException |
|
66 | - */ |
|
67 | - public function __construct( |
|
68 | - CapabilitiesChecker $capabilities_checker, |
|
69 | - RequestInterface $request, |
|
70 | - $return_url = '' |
|
71 | - ) { |
|
72 | - $return_url = (string) $return_url; |
|
73 | - $this->setReturnUrl($return_url); |
|
74 | - $this->capabilities_checker = $capabilities_checker; |
|
75 | - $this->request = $request; |
|
76 | - // setup up notices at priority 9 because `EE_Admin::display_admin_notices()` runs at priority 10, |
|
77 | - // and we want to retrieve and generate any nag notices at the last possible moment |
|
78 | - add_action('admin_notices', array($this, 'displayNotices'), 9); |
|
79 | - add_action('network_admin_notices', array($this, 'displayNotices'), 9); |
|
80 | - add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismissNotice')); |
|
81 | - add_action('shutdown', array($this, 'registerAndSaveNotices'), 998); |
|
82 | - } |
|
83 | - |
|
84 | - |
|
85 | - /** |
|
86 | - * @param string $return_url |
|
87 | - * @throws InvalidDataTypeException |
|
88 | - */ |
|
89 | - public function setReturnUrl($return_url) |
|
90 | - { |
|
91 | - if (! is_string($return_url)) { |
|
92 | - throw new InvalidDataTypeException('$return_url', $return_url, 'string'); |
|
93 | - } |
|
94 | - $this->return_url = $return_url; |
|
95 | - } |
|
96 | - |
|
97 | - |
|
98 | - /** |
|
99 | - * @return Collection |
|
100 | - * @throws InvalidEntityException |
|
101 | - * @throws InvalidInterfaceException |
|
102 | - * @throws InvalidDataTypeException |
|
103 | - * @throws DomainException |
|
104 | - * @throws DuplicateCollectionIdentifierException |
|
105 | - */ |
|
106 | - protected function getPersistentAdminNoticeCollection() |
|
107 | - { |
|
108 | - if (! $this->notice_collection instanceof Collection) { |
|
109 | - $this->notice_collection = new Collection( |
|
110 | - 'EventEspresso\core\domain\entities\notifications\PersistentAdminNotice' |
|
111 | - ); |
|
112 | - $this->retrieveStoredNotices(); |
|
113 | - $this->registerNotices(); |
|
114 | - } |
|
115 | - return $this->notice_collection; |
|
116 | - } |
|
117 | - |
|
118 | - |
|
119 | - /** |
|
120 | - * generates PersistentAdminNotice objects for all non-dismissed notices saved to the db |
|
121 | - * |
|
122 | - * @return void |
|
123 | - * @throws InvalidEntityException |
|
124 | - * @throws DomainException |
|
125 | - * @throws InvalidDataTypeException |
|
126 | - * @throws DuplicateCollectionIdentifierException |
|
127 | - */ |
|
128 | - protected function retrieveStoredNotices() |
|
129 | - { |
|
130 | - $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array()); |
|
131 | - if (! empty($persistent_admin_notices)) { |
|
132 | - foreach ($persistent_admin_notices as $name => $details) { |
|
133 | - if (is_array($details)) { |
|
134 | - if ( |
|
135 | - ! isset( |
|
136 | - $details['message'], |
|
137 | - $details['capability'], |
|
138 | - $details['cap_context'], |
|
139 | - $details['dismissed'] |
|
140 | - ) |
|
141 | - ) { |
|
142 | - throw new DomainException( |
|
143 | - sprintf( |
|
144 | - esc_html__( |
|
145 | - 'The "%1$s" PersistentAdminNotice could not be retrieved from the database.', |
|
146 | - 'event_espresso' |
|
147 | - ), |
|
148 | - $name |
|
149 | - ) |
|
150 | - ); |
|
151 | - } |
|
152 | - // new format for nag notices |
|
153 | - $this->notice_collection->add( |
|
154 | - new PersistentAdminNotice( |
|
155 | - $name, |
|
156 | - $details['message'], |
|
157 | - false, |
|
158 | - $details['capability'], |
|
159 | - $details['cap_context'], |
|
160 | - $details['dismissed'] |
|
161 | - ), |
|
162 | - sanitize_key($name) |
|
163 | - ); |
|
164 | - } else { |
|
165 | - try { |
|
166 | - // old nag notices, that we want to convert to the new format |
|
167 | - $this->notice_collection->add( |
|
168 | - new PersistentAdminNotice( |
|
169 | - $name, |
|
170 | - (string) $details, |
|
171 | - false, |
|
172 | - '', |
|
173 | - '', |
|
174 | - empty($details) |
|
175 | - ), |
|
176 | - sanitize_key($name) |
|
177 | - ); |
|
178 | - } catch (Exception $e) { |
|
179 | - EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
180 | - } |
|
181 | - } |
|
182 | - // each notice will self register when the action hook in registerNotices is triggered |
|
183 | - } |
|
184 | - } |
|
185 | - } |
|
186 | - |
|
187 | - |
|
188 | - /** |
|
189 | - * exposes the Persistent Admin Notice Collection via an action |
|
190 | - * so that PersistentAdminNotice objects can be added and/or removed |
|
191 | - * without compromising the actual collection like a filter would |
|
192 | - */ |
|
193 | - protected function registerNotices() |
|
194 | - { |
|
195 | - do_action( |
|
196 | - 'AHEE__EventEspresso_core_services_notifications_PersistentAdminNoticeManager__registerNotices', |
|
197 | - $this->notice_collection |
|
198 | - ); |
|
199 | - } |
|
200 | - |
|
201 | - |
|
202 | - /** |
|
203 | - * @throws DomainException |
|
204 | - * @throws InvalidClassException |
|
205 | - * @throws InvalidDataTypeException |
|
206 | - * @throws InvalidInterfaceException |
|
207 | - * @throws InvalidEntityException |
|
208 | - * @throws DuplicateCollectionIdentifierException |
|
209 | - */ |
|
210 | - public function displayNotices() |
|
211 | - { |
|
212 | - $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
213 | - if ($this->notice_collection->hasObjects()) { |
|
214 | - $enqueue_assets = false; |
|
215 | - // and display notices |
|
216 | - foreach ($this->notice_collection as $persistent_admin_notice) { |
|
217 | - /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
218 | - // don't display notices that have already been dismissed |
|
219 | - if ($persistent_admin_notice->getDismissed()) { |
|
220 | - continue; |
|
221 | - } |
|
222 | - try { |
|
223 | - $this->capabilities_checker->processCapCheck( |
|
224 | - $persistent_admin_notice->getCapCheck() |
|
225 | - ); |
|
226 | - } catch (InsufficientPermissionsException $e) { |
|
227 | - // user does not have required cap, so skip to next notice |
|
228 | - // and just eat the exception - nom nom nom nom |
|
229 | - continue; |
|
230 | - } |
|
231 | - if ($persistent_admin_notice->getMessage() === '') { |
|
232 | - continue; |
|
233 | - } |
|
234 | - $this->displayPersistentAdminNotice($persistent_admin_notice); |
|
235 | - $enqueue_assets = true; |
|
236 | - } |
|
237 | - if ($enqueue_assets) { |
|
238 | - $this->enqueueAssets(); |
|
239 | - } |
|
240 | - } |
|
241 | - } |
|
242 | - |
|
243 | - |
|
244 | - /** |
|
245 | - * does what it's named |
|
246 | - * |
|
247 | - * @return void |
|
248 | - */ |
|
249 | - public function enqueueAssets() |
|
250 | - { |
|
251 | - wp_register_script( |
|
252 | - 'espresso_core', |
|
253 | - EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js', |
|
254 | - array('jquery'), |
|
255 | - EVENT_ESPRESSO_VERSION, |
|
256 | - true |
|
257 | - ); |
|
258 | - wp_register_script( |
|
259 | - 'ee_error_js', |
|
260 | - EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js', |
|
261 | - array('espresso_core'), |
|
262 | - EVENT_ESPRESSO_VERSION, |
|
263 | - true |
|
264 | - ); |
|
265 | - wp_localize_script( |
|
266 | - 'ee_error_js', |
|
267 | - 'ee_dismiss', |
|
268 | - array( |
|
269 | - 'return_url' => urlencode($this->return_url), |
|
270 | - 'ajax_url' => WP_AJAX_URL, |
|
271 | - 'unknown_error' => wp_strip_all_tags( |
|
272 | - __( |
|
273 | - 'An unknown error has occurred on the server while attempting to dismiss this notice.', |
|
274 | - 'event_espresso' |
|
275 | - ) |
|
276 | - ), |
|
277 | - ) |
|
278 | - ); |
|
279 | - wp_enqueue_script('ee_error_js'); |
|
280 | - } |
|
281 | - |
|
282 | - |
|
283 | - /** |
|
284 | - * displayPersistentAdminNoticeHtml |
|
285 | - * |
|
286 | - * @param PersistentAdminNotice $persistent_admin_notice |
|
287 | - */ |
|
288 | - protected function displayPersistentAdminNotice($persistent_admin_notice) |
|
289 | - { |
|
290 | - // used in template |
|
291 | - $persistent_admin_notice_name = $persistent_admin_notice->getName(); |
|
292 | - $persistent_admin_notice_message = $persistent_admin_notice->getMessage(); |
|
293 | - require EE_TEMPLATES . '/notifications/persistent_admin_notice.template.php'; |
|
294 | - } |
|
295 | - |
|
296 | - |
|
297 | - /** |
|
298 | - * dismissNotice |
|
299 | - * |
|
300 | - * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed |
|
301 | - * @param bool $purge if true, then delete it from the db |
|
302 | - * @param bool $return forget all of this AJAX or redirect nonsense, and just return |
|
303 | - * @return void |
|
304 | - * @throws InvalidEntityException |
|
305 | - * @throws InvalidInterfaceException |
|
306 | - * @throws InvalidDataTypeException |
|
307 | - * @throws DomainException |
|
308 | - * @throws InvalidArgumentException |
|
309 | - * @throws InvalidArgumentException |
|
310 | - * @throws InvalidArgumentException |
|
311 | - * @throws InvalidArgumentException |
|
312 | - * @throws DuplicateCollectionIdentifierException |
|
313 | - */ |
|
314 | - public function dismissNotice($pan_name = '', $purge = false, $return = false) |
|
315 | - { |
|
316 | - $pan_name = $this->request->getRequestParam('ee_nag_notice', $pan_name); |
|
317 | - $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
318 | - if (! empty($pan_name) && $this->notice_collection->has($pan_name)) { |
|
319 | - /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
320 | - $persistent_admin_notice = $this->notice_collection->get($pan_name); |
|
321 | - $persistent_admin_notice->setDismissed(true); |
|
322 | - $persistent_admin_notice->setPurge($purge); |
|
323 | - $this->saveNotices(); |
|
324 | - } |
|
325 | - if ($return) { |
|
326 | - return; |
|
327 | - } |
|
328 | - if ($this->request->isAjax()) { |
|
329 | - // grab any notices and concatenate into string |
|
330 | - echo wp_json_encode( |
|
331 | - array( |
|
332 | - 'errors' => implode('<br />', EE_Error::get_notices(false)), |
|
333 | - ) |
|
334 | - ); |
|
335 | - exit(); |
|
336 | - } |
|
337 | - // save errors to a transient to be displayed on next request (after redirect) |
|
338 | - EE_Error::get_notices(false, true); |
|
339 | - wp_safe_redirect( |
|
340 | - urldecode( |
|
341 | - $this->request->getRequestParam('return_url', '') |
|
342 | - ) |
|
343 | - ); |
|
344 | - } |
|
345 | - |
|
346 | - |
|
347 | - /** |
|
348 | - * saveNotices |
|
349 | - * |
|
350 | - * @throws DomainException |
|
351 | - * @throws InvalidDataTypeException |
|
352 | - * @throws InvalidInterfaceException |
|
353 | - * @throws InvalidEntityException |
|
354 | - * @throws DuplicateCollectionIdentifierException |
|
355 | - */ |
|
356 | - public function saveNotices() |
|
357 | - { |
|
358 | - $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
359 | - if ($this->notice_collection->hasObjects()) { |
|
360 | - $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array()); |
|
361 | - // maybe initialize persistent_admin_notices |
|
362 | - if (empty($persistent_admin_notices)) { |
|
363 | - add_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array(), '', 'no'); |
|
364 | - } |
|
365 | - foreach ($this->notice_collection as $persistent_admin_notice) { |
|
366 | - // are we deleting this notice ? |
|
367 | - if ($persistent_admin_notice->getPurge()) { |
|
368 | - unset($persistent_admin_notices[ $persistent_admin_notice->getName() ]); |
|
369 | - } else { |
|
370 | - /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
371 | - $persistent_admin_notices[ $persistent_admin_notice->getName() ] = array( |
|
372 | - 'message' => $persistent_admin_notice->getMessage(), |
|
373 | - 'capability' => $persistent_admin_notice->getCapability(), |
|
374 | - 'cap_context' => $persistent_admin_notice->getCapContext(), |
|
375 | - 'dismissed' => $persistent_admin_notice->getDismissed(), |
|
376 | - ); |
|
377 | - } |
|
378 | - } |
|
379 | - update_option(PersistentAdminNoticeManager::WP_OPTION_KEY, $persistent_admin_notices); |
|
380 | - } |
|
381 | - } |
|
382 | - |
|
383 | - |
|
384 | - /** |
|
385 | - * @throws DomainException |
|
386 | - * @throws InvalidDataTypeException |
|
387 | - * @throws InvalidEntityException |
|
388 | - * @throws InvalidInterfaceException |
|
389 | - * @throws DuplicateCollectionIdentifierException |
|
390 | - */ |
|
391 | - public function registerAndSaveNotices() |
|
392 | - { |
|
393 | - $this->getPersistentAdminNoticeCollection(); |
|
394 | - $this->registerNotices(); |
|
395 | - $this->saveNotices(); |
|
396 | - add_filter( |
|
397 | - 'PersistentAdminNoticeManager__registerAndSaveNotices__complete', |
|
398 | - '__return_true' |
|
399 | - ); |
|
400 | - } |
|
401 | - |
|
402 | - |
|
403 | - /** |
|
404 | - * @throws DomainException |
|
405 | - * @throws InvalidDataTypeException |
|
406 | - * @throws InvalidEntityException |
|
407 | - * @throws InvalidInterfaceException |
|
408 | - * @throws InvalidArgumentException |
|
409 | - * @throws DuplicateCollectionIdentifierException |
|
410 | - */ |
|
411 | - public static function loadRegisterAndSaveNotices() |
|
412 | - { |
|
413 | - /** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */ |
|
414 | - $persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared( |
|
415 | - 'EventEspresso\core\services\notifications\PersistentAdminNoticeManager' |
|
416 | - ); |
|
417 | - // if shutdown has already run, then call registerAndSaveNotices() manually |
|
418 | - if (did_action('shutdown')) { |
|
419 | - $persistent_admin_notice_manager->registerAndSaveNotices(); |
|
420 | - } |
|
421 | - } |
|
33 | + const WP_OPTION_KEY = 'ee_pers_admin_notices'; |
|
34 | + |
|
35 | + /** |
|
36 | + * @var Collection|PersistentAdminNotice[] $notice_collection |
|
37 | + */ |
|
38 | + private $notice_collection; |
|
39 | + |
|
40 | + /** |
|
41 | + * if AJAX is not enabled, then the return URL will be used for redirecting back to the admin page where the |
|
42 | + * persistent admin notice was displayed, and ultimately dismissed from. |
|
43 | + * |
|
44 | + * @var string $return_url |
|
45 | + */ |
|
46 | + private $return_url; |
|
47 | + |
|
48 | + /** |
|
49 | + * @var CapabilitiesChecker $capabilities_checker |
|
50 | + */ |
|
51 | + private $capabilities_checker; |
|
52 | + |
|
53 | + /** |
|
54 | + * @var RequestInterface $request |
|
55 | + */ |
|
56 | + private $request; |
|
57 | + |
|
58 | + |
|
59 | + /** |
|
60 | + * PersistentAdminNoticeManager constructor |
|
61 | + * |
|
62 | + * @param CapabilitiesChecker $capabilities_checker |
|
63 | + * @param RequestInterface $request |
|
64 | + * @param string $return_url where to redirect to after dismissing notices |
|
65 | + * @throws InvalidDataTypeException |
|
66 | + */ |
|
67 | + public function __construct( |
|
68 | + CapabilitiesChecker $capabilities_checker, |
|
69 | + RequestInterface $request, |
|
70 | + $return_url = '' |
|
71 | + ) { |
|
72 | + $return_url = (string) $return_url; |
|
73 | + $this->setReturnUrl($return_url); |
|
74 | + $this->capabilities_checker = $capabilities_checker; |
|
75 | + $this->request = $request; |
|
76 | + // setup up notices at priority 9 because `EE_Admin::display_admin_notices()` runs at priority 10, |
|
77 | + // and we want to retrieve and generate any nag notices at the last possible moment |
|
78 | + add_action('admin_notices', array($this, 'displayNotices'), 9); |
|
79 | + add_action('network_admin_notices', array($this, 'displayNotices'), 9); |
|
80 | + add_action('wp_ajax_dismiss_ee_nag_notice', array($this, 'dismissNotice')); |
|
81 | + add_action('shutdown', array($this, 'registerAndSaveNotices'), 998); |
|
82 | + } |
|
83 | + |
|
84 | + |
|
85 | + /** |
|
86 | + * @param string $return_url |
|
87 | + * @throws InvalidDataTypeException |
|
88 | + */ |
|
89 | + public function setReturnUrl($return_url) |
|
90 | + { |
|
91 | + if (! is_string($return_url)) { |
|
92 | + throw new InvalidDataTypeException('$return_url', $return_url, 'string'); |
|
93 | + } |
|
94 | + $this->return_url = $return_url; |
|
95 | + } |
|
96 | + |
|
97 | + |
|
98 | + /** |
|
99 | + * @return Collection |
|
100 | + * @throws InvalidEntityException |
|
101 | + * @throws InvalidInterfaceException |
|
102 | + * @throws InvalidDataTypeException |
|
103 | + * @throws DomainException |
|
104 | + * @throws DuplicateCollectionIdentifierException |
|
105 | + */ |
|
106 | + protected function getPersistentAdminNoticeCollection() |
|
107 | + { |
|
108 | + if (! $this->notice_collection instanceof Collection) { |
|
109 | + $this->notice_collection = new Collection( |
|
110 | + 'EventEspresso\core\domain\entities\notifications\PersistentAdminNotice' |
|
111 | + ); |
|
112 | + $this->retrieveStoredNotices(); |
|
113 | + $this->registerNotices(); |
|
114 | + } |
|
115 | + return $this->notice_collection; |
|
116 | + } |
|
117 | + |
|
118 | + |
|
119 | + /** |
|
120 | + * generates PersistentAdminNotice objects for all non-dismissed notices saved to the db |
|
121 | + * |
|
122 | + * @return void |
|
123 | + * @throws InvalidEntityException |
|
124 | + * @throws DomainException |
|
125 | + * @throws InvalidDataTypeException |
|
126 | + * @throws DuplicateCollectionIdentifierException |
|
127 | + */ |
|
128 | + protected function retrieveStoredNotices() |
|
129 | + { |
|
130 | + $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array()); |
|
131 | + if (! empty($persistent_admin_notices)) { |
|
132 | + foreach ($persistent_admin_notices as $name => $details) { |
|
133 | + if (is_array($details)) { |
|
134 | + if ( |
|
135 | + ! isset( |
|
136 | + $details['message'], |
|
137 | + $details['capability'], |
|
138 | + $details['cap_context'], |
|
139 | + $details['dismissed'] |
|
140 | + ) |
|
141 | + ) { |
|
142 | + throw new DomainException( |
|
143 | + sprintf( |
|
144 | + esc_html__( |
|
145 | + 'The "%1$s" PersistentAdminNotice could not be retrieved from the database.', |
|
146 | + 'event_espresso' |
|
147 | + ), |
|
148 | + $name |
|
149 | + ) |
|
150 | + ); |
|
151 | + } |
|
152 | + // new format for nag notices |
|
153 | + $this->notice_collection->add( |
|
154 | + new PersistentAdminNotice( |
|
155 | + $name, |
|
156 | + $details['message'], |
|
157 | + false, |
|
158 | + $details['capability'], |
|
159 | + $details['cap_context'], |
|
160 | + $details['dismissed'] |
|
161 | + ), |
|
162 | + sanitize_key($name) |
|
163 | + ); |
|
164 | + } else { |
|
165 | + try { |
|
166 | + // old nag notices, that we want to convert to the new format |
|
167 | + $this->notice_collection->add( |
|
168 | + new PersistentAdminNotice( |
|
169 | + $name, |
|
170 | + (string) $details, |
|
171 | + false, |
|
172 | + '', |
|
173 | + '', |
|
174 | + empty($details) |
|
175 | + ), |
|
176 | + sanitize_key($name) |
|
177 | + ); |
|
178 | + } catch (Exception $e) { |
|
179 | + EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
180 | + } |
|
181 | + } |
|
182 | + // each notice will self register when the action hook in registerNotices is triggered |
|
183 | + } |
|
184 | + } |
|
185 | + } |
|
186 | + |
|
187 | + |
|
188 | + /** |
|
189 | + * exposes the Persistent Admin Notice Collection via an action |
|
190 | + * so that PersistentAdminNotice objects can be added and/or removed |
|
191 | + * without compromising the actual collection like a filter would |
|
192 | + */ |
|
193 | + protected function registerNotices() |
|
194 | + { |
|
195 | + do_action( |
|
196 | + 'AHEE__EventEspresso_core_services_notifications_PersistentAdminNoticeManager__registerNotices', |
|
197 | + $this->notice_collection |
|
198 | + ); |
|
199 | + } |
|
200 | + |
|
201 | + |
|
202 | + /** |
|
203 | + * @throws DomainException |
|
204 | + * @throws InvalidClassException |
|
205 | + * @throws InvalidDataTypeException |
|
206 | + * @throws InvalidInterfaceException |
|
207 | + * @throws InvalidEntityException |
|
208 | + * @throws DuplicateCollectionIdentifierException |
|
209 | + */ |
|
210 | + public function displayNotices() |
|
211 | + { |
|
212 | + $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
213 | + if ($this->notice_collection->hasObjects()) { |
|
214 | + $enqueue_assets = false; |
|
215 | + // and display notices |
|
216 | + foreach ($this->notice_collection as $persistent_admin_notice) { |
|
217 | + /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
218 | + // don't display notices that have already been dismissed |
|
219 | + if ($persistent_admin_notice->getDismissed()) { |
|
220 | + continue; |
|
221 | + } |
|
222 | + try { |
|
223 | + $this->capabilities_checker->processCapCheck( |
|
224 | + $persistent_admin_notice->getCapCheck() |
|
225 | + ); |
|
226 | + } catch (InsufficientPermissionsException $e) { |
|
227 | + // user does not have required cap, so skip to next notice |
|
228 | + // and just eat the exception - nom nom nom nom |
|
229 | + continue; |
|
230 | + } |
|
231 | + if ($persistent_admin_notice->getMessage() === '') { |
|
232 | + continue; |
|
233 | + } |
|
234 | + $this->displayPersistentAdminNotice($persistent_admin_notice); |
|
235 | + $enqueue_assets = true; |
|
236 | + } |
|
237 | + if ($enqueue_assets) { |
|
238 | + $this->enqueueAssets(); |
|
239 | + } |
|
240 | + } |
|
241 | + } |
|
242 | + |
|
243 | + |
|
244 | + /** |
|
245 | + * does what it's named |
|
246 | + * |
|
247 | + * @return void |
|
248 | + */ |
|
249 | + public function enqueueAssets() |
|
250 | + { |
|
251 | + wp_register_script( |
|
252 | + 'espresso_core', |
|
253 | + EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js', |
|
254 | + array('jquery'), |
|
255 | + EVENT_ESPRESSO_VERSION, |
|
256 | + true |
|
257 | + ); |
|
258 | + wp_register_script( |
|
259 | + 'ee_error_js', |
|
260 | + EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js', |
|
261 | + array('espresso_core'), |
|
262 | + EVENT_ESPRESSO_VERSION, |
|
263 | + true |
|
264 | + ); |
|
265 | + wp_localize_script( |
|
266 | + 'ee_error_js', |
|
267 | + 'ee_dismiss', |
|
268 | + array( |
|
269 | + 'return_url' => urlencode($this->return_url), |
|
270 | + 'ajax_url' => WP_AJAX_URL, |
|
271 | + 'unknown_error' => wp_strip_all_tags( |
|
272 | + __( |
|
273 | + 'An unknown error has occurred on the server while attempting to dismiss this notice.', |
|
274 | + 'event_espresso' |
|
275 | + ) |
|
276 | + ), |
|
277 | + ) |
|
278 | + ); |
|
279 | + wp_enqueue_script('ee_error_js'); |
|
280 | + } |
|
281 | + |
|
282 | + |
|
283 | + /** |
|
284 | + * displayPersistentAdminNoticeHtml |
|
285 | + * |
|
286 | + * @param PersistentAdminNotice $persistent_admin_notice |
|
287 | + */ |
|
288 | + protected function displayPersistentAdminNotice($persistent_admin_notice) |
|
289 | + { |
|
290 | + // used in template |
|
291 | + $persistent_admin_notice_name = $persistent_admin_notice->getName(); |
|
292 | + $persistent_admin_notice_message = $persistent_admin_notice->getMessage(); |
|
293 | + require EE_TEMPLATES . '/notifications/persistent_admin_notice.template.php'; |
|
294 | + } |
|
295 | + |
|
296 | + |
|
297 | + /** |
|
298 | + * dismissNotice |
|
299 | + * |
|
300 | + * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed |
|
301 | + * @param bool $purge if true, then delete it from the db |
|
302 | + * @param bool $return forget all of this AJAX or redirect nonsense, and just return |
|
303 | + * @return void |
|
304 | + * @throws InvalidEntityException |
|
305 | + * @throws InvalidInterfaceException |
|
306 | + * @throws InvalidDataTypeException |
|
307 | + * @throws DomainException |
|
308 | + * @throws InvalidArgumentException |
|
309 | + * @throws InvalidArgumentException |
|
310 | + * @throws InvalidArgumentException |
|
311 | + * @throws InvalidArgumentException |
|
312 | + * @throws DuplicateCollectionIdentifierException |
|
313 | + */ |
|
314 | + public function dismissNotice($pan_name = '', $purge = false, $return = false) |
|
315 | + { |
|
316 | + $pan_name = $this->request->getRequestParam('ee_nag_notice', $pan_name); |
|
317 | + $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
318 | + if (! empty($pan_name) && $this->notice_collection->has($pan_name)) { |
|
319 | + /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
320 | + $persistent_admin_notice = $this->notice_collection->get($pan_name); |
|
321 | + $persistent_admin_notice->setDismissed(true); |
|
322 | + $persistent_admin_notice->setPurge($purge); |
|
323 | + $this->saveNotices(); |
|
324 | + } |
|
325 | + if ($return) { |
|
326 | + return; |
|
327 | + } |
|
328 | + if ($this->request->isAjax()) { |
|
329 | + // grab any notices and concatenate into string |
|
330 | + echo wp_json_encode( |
|
331 | + array( |
|
332 | + 'errors' => implode('<br />', EE_Error::get_notices(false)), |
|
333 | + ) |
|
334 | + ); |
|
335 | + exit(); |
|
336 | + } |
|
337 | + // save errors to a transient to be displayed on next request (after redirect) |
|
338 | + EE_Error::get_notices(false, true); |
|
339 | + wp_safe_redirect( |
|
340 | + urldecode( |
|
341 | + $this->request->getRequestParam('return_url', '') |
|
342 | + ) |
|
343 | + ); |
|
344 | + } |
|
345 | + |
|
346 | + |
|
347 | + /** |
|
348 | + * saveNotices |
|
349 | + * |
|
350 | + * @throws DomainException |
|
351 | + * @throws InvalidDataTypeException |
|
352 | + * @throws InvalidInterfaceException |
|
353 | + * @throws InvalidEntityException |
|
354 | + * @throws DuplicateCollectionIdentifierException |
|
355 | + */ |
|
356 | + public function saveNotices() |
|
357 | + { |
|
358 | + $this->notice_collection = $this->getPersistentAdminNoticeCollection(); |
|
359 | + if ($this->notice_collection->hasObjects()) { |
|
360 | + $persistent_admin_notices = get_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array()); |
|
361 | + // maybe initialize persistent_admin_notices |
|
362 | + if (empty($persistent_admin_notices)) { |
|
363 | + add_option(PersistentAdminNoticeManager::WP_OPTION_KEY, array(), '', 'no'); |
|
364 | + } |
|
365 | + foreach ($this->notice_collection as $persistent_admin_notice) { |
|
366 | + // are we deleting this notice ? |
|
367 | + if ($persistent_admin_notice->getPurge()) { |
|
368 | + unset($persistent_admin_notices[ $persistent_admin_notice->getName() ]); |
|
369 | + } else { |
|
370 | + /** @var PersistentAdminNotice $persistent_admin_notice */ |
|
371 | + $persistent_admin_notices[ $persistent_admin_notice->getName() ] = array( |
|
372 | + 'message' => $persistent_admin_notice->getMessage(), |
|
373 | + 'capability' => $persistent_admin_notice->getCapability(), |
|
374 | + 'cap_context' => $persistent_admin_notice->getCapContext(), |
|
375 | + 'dismissed' => $persistent_admin_notice->getDismissed(), |
|
376 | + ); |
|
377 | + } |
|
378 | + } |
|
379 | + update_option(PersistentAdminNoticeManager::WP_OPTION_KEY, $persistent_admin_notices); |
|
380 | + } |
|
381 | + } |
|
382 | + |
|
383 | + |
|
384 | + /** |
|
385 | + * @throws DomainException |
|
386 | + * @throws InvalidDataTypeException |
|
387 | + * @throws InvalidEntityException |
|
388 | + * @throws InvalidInterfaceException |
|
389 | + * @throws DuplicateCollectionIdentifierException |
|
390 | + */ |
|
391 | + public function registerAndSaveNotices() |
|
392 | + { |
|
393 | + $this->getPersistentAdminNoticeCollection(); |
|
394 | + $this->registerNotices(); |
|
395 | + $this->saveNotices(); |
|
396 | + add_filter( |
|
397 | + 'PersistentAdminNoticeManager__registerAndSaveNotices__complete', |
|
398 | + '__return_true' |
|
399 | + ); |
|
400 | + } |
|
401 | + |
|
402 | + |
|
403 | + /** |
|
404 | + * @throws DomainException |
|
405 | + * @throws InvalidDataTypeException |
|
406 | + * @throws InvalidEntityException |
|
407 | + * @throws InvalidInterfaceException |
|
408 | + * @throws InvalidArgumentException |
|
409 | + * @throws DuplicateCollectionIdentifierException |
|
410 | + */ |
|
411 | + public static function loadRegisterAndSaveNotices() |
|
412 | + { |
|
413 | + /** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */ |
|
414 | + $persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared( |
|
415 | + 'EventEspresso\core\services\notifications\PersistentAdminNoticeManager' |
|
416 | + ); |
|
417 | + // if shutdown has already run, then call registerAndSaveNotices() manually |
|
418 | + if (did_action('shutdown')) { |
|
419 | + $persistent_admin_notice_manager->registerAndSaveNotices(); |
|
420 | + } |
|
421 | + } |
|
422 | 422 | } |
@@ -57,7 +57,7 @@ discard block |
||
57 | 57 | // round current time down to closest 5 minutes to simplify scheduling |
58 | 58 | $this->current_time = $this->roundTimestamp(time(), '5-minutes', false); |
59 | 59 | $this->transients = (array) get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array()); |
60 | - if (! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') { |
|
60 | + if ( ! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') { |
|
61 | 61 | add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999); |
62 | 62 | } |
63 | 63 | } |
@@ -190,7 +190,7 @@ discard block |
||
190 | 190 | */ |
191 | 191 | public function get($transient_key, $standard_cache = true) |
192 | 192 | { |
193 | - if (isset($this->transients[ $transient_key ])) { |
|
193 | + if (isset($this->transients[$transient_key])) { |
|
194 | 194 | // to avoid cache stampedes (AKA:dogpiles) for standard cache items, |
195 | 195 | // check if known cache expires within the next minute, |
196 | 196 | // and if so, remove it from our tracking and and return nothing. |
@@ -199,17 +199,17 @@ discard block |
||
199 | 199 | // until it gets replaced with the refreshed content |
200 | 200 | if ( |
201 | 201 | $standard_cache |
202 | - && $this->transients[ $transient_key ] - time() <= MINUTE_IN_SECONDS |
|
202 | + && $this->transients[$transient_key] - time() <= MINUTE_IN_SECONDS |
|
203 | 203 | ) { |
204 | - unset($this->transients[ $transient_key ]); |
|
204 | + unset($this->transients[$transient_key]); |
|
205 | 205 | $this->updateTransients(); |
206 | 206 | return null; |
207 | 207 | } |
208 | 208 | |
209 | 209 | // for non standard cache items, remove the key from our tracking, |
210 | 210 | // but proceed to retrieve the transient so that it also gets removed from the db |
211 | - if ($this->transients[ $transient_key ] <= time()) { |
|
212 | - unset($this->transients[ $transient_key ]); |
|
211 | + if ($this->transients[$transient_key] <= time()) { |
|
212 | + unset($this->transients[$transient_key]); |
|
213 | 213 | $this->updateTransients(); |
214 | 214 | } |
215 | 215 | } |
@@ -282,7 +282,7 @@ discard block |
||
282 | 282 | // and round to the closest 15 minutes |
283 | 283 | $expiration = $this->roundTimestamp($expiration); |
284 | 284 | // save transients to clear using their ID as the key to avoid duplicates |
285 | - $this->transients[ $transient_key ] = $expiration; |
|
285 | + $this->transients[$transient_key] = $expiration; |
|
286 | 286 | $this->updateTransients(); |
287 | 287 | } |
288 | 288 | |
@@ -334,8 +334,8 @@ discard block |
||
334 | 334 | if ($expiration > $this->current_time) { |
335 | 335 | continue; |
336 | 336 | } |
337 | - if (! $expiration || ! $transient_key) { |
|
338 | - unset($this->transients[ $transient_key ]); |
|
337 | + if ( ! $expiration || ! $transient_key) { |
|
338 | + unset($this->transients[$transient_key]); |
|
339 | 339 | $update = true; |
340 | 340 | continue; |
341 | 341 | } |
@@ -374,7 +374,7 @@ discard block |
||
374 | 374 | ? str_replace('_transient_', '', $transient_key) |
375 | 375 | : $transient_key; |
376 | 376 | delete_transient($transient_key); |
377 | - unset($this->transients[ $transient_key ]); |
|
377 | + unset($this->transients[$transient_key]); |
|
378 | 378 | $counter++; |
379 | 379 | } |
380 | 380 | return $counter > 0; |
@@ -15,367 +15,367 @@ |
||
15 | 15 | */ |
16 | 16 | class TransientCacheStorage implements CacheStorageInterface |
17 | 17 | { |
18 | - /** |
|
19 | - * wp-option option_name for tracking transients |
|
20 | - * |
|
21 | - * @type string |
|
22 | - */ |
|
23 | - const TRANSIENT_SCHEDULE_OPTIONS_KEY = 'ee_transient_schedule'; |
|
24 | - |
|
25 | - /** |
|
26 | - * @var int $current_time |
|
27 | - */ |
|
28 | - private $current_time; |
|
29 | - |
|
30 | - /** |
|
31 | - * how often to perform transient cleanup |
|
32 | - * |
|
33 | - * @var string $transient_cleanup_frequency |
|
34 | - */ |
|
35 | - private $transient_cleanup_frequency; |
|
36 | - |
|
37 | - /** |
|
38 | - * options for how often to perform transient cleanup |
|
39 | - * |
|
40 | - * @var array $transient_cleanup_frequency_options |
|
41 | - */ |
|
42 | - private $transient_cleanup_frequency_options = array(); |
|
43 | - |
|
44 | - /** |
|
45 | - * @var array $transients |
|
46 | - */ |
|
47 | - private $transients; |
|
48 | - |
|
49 | - |
|
50 | - /** |
|
51 | - * TransientCacheStorage constructor. |
|
52 | - */ |
|
53 | - public function __construct() |
|
54 | - { |
|
55 | - $this->transient_cleanup_frequency = $this->setTransientCleanupFrequency(); |
|
56 | - // round current time down to closest 5 minutes to simplify scheduling |
|
57 | - $this->current_time = $this->roundTimestamp(time(), '5-minutes', false); |
|
58 | - $this->transients = (array) get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array()); |
|
59 | - if (! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') { |
|
60 | - add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999); |
|
61 | - } |
|
62 | - } |
|
63 | - |
|
64 | - |
|
65 | - /** |
|
66 | - * Sets how often transient cleanup occurs |
|
67 | - * |
|
68 | - * @return string |
|
69 | - */ |
|
70 | - private function setTransientCleanupFrequency() |
|
71 | - { |
|
72 | - // sets how often transients are cleaned up |
|
73 | - $this->transient_cleanup_frequency_options = apply_filters( |
|
74 | - 'FHEE__TransientCacheStorage__transient_cleanup_schedule_options', |
|
75 | - array( |
|
76 | - 'off', |
|
77 | - '15-minutes', |
|
78 | - 'hour', |
|
79 | - '12-hours', |
|
80 | - 'day', |
|
81 | - ) |
|
82 | - ); |
|
83 | - $transient_cleanup_frequency = apply_filters( |
|
84 | - 'FHEE__TransientCacheStorage__transient_cleanup_schedule', |
|
85 | - 'hour' |
|
86 | - ); |
|
87 | - return in_array( |
|
88 | - $transient_cleanup_frequency, |
|
89 | - $this->transient_cleanup_frequency_options, |
|
90 | - true |
|
91 | - ) |
|
92 | - ? $transient_cleanup_frequency |
|
93 | - : 'hour'; |
|
94 | - } |
|
95 | - |
|
96 | - |
|
97 | - /** |
|
98 | - * we need to be able to round timestamps off to match the set transient cleanup frequency |
|
99 | - * so if a transient is set to expire at 1:17 pm for example, and our cleanup schedule is every hour, |
|
100 | - * then that timestamp needs to be rounded up to 2:00 pm so that it is removed |
|
101 | - * during the next scheduled cleanup after its expiration. |
|
102 | - * We also round off the current time timestamp to the closest 5 minutes |
|
103 | - * just to make the timestamps a little easier to round which helps with debugging. |
|
104 | - * |
|
105 | - * @param int $timestamp [required] |
|
106 | - * @param string $cleanup_frequency |
|
107 | - * @param bool $round_up |
|
108 | - * @return int |
|
109 | - */ |
|
110 | - private function roundTimestamp($timestamp, $cleanup_frequency = 'hour', $round_up = true) |
|
111 | - { |
|
112 | - $cleanup_frequency = $cleanup_frequency ? $cleanup_frequency : $this->transient_cleanup_frequency; |
|
113 | - // in order to round the time to the closest xx minutes (or hours), |
|
114 | - // we take the minutes (or hours) portion of the timestamp and divide it by xx, |
|
115 | - // round down to a whole number, then multiply by xx to bring us almost back up to where we were |
|
116 | - // why round down ? so the minutes (or hours) don't go over 60 (or 24) |
|
117 | - // and bump the hour, which could bump the day, which could bump the month, etc, |
|
118 | - // which would be bad because we don't always want to round up, |
|
119 | - // but when we do we can easily achieve that by simply adding the desired offset, |
|
120 | - $minutes = '00'; |
|
121 | - $hours = 'H'; |
|
122 | - switch ($cleanup_frequency) { |
|
123 | - case '5-minutes': |
|
124 | - $minutes = floor((int) date('i', $timestamp) / 5) * 5; |
|
125 | - $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT); |
|
126 | - $offset = MINUTE_IN_SECONDS * 5; |
|
127 | - break; |
|
128 | - case '15-minutes': |
|
129 | - $minutes = floor((int) date('i', $timestamp) / 15) * 15; |
|
130 | - $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT); |
|
131 | - $offset = MINUTE_IN_SECONDS * 15; |
|
132 | - break; |
|
133 | - case '12-hours': |
|
134 | - $hours = floor((int) date('H', $timestamp) / 12) * 12; |
|
135 | - $hours = str_pad($hours, 2, '0', STR_PAD_LEFT); |
|
136 | - $offset = HOUR_IN_SECONDS * 12; |
|
137 | - break; |
|
138 | - case 'day': |
|
139 | - $hours = '03'; // run cleanup at 3:00 am (or first site hit after that) |
|
140 | - $offset = DAY_IN_SECONDS; |
|
141 | - break; |
|
142 | - case 'hour': |
|
143 | - default: |
|
144 | - $offset = HOUR_IN_SECONDS; |
|
145 | - break; |
|
146 | - } |
|
147 | - $rounded_timestamp = (int) strtotime(date("Y-m-d {$hours}:{$minutes}:00", $timestamp)); |
|
148 | - $rounded_timestamp += $round_up ? $offset : 0; |
|
149 | - return apply_filters( |
|
150 | - 'FHEE__TransientCacheStorage__roundTimestamp__timestamp', |
|
151 | - $rounded_timestamp, |
|
152 | - $timestamp, |
|
153 | - $cleanup_frequency, |
|
154 | - $round_up |
|
155 | - ); |
|
156 | - } |
|
157 | - |
|
158 | - |
|
159 | - /** |
|
160 | - * Saves supplied data to a transient |
|
161 | - * if an expiration is set, then it automatically schedules the transient for cleanup |
|
162 | - * |
|
163 | - * @param string $transient_key [required] |
|
164 | - * @param string $data [required] |
|
165 | - * @param int $expiration number of seconds until the cache expires |
|
166 | - * @return bool |
|
167 | - */ |
|
168 | - public function add($transient_key, $data, $expiration = 0) |
|
169 | - { |
|
170 | - $expiration = (int) abs($expiration); |
|
171 | - $saved = set_transient($transient_key, $data, $expiration); |
|
172 | - if ($saved && $expiration) { |
|
173 | - $this->scheduleTransientCleanup($transient_key, $expiration); |
|
174 | - } |
|
175 | - return $saved; |
|
176 | - } |
|
177 | - |
|
178 | - |
|
179 | - /** |
|
180 | - * retrieves transient data |
|
181 | - * automatically triggers early cache refresh for standard cache items |
|
182 | - * in order to avoid cache stampedes on busy sites. |
|
183 | - * For non-standard cache items like PHP Session data where early refreshing is not wanted, |
|
184 | - * the $standard_cache parameter should be set to false when retrieving data |
|
185 | - * |
|
186 | - * @param string $transient_key [required] |
|
187 | - * @param bool $standard_cache |
|
188 | - * @return mixed|null |
|
189 | - */ |
|
190 | - public function get($transient_key, $standard_cache = true) |
|
191 | - { |
|
192 | - if (isset($this->transients[ $transient_key ])) { |
|
193 | - // to avoid cache stampedes (AKA:dogpiles) for standard cache items, |
|
194 | - // check if known cache expires within the next minute, |
|
195 | - // and if so, remove it from our tracking and and return nothing. |
|
196 | - // this should trigger the cache content to be regenerated during this request, |
|
197 | - // while allowing any following requests to still access the existing cache |
|
198 | - // until it gets replaced with the refreshed content |
|
199 | - if ( |
|
200 | - $standard_cache |
|
201 | - && $this->transients[ $transient_key ] - time() <= MINUTE_IN_SECONDS |
|
202 | - ) { |
|
203 | - unset($this->transients[ $transient_key ]); |
|
204 | - $this->updateTransients(); |
|
205 | - return null; |
|
206 | - } |
|
207 | - |
|
208 | - // for non standard cache items, remove the key from our tracking, |
|
209 | - // but proceed to retrieve the transient so that it also gets removed from the db |
|
210 | - if ($this->transients[ $transient_key ] <= time()) { |
|
211 | - unset($this->transients[ $transient_key ]); |
|
212 | - $this->updateTransients(); |
|
213 | - } |
|
214 | - } |
|
215 | - |
|
216 | - $content = get_transient($transient_key); |
|
217 | - return $content !== false ? $content : null; |
|
218 | - } |
|
219 | - |
|
220 | - |
|
221 | - /** |
|
222 | - * delete a single transient and remove tracking |
|
223 | - * |
|
224 | - * @param string $transient_key [required] full or partial transient key to be deleted |
|
225 | - */ |
|
226 | - public function delete($transient_key) |
|
227 | - { |
|
228 | - $this->deleteMany(array($transient_key)); |
|
229 | - } |
|
230 | - |
|
231 | - |
|
232 | - /** |
|
233 | - * delete multiple transients and remove tracking |
|
234 | - * |
|
235 | - * @param array $transient_keys [required] array of full or partial transient keys to be deleted |
|
236 | - * @param bool $force_delete [optional] if true, then will not check incoming keys against those being tracked |
|
237 | - * and proceed directly to deleting those entries from the cache storage |
|
238 | - */ |
|
239 | - public function deleteMany($transient_keys, $force_delete = false) |
|
240 | - { |
|
241 | - $full_transient_keys = $force_delete ? $transient_keys : array(); |
|
242 | - if (empty($full_transient_keys)) { |
|
243 | - foreach ($this->transients as $transient_key => $expiration) { |
|
244 | - foreach ($transient_keys as $transient_key_to_delete) { |
|
245 | - if (strpos($transient_key, $transient_key_to_delete) !== false) { |
|
246 | - $full_transient_keys[] = $transient_key; |
|
247 | - } |
|
248 | - } |
|
249 | - } |
|
250 | - } |
|
251 | - if ($this->deleteTransientKeys($full_transient_keys)) { |
|
252 | - $this->updateTransients(); |
|
253 | - } |
|
254 | - } |
|
255 | - |
|
256 | - |
|
257 | - /** |
|
258 | - * sorts transients numerically by timestamp |
|
259 | - * then saves the transient schedule to a WP option |
|
260 | - */ |
|
261 | - private function updateTransients() |
|
262 | - { |
|
263 | - asort($this->transients, SORT_NUMERIC); |
|
264 | - update_option( |
|
265 | - TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, |
|
266 | - $this->transients |
|
267 | - ); |
|
268 | - } |
|
269 | - |
|
270 | - |
|
271 | - /** |
|
272 | - * schedules a transient for cleanup by adding it to the transient tracking |
|
273 | - * |
|
274 | - * @param string $transient_key [required] |
|
275 | - * @param int $expiration [required] |
|
276 | - */ |
|
277 | - private function scheduleTransientCleanup($transient_key, $expiration) |
|
278 | - { |
|
279 | - // make sure a valid future timestamp is set |
|
280 | - $expiration += $expiration < time() ? time() : 0; |
|
281 | - // and round to the closest 15 minutes |
|
282 | - $expiration = $this->roundTimestamp($expiration); |
|
283 | - // save transients to clear using their ID as the key to avoid duplicates |
|
284 | - $this->transients[ $transient_key ] = $expiration; |
|
285 | - $this->updateTransients(); |
|
286 | - } |
|
287 | - |
|
288 | - |
|
289 | - /** |
|
290 | - * Since our tracked transients are sorted by their timestamps |
|
291 | - * we can grab the first transient and see when it is scheduled for cleanup. |
|
292 | - * If that timestamp is less than or equal to the current time, |
|
293 | - * then cleanup is triggered |
|
294 | - */ |
|
295 | - public function checkTransientCleanupSchedule() |
|
296 | - { |
|
297 | - if (empty($this->transients)) { |
|
298 | - return; |
|
299 | - } |
|
300 | - // when do we run the next cleanup job? |
|
301 | - reset($this->transients); |
|
302 | - $next_scheduled_cleanup = current($this->transients); |
|
303 | - // if the next cleanup job is scheduled for the current hour |
|
304 | - if ($next_scheduled_cleanup <= $this->current_time) { |
|
305 | - if ($this->cleanupExpiredTransients()) { |
|
306 | - $this->updateTransients(); |
|
307 | - } |
|
308 | - } |
|
309 | - } |
|
310 | - |
|
311 | - |
|
312 | - /** |
|
313 | - * loops through the array of tracked transients, |
|
314 | - * compiles a list of those that have expired, and sends that list off for deletion. |
|
315 | - * Also removes any bad records from the transients array |
|
316 | - * |
|
317 | - * @return bool |
|
318 | - */ |
|
319 | - private function cleanupExpiredTransients() |
|
320 | - { |
|
321 | - $update = false; |
|
322 | - // filter the query limit. Set to 0 to turn off garbage collection |
|
323 | - $limit = (int) abs( |
|
324 | - apply_filters( |
|
325 | - 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
326 | - 50 |
|
327 | - ) |
|
328 | - ); |
|
329 | - // non-zero LIMIT means take out the trash |
|
330 | - if ($limit) { |
|
331 | - $transient_keys = array(); |
|
332 | - foreach ($this->transients as $transient_key => $expiration) { |
|
333 | - if ($expiration > $this->current_time) { |
|
334 | - continue; |
|
335 | - } |
|
336 | - if (! $expiration || ! $transient_key) { |
|
337 | - unset($this->transients[ $transient_key ]); |
|
338 | - $update = true; |
|
339 | - continue; |
|
340 | - } |
|
341 | - $transient_keys[] = $transient_key; |
|
342 | - } |
|
343 | - // delete expired keys, but maintain value of $update if nothing is deleted |
|
344 | - $update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update; |
|
345 | - do_action('FHEE__TransientCacheStorage__clearExpiredTransients__end', $this); |
|
346 | - } |
|
347 | - return $update; |
|
348 | - } |
|
349 | - |
|
350 | - |
|
351 | - /** |
|
352 | - * calls delete_transient() on each transient key provided, up to the specified limit |
|
353 | - * |
|
354 | - * @param array $transient_keys [required] |
|
355 | - * @param int $limit |
|
356 | - * @return bool |
|
357 | - */ |
|
358 | - private function deleteTransientKeys(array $transient_keys, $limit = 50) |
|
359 | - { |
|
360 | - if (empty($transient_keys)) { |
|
361 | - return false; |
|
362 | - } |
|
363 | - $counter = 0; |
|
364 | - foreach ($transient_keys as $transient_key) { |
|
365 | - if ($counter === $limit) { |
|
366 | - break; |
|
367 | - } |
|
368 | - // remove any transient prefixes |
|
369 | - $transient_key = strpos($transient_key, '_transient_timeout_') === 0 |
|
370 | - ? str_replace('_transient_timeout_', '', $transient_key) |
|
371 | - : $transient_key; |
|
372 | - $transient_key = strpos($transient_key, '_transient_') === 0 |
|
373 | - ? str_replace('_transient_', '', $transient_key) |
|
374 | - : $transient_key; |
|
375 | - delete_transient($transient_key); |
|
376 | - unset($this->transients[ $transient_key ]); |
|
377 | - $counter++; |
|
378 | - } |
|
379 | - return $counter > 0; |
|
380 | - } |
|
18 | + /** |
|
19 | + * wp-option option_name for tracking transients |
|
20 | + * |
|
21 | + * @type string |
|
22 | + */ |
|
23 | + const TRANSIENT_SCHEDULE_OPTIONS_KEY = 'ee_transient_schedule'; |
|
24 | + |
|
25 | + /** |
|
26 | + * @var int $current_time |
|
27 | + */ |
|
28 | + private $current_time; |
|
29 | + |
|
30 | + /** |
|
31 | + * how often to perform transient cleanup |
|
32 | + * |
|
33 | + * @var string $transient_cleanup_frequency |
|
34 | + */ |
|
35 | + private $transient_cleanup_frequency; |
|
36 | + |
|
37 | + /** |
|
38 | + * options for how often to perform transient cleanup |
|
39 | + * |
|
40 | + * @var array $transient_cleanup_frequency_options |
|
41 | + */ |
|
42 | + private $transient_cleanup_frequency_options = array(); |
|
43 | + |
|
44 | + /** |
|
45 | + * @var array $transients |
|
46 | + */ |
|
47 | + private $transients; |
|
48 | + |
|
49 | + |
|
50 | + /** |
|
51 | + * TransientCacheStorage constructor. |
|
52 | + */ |
|
53 | + public function __construct() |
|
54 | + { |
|
55 | + $this->transient_cleanup_frequency = $this->setTransientCleanupFrequency(); |
|
56 | + // round current time down to closest 5 minutes to simplify scheduling |
|
57 | + $this->current_time = $this->roundTimestamp(time(), '5-minutes', false); |
|
58 | + $this->transients = (array) get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array()); |
|
59 | + if (! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') { |
|
60 | + add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999); |
|
61 | + } |
|
62 | + } |
|
63 | + |
|
64 | + |
|
65 | + /** |
|
66 | + * Sets how often transient cleanup occurs |
|
67 | + * |
|
68 | + * @return string |
|
69 | + */ |
|
70 | + private function setTransientCleanupFrequency() |
|
71 | + { |
|
72 | + // sets how often transients are cleaned up |
|
73 | + $this->transient_cleanup_frequency_options = apply_filters( |
|
74 | + 'FHEE__TransientCacheStorage__transient_cleanup_schedule_options', |
|
75 | + array( |
|
76 | + 'off', |
|
77 | + '15-minutes', |
|
78 | + 'hour', |
|
79 | + '12-hours', |
|
80 | + 'day', |
|
81 | + ) |
|
82 | + ); |
|
83 | + $transient_cleanup_frequency = apply_filters( |
|
84 | + 'FHEE__TransientCacheStorage__transient_cleanup_schedule', |
|
85 | + 'hour' |
|
86 | + ); |
|
87 | + return in_array( |
|
88 | + $transient_cleanup_frequency, |
|
89 | + $this->transient_cleanup_frequency_options, |
|
90 | + true |
|
91 | + ) |
|
92 | + ? $transient_cleanup_frequency |
|
93 | + : 'hour'; |
|
94 | + } |
|
95 | + |
|
96 | + |
|
97 | + /** |
|
98 | + * we need to be able to round timestamps off to match the set transient cleanup frequency |
|
99 | + * so if a transient is set to expire at 1:17 pm for example, and our cleanup schedule is every hour, |
|
100 | + * then that timestamp needs to be rounded up to 2:00 pm so that it is removed |
|
101 | + * during the next scheduled cleanup after its expiration. |
|
102 | + * We also round off the current time timestamp to the closest 5 minutes |
|
103 | + * just to make the timestamps a little easier to round which helps with debugging. |
|
104 | + * |
|
105 | + * @param int $timestamp [required] |
|
106 | + * @param string $cleanup_frequency |
|
107 | + * @param bool $round_up |
|
108 | + * @return int |
|
109 | + */ |
|
110 | + private function roundTimestamp($timestamp, $cleanup_frequency = 'hour', $round_up = true) |
|
111 | + { |
|
112 | + $cleanup_frequency = $cleanup_frequency ? $cleanup_frequency : $this->transient_cleanup_frequency; |
|
113 | + // in order to round the time to the closest xx minutes (or hours), |
|
114 | + // we take the minutes (or hours) portion of the timestamp and divide it by xx, |
|
115 | + // round down to a whole number, then multiply by xx to bring us almost back up to where we were |
|
116 | + // why round down ? so the minutes (or hours) don't go over 60 (or 24) |
|
117 | + // and bump the hour, which could bump the day, which could bump the month, etc, |
|
118 | + // which would be bad because we don't always want to round up, |
|
119 | + // but when we do we can easily achieve that by simply adding the desired offset, |
|
120 | + $minutes = '00'; |
|
121 | + $hours = 'H'; |
|
122 | + switch ($cleanup_frequency) { |
|
123 | + case '5-minutes': |
|
124 | + $minutes = floor((int) date('i', $timestamp) / 5) * 5; |
|
125 | + $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT); |
|
126 | + $offset = MINUTE_IN_SECONDS * 5; |
|
127 | + break; |
|
128 | + case '15-minutes': |
|
129 | + $minutes = floor((int) date('i', $timestamp) / 15) * 15; |
|
130 | + $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT); |
|
131 | + $offset = MINUTE_IN_SECONDS * 15; |
|
132 | + break; |
|
133 | + case '12-hours': |
|
134 | + $hours = floor((int) date('H', $timestamp) / 12) * 12; |
|
135 | + $hours = str_pad($hours, 2, '0', STR_PAD_LEFT); |
|
136 | + $offset = HOUR_IN_SECONDS * 12; |
|
137 | + break; |
|
138 | + case 'day': |
|
139 | + $hours = '03'; // run cleanup at 3:00 am (or first site hit after that) |
|
140 | + $offset = DAY_IN_SECONDS; |
|
141 | + break; |
|
142 | + case 'hour': |
|
143 | + default: |
|
144 | + $offset = HOUR_IN_SECONDS; |
|
145 | + break; |
|
146 | + } |
|
147 | + $rounded_timestamp = (int) strtotime(date("Y-m-d {$hours}:{$minutes}:00", $timestamp)); |
|
148 | + $rounded_timestamp += $round_up ? $offset : 0; |
|
149 | + return apply_filters( |
|
150 | + 'FHEE__TransientCacheStorage__roundTimestamp__timestamp', |
|
151 | + $rounded_timestamp, |
|
152 | + $timestamp, |
|
153 | + $cleanup_frequency, |
|
154 | + $round_up |
|
155 | + ); |
|
156 | + } |
|
157 | + |
|
158 | + |
|
159 | + /** |
|
160 | + * Saves supplied data to a transient |
|
161 | + * if an expiration is set, then it automatically schedules the transient for cleanup |
|
162 | + * |
|
163 | + * @param string $transient_key [required] |
|
164 | + * @param string $data [required] |
|
165 | + * @param int $expiration number of seconds until the cache expires |
|
166 | + * @return bool |
|
167 | + */ |
|
168 | + public function add($transient_key, $data, $expiration = 0) |
|
169 | + { |
|
170 | + $expiration = (int) abs($expiration); |
|
171 | + $saved = set_transient($transient_key, $data, $expiration); |
|
172 | + if ($saved && $expiration) { |
|
173 | + $this->scheduleTransientCleanup($transient_key, $expiration); |
|
174 | + } |
|
175 | + return $saved; |
|
176 | + } |
|
177 | + |
|
178 | + |
|
179 | + /** |
|
180 | + * retrieves transient data |
|
181 | + * automatically triggers early cache refresh for standard cache items |
|
182 | + * in order to avoid cache stampedes on busy sites. |
|
183 | + * For non-standard cache items like PHP Session data where early refreshing is not wanted, |
|
184 | + * the $standard_cache parameter should be set to false when retrieving data |
|
185 | + * |
|
186 | + * @param string $transient_key [required] |
|
187 | + * @param bool $standard_cache |
|
188 | + * @return mixed|null |
|
189 | + */ |
|
190 | + public function get($transient_key, $standard_cache = true) |
|
191 | + { |
|
192 | + if (isset($this->transients[ $transient_key ])) { |
|
193 | + // to avoid cache stampedes (AKA:dogpiles) for standard cache items, |
|
194 | + // check if known cache expires within the next minute, |
|
195 | + // and if so, remove it from our tracking and and return nothing. |
|
196 | + // this should trigger the cache content to be regenerated during this request, |
|
197 | + // while allowing any following requests to still access the existing cache |
|
198 | + // until it gets replaced with the refreshed content |
|
199 | + if ( |
|
200 | + $standard_cache |
|
201 | + && $this->transients[ $transient_key ] - time() <= MINUTE_IN_SECONDS |
|
202 | + ) { |
|
203 | + unset($this->transients[ $transient_key ]); |
|
204 | + $this->updateTransients(); |
|
205 | + return null; |
|
206 | + } |
|
207 | + |
|
208 | + // for non standard cache items, remove the key from our tracking, |
|
209 | + // but proceed to retrieve the transient so that it also gets removed from the db |
|
210 | + if ($this->transients[ $transient_key ] <= time()) { |
|
211 | + unset($this->transients[ $transient_key ]); |
|
212 | + $this->updateTransients(); |
|
213 | + } |
|
214 | + } |
|
215 | + |
|
216 | + $content = get_transient($transient_key); |
|
217 | + return $content !== false ? $content : null; |
|
218 | + } |
|
219 | + |
|
220 | + |
|
221 | + /** |
|
222 | + * delete a single transient and remove tracking |
|
223 | + * |
|
224 | + * @param string $transient_key [required] full or partial transient key to be deleted |
|
225 | + */ |
|
226 | + public function delete($transient_key) |
|
227 | + { |
|
228 | + $this->deleteMany(array($transient_key)); |
|
229 | + } |
|
230 | + |
|
231 | + |
|
232 | + /** |
|
233 | + * delete multiple transients and remove tracking |
|
234 | + * |
|
235 | + * @param array $transient_keys [required] array of full or partial transient keys to be deleted |
|
236 | + * @param bool $force_delete [optional] if true, then will not check incoming keys against those being tracked |
|
237 | + * and proceed directly to deleting those entries from the cache storage |
|
238 | + */ |
|
239 | + public function deleteMany($transient_keys, $force_delete = false) |
|
240 | + { |
|
241 | + $full_transient_keys = $force_delete ? $transient_keys : array(); |
|
242 | + if (empty($full_transient_keys)) { |
|
243 | + foreach ($this->transients as $transient_key => $expiration) { |
|
244 | + foreach ($transient_keys as $transient_key_to_delete) { |
|
245 | + if (strpos($transient_key, $transient_key_to_delete) !== false) { |
|
246 | + $full_transient_keys[] = $transient_key; |
|
247 | + } |
|
248 | + } |
|
249 | + } |
|
250 | + } |
|
251 | + if ($this->deleteTransientKeys($full_transient_keys)) { |
|
252 | + $this->updateTransients(); |
|
253 | + } |
|
254 | + } |
|
255 | + |
|
256 | + |
|
257 | + /** |
|
258 | + * sorts transients numerically by timestamp |
|
259 | + * then saves the transient schedule to a WP option |
|
260 | + */ |
|
261 | + private function updateTransients() |
|
262 | + { |
|
263 | + asort($this->transients, SORT_NUMERIC); |
|
264 | + update_option( |
|
265 | + TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, |
|
266 | + $this->transients |
|
267 | + ); |
|
268 | + } |
|
269 | + |
|
270 | + |
|
271 | + /** |
|
272 | + * schedules a transient for cleanup by adding it to the transient tracking |
|
273 | + * |
|
274 | + * @param string $transient_key [required] |
|
275 | + * @param int $expiration [required] |
|
276 | + */ |
|
277 | + private function scheduleTransientCleanup($transient_key, $expiration) |
|
278 | + { |
|
279 | + // make sure a valid future timestamp is set |
|
280 | + $expiration += $expiration < time() ? time() : 0; |
|
281 | + // and round to the closest 15 minutes |
|
282 | + $expiration = $this->roundTimestamp($expiration); |
|
283 | + // save transients to clear using their ID as the key to avoid duplicates |
|
284 | + $this->transients[ $transient_key ] = $expiration; |
|
285 | + $this->updateTransients(); |
|
286 | + } |
|
287 | + |
|
288 | + |
|
289 | + /** |
|
290 | + * Since our tracked transients are sorted by their timestamps |
|
291 | + * we can grab the first transient and see when it is scheduled for cleanup. |
|
292 | + * If that timestamp is less than or equal to the current time, |
|
293 | + * then cleanup is triggered |
|
294 | + */ |
|
295 | + public function checkTransientCleanupSchedule() |
|
296 | + { |
|
297 | + if (empty($this->transients)) { |
|
298 | + return; |
|
299 | + } |
|
300 | + // when do we run the next cleanup job? |
|
301 | + reset($this->transients); |
|
302 | + $next_scheduled_cleanup = current($this->transients); |
|
303 | + // if the next cleanup job is scheduled for the current hour |
|
304 | + if ($next_scheduled_cleanup <= $this->current_time) { |
|
305 | + if ($this->cleanupExpiredTransients()) { |
|
306 | + $this->updateTransients(); |
|
307 | + } |
|
308 | + } |
|
309 | + } |
|
310 | + |
|
311 | + |
|
312 | + /** |
|
313 | + * loops through the array of tracked transients, |
|
314 | + * compiles a list of those that have expired, and sends that list off for deletion. |
|
315 | + * Also removes any bad records from the transients array |
|
316 | + * |
|
317 | + * @return bool |
|
318 | + */ |
|
319 | + private function cleanupExpiredTransients() |
|
320 | + { |
|
321 | + $update = false; |
|
322 | + // filter the query limit. Set to 0 to turn off garbage collection |
|
323 | + $limit = (int) abs( |
|
324 | + apply_filters( |
|
325 | + 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
326 | + 50 |
|
327 | + ) |
|
328 | + ); |
|
329 | + // non-zero LIMIT means take out the trash |
|
330 | + if ($limit) { |
|
331 | + $transient_keys = array(); |
|
332 | + foreach ($this->transients as $transient_key => $expiration) { |
|
333 | + if ($expiration > $this->current_time) { |
|
334 | + continue; |
|
335 | + } |
|
336 | + if (! $expiration || ! $transient_key) { |
|
337 | + unset($this->transients[ $transient_key ]); |
|
338 | + $update = true; |
|
339 | + continue; |
|
340 | + } |
|
341 | + $transient_keys[] = $transient_key; |
|
342 | + } |
|
343 | + // delete expired keys, but maintain value of $update if nothing is deleted |
|
344 | + $update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update; |
|
345 | + do_action('FHEE__TransientCacheStorage__clearExpiredTransients__end', $this); |
|
346 | + } |
|
347 | + return $update; |
|
348 | + } |
|
349 | + |
|
350 | + |
|
351 | + /** |
|
352 | + * calls delete_transient() on each transient key provided, up to the specified limit |
|
353 | + * |
|
354 | + * @param array $transient_keys [required] |
|
355 | + * @param int $limit |
|
356 | + * @return bool |
|
357 | + */ |
|
358 | + private function deleteTransientKeys(array $transient_keys, $limit = 50) |
|
359 | + { |
|
360 | + if (empty($transient_keys)) { |
|
361 | + return false; |
|
362 | + } |
|
363 | + $counter = 0; |
|
364 | + foreach ($transient_keys as $transient_key) { |
|
365 | + if ($counter === $limit) { |
|
366 | + break; |
|
367 | + } |
|
368 | + // remove any transient prefixes |
|
369 | + $transient_key = strpos($transient_key, '_transient_timeout_') === 0 |
|
370 | + ? str_replace('_transient_timeout_', '', $transient_key) |
|
371 | + : $transient_key; |
|
372 | + $transient_key = strpos($transient_key, '_transient_') === 0 |
|
373 | + ? str_replace('_transient_', '', $transient_key) |
|
374 | + : $transient_key; |
|
375 | + delete_transient($transient_key); |
|
376 | + unset($this->transients[ $transient_key ]); |
|
377 | + $counter++; |
|
378 | + } |
|
379 | + return $counter > 0; |
|
380 | + } |
|
381 | 381 | } |
@@ -533,7 +533,7 @@ discard block |
||
533 | 533 | $date_or_time, |
534 | 534 | $echo |
535 | 535 | ); |
536 | - if (! $echo) { |
|
536 | + if ( ! $echo) { |
|
537 | 537 | return $dtt; |
538 | 538 | } |
539 | 539 | return ''; |
@@ -635,7 +635,7 @@ discard block |
||
635 | 635 | ' ', |
636 | 636 | $this->get_i18n_datetime('DTT_EVT_end', $dt_frmt) |
637 | 637 | ); |
638 | - return $start !== $end ? $start . $conjunction . $end : $start; |
|
638 | + return $start !== $end ? $start.$conjunction.$end : $start; |
|
639 | 639 | } |
640 | 640 | |
641 | 641 | |
@@ -743,7 +743,7 @@ discard block |
||
743 | 743 | ' ', |
744 | 744 | $this->get_i18n_datetime('DTT_EVT_end', $tm_format) |
745 | 745 | ); |
746 | - return $start !== $end ? $start . $conjunction . $end : $start; |
|
746 | + return $start !== $end ? $start.$conjunction.$end : $start; |
|
747 | 747 | } |
748 | 748 | |
749 | 749 | |
@@ -788,7 +788,7 @@ discard block |
||
788 | 788 | ) { |
789 | 789 | $dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt; |
790 | 790 | $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt; |
791 | - $full_format = $dt_format . $separator . $tm_format; |
|
791 | + $full_format = $dt_format.$separator.$tm_format; |
|
792 | 792 | // the range output depends on various conditions |
793 | 793 | switch (true) { |
794 | 794 | // start date timestamp and end date timestamp are the same. |
@@ -1029,7 +1029,7 @@ discard block |
||
1029 | 1029 | // tickets remaining available for purchase |
1030 | 1030 | // no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF |
1031 | 1031 | $dtt_remaining = $this->reg_limit() - $this->sold_and_reserved(); |
1032 | - if (! $consider_tickets) { |
|
1032 | + if ( ! $consider_tickets) { |
|
1033 | 1033 | return $dtt_remaining; |
1034 | 1034 | } |
1035 | 1035 | $tickets_remaining = $this->tickets_remaining(); |
@@ -1053,7 +1053,7 @@ discard block |
||
1053 | 1053 | { |
1054 | 1054 | $sum = 0; |
1055 | 1055 | $tickets = $this->tickets($query_params); |
1056 | - if (! empty($tickets)) { |
|
1056 | + if ( ! empty($tickets)) { |
|
1057 | 1057 | foreach ($tickets as $ticket) { |
1058 | 1058 | if ($ticket instanceof EE_Ticket) { |
1059 | 1059 | // get the actual amount of tickets that can be sold |
@@ -1204,7 +1204,7 @@ discard block |
||
1204 | 1204 | { |
1205 | 1205 | if ($use_dtt_name) { |
1206 | 1206 | $dtt_name = $this->name(); |
1207 | - if (! empty($dtt_name)) { |
|
1207 | + if ( ! empty($dtt_name)) { |
|
1208 | 1208 | return $dtt_name; |
1209 | 1209 | } |
1210 | 1210 | } |
@@ -1212,14 +1212,14 @@ discard block |
||
1212 | 1212 | if ( |
1213 | 1213 | date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end')) |
1214 | 1214 | ) { |
1215 | - $display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a'); |
|
1215 | + $display_date = $this->start_date('M j\, Y g:i a').' - '.$this->end_date('M j\, Y g:i a'); |
|
1216 | 1216 | // next condition is if its the same month but different day |
1217 | 1217 | } else { |
1218 | 1218 | if ( |
1219 | 1219 | date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end')) |
1220 | 1220 | && date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end')) |
1221 | 1221 | ) { |
1222 | - $display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y'); |
|
1222 | + $display_date = $this->start_date('M j\, g:i a').' - '.$this->end_date('M j\, g:i a Y'); |
|
1223 | 1223 | } else { |
1224 | 1224 | $display_date = $this->start_date('F j\, Y') |
1225 | 1225 | . ' @ ' |
@@ -12,1560 +12,1560 @@ |
||
12 | 12 | */ |
13 | 13 | class EE_Datetime extends EE_Soft_Delete_Base_Class |
14 | 14 | { |
15 | - /** |
|
16 | - * constant used by get_active_status, indicates datetime has no more available spaces |
|
17 | - */ |
|
18 | - const sold_out = 'DTS'; |
|
19 | - |
|
20 | - /** |
|
21 | - * constant used by get_active_status, indicating datetime is still active (even is not over, can be registered-for) |
|
22 | - */ |
|
23 | - const active = 'DTA'; |
|
24 | - |
|
25 | - /** |
|
26 | - * constant used by get_active_status, indicating the datetime cannot be used for registrations yet, but has not |
|
27 | - * expired |
|
28 | - */ |
|
29 | - const upcoming = 'DTU'; |
|
30 | - |
|
31 | - /** |
|
32 | - * Datetime is postponed |
|
33 | - */ |
|
34 | - const postponed = 'DTP'; |
|
35 | - |
|
36 | - /** |
|
37 | - * Datetime is cancelled |
|
38 | - */ |
|
39 | - const cancelled = 'DTC'; |
|
40 | - |
|
41 | - /** |
|
42 | - * constant used by get_active_status, indicates datetime has expired (event is over) |
|
43 | - */ |
|
44 | - const expired = 'DTE'; |
|
45 | - |
|
46 | - /** |
|
47 | - * constant used in various places indicating that an event is INACTIVE (not yet ready to be published) |
|
48 | - */ |
|
49 | - const inactive = 'DTI'; |
|
50 | - |
|
51 | - |
|
52 | - /** |
|
53 | - * @param array $props_n_values incoming values |
|
54 | - * @param string $timezone incoming timezone (if not set the timezone set for the website will be used.) |
|
55 | - * @param array $date_formats incoming date_formats in an array where the first value is the date_format |
|
56 | - * and the second value is the time format |
|
57 | - * @return EE_Datetime |
|
58 | - * @throws ReflectionException |
|
59 | - * @throws InvalidArgumentException |
|
60 | - * @throws InvalidInterfaceException |
|
61 | - * @throws InvalidDataTypeException |
|
62 | - * @throws EE_Error |
|
63 | - */ |
|
64 | - public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
65 | - { |
|
66 | - $has_object = parent::_check_for_object( |
|
67 | - $props_n_values, |
|
68 | - __CLASS__, |
|
69 | - $timezone, |
|
70 | - $date_formats |
|
71 | - ); |
|
72 | - return $has_object |
|
73 | - ? $has_object |
|
74 | - : new self($props_n_values, false, $timezone, $date_formats); |
|
75 | - } |
|
76 | - |
|
77 | - |
|
78 | - /** |
|
79 | - * @param array $props_n_values incoming values from the database |
|
80 | - * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
81 | - * the website will be used. |
|
82 | - * @return EE_Datetime |
|
83 | - * @throws ReflectionException |
|
84 | - * @throws InvalidArgumentException |
|
85 | - * @throws InvalidInterfaceException |
|
86 | - * @throws InvalidDataTypeException |
|
87 | - * @throws EE_Error |
|
88 | - */ |
|
89 | - public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
90 | - { |
|
91 | - return new self($props_n_values, true, $timezone); |
|
92 | - } |
|
93 | - |
|
94 | - |
|
95 | - /** |
|
96 | - * @param $name |
|
97 | - * @throws ReflectionException |
|
98 | - * @throws InvalidArgumentException |
|
99 | - * @throws InvalidInterfaceException |
|
100 | - * @throws InvalidDataTypeException |
|
101 | - * @throws EE_Error |
|
102 | - */ |
|
103 | - public function set_name($name) |
|
104 | - { |
|
105 | - $this->set('DTT_name', $name); |
|
106 | - } |
|
107 | - |
|
108 | - |
|
109 | - /** |
|
110 | - * @param $description |
|
111 | - * @throws ReflectionException |
|
112 | - * @throws InvalidArgumentException |
|
113 | - * @throws InvalidInterfaceException |
|
114 | - * @throws InvalidDataTypeException |
|
115 | - * @throws EE_Error |
|
116 | - */ |
|
117 | - public function set_description($description) |
|
118 | - { |
|
119 | - $this->set('DTT_description', $description); |
|
120 | - } |
|
121 | - |
|
122 | - |
|
123 | - /** |
|
124 | - * Set event start date |
|
125 | - * set the start date for an event |
|
126 | - * |
|
127 | - * @param string $date a string representation of the event's date ex: Dec. 25, 2025 or 12-25-2025 |
|
128 | - * @throws ReflectionException |
|
129 | - * @throws InvalidArgumentException |
|
130 | - * @throws InvalidInterfaceException |
|
131 | - * @throws InvalidDataTypeException |
|
132 | - * @throws EE_Error |
|
133 | - */ |
|
134 | - public function set_start_date($date) |
|
135 | - { |
|
136 | - $this->_set_date_for($date, 'DTT_EVT_start'); |
|
137 | - } |
|
138 | - |
|
139 | - |
|
140 | - /** |
|
141 | - * Set event start time |
|
142 | - * set the start time for an event |
|
143 | - * |
|
144 | - * @param string $time a string representation of the event time ex: 9am or 7:30 PM |
|
145 | - * @throws ReflectionException |
|
146 | - * @throws InvalidArgumentException |
|
147 | - * @throws InvalidInterfaceException |
|
148 | - * @throws InvalidDataTypeException |
|
149 | - * @throws EE_Error |
|
150 | - */ |
|
151 | - public function set_start_time($time) |
|
152 | - { |
|
153 | - $this->_set_time_for($time, 'DTT_EVT_start'); |
|
154 | - } |
|
155 | - |
|
156 | - |
|
157 | - /** |
|
158 | - * Set event end date |
|
159 | - * set the end date for an event |
|
160 | - * |
|
161 | - * @param string $date a string representation of the event's date ex: Dec. 25, 2025 or 12-25-2025 |
|
162 | - * @throws ReflectionException |
|
163 | - * @throws InvalidArgumentException |
|
164 | - * @throws InvalidInterfaceException |
|
165 | - * @throws InvalidDataTypeException |
|
166 | - * @throws EE_Error |
|
167 | - */ |
|
168 | - public function set_end_date($date) |
|
169 | - { |
|
170 | - $this->_set_date_for($date, 'DTT_EVT_end'); |
|
171 | - } |
|
172 | - |
|
173 | - |
|
174 | - /** |
|
175 | - * Set event end time |
|
176 | - * set the end time for an event |
|
177 | - * |
|
178 | - * @param string $time a string representation of the event time ex: 9am or 7:30 PM |
|
179 | - * @throws ReflectionException |
|
180 | - * @throws InvalidArgumentException |
|
181 | - * @throws InvalidInterfaceException |
|
182 | - * @throws InvalidDataTypeException |
|
183 | - * @throws EE_Error |
|
184 | - */ |
|
185 | - public function set_end_time($time) |
|
186 | - { |
|
187 | - $this->_set_time_for($time, 'DTT_EVT_end'); |
|
188 | - } |
|
189 | - |
|
190 | - |
|
191 | - /** |
|
192 | - * Set registration limit |
|
193 | - * set the maximum number of attendees that can be registered for this datetime slot |
|
194 | - * |
|
195 | - * @param int|float $reg_limit |
|
196 | - * @throws ReflectionException |
|
197 | - * @throws InvalidArgumentException |
|
198 | - * @throws InvalidInterfaceException |
|
199 | - * @throws InvalidDataTypeException |
|
200 | - * @throws EE_Error |
|
201 | - */ |
|
202 | - public function set_reg_limit($reg_limit) |
|
203 | - { |
|
204 | - $this->set('DTT_reg_limit', $reg_limit); |
|
205 | - } |
|
206 | - |
|
207 | - |
|
208 | - /** |
|
209 | - * get the number of tickets sold for this datetime slot |
|
210 | - * |
|
211 | - * @return mixed int on success, FALSE on fail |
|
212 | - * @throws ReflectionException |
|
213 | - * @throws InvalidArgumentException |
|
214 | - * @throws InvalidInterfaceException |
|
215 | - * @throws InvalidDataTypeException |
|
216 | - * @throws EE_Error |
|
217 | - */ |
|
218 | - public function sold() |
|
219 | - { |
|
220 | - return $this->get_raw('DTT_sold'); |
|
221 | - } |
|
222 | - |
|
223 | - |
|
224 | - /** |
|
225 | - * @param int $sold |
|
226 | - * @throws ReflectionException |
|
227 | - * @throws InvalidArgumentException |
|
228 | - * @throws InvalidInterfaceException |
|
229 | - * @throws InvalidDataTypeException |
|
230 | - * @throws EE_Error |
|
231 | - */ |
|
232 | - public function set_sold($sold) |
|
233 | - { |
|
234 | - // sold can not go below zero |
|
235 | - $sold = max(0, $sold); |
|
236 | - $this->set('DTT_sold', $sold); |
|
237 | - } |
|
238 | - |
|
239 | - |
|
240 | - /** |
|
241 | - * Increments sold by amount passed by $qty, and persists it immediately to the database. |
|
242 | - * Simultaneously decreases the reserved count, unless $also_decrease_reserved is false. |
|
243 | - * |
|
244 | - * @param int $qty |
|
245 | - * @param boolean $also_decrease_reserved |
|
246 | - * @return boolean indicating success |
|
247 | - * @throws ReflectionException |
|
248 | - * @throws InvalidArgumentException |
|
249 | - * @throws InvalidInterfaceException |
|
250 | - * @throws InvalidDataTypeException |
|
251 | - * @throws EE_Error |
|
252 | - */ |
|
253 | - public function increaseSold($qty = 1, $also_decrease_reserved = true) |
|
254 | - { |
|
255 | - $qty = absint($qty); |
|
256 | - if ($also_decrease_reserved) { |
|
257 | - $success = $this->adjustNumericFieldsInDb( |
|
258 | - [ |
|
259 | - 'DTT_reserved' => $qty * -1, |
|
260 | - 'DTT_sold' => $qty |
|
261 | - ] |
|
262 | - ); |
|
263 | - } else { |
|
264 | - $success = $this->adjustNumericFieldsInDb( |
|
265 | - [ |
|
266 | - 'DTT_sold' => $qty |
|
267 | - ] |
|
268 | - ); |
|
269 | - } |
|
270 | - |
|
271 | - do_action( |
|
272 | - 'AHEE__EE_Datetime__increase_sold', |
|
273 | - $this, |
|
274 | - $qty, |
|
275 | - $this->sold(), |
|
276 | - $success |
|
277 | - ); |
|
278 | - return $success; |
|
279 | - } |
|
280 | - |
|
281 | - |
|
282 | - /** |
|
283 | - * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need |
|
284 | - * to save afterwards.) |
|
285 | - * |
|
286 | - * @param int $qty |
|
287 | - * @return boolean indicating success |
|
288 | - * @throws ReflectionException |
|
289 | - * @throws InvalidArgumentException |
|
290 | - * @throws InvalidInterfaceException |
|
291 | - * @throws InvalidDataTypeException |
|
292 | - * @throws EE_Error |
|
293 | - */ |
|
294 | - public function decreaseSold($qty = 1) |
|
295 | - { |
|
296 | - $qty = absint($qty); |
|
297 | - $success = $this->adjustNumericFieldsInDb( |
|
298 | - [ |
|
299 | - 'DTT_sold' => $qty * -1 |
|
300 | - ] |
|
301 | - ); |
|
302 | - do_action( |
|
303 | - 'AHEE__EE_Datetime__decrease_sold', |
|
304 | - $this, |
|
305 | - $qty, |
|
306 | - $this->sold(), |
|
307 | - $success |
|
308 | - ); |
|
309 | - return $success; |
|
310 | - } |
|
311 | - |
|
312 | - |
|
313 | - /** |
|
314 | - * Gets qty of reserved tickets for this datetime |
|
315 | - * |
|
316 | - * @return int |
|
317 | - * @throws ReflectionException |
|
318 | - * @throws InvalidArgumentException |
|
319 | - * @throws InvalidInterfaceException |
|
320 | - * @throws InvalidDataTypeException |
|
321 | - * @throws EE_Error |
|
322 | - */ |
|
323 | - public function reserved() |
|
324 | - { |
|
325 | - return $this->get_raw('DTT_reserved'); |
|
326 | - } |
|
327 | - |
|
328 | - |
|
329 | - /** |
|
330 | - * Sets qty of reserved tickets for this datetime |
|
331 | - * |
|
332 | - * @param int $reserved |
|
333 | - * @throws ReflectionException |
|
334 | - * @throws InvalidArgumentException |
|
335 | - * @throws InvalidInterfaceException |
|
336 | - * @throws InvalidDataTypeException |
|
337 | - * @throws EE_Error |
|
338 | - */ |
|
339 | - public function set_reserved($reserved) |
|
340 | - { |
|
341 | - // reserved can not go below zero |
|
342 | - $reserved = max(0, $reserved); |
|
343 | - $this->set('DTT_reserved', $reserved); |
|
344 | - } |
|
345 | - |
|
346 | - |
|
347 | - /** |
|
348 | - * Increments reserved by amount passed by $qty, and persists it immediately to the database. |
|
349 | - * |
|
350 | - * @param int $qty |
|
351 | - * @return boolean indicating success |
|
352 | - * @throws ReflectionException |
|
353 | - * @throws InvalidArgumentException |
|
354 | - * @throws InvalidInterfaceException |
|
355 | - * @throws InvalidDataTypeException |
|
356 | - * @throws EE_Error |
|
357 | - */ |
|
358 | - public function increaseReserved($qty = 1) |
|
359 | - { |
|
360 | - $qty = absint($qty); |
|
361 | - $success = $this->incrementFieldConditionallyInDb( |
|
362 | - 'DTT_reserved', |
|
363 | - 'DTT_sold', |
|
364 | - 'DTT_reg_limit', |
|
365 | - $qty |
|
366 | - ); |
|
367 | - do_action( |
|
368 | - 'AHEE__EE_Datetime__increase_reserved', |
|
369 | - $this, |
|
370 | - $qty, |
|
371 | - $this->reserved(), |
|
372 | - $success |
|
373 | - ); |
|
374 | - return $success; |
|
375 | - } |
|
376 | - |
|
377 | - |
|
378 | - /** |
|
379 | - * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database. |
|
380 | - * |
|
381 | - * @param int $qty |
|
382 | - * @return boolean indicating success |
|
383 | - * @throws ReflectionException |
|
384 | - * @throws InvalidArgumentException |
|
385 | - * @throws InvalidInterfaceException |
|
386 | - * @throws InvalidDataTypeException |
|
387 | - * @throws EE_Error |
|
388 | - */ |
|
389 | - public function decreaseReserved($qty = 1) |
|
390 | - { |
|
391 | - $qty = absint($qty); |
|
392 | - $success = $this->adjustNumericFieldsInDb( |
|
393 | - [ |
|
394 | - 'DTT_reserved' => $qty * -1 |
|
395 | - ] |
|
396 | - ); |
|
397 | - do_action( |
|
398 | - 'AHEE__EE_Datetime__decrease_reserved', |
|
399 | - $this, |
|
400 | - $qty, |
|
401 | - $this->reserved(), |
|
402 | - $success |
|
403 | - ); |
|
404 | - return $success; |
|
405 | - } |
|
406 | - |
|
407 | - |
|
408 | - /** |
|
409 | - * total sold and reserved tickets |
|
410 | - * |
|
411 | - * @return int |
|
412 | - * @throws ReflectionException |
|
413 | - * @throws InvalidArgumentException |
|
414 | - * @throws InvalidInterfaceException |
|
415 | - * @throws InvalidDataTypeException |
|
416 | - * @throws EE_Error |
|
417 | - */ |
|
418 | - public function sold_and_reserved() |
|
419 | - { |
|
420 | - return $this->sold() + $this->reserved(); |
|
421 | - } |
|
422 | - |
|
423 | - |
|
424 | - /** |
|
425 | - * returns the datetime name |
|
426 | - * |
|
427 | - * @return string |
|
428 | - * @throws ReflectionException |
|
429 | - * @throws InvalidArgumentException |
|
430 | - * @throws InvalidInterfaceException |
|
431 | - * @throws InvalidDataTypeException |
|
432 | - * @throws EE_Error |
|
433 | - */ |
|
434 | - public function name() |
|
435 | - { |
|
436 | - return $this->get('DTT_name'); |
|
437 | - } |
|
438 | - |
|
439 | - |
|
440 | - /** |
|
441 | - * returns the datetime description |
|
442 | - * |
|
443 | - * @return string |
|
444 | - * @throws ReflectionException |
|
445 | - * @throws InvalidArgumentException |
|
446 | - * @throws InvalidInterfaceException |
|
447 | - * @throws InvalidDataTypeException |
|
448 | - * @throws EE_Error |
|
449 | - */ |
|
450 | - public function description() |
|
451 | - { |
|
452 | - return $this->get('DTT_description'); |
|
453 | - } |
|
454 | - |
|
455 | - |
|
456 | - /** |
|
457 | - * This helper simply returns whether the event_datetime for the current datetime is a primary datetime |
|
458 | - * |
|
459 | - * @return boolean TRUE if is primary, FALSE if not. |
|
460 | - * @throws ReflectionException |
|
461 | - * @throws InvalidArgumentException |
|
462 | - * @throws InvalidInterfaceException |
|
463 | - * @throws InvalidDataTypeException |
|
464 | - * @throws EE_Error |
|
465 | - */ |
|
466 | - public function is_primary() |
|
467 | - { |
|
468 | - return $this->get('DTT_is_primary'); |
|
469 | - } |
|
470 | - |
|
471 | - |
|
472 | - /** |
|
473 | - * This helper simply returns the order for the datetime |
|
474 | - * |
|
475 | - * @return int The order of the datetime for this event. |
|
476 | - * @throws ReflectionException |
|
477 | - * @throws InvalidArgumentException |
|
478 | - * @throws InvalidInterfaceException |
|
479 | - * @throws InvalidDataTypeException |
|
480 | - * @throws EE_Error |
|
481 | - */ |
|
482 | - public function order() |
|
483 | - { |
|
484 | - return $this->get('DTT_order'); |
|
485 | - } |
|
486 | - |
|
487 | - |
|
488 | - /** |
|
489 | - * This helper simply returns the parent id for the datetime |
|
490 | - * |
|
491 | - * @return int |
|
492 | - * @throws ReflectionException |
|
493 | - * @throws InvalidArgumentException |
|
494 | - * @throws InvalidInterfaceException |
|
495 | - * @throws InvalidDataTypeException |
|
496 | - * @throws EE_Error |
|
497 | - */ |
|
498 | - public function parent() |
|
499 | - { |
|
500 | - return $this->get('DTT_parent'); |
|
501 | - } |
|
502 | - |
|
503 | - |
|
504 | - /** |
|
505 | - * show date and/or time |
|
506 | - * |
|
507 | - * @param string $date_or_time whether to display a date or time or both |
|
508 | - * @param string $start_or_end whether to display start or end datetimes |
|
509 | - * @param string $dt_frmt |
|
510 | - * @param string $tm_frmt |
|
511 | - * @param bool $echo whether we echo or return (note echoing uses "pretty" formats, |
|
512 | - * otherwise we use the standard formats) |
|
513 | - * @return string|bool string on success, FALSE on fail |
|
514 | - * @throws ReflectionException |
|
515 | - * @throws InvalidArgumentException |
|
516 | - * @throws InvalidInterfaceException |
|
517 | - * @throws InvalidDataTypeException |
|
518 | - * @throws EE_Error |
|
519 | - */ |
|
520 | - private function _show_datetime( |
|
521 | - $date_or_time = null, |
|
522 | - $start_or_end = 'start', |
|
523 | - $dt_frmt = '', |
|
524 | - $tm_frmt = '', |
|
525 | - $echo = false |
|
526 | - ) { |
|
527 | - $field_name = "DTT_EVT_{$start_or_end}"; |
|
528 | - $dtt = $this->_get_datetime( |
|
529 | - $field_name, |
|
530 | - $dt_frmt, |
|
531 | - $tm_frmt, |
|
532 | - $date_or_time, |
|
533 | - $echo |
|
534 | - ); |
|
535 | - if (! $echo) { |
|
536 | - return $dtt; |
|
537 | - } |
|
538 | - return ''; |
|
539 | - } |
|
540 | - |
|
541 | - |
|
542 | - /** |
|
543 | - * get event start date. Provide either the date format, or NULL to re-use the |
|
544 | - * last-used format, or '' to use the default date format |
|
545 | - * |
|
546 | - * @param string $dt_frmt string representation of date format defaults to 'F j, Y' |
|
547 | - * @return mixed string on success, FALSE on fail |
|
548 | - * @throws ReflectionException |
|
549 | - * @throws InvalidArgumentException |
|
550 | - * @throws InvalidInterfaceException |
|
551 | - * @throws InvalidDataTypeException |
|
552 | - * @throws EE_Error |
|
553 | - */ |
|
554 | - public function start_date($dt_frmt = '') |
|
555 | - { |
|
556 | - return $this->_show_datetime('D', 'start', $dt_frmt); |
|
557 | - } |
|
558 | - |
|
559 | - |
|
560 | - /** |
|
561 | - * Echoes start_date() |
|
562 | - * |
|
563 | - * @param string $dt_frmt |
|
564 | - * @throws ReflectionException |
|
565 | - * @throws InvalidArgumentException |
|
566 | - * @throws InvalidInterfaceException |
|
567 | - * @throws InvalidDataTypeException |
|
568 | - * @throws EE_Error |
|
569 | - */ |
|
570 | - public function e_start_date($dt_frmt = '') |
|
571 | - { |
|
572 | - $this->_show_datetime('D', 'start', $dt_frmt, null, true); |
|
573 | - } |
|
574 | - |
|
575 | - |
|
576 | - /** |
|
577 | - * get end date. Provide either the date format, or NULL to re-use the |
|
578 | - * last-used format, or '' to use the default date format |
|
579 | - * |
|
580 | - * @param string $dt_frmt string representation of date format defaults to 'F j, Y' |
|
581 | - * @return mixed string on success, FALSE on fail |
|
582 | - * @throws ReflectionException |
|
583 | - * @throws InvalidArgumentException |
|
584 | - * @throws InvalidInterfaceException |
|
585 | - * @throws InvalidDataTypeException |
|
586 | - * @throws EE_Error |
|
587 | - */ |
|
588 | - public function end_date($dt_frmt = '') |
|
589 | - { |
|
590 | - return $this->_show_datetime('D', 'end', $dt_frmt); |
|
591 | - } |
|
592 | - |
|
593 | - |
|
594 | - /** |
|
595 | - * Echoes the end date. See end_date() |
|
596 | - * |
|
597 | - * @param string $dt_frmt |
|
598 | - * @throws ReflectionException |
|
599 | - * @throws InvalidArgumentException |
|
600 | - * @throws InvalidInterfaceException |
|
601 | - * @throws InvalidDataTypeException |
|
602 | - * @throws EE_Error |
|
603 | - */ |
|
604 | - public function e_end_date($dt_frmt = '') |
|
605 | - { |
|
606 | - $this->_show_datetime('D', 'end', $dt_frmt, null, true); |
|
607 | - } |
|
608 | - |
|
609 | - |
|
610 | - /** |
|
611 | - * get date_range - meaning the start AND end date |
|
612 | - * |
|
613 | - * @access public |
|
614 | - * @param string $dt_frmt string representation of date format defaults to WP settings |
|
615 | - * @param string $conjunction conjunction junction what's your function ? |
|
616 | - * this string joins the start date with the end date ie: Jan 01 "to" Dec 31 |
|
617 | - * @return mixed string on success, FALSE on fail |
|
618 | - * @throws ReflectionException |
|
619 | - * @throws InvalidArgumentException |
|
620 | - * @throws InvalidInterfaceException |
|
621 | - * @throws InvalidDataTypeException |
|
622 | - * @throws EE_Error |
|
623 | - */ |
|
624 | - public function date_range($dt_frmt = '', $conjunction = ' - ') |
|
625 | - { |
|
626 | - $dt_frmt = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt; |
|
627 | - $start = str_replace( |
|
628 | - ' ', |
|
629 | - ' ', |
|
630 | - $this->get_i18n_datetime('DTT_EVT_start', $dt_frmt) |
|
631 | - ); |
|
632 | - $end = str_replace( |
|
633 | - ' ', |
|
634 | - ' ', |
|
635 | - $this->get_i18n_datetime('DTT_EVT_end', $dt_frmt) |
|
636 | - ); |
|
637 | - return $start !== $end ? $start . $conjunction . $end : $start; |
|
638 | - } |
|
639 | - |
|
640 | - |
|
641 | - /** |
|
642 | - * @param string $dt_frmt |
|
643 | - * @param string $conjunction |
|
644 | - * @throws ReflectionException |
|
645 | - * @throws InvalidArgumentException |
|
646 | - * @throws InvalidInterfaceException |
|
647 | - * @throws InvalidDataTypeException |
|
648 | - * @throws EE_Error |
|
649 | - */ |
|
650 | - public function e_date_range($dt_frmt = '', $conjunction = ' - ') |
|
651 | - { |
|
652 | - echo esc_html($this->date_range($dt_frmt, $conjunction)); |
|
653 | - } |
|
654 | - |
|
655 | - |
|
656 | - /** |
|
657 | - * get start time |
|
658 | - * |
|
659 | - * @param string $tm_format - string representation of time format defaults to 'g:i a' |
|
660 | - * @return mixed string on success, FALSE on fail |
|
661 | - * @throws ReflectionException |
|
662 | - * @throws InvalidArgumentException |
|
663 | - * @throws InvalidInterfaceException |
|
664 | - * @throws InvalidDataTypeException |
|
665 | - * @throws EE_Error |
|
666 | - */ |
|
667 | - public function start_time($tm_format = '') |
|
668 | - { |
|
669 | - return $this->_show_datetime('T', 'start', null, $tm_format); |
|
670 | - } |
|
671 | - |
|
672 | - |
|
673 | - /** |
|
674 | - * @param string $tm_format |
|
675 | - * @throws ReflectionException |
|
676 | - * @throws InvalidArgumentException |
|
677 | - * @throws InvalidInterfaceException |
|
678 | - * @throws InvalidDataTypeException |
|
679 | - * @throws EE_Error |
|
680 | - */ |
|
681 | - public function e_start_time($tm_format = '') |
|
682 | - { |
|
683 | - $this->_show_datetime('T', 'start', null, $tm_format, true); |
|
684 | - } |
|
685 | - |
|
686 | - |
|
687 | - /** |
|
688 | - * get end time |
|
689 | - * |
|
690 | - * @param string $tm_format string representation of time format defaults to 'g:i a' |
|
691 | - * @return mixed string on success, FALSE on fail |
|
692 | - * @throws ReflectionException |
|
693 | - * @throws InvalidArgumentException |
|
694 | - * @throws InvalidInterfaceException |
|
695 | - * @throws InvalidDataTypeException |
|
696 | - * @throws EE_Error |
|
697 | - */ |
|
698 | - public function end_time($tm_format = '') |
|
699 | - { |
|
700 | - return $this->_show_datetime('T', 'end', null, $tm_format); |
|
701 | - } |
|
702 | - |
|
703 | - |
|
704 | - /** |
|
705 | - * @param string $tm_format |
|
706 | - * @throws ReflectionException |
|
707 | - * @throws InvalidArgumentException |
|
708 | - * @throws InvalidInterfaceException |
|
709 | - * @throws InvalidDataTypeException |
|
710 | - * @throws EE_Error |
|
711 | - */ |
|
712 | - public function e_end_time($tm_format = '') |
|
713 | - { |
|
714 | - $this->_show_datetime('T', 'end', null, $tm_format, true); |
|
715 | - } |
|
716 | - |
|
717 | - |
|
718 | - /** |
|
719 | - * get time_range |
|
720 | - * |
|
721 | - * @access public |
|
722 | - * @param string $tm_format string representation of time format defaults to 'g:i a' |
|
723 | - * @param string $conjunction conjunction junction what's your function ? |
|
724 | - * this string joins the start date with the end date ie: Jan 01 "to" Dec 31 |
|
725 | - * @return mixed string on success, FALSE on fail |
|
726 | - * @throws ReflectionException |
|
727 | - * @throws InvalidArgumentException |
|
728 | - * @throws InvalidInterfaceException |
|
729 | - * @throws InvalidDataTypeException |
|
730 | - * @throws EE_Error |
|
731 | - */ |
|
732 | - public function time_range($tm_format = '', $conjunction = ' - ') |
|
733 | - { |
|
734 | - $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt; |
|
735 | - $start = str_replace( |
|
736 | - ' ', |
|
737 | - ' ', |
|
738 | - $this->get_i18n_datetime('DTT_EVT_start', $tm_format) |
|
739 | - ); |
|
740 | - $end = str_replace( |
|
741 | - ' ', |
|
742 | - ' ', |
|
743 | - $this->get_i18n_datetime('DTT_EVT_end', $tm_format) |
|
744 | - ); |
|
745 | - return $start !== $end ? $start . $conjunction . $end : $start; |
|
746 | - } |
|
747 | - |
|
748 | - |
|
749 | - /** |
|
750 | - * @param string $tm_format |
|
751 | - * @param string $conjunction |
|
752 | - * @throws ReflectionException |
|
753 | - * @throws InvalidArgumentException |
|
754 | - * @throws InvalidInterfaceException |
|
755 | - * @throws InvalidDataTypeException |
|
756 | - * @throws EE_Error |
|
757 | - */ |
|
758 | - public function e_time_range($tm_format = '', $conjunction = ' - ') |
|
759 | - { |
|
760 | - echo esc_html($this->time_range($tm_format, $conjunction)); |
|
761 | - } |
|
762 | - |
|
763 | - |
|
764 | - /** |
|
765 | - * This returns a range representation of the date and times. |
|
766 | - * Output is dependent on the difference (or similarity) between DTT_EVT_start and DTT_EVT_end. |
|
767 | - * Also, the return value is localized. |
|
768 | - * |
|
769 | - * @param string $dt_format |
|
770 | - * @param string $tm_format |
|
771 | - * @param string $conjunction used between two different dates or times. |
|
772 | - * ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm |
|
773 | - * @param string $separator used between the date and time formats. |
|
774 | - * ex: Dec 1, 2016{$separator}2pm |
|
775 | - * @return string |
|
776 | - * @throws ReflectionException |
|
777 | - * @throws InvalidArgumentException |
|
778 | - * @throws InvalidInterfaceException |
|
779 | - * @throws InvalidDataTypeException |
|
780 | - * @throws EE_Error |
|
781 | - */ |
|
782 | - public function date_and_time_range( |
|
783 | - $dt_format = '', |
|
784 | - $tm_format = '', |
|
785 | - $conjunction = ' - ', |
|
786 | - $separator = ' ' |
|
787 | - ) { |
|
788 | - $dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt; |
|
789 | - $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt; |
|
790 | - $full_format = $dt_format . $separator . $tm_format; |
|
791 | - // the range output depends on various conditions |
|
792 | - switch (true) { |
|
793 | - // start date timestamp and end date timestamp are the same. |
|
794 | - case ($this->get_raw('DTT_EVT_start') === $this->get_raw('DTT_EVT_end')): |
|
795 | - $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format); |
|
796 | - break; |
|
797 | - // start and end date are the same but times are different |
|
798 | - case ($this->start_date() === $this->end_date()): |
|
799 | - $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format) |
|
800 | - . $conjunction |
|
801 | - . $this->get_i18n_datetime('DTT_EVT_end', $tm_format); |
|
802 | - break; |
|
803 | - // all other conditions |
|
804 | - default: |
|
805 | - $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format) |
|
806 | - . $conjunction |
|
807 | - . $this->get_i18n_datetime('DTT_EVT_end', $full_format); |
|
808 | - break; |
|
809 | - } |
|
810 | - return $output; |
|
811 | - } |
|
812 | - |
|
813 | - |
|
814 | - /** |
|
815 | - * This echos the results of date and time range. |
|
816 | - * |
|
817 | - * @see date_and_time_range() for more details on purpose. |
|
818 | - * @param string $dt_format |
|
819 | - * @param string $tm_format |
|
820 | - * @param string $conjunction |
|
821 | - * @return void |
|
822 | - * @throws ReflectionException |
|
823 | - * @throws InvalidArgumentException |
|
824 | - * @throws InvalidInterfaceException |
|
825 | - * @throws InvalidDataTypeException |
|
826 | - * @throws EE_Error |
|
827 | - */ |
|
828 | - public function e_date_and_time_range($dt_format = '', $tm_format = '', $conjunction = ' - ') |
|
829 | - { |
|
830 | - echo esc_html($this->date_and_time_range($dt_format, $tm_format, $conjunction)); |
|
831 | - } |
|
832 | - |
|
833 | - |
|
834 | - /** |
|
835 | - * get start date and start time |
|
836 | - * |
|
837 | - * @param string $dt_format - string representation of date format defaults to 'F j, Y' |
|
838 | - * @param string $tm_format - string representation of time format defaults to 'g:i a' |
|
839 | - * @return mixed string on success, FALSE on fail |
|
840 | - * @throws ReflectionException |
|
841 | - * @throws InvalidArgumentException |
|
842 | - * @throws InvalidInterfaceException |
|
843 | - * @throws InvalidDataTypeException |
|
844 | - * @throws EE_Error |
|
845 | - */ |
|
846 | - public function start_date_and_time($dt_format = '', $tm_format = '') |
|
847 | - { |
|
848 | - return $this->_show_datetime('', 'start', $dt_format, $tm_format); |
|
849 | - } |
|
850 | - |
|
851 | - |
|
852 | - /** |
|
853 | - * @param string $dt_frmt |
|
854 | - * @param string $tm_format |
|
855 | - * @throws ReflectionException |
|
856 | - * @throws InvalidArgumentException |
|
857 | - * @throws InvalidInterfaceException |
|
858 | - * @throws InvalidDataTypeException |
|
859 | - * @throws EE_Error |
|
860 | - */ |
|
861 | - public function e_start_date_and_time($dt_frmt = '', $tm_format = '') |
|
862 | - { |
|
863 | - $this->_show_datetime('', 'start', $dt_frmt, $tm_format, true); |
|
864 | - } |
|
865 | - |
|
866 | - |
|
867 | - /** |
|
868 | - * Shows the length of the event (start to end time). |
|
869 | - * Can be shown in 'seconds','minutes','hours', or 'days'. |
|
870 | - * By default, rounds up. (So if you use 'days', and then event |
|
871 | - * only occurs for 1 hour, it will return 1 day). |
|
872 | - * |
|
873 | - * @param string $units 'seconds','minutes','hours','days' |
|
874 | - * @param bool $round_up |
|
875 | - * @return float|int|mixed |
|
876 | - * @throws ReflectionException |
|
877 | - * @throws InvalidArgumentException |
|
878 | - * @throws InvalidInterfaceException |
|
879 | - * @throws InvalidDataTypeException |
|
880 | - * @throws EE_Error |
|
881 | - */ |
|
882 | - public function length($units = 'seconds', $round_up = false) |
|
883 | - { |
|
884 | - $start = $this->get_raw('DTT_EVT_start'); |
|
885 | - $end = $this->get_raw('DTT_EVT_end'); |
|
886 | - $length_in_units = $end - $start; |
|
887 | - switch ($units) { |
|
888 | - // NOTE: We purposefully don't use "break;" in order to chain the divisions |
|
889 | - /** @noinspection PhpMissingBreakStatementInspection */ |
|
890 | - // phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment |
|
891 | - case 'days': |
|
892 | - $length_in_units /= 24; |
|
893 | - /** @noinspection PhpMissingBreakStatementInspection */ |
|
894 | - case 'hours': |
|
895 | - // fall through is intentional |
|
896 | - $length_in_units /= 60; |
|
897 | - /** @noinspection PhpMissingBreakStatementInspection */ |
|
898 | - case 'minutes': |
|
899 | - // fall through is intentional |
|
900 | - $length_in_units /= 60; |
|
901 | - case 'seconds': |
|
902 | - default: |
|
903 | - $length_in_units = ceil($length_in_units); |
|
904 | - } |
|
905 | - // phpcs:enable |
|
906 | - if ($round_up) { |
|
907 | - $length_in_units = max($length_in_units, 1); |
|
908 | - } |
|
909 | - return $length_in_units; |
|
910 | - } |
|
911 | - |
|
912 | - |
|
913 | - /** |
|
914 | - * get end date and time |
|
915 | - * |
|
916 | - * @param string $dt_frmt - string representation of date format defaults to 'F j, Y' |
|
917 | - * @param string $tm_format - string representation of time format defaults to 'g:i a' |
|
918 | - * @return mixed string on success, FALSE on fail |
|
919 | - * @throws ReflectionException |
|
920 | - * @throws InvalidArgumentException |
|
921 | - * @throws InvalidInterfaceException |
|
922 | - * @throws InvalidDataTypeException |
|
923 | - * @throws EE_Error |
|
924 | - */ |
|
925 | - public function end_date_and_time($dt_frmt = '', $tm_format = '') |
|
926 | - { |
|
927 | - return $this->_show_datetime('', 'end', $dt_frmt, $tm_format); |
|
928 | - } |
|
929 | - |
|
930 | - |
|
931 | - /** |
|
932 | - * @param string $dt_frmt |
|
933 | - * @param string $tm_format |
|
934 | - * @throws ReflectionException |
|
935 | - * @throws InvalidArgumentException |
|
936 | - * @throws InvalidInterfaceException |
|
937 | - * @throws InvalidDataTypeException |
|
938 | - * @throws EE_Error |
|
939 | - */ |
|
940 | - public function e_end_date_and_time($dt_frmt = '', $tm_format = '') |
|
941 | - { |
|
942 | - $this->_show_datetime('', 'end', $dt_frmt, $tm_format, true); |
|
943 | - } |
|
944 | - |
|
945 | - |
|
946 | - /** |
|
947 | - * get start timestamp |
|
948 | - * |
|
949 | - * @return int |
|
950 | - * @throws ReflectionException |
|
951 | - * @throws InvalidArgumentException |
|
952 | - * @throws InvalidInterfaceException |
|
953 | - * @throws InvalidDataTypeException |
|
954 | - * @throws EE_Error |
|
955 | - */ |
|
956 | - public function start() |
|
957 | - { |
|
958 | - return $this->get_raw('DTT_EVT_start'); |
|
959 | - } |
|
960 | - |
|
961 | - |
|
962 | - /** |
|
963 | - * get end timestamp |
|
964 | - * |
|
965 | - * @return int |
|
966 | - * @throws ReflectionException |
|
967 | - * @throws InvalidArgumentException |
|
968 | - * @throws InvalidInterfaceException |
|
969 | - * @throws InvalidDataTypeException |
|
970 | - * @throws EE_Error |
|
971 | - */ |
|
972 | - public function end() |
|
973 | - { |
|
974 | - return $this->get_raw('DTT_EVT_end'); |
|
975 | - } |
|
976 | - |
|
977 | - |
|
978 | - /** |
|
979 | - * get the registration limit for this datetime slot |
|
980 | - * |
|
981 | - * @return int|float int = finite limit EE_INF(float) = unlimited |
|
982 | - * @throws ReflectionException |
|
983 | - * @throws InvalidArgumentException |
|
984 | - * @throws InvalidInterfaceException |
|
985 | - * @throws InvalidDataTypeException |
|
986 | - * @throws EE_Error |
|
987 | - */ |
|
988 | - public function reg_limit() |
|
989 | - { |
|
990 | - return $this->get_raw('DTT_reg_limit'); |
|
991 | - } |
|
992 | - |
|
993 | - |
|
994 | - /** |
|
995 | - * have the tickets sold for this datetime, met or exceed the registration limit ? |
|
996 | - * |
|
997 | - * @return boolean |
|
998 | - * @throws ReflectionException |
|
999 | - * @throws InvalidArgumentException |
|
1000 | - * @throws InvalidInterfaceException |
|
1001 | - * @throws InvalidDataTypeException |
|
1002 | - * @throws EE_Error |
|
1003 | - */ |
|
1004 | - public function sold_out() |
|
1005 | - { |
|
1006 | - return $this->reg_limit() > 0 && $this->sold() >= $this->reg_limit(); |
|
1007 | - } |
|
1008 | - |
|
1009 | - |
|
1010 | - /** |
|
1011 | - * return the total number of spaces remaining at this venue. |
|
1012 | - * This only takes the venue's capacity into account, NOT the tickets available for sale |
|
1013 | - * |
|
1014 | - * @param bool $consider_tickets Whether to consider tickets remaining when determining if there are any spaces left |
|
1015 | - * Because if all tickets attached to this datetime have no spaces left, |
|
1016 | - * then this datetime IS effectively sold out. |
|
1017 | - * However, there are cases where we just want to know the spaces |
|
1018 | - * remaining for this particular datetime, hence the flag. |
|
1019 | - * @return int|float |
|
1020 | - * @throws ReflectionException |
|
1021 | - * @throws InvalidArgumentException |
|
1022 | - * @throws InvalidInterfaceException |
|
1023 | - * @throws InvalidDataTypeException |
|
1024 | - * @throws EE_Error |
|
1025 | - */ |
|
1026 | - public function spaces_remaining($consider_tickets = false) |
|
1027 | - { |
|
1028 | - // tickets remaining available for purchase |
|
1029 | - // no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF |
|
1030 | - $dtt_remaining = $this->reg_limit() - $this->sold_and_reserved(); |
|
1031 | - if (! $consider_tickets) { |
|
1032 | - return $dtt_remaining; |
|
1033 | - } |
|
1034 | - $tickets_remaining = $this->tickets_remaining(); |
|
1035 | - return min($dtt_remaining, $tickets_remaining); |
|
1036 | - } |
|
1037 | - |
|
1038 | - |
|
1039 | - /** |
|
1040 | - * Counts the total tickets available |
|
1041 | - * (from all the different types of tickets which are available for this datetime). |
|
1042 | - * |
|
1043 | - * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1044 | - * @return int |
|
1045 | - * @throws ReflectionException |
|
1046 | - * @throws InvalidArgumentException |
|
1047 | - * @throws InvalidInterfaceException |
|
1048 | - * @throws InvalidDataTypeException |
|
1049 | - * @throws EE_Error |
|
1050 | - */ |
|
1051 | - public function tickets_remaining($query_params = array()) |
|
1052 | - { |
|
1053 | - $sum = 0; |
|
1054 | - $tickets = $this->tickets($query_params); |
|
1055 | - if (! empty($tickets)) { |
|
1056 | - foreach ($tickets as $ticket) { |
|
1057 | - if ($ticket instanceof EE_Ticket) { |
|
1058 | - // get the actual amount of tickets that can be sold |
|
1059 | - $qty = $ticket->qty('saleable'); |
|
1060 | - if ($qty === EE_INF) { |
|
1061 | - return EE_INF; |
|
1062 | - } |
|
1063 | - // no negative ticket quantities plz |
|
1064 | - if ($qty > 0) { |
|
1065 | - $sum += $qty; |
|
1066 | - } |
|
1067 | - } |
|
1068 | - } |
|
1069 | - } |
|
1070 | - return $sum; |
|
1071 | - } |
|
1072 | - |
|
1073 | - |
|
1074 | - /** |
|
1075 | - * Gets the count of all the tickets available at this datetime (not ticket types) |
|
1076 | - * before any were sold |
|
1077 | - * |
|
1078 | - * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1079 | - * @return int |
|
1080 | - * @throws ReflectionException |
|
1081 | - * @throws InvalidArgumentException |
|
1082 | - * @throws InvalidInterfaceException |
|
1083 | - * @throws InvalidDataTypeException |
|
1084 | - * @throws EE_Error |
|
1085 | - */ |
|
1086 | - public function sum_tickets_initially_available($query_params = array()) |
|
1087 | - { |
|
1088 | - return $this->sum_related('Ticket', $query_params, 'TKT_qty'); |
|
1089 | - } |
|
1090 | - |
|
1091 | - |
|
1092 | - /** |
|
1093 | - * Returns the lesser-of-the two: spaces remaining at this datetime, or |
|
1094 | - * the total tickets remaining (a sum of the tickets remaining for each ticket type |
|
1095 | - * that is available for this datetime). |
|
1096 | - * |
|
1097 | - * @return int |
|
1098 | - * @throws ReflectionException |
|
1099 | - * @throws InvalidArgumentException |
|
1100 | - * @throws InvalidInterfaceException |
|
1101 | - * @throws InvalidDataTypeException |
|
1102 | - * @throws EE_Error |
|
1103 | - */ |
|
1104 | - public function total_tickets_available_at_this_datetime() |
|
1105 | - { |
|
1106 | - return $this->spaces_remaining(true); |
|
1107 | - } |
|
1108 | - |
|
1109 | - |
|
1110 | - /** |
|
1111 | - * This simply compares the internal dtt for the given string with NOW |
|
1112 | - * and determines if the date is upcoming or not. |
|
1113 | - * |
|
1114 | - * @access public |
|
1115 | - * @return boolean |
|
1116 | - * @throws ReflectionException |
|
1117 | - * @throws InvalidArgumentException |
|
1118 | - * @throws InvalidInterfaceException |
|
1119 | - * @throws InvalidDataTypeException |
|
1120 | - * @throws EE_Error |
|
1121 | - */ |
|
1122 | - public function is_upcoming() |
|
1123 | - { |
|
1124 | - return ($this->get_raw('DTT_EVT_start') > time()); |
|
1125 | - } |
|
1126 | - |
|
1127 | - |
|
1128 | - /** |
|
1129 | - * This simply compares the internal datetime for the given string with NOW |
|
1130 | - * and returns if the date is active (i.e. start and end time) |
|
1131 | - * |
|
1132 | - * @return boolean |
|
1133 | - * @throws ReflectionException |
|
1134 | - * @throws InvalidArgumentException |
|
1135 | - * @throws InvalidInterfaceException |
|
1136 | - * @throws InvalidDataTypeException |
|
1137 | - * @throws EE_Error |
|
1138 | - */ |
|
1139 | - public function is_active() |
|
1140 | - { |
|
1141 | - return ($this->get_raw('DTT_EVT_start') < time() && $this->get_raw('DTT_EVT_end') > time()); |
|
1142 | - } |
|
1143 | - |
|
1144 | - |
|
1145 | - /** |
|
1146 | - * This simply compares the internal dtt for the given string with NOW |
|
1147 | - * and determines if the date is expired or not. |
|
1148 | - * |
|
1149 | - * @return boolean |
|
1150 | - * @throws ReflectionException |
|
1151 | - * @throws InvalidArgumentException |
|
1152 | - * @throws InvalidInterfaceException |
|
1153 | - * @throws InvalidDataTypeException |
|
1154 | - * @throws EE_Error |
|
1155 | - */ |
|
1156 | - public function is_expired() |
|
1157 | - { |
|
1158 | - return ($this->get_raw('DTT_EVT_end') < time()); |
|
1159 | - } |
|
1160 | - |
|
1161 | - |
|
1162 | - /** |
|
1163 | - * This returns the active status for whether an event is active, upcoming, or expired |
|
1164 | - * |
|
1165 | - * @return int return value will be one of the EE_Datetime status constants. |
|
1166 | - * @throws ReflectionException |
|
1167 | - * @throws InvalidArgumentException |
|
1168 | - * @throws InvalidInterfaceException |
|
1169 | - * @throws InvalidDataTypeException |
|
1170 | - * @throws EE_Error |
|
1171 | - */ |
|
1172 | - public function get_active_status() |
|
1173 | - { |
|
1174 | - $total_tickets_for_this_dtt = $this->total_tickets_available_at_this_datetime(); |
|
1175 | - if ($total_tickets_for_this_dtt !== false && $total_tickets_for_this_dtt < 1) { |
|
1176 | - return EE_Datetime::sold_out; |
|
1177 | - } |
|
1178 | - if ($this->is_expired()) { |
|
1179 | - return EE_Datetime::expired; |
|
1180 | - } |
|
1181 | - if ($this->is_upcoming()) { |
|
1182 | - return EE_Datetime::upcoming; |
|
1183 | - } |
|
1184 | - if ($this->is_active()) { |
|
1185 | - return EE_Datetime::active; |
|
1186 | - } |
|
1187 | - return null; |
|
1188 | - } |
|
1189 | - |
|
1190 | - |
|
1191 | - /** |
|
1192 | - * This returns a nice display name for the datetime that is contingent on the span between the dates and times. |
|
1193 | - * |
|
1194 | - * @param boolean $use_dtt_name if TRUE then we'll use DTT->name() if its not empty. |
|
1195 | - * @return string |
|
1196 | - * @throws ReflectionException |
|
1197 | - * @throws InvalidArgumentException |
|
1198 | - * @throws InvalidInterfaceException |
|
1199 | - * @throws InvalidDataTypeException |
|
1200 | - * @throws EE_Error |
|
1201 | - */ |
|
1202 | - public function get_dtt_display_name($use_dtt_name = false) |
|
1203 | - { |
|
1204 | - if ($use_dtt_name) { |
|
1205 | - $dtt_name = $this->name(); |
|
1206 | - if (! empty($dtt_name)) { |
|
1207 | - return $dtt_name; |
|
1208 | - } |
|
1209 | - } |
|
1210 | - // first condition is to see if the months are different |
|
1211 | - if ( |
|
1212 | - date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end')) |
|
1213 | - ) { |
|
1214 | - $display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a'); |
|
1215 | - // next condition is if its the same month but different day |
|
1216 | - } else { |
|
1217 | - if ( |
|
1218 | - date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end')) |
|
1219 | - && date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end')) |
|
1220 | - ) { |
|
1221 | - $display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y'); |
|
1222 | - } else { |
|
1223 | - $display_date = $this->start_date('F j\, Y') |
|
1224 | - . ' @ ' |
|
1225 | - . $this->start_date('g:i a') |
|
1226 | - . ' - ' |
|
1227 | - . $this->end_date('g:i a'); |
|
1228 | - } |
|
1229 | - } |
|
1230 | - return $display_date; |
|
1231 | - } |
|
1232 | - |
|
1233 | - |
|
1234 | - /** |
|
1235 | - * Gets all the tickets for this datetime |
|
1236 | - * |
|
1237 | - * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1238 | - * @return EE_Base_Class[]|EE_Ticket[] |
|
1239 | - * @throws ReflectionException |
|
1240 | - * @throws InvalidArgumentException |
|
1241 | - * @throws InvalidInterfaceException |
|
1242 | - * @throws InvalidDataTypeException |
|
1243 | - * @throws EE_Error |
|
1244 | - */ |
|
1245 | - public function tickets($query_params = array()) |
|
1246 | - { |
|
1247 | - return $this->get_many_related('Ticket', $query_params); |
|
1248 | - } |
|
1249 | - |
|
1250 | - |
|
1251 | - /** |
|
1252 | - * Gets all the ticket types currently available for purchase |
|
1253 | - * |
|
1254 | - * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1255 | - * @return EE_Ticket[] |
|
1256 | - * @throws ReflectionException |
|
1257 | - * @throws InvalidArgumentException |
|
1258 | - * @throws InvalidInterfaceException |
|
1259 | - * @throws InvalidDataTypeException |
|
1260 | - * @throws EE_Error |
|
1261 | - */ |
|
1262 | - public function ticket_types_available_for_purchase($query_params = array()) |
|
1263 | - { |
|
1264 | - // first check if datetime is valid |
|
1265 | - if ($this->sold_out() || ! ($this->is_upcoming() || $this->is_active())) { |
|
1266 | - return array(); |
|
1267 | - } |
|
1268 | - if (empty($query_params)) { |
|
1269 | - $query_params = array( |
|
1270 | - array( |
|
1271 | - 'TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')), |
|
1272 | - 'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')), |
|
1273 | - 'TKT_deleted' => false, |
|
1274 | - ), |
|
1275 | - ); |
|
1276 | - } |
|
1277 | - return $this->tickets($query_params); |
|
1278 | - } |
|
1279 | - |
|
1280 | - |
|
1281 | - /** |
|
1282 | - * @return EE_Base_Class|EE_Event |
|
1283 | - * @throws ReflectionException |
|
1284 | - * @throws InvalidArgumentException |
|
1285 | - * @throws InvalidInterfaceException |
|
1286 | - * @throws InvalidDataTypeException |
|
1287 | - * @throws EE_Error |
|
1288 | - */ |
|
1289 | - public function event() |
|
1290 | - { |
|
1291 | - return $this->get_first_related('Event'); |
|
1292 | - } |
|
1293 | - |
|
1294 | - |
|
1295 | - /** |
|
1296 | - * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime |
|
1297 | - * (via the tickets). |
|
1298 | - * |
|
1299 | - * @return int |
|
1300 | - * @throws ReflectionException |
|
1301 | - * @throws InvalidArgumentException |
|
1302 | - * @throws InvalidInterfaceException |
|
1303 | - * @throws InvalidDataTypeException |
|
1304 | - * @throws EE_Error |
|
1305 | - */ |
|
1306 | - public function update_sold() |
|
1307 | - { |
|
1308 | - $count_regs_for_this_datetime = EEM_Registration::instance()->count( |
|
1309 | - array( |
|
1310 | - array( |
|
1311 | - 'STS_ID' => EEM_Registration::status_id_approved, |
|
1312 | - 'REG_deleted' => 0, |
|
1313 | - 'Ticket.Datetime.DTT_ID' => $this->ID(), |
|
1314 | - ), |
|
1315 | - ) |
|
1316 | - ); |
|
1317 | - $this->set_sold($count_regs_for_this_datetime); |
|
1318 | - $this->save(); |
|
1319 | - return $count_regs_for_this_datetime; |
|
1320 | - } |
|
1321 | - |
|
1322 | - |
|
1323 | - /** |
|
1324 | - * Adds a venue to this event |
|
1325 | - * |
|
1326 | - * @param int|EE_Venue /int $venue_id_or_obj |
|
1327 | - * @return EE_Base_Class|EE_Venue |
|
1328 | - * @throws EE_Error |
|
1329 | - * @throws ReflectionException |
|
1330 | - */ |
|
1331 | - public function add_venue($venue_id_or_obj) |
|
1332 | - { |
|
1333 | - return $this->_add_relation_to($venue_id_or_obj, 'Venue'); |
|
1334 | - } |
|
1335 | - |
|
1336 | - |
|
1337 | - /** |
|
1338 | - * Removes a venue from the event |
|
1339 | - * |
|
1340 | - * @param EE_Venue /int $venue_id_or_obj |
|
1341 | - * @return EE_Base_Class|EE_Venue |
|
1342 | - * @throws EE_Error |
|
1343 | - * @throws ReflectionException |
|
1344 | - */ |
|
1345 | - public function remove_venue($venue_id_or_obj) |
|
1346 | - { |
|
1347 | - $venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue(); |
|
1348 | - return $this->_remove_relation_to($venue_id_or_obj, 'Venue'); |
|
1349 | - } |
|
1350 | - |
|
1351 | - |
|
1352 | - /** |
|
1353 | - * Gets the venue related to the event. May provide additional $query_params if desired |
|
1354 | - * |
|
1355 | - * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1356 | - * @return int |
|
1357 | - * @throws EE_Error |
|
1358 | - * @throws ReflectionException |
|
1359 | - */ |
|
1360 | - public function venue_ID($query_params = []) |
|
1361 | - { |
|
1362 | - $venue = $this->get_first_related('Venue', $query_params); |
|
1363 | - return $venue instanceof EE_Venue |
|
1364 | - ? $venue->ID() |
|
1365 | - : 0; |
|
1366 | - } |
|
1367 | - |
|
1368 | - |
|
1369 | - /** |
|
1370 | - * Gets the venue related to the event. May provide additional $query_params if desired |
|
1371 | - * |
|
1372 | - * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1373 | - * @return EE_Base_Class|EE_Venue |
|
1374 | - * @throws EE_Error |
|
1375 | - * @throws ReflectionException |
|
1376 | - */ |
|
1377 | - public function venue($query_params = []) |
|
1378 | - { |
|
1379 | - return $this->get_first_related('Venue', $query_params); |
|
1380 | - } |
|
1381 | - |
|
1382 | - |
|
1383 | - /** |
|
1384 | - * @param EE_Base_Class|int|string $otherObjectModelObjectOrID |
|
1385 | - * @param string $relationName |
|
1386 | - * @param array $extra_join_model_fields_n_values |
|
1387 | - * @param string|null $cache_id |
|
1388 | - * @return EE_Base_Class |
|
1389 | - * @throws EE_Error |
|
1390 | - * @throws ReflectionException |
|
1391 | - * @since $VID:$ |
|
1392 | - */ |
|
1393 | - public function _add_relation_to( |
|
1394 | - $otherObjectModelObjectOrID, |
|
1395 | - $relationName, |
|
1396 | - $extra_join_model_fields_n_values = [], |
|
1397 | - $cache_id = null |
|
1398 | - ) { |
|
1399 | - // if we're adding a new relation to a ticket |
|
1400 | - if ($relationName === 'Ticket' && ! $this->hasRelation($otherObjectModelObjectOrID, $relationName)) { |
|
1401 | - /** @var EE_Ticket $ticket */ |
|
1402 | - $ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID); |
|
1403 | - $this->increaseSold($ticket->sold(), false); |
|
1404 | - $this->increaseReserved($ticket->reserved()); |
|
1405 | - $this->save(); |
|
1406 | - $otherObjectModelObjectOrID = $ticket; |
|
1407 | - } |
|
1408 | - return parent::_add_relation_to( |
|
1409 | - $otherObjectModelObjectOrID, |
|
1410 | - $relationName, |
|
1411 | - $extra_join_model_fields_n_values, |
|
1412 | - $cache_id |
|
1413 | - ); |
|
1414 | - } |
|
1415 | - |
|
1416 | - |
|
1417 | - /** |
|
1418 | - * @param EE_Base_Class|int|string $otherObjectModelObjectOrID |
|
1419 | - * @param string $relationName |
|
1420 | - * @param array $where_query |
|
1421 | - * @return bool|EE_Base_Class|null |
|
1422 | - * @throws EE_Error |
|
1423 | - * @throws ReflectionException |
|
1424 | - * @since $VID:$ |
|
1425 | - */ |
|
1426 | - public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = []) |
|
1427 | - { |
|
1428 | - if ($relationName === 'Ticket' && $this->hasRelation($otherObjectModelObjectOrID, $relationName)) { |
|
1429 | - /** @var EE_Ticket $ticket */ |
|
1430 | - $ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID); |
|
1431 | - $this->decreaseSold($ticket->sold()); |
|
1432 | - $this->decreaseReserved($ticket->reserved()); |
|
1433 | - $this->save(); |
|
1434 | - $otherObjectModelObjectOrID = $ticket; |
|
1435 | - } |
|
1436 | - return parent::_remove_relation_to( |
|
1437 | - $otherObjectModelObjectOrID, |
|
1438 | - $relationName, |
|
1439 | - $where_query |
|
1440 | - ); |
|
1441 | - } |
|
1442 | - |
|
1443 | - |
|
1444 | - /** |
|
1445 | - * Removes ALL the related things for the $relationName. |
|
1446 | - * |
|
1447 | - * @param string $relationName |
|
1448 | - * @param array $where_query_params |
|
1449 | - * @return EE_Base_Class |
|
1450 | - * @throws ReflectionException |
|
1451 | - * @throws InvalidArgumentException |
|
1452 | - * @throws InvalidInterfaceException |
|
1453 | - * @throws InvalidDataTypeException |
|
1454 | - * @throws EE_Error |
|
1455 | - * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions |
|
1456 | - */ |
|
1457 | - public function _remove_relations($relationName, $where_query_params = []) |
|
1458 | - { |
|
1459 | - if ($relationName === 'Ticket') { |
|
1460 | - $tickets = $this->tickets(); |
|
1461 | - foreach ($tickets as $ticket) { |
|
1462 | - $this->decreaseSold($ticket->sold()); |
|
1463 | - $this->decreaseReserved($ticket->reserved()); |
|
1464 | - $this->save(); |
|
1465 | - } |
|
1466 | - } |
|
1467 | - return parent::_remove_relations($relationName, $where_query_params); |
|
1468 | - } |
|
1469 | - |
|
1470 | - |
|
1471 | - /******************************************************************* |
|
15 | + /** |
|
16 | + * constant used by get_active_status, indicates datetime has no more available spaces |
|
17 | + */ |
|
18 | + const sold_out = 'DTS'; |
|
19 | + |
|
20 | + /** |
|
21 | + * constant used by get_active_status, indicating datetime is still active (even is not over, can be registered-for) |
|
22 | + */ |
|
23 | + const active = 'DTA'; |
|
24 | + |
|
25 | + /** |
|
26 | + * constant used by get_active_status, indicating the datetime cannot be used for registrations yet, but has not |
|
27 | + * expired |
|
28 | + */ |
|
29 | + const upcoming = 'DTU'; |
|
30 | + |
|
31 | + /** |
|
32 | + * Datetime is postponed |
|
33 | + */ |
|
34 | + const postponed = 'DTP'; |
|
35 | + |
|
36 | + /** |
|
37 | + * Datetime is cancelled |
|
38 | + */ |
|
39 | + const cancelled = 'DTC'; |
|
40 | + |
|
41 | + /** |
|
42 | + * constant used by get_active_status, indicates datetime has expired (event is over) |
|
43 | + */ |
|
44 | + const expired = 'DTE'; |
|
45 | + |
|
46 | + /** |
|
47 | + * constant used in various places indicating that an event is INACTIVE (not yet ready to be published) |
|
48 | + */ |
|
49 | + const inactive = 'DTI'; |
|
50 | + |
|
51 | + |
|
52 | + /** |
|
53 | + * @param array $props_n_values incoming values |
|
54 | + * @param string $timezone incoming timezone (if not set the timezone set for the website will be used.) |
|
55 | + * @param array $date_formats incoming date_formats in an array where the first value is the date_format |
|
56 | + * and the second value is the time format |
|
57 | + * @return EE_Datetime |
|
58 | + * @throws ReflectionException |
|
59 | + * @throws InvalidArgumentException |
|
60 | + * @throws InvalidInterfaceException |
|
61 | + * @throws InvalidDataTypeException |
|
62 | + * @throws EE_Error |
|
63 | + */ |
|
64 | + public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
65 | + { |
|
66 | + $has_object = parent::_check_for_object( |
|
67 | + $props_n_values, |
|
68 | + __CLASS__, |
|
69 | + $timezone, |
|
70 | + $date_formats |
|
71 | + ); |
|
72 | + return $has_object |
|
73 | + ? $has_object |
|
74 | + : new self($props_n_values, false, $timezone, $date_formats); |
|
75 | + } |
|
76 | + |
|
77 | + |
|
78 | + /** |
|
79 | + * @param array $props_n_values incoming values from the database |
|
80 | + * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
81 | + * the website will be used. |
|
82 | + * @return EE_Datetime |
|
83 | + * @throws ReflectionException |
|
84 | + * @throws InvalidArgumentException |
|
85 | + * @throws InvalidInterfaceException |
|
86 | + * @throws InvalidDataTypeException |
|
87 | + * @throws EE_Error |
|
88 | + */ |
|
89 | + public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
90 | + { |
|
91 | + return new self($props_n_values, true, $timezone); |
|
92 | + } |
|
93 | + |
|
94 | + |
|
95 | + /** |
|
96 | + * @param $name |
|
97 | + * @throws ReflectionException |
|
98 | + * @throws InvalidArgumentException |
|
99 | + * @throws InvalidInterfaceException |
|
100 | + * @throws InvalidDataTypeException |
|
101 | + * @throws EE_Error |
|
102 | + */ |
|
103 | + public function set_name($name) |
|
104 | + { |
|
105 | + $this->set('DTT_name', $name); |
|
106 | + } |
|
107 | + |
|
108 | + |
|
109 | + /** |
|
110 | + * @param $description |
|
111 | + * @throws ReflectionException |
|
112 | + * @throws InvalidArgumentException |
|
113 | + * @throws InvalidInterfaceException |
|
114 | + * @throws InvalidDataTypeException |
|
115 | + * @throws EE_Error |
|
116 | + */ |
|
117 | + public function set_description($description) |
|
118 | + { |
|
119 | + $this->set('DTT_description', $description); |
|
120 | + } |
|
121 | + |
|
122 | + |
|
123 | + /** |
|
124 | + * Set event start date |
|
125 | + * set the start date for an event |
|
126 | + * |
|
127 | + * @param string $date a string representation of the event's date ex: Dec. 25, 2025 or 12-25-2025 |
|
128 | + * @throws ReflectionException |
|
129 | + * @throws InvalidArgumentException |
|
130 | + * @throws InvalidInterfaceException |
|
131 | + * @throws InvalidDataTypeException |
|
132 | + * @throws EE_Error |
|
133 | + */ |
|
134 | + public function set_start_date($date) |
|
135 | + { |
|
136 | + $this->_set_date_for($date, 'DTT_EVT_start'); |
|
137 | + } |
|
138 | + |
|
139 | + |
|
140 | + /** |
|
141 | + * Set event start time |
|
142 | + * set the start time for an event |
|
143 | + * |
|
144 | + * @param string $time a string representation of the event time ex: 9am or 7:30 PM |
|
145 | + * @throws ReflectionException |
|
146 | + * @throws InvalidArgumentException |
|
147 | + * @throws InvalidInterfaceException |
|
148 | + * @throws InvalidDataTypeException |
|
149 | + * @throws EE_Error |
|
150 | + */ |
|
151 | + public function set_start_time($time) |
|
152 | + { |
|
153 | + $this->_set_time_for($time, 'DTT_EVT_start'); |
|
154 | + } |
|
155 | + |
|
156 | + |
|
157 | + /** |
|
158 | + * Set event end date |
|
159 | + * set the end date for an event |
|
160 | + * |
|
161 | + * @param string $date a string representation of the event's date ex: Dec. 25, 2025 or 12-25-2025 |
|
162 | + * @throws ReflectionException |
|
163 | + * @throws InvalidArgumentException |
|
164 | + * @throws InvalidInterfaceException |
|
165 | + * @throws InvalidDataTypeException |
|
166 | + * @throws EE_Error |
|
167 | + */ |
|
168 | + public function set_end_date($date) |
|
169 | + { |
|
170 | + $this->_set_date_for($date, 'DTT_EVT_end'); |
|
171 | + } |
|
172 | + |
|
173 | + |
|
174 | + /** |
|
175 | + * Set event end time |
|
176 | + * set the end time for an event |
|
177 | + * |
|
178 | + * @param string $time a string representation of the event time ex: 9am or 7:30 PM |
|
179 | + * @throws ReflectionException |
|
180 | + * @throws InvalidArgumentException |
|
181 | + * @throws InvalidInterfaceException |
|
182 | + * @throws InvalidDataTypeException |
|
183 | + * @throws EE_Error |
|
184 | + */ |
|
185 | + public function set_end_time($time) |
|
186 | + { |
|
187 | + $this->_set_time_for($time, 'DTT_EVT_end'); |
|
188 | + } |
|
189 | + |
|
190 | + |
|
191 | + /** |
|
192 | + * Set registration limit |
|
193 | + * set the maximum number of attendees that can be registered for this datetime slot |
|
194 | + * |
|
195 | + * @param int|float $reg_limit |
|
196 | + * @throws ReflectionException |
|
197 | + * @throws InvalidArgumentException |
|
198 | + * @throws InvalidInterfaceException |
|
199 | + * @throws InvalidDataTypeException |
|
200 | + * @throws EE_Error |
|
201 | + */ |
|
202 | + public function set_reg_limit($reg_limit) |
|
203 | + { |
|
204 | + $this->set('DTT_reg_limit', $reg_limit); |
|
205 | + } |
|
206 | + |
|
207 | + |
|
208 | + /** |
|
209 | + * get the number of tickets sold for this datetime slot |
|
210 | + * |
|
211 | + * @return mixed int on success, FALSE on fail |
|
212 | + * @throws ReflectionException |
|
213 | + * @throws InvalidArgumentException |
|
214 | + * @throws InvalidInterfaceException |
|
215 | + * @throws InvalidDataTypeException |
|
216 | + * @throws EE_Error |
|
217 | + */ |
|
218 | + public function sold() |
|
219 | + { |
|
220 | + return $this->get_raw('DTT_sold'); |
|
221 | + } |
|
222 | + |
|
223 | + |
|
224 | + /** |
|
225 | + * @param int $sold |
|
226 | + * @throws ReflectionException |
|
227 | + * @throws InvalidArgumentException |
|
228 | + * @throws InvalidInterfaceException |
|
229 | + * @throws InvalidDataTypeException |
|
230 | + * @throws EE_Error |
|
231 | + */ |
|
232 | + public function set_sold($sold) |
|
233 | + { |
|
234 | + // sold can not go below zero |
|
235 | + $sold = max(0, $sold); |
|
236 | + $this->set('DTT_sold', $sold); |
|
237 | + } |
|
238 | + |
|
239 | + |
|
240 | + /** |
|
241 | + * Increments sold by amount passed by $qty, and persists it immediately to the database. |
|
242 | + * Simultaneously decreases the reserved count, unless $also_decrease_reserved is false. |
|
243 | + * |
|
244 | + * @param int $qty |
|
245 | + * @param boolean $also_decrease_reserved |
|
246 | + * @return boolean indicating success |
|
247 | + * @throws ReflectionException |
|
248 | + * @throws InvalidArgumentException |
|
249 | + * @throws InvalidInterfaceException |
|
250 | + * @throws InvalidDataTypeException |
|
251 | + * @throws EE_Error |
|
252 | + */ |
|
253 | + public function increaseSold($qty = 1, $also_decrease_reserved = true) |
|
254 | + { |
|
255 | + $qty = absint($qty); |
|
256 | + if ($also_decrease_reserved) { |
|
257 | + $success = $this->adjustNumericFieldsInDb( |
|
258 | + [ |
|
259 | + 'DTT_reserved' => $qty * -1, |
|
260 | + 'DTT_sold' => $qty |
|
261 | + ] |
|
262 | + ); |
|
263 | + } else { |
|
264 | + $success = $this->adjustNumericFieldsInDb( |
|
265 | + [ |
|
266 | + 'DTT_sold' => $qty |
|
267 | + ] |
|
268 | + ); |
|
269 | + } |
|
270 | + |
|
271 | + do_action( |
|
272 | + 'AHEE__EE_Datetime__increase_sold', |
|
273 | + $this, |
|
274 | + $qty, |
|
275 | + $this->sold(), |
|
276 | + $success |
|
277 | + ); |
|
278 | + return $success; |
|
279 | + } |
|
280 | + |
|
281 | + |
|
282 | + /** |
|
283 | + * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need |
|
284 | + * to save afterwards.) |
|
285 | + * |
|
286 | + * @param int $qty |
|
287 | + * @return boolean indicating success |
|
288 | + * @throws ReflectionException |
|
289 | + * @throws InvalidArgumentException |
|
290 | + * @throws InvalidInterfaceException |
|
291 | + * @throws InvalidDataTypeException |
|
292 | + * @throws EE_Error |
|
293 | + */ |
|
294 | + public function decreaseSold($qty = 1) |
|
295 | + { |
|
296 | + $qty = absint($qty); |
|
297 | + $success = $this->adjustNumericFieldsInDb( |
|
298 | + [ |
|
299 | + 'DTT_sold' => $qty * -1 |
|
300 | + ] |
|
301 | + ); |
|
302 | + do_action( |
|
303 | + 'AHEE__EE_Datetime__decrease_sold', |
|
304 | + $this, |
|
305 | + $qty, |
|
306 | + $this->sold(), |
|
307 | + $success |
|
308 | + ); |
|
309 | + return $success; |
|
310 | + } |
|
311 | + |
|
312 | + |
|
313 | + /** |
|
314 | + * Gets qty of reserved tickets for this datetime |
|
315 | + * |
|
316 | + * @return int |
|
317 | + * @throws ReflectionException |
|
318 | + * @throws InvalidArgumentException |
|
319 | + * @throws InvalidInterfaceException |
|
320 | + * @throws InvalidDataTypeException |
|
321 | + * @throws EE_Error |
|
322 | + */ |
|
323 | + public function reserved() |
|
324 | + { |
|
325 | + return $this->get_raw('DTT_reserved'); |
|
326 | + } |
|
327 | + |
|
328 | + |
|
329 | + /** |
|
330 | + * Sets qty of reserved tickets for this datetime |
|
331 | + * |
|
332 | + * @param int $reserved |
|
333 | + * @throws ReflectionException |
|
334 | + * @throws InvalidArgumentException |
|
335 | + * @throws InvalidInterfaceException |
|
336 | + * @throws InvalidDataTypeException |
|
337 | + * @throws EE_Error |
|
338 | + */ |
|
339 | + public function set_reserved($reserved) |
|
340 | + { |
|
341 | + // reserved can not go below zero |
|
342 | + $reserved = max(0, $reserved); |
|
343 | + $this->set('DTT_reserved', $reserved); |
|
344 | + } |
|
345 | + |
|
346 | + |
|
347 | + /** |
|
348 | + * Increments reserved by amount passed by $qty, and persists it immediately to the database. |
|
349 | + * |
|
350 | + * @param int $qty |
|
351 | + * @return boolean indicating success |
|
352 | + * @throws ReflectionException |
|
353 | + * @throws InvalidArgumentException |
|
354 | + * @throws InvalidInterfaceException |
|
355 | + * @throws InvalidDataTypeException |
|
356 | + * @throws EE_Error |
|
357 | + */ |
|
358 | + public function increaseReserved($qty = 1) |
|
359 | + { |
|
360 | + $qty = absint($qty); |
|
361 | + $success = $this->incrementFieldConditionallyInDb( |
|
362 | + 'DTT_reserved', |
|
363 | + 'DTT_sold', |
|
364 | + 'DTT_reg_limit', |
|
365 | + $qty |
|
366 | + ); |
|
367 | + do_action( |
|
368 | + 'AHEE__EE_Datetime__increase_reserved', |
|
369 | + $this, |
|
370 | + $qty, |
|
371 | + $this->reserved(), |
|
372 | + $success |
|
373 | + ); |
|
374 | + return $success; |
|
375 | + } |
|
376 | + |
|
377 | + |
|
378 | + /** |
|
379 | + * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database. |
|
380 | + * |
|
381 | + * @param int $qty |
|
382 | + * @return boolean indicating success |
|
383 | + * @throws ReflectionException |
|
384 | + * @throws InvalidArgumentException |
|
385 | + * @throws InvalidInterfaceException |
|
386 | + * @throws InvalidDataTypeException |
|
387 | + * @throws EE_Error |
|
388 | + */ |
|
389 | + public function decreaseReserved($qty = 1) |
|
390 | + { |
|
391 | + $qty = absint($qty); |
|
392 | + $success = $this->adjustNumericFieldsInDb( |
|
393 | + [ |
|
394 | + 'DTT_reserved' => $qty * -1 |
|
395 | + ] |
|
396 | + ); |
|
397 | + do_action( |
|
398 | + 'AHEE__EE_Datetime__decrease_reserved', |
|
399 | + $this, |
|
400 | + $qty, |
|
401 | + $this->reserved(), |
|
402 | + $success |
|
403 | + ); |
|
404 | + return $success; |
|
405 | + } |
|
406 | + |
|
407 | + |
|
408 | + /** |
|
409 | + * total sold and reserved tickets |
|
410 | + * |
|
411 | + * @return int |
|
412 | + * @throws ReflectionException |
|
413 | + * @throws InvalidArgumentException |
|
414 | + * @throws InvalidInterfaceException |
|
415 | + * @throws InvalidDataTypeException |
|
416 | + * @throws EE_Error |
|
417 | + */ |
|
418 | + public function sold_and_reserved() |
|
419 | + { |
|
420 | + return $this->sold() + $this->reserved(); |
|
421 | + } |
|
422 | + |
|
423 | + |
|
424 | + /** |
|
425 | + * returns the datetime name |
|
426 | + * |
|
427 | + * @return string |
|
428 | + * @throws ReflectionException |
|
429 | + * @throws InvalidArgumentException |
|
430 | + * @throws InvalidInterfaceException |
|
431 | + * @throws InvalidDataTypeException |
|
432 | + * @throws EE_Error |
|
433 | + */ |
|
434 | + public function name() |
|
435 | + { |
|
436 | + return $this->get('DTT_name'); |
|
437 | + } |
|
438 | + |
|
439 | + |
|
440 | + /** |
|
441 | + * returns the datetime description |
|
442 | + * |
|
443 | + * @return string |
|
444 | + * @throws ReflectionException |
|
445 | + * @throws InvalidArgumentException |
|
446 | + * @throws InvalidInterfaceException |
|
447 | + * @throws InvalidDataTypeException |
|
448 | + * @throws EE_Error |
|
449 | + */ |
|
450 | + public function description() |
|
451 | + { |
|
452 | + return $this->get('DTT_description'); |
|
453 | + } |
|
454 | + |
|
455 | + |
|
456 | + /** |
|
457 | + * This helper simply returns whether the event_datetime for the current datetime is a primary datetime |
|
458 | + * |
|
459 | + * @return boolean TRUE if is primary, FALSE if not. |
|
460 | + * @throws ReflectionException |
|
461 | + * @throws InvalidArgumentException |
|
462 | + * @throws InvalidInterfaceException |
|
463 | + * @throws InvalidDataTypeException |
|
464 | + * @throws EE_Error |
|
465 | + */ |
|
466 | + public function is_primary() |
|
467 | + { |
|
468 | + return $this->get('DTT_is_primary'); |
|
469 | + } |
|
470 | + |
|
471 | + |
|
472 | + /** |
|
473 | + * This helper simply returns the order for the datetime |
|
474 | + * |
|
475 | + * @return int The order of the datetime for this event. |
|
476 | + * @throws ReflectionException |
|
477 | + * @throws InvalidArgumentException |
|
478 | + * @throws InvalidInterfaceException |
|
479 | + * @throws InvalidDataTypeException |
|
480 | + * @throws EE_Error |
|
481 | + */ |
|
482 | + public function order() |
|
483 | + { |
|
484 | + return $this->get('DTT_order'); |
|
485 | + } |
|
486 | + |
|
487 | + |
|
488 | + /** |
|
489 | + * This helper simply returns the parent id for the datetime |
|
490 | + * |
|
491 | + * @return int |
|
492 | + * @throws ReflectionException |
|
493 | + * @throws InvalidArgumentException |
|
494 | + * @throws InvalidInterfaceException |
|
495 | + * @throws InvalidDataTypeException |
|
496 | + * @throws EE_Error |
|
497 | + */ |
|
498 | + public function parent() |
|
499 | + { |
|
500 | + return $this->get('DTT_parent'); |
|
501 | + } |
|
502 | + |
|
503 | + |
|
504 | + /** |
|
505 | + * show date and/or time |
|
506 | + * |
|
507 | + * @param string $date_or_time whether to display a date or time or both |
|
508 | + * @param string $start_or_end whether to display start or end datetimes |
|
509 | + * @param string $dt_frmt |
|
510 | + * @param string $tm_frmt |
|
511 | + * @param bool $echo whether we echo or return (note echoing uses "pretty" formats, |
|
512 | + * otherwise we use the standard formats) |
|
513 | + * @return string|bool string on success, FALSE on fail |
|
514 | + * @throws ReflectionException |
|
515 | + * @throws InvalidArgumentException |
|
516 | + * @throws InvalidInterfaceException |
|
517 | + * @throws InvalidDataTypeException |
|
518 | + * @throws EE_Error |
|
519 | + */ |
|
520 | + private function _show_datetime( |
|
521 | + $date_or_time = null, |
|
522 | + $start_or_end = 'start', |
|
523 | + $dt_frmt = '', |
|
524 | + $tm_frmt = '', |
|
525 | + $echo = false |
|
526 | + ) { |
|
527 | + $field_name = "DTT_EVT_{$start_or_end}"; |
|
528 | + $dtt = $this->_get_datetime( |
|
529 | + $field_name, |
|
530 | + $dt_frmt, |
|
531 | + $tm_frmt, |
|
532 | + $date_or_time, |
|
533 | + $echo |
|
534 | + ); |
|
535 | + if (! $echo) { |
|
536 | + return $dtt; |
|
537 | + } |
|
538 | + return ''; |
|
539 | + } |
|
540 | + |
|
541 | + |
|
542 | + /** |
|
543 | + * get event start date. Provide either the date format, or NULL to re-use the |
|
544 | + * last-used format, or '' to use the default date format |
|
545 | + * |
|
546 | + * @param string $dt_frmt string representation of date format defaults to 'F j, Y' |
|
547 | + * @return mixed string on success, FALSE on fail |
|
548 | + * @throws ReflectionException |
|
549 | + * @throws InvalidArgumentException |
|
550 | + * @throws InvalidInterfaceException |
|
551 | + * @throws InvalidDataTypeException |
|
552 | + * @throws EE_Error |
|
553 | + */ |
|
554 | + public function start_date($dt_frmt = '') |
|
555 | + { |
|
556 | + return $this->_show_datetime('D', 'start', $dt_frmt); |
|
557 | + } |
|
558 | + |
|
559 | + |
|
560 | + /** |
|
561 | + * Echoes start_date() |
|
562 | + * |
|
563 | + * @param string $dt_frmt |
|
564 | + * @throws ReflectionException |
|
565 | + * @throws InvalidArgumentException |
|
566 | + * @throws InvalidInterfaceException |
|
567 | + * @throws InvalidDataTypeException |
|
568 | + * @throws EE_Error |
|
569 | + */ |
|
570 | + public function e_start_date($dt_frmt = '') |
|
571 | + { |
|
572 | + $this->_show_datetime('D', 'start', $dt_frmt, null, true); |
|
573 | + } |
|
574 | + |
|
575 | + |
|
576 | + /** |
|
577 | + * get end date. Provide either the date format, or NULL to re-use the |
|
578 | + * last-used format, or '' to use the default date format |
|
579 | + * |
|
580 | + * @param string $dt_frmt string representation of date format defaults to 'F j, Y' |
|
581 | + * @return mixed string on success, FALSE on fail |
|
582 | + * @throws ReflectionException |
|
583 | + * @throws InvalidArgumentException |
|
584 | + * @throws InvalidInterfaceException |
|
585 | + * @throws InvalidDataTypeException |
|
586 | + * @throws EE_Error |
|
587 | + */ |
|
588 | + public function end_date($dt_frmt = '') |
|
589 | + { |
|
590 | + return $this->_show_datetime('D', 'end', $dt_frmt); |
|
591 | + } |
|
592 | + |
|
593 | + |
|
594 | + /** |
|
595 | + * Echoes the end date. See end_date() |
|
596 | + * |
|
597 | + * @param string $dt_frmt |
|
598 | + * @throws ReflectionException |
|
599 | + * @throws InvalidArgumentException |
|
600 | + * @throws InvalidInterfaceException |
|
601 | + * @throws InvalidDataTypeException |
|
602 | + * @throws EE_Error |
|
603 | + */ |
|
604 | + public function e_end_date($dt_frmt = '') |
|
605 | + { |
|
606 | + $this->_show_datetime('D', 'end', $dt_frmt, null, true); |
|
607 | + } |
|
608 | + |
|
609 | + |
|
610 | + /** |
|
611 | + * get date_range - meaning the start AND end date |
|
612 | + * |
|
613 | + * @access public |
|
614 | + * @param string $dt_frmt string representation of date format defaults to WP settings |
|
615 | + * @param string $conjunction conjunction junction what's your function ? |
|
616 | + * this string joins the start date with the end date ie: Jan 01 "to" Dec 31 |
|
617 | + * @return mixed string on success, FALSE on fail |
|
618 | + * @throws ReflectionException |
|
619 | + * @throws InvalidArgumentException |
|
620 | + * @throws InvalidInterfaceException |
|
621 | + * @throws InvalidDataTypeException |
|
622 | + * @throws EE_Error |
|
623 | + */ |
|
624 | + public function date_range($dt_frmt = '', $conjunction = ' - ') |
|
625 | + { |
|
626 | + $dt_frmt = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt; |
|
627 | + $start = str_replace( |
|
628 | + ' ', |
|
629 | + ' ', |
|
630 | + $this->get_i18n_datetime('DTT_EVT_start', $dt_frmt) |
|
631 | + ); |
|
632 | + $end = str_replace( |
|
633 | + ' ', |
|
634 | + ' ', |
|
635 | + $this->get_i18n_datetime('DTT_EVT_end', $dt_frmt) |
|
636 | + ); |
|
637 | + return $start !== $end ? $start . $conjunction . $end : $start; |
|
638 | + } |
|
639 | + |
|
640 | + |
|
641 | + /** |
|
642 | + * @param string $dt_frmt |
|
643 | + * @param string $conjunction |
|
644 | + * @throws ReflectionException |
|
645 | + * @throws InvalidArgumentException |
|
646 | + * @throws InvalidInterfaceException |
|
647 | + * @throws InvalidDataTypeException |
|
648 | + * @throws EE_Error |
|
649 | + */ |
|
650 | + public function e_date_range($dt_frmt = '', $conjunction = ' - ') |
|
651 | + { |
|
652 | + echo esc_html($this->date_range($dt_frmt, $conjunction)); |
|
653 | + } |
|
654 | + |
|
655 | + |
|
656 | + /** |
|
657 | + * get start time |
|
658 | + * |
|
659 | + * @param string $tm_format - string representation of time format defaults to 'g:i a' |
|
660 | + * @return mixed string on success, FALSE on fail |
|
661 | + * @throws ReflectionException |
|
662 | + * @throws InvalidArgumentException |
|
663 | + * @throws InvalidInterfaceException |
|
664 | + * @throws InvalidDataTypeException |
|
665 | + * @throws EE_Error |
|
666 | + */ |
|
667 | + public function start_time($tm_format = '') |
|
668 | + { |
|
669 | + return $this->_show_datetime('T', 'start', null, $tm_format); |
|
670 | + } |
|
671 | + |
|
672 | + |
|
673 | + /** |
|
674 | + * @param string $tm_format |
|
675 | + * @throws ReflectionException |
|
676 | + * @throws InvalidArgumentException |
|
677 | + * @throws InvalidInterfaceException |
|
678 | + * @throws InvalidDataTypeException |
|
679 | + * @throws EE_Error |
|
680 | + */ |
|
681 | + public function e_start_time($tm_format = '') |
|
682 | + { |
|
683 | + $this->_show_datetime('T', 'start', null, $tm_format, true); |
|
684 | + } |
|
685 | + |
|
686 | + |
|
687 | + /** |
|
688 | + * get end time |
|
689 | + * |
|
690 | + * @param string $tm_format string representation of time format defaults to 'g:i a' |
|
691 | + * @return mixed string on success, FALSE on fail |
|
692 | + * @throws ReflectionException |
|
693 | + * @throws InvalidArgumentException |
|
694 | + * @throws InvalidInterfaceException |
|
695 | + * @throws InvalidDataTypeException |
|
696 | + * @throws EE_Error |
|
697 | + */ |
|
698 | + public function end_time($tm_format = '') |
|
699 | + { |
|
700 | + return $this->_show_datetime('T', 'end', null, $tm_format); |
|
701 | + } |
|
702 | + |
|
703 | + |
|
704 | + /** |
|
705 | + * @param string $tm_format |
|
706 | + * @throws ReflectionException |
|
707 | + * @throws InvalidArgumentException |
|
708 | + * @throws InvalidInterfaceException |
|
709 | + * @throws InvalidDataTypeException |
|
710 | + * @throws EE_Error |
|
711 | + */ |
|
712 | + public function e_end_time($tm_format = '') |
|
713 | + { |
|
714 | + $this->_show_datetime('T', 'end', null, $tm_format, true); |
|
715 | + } |
|
716 | + |
|
717 | + |
|
718 | + /** |
|
719 | + * get time_range |
|
720 | + * |
|
721 | + * @access public |
|
722 | + * @param string $tm_format string representation of time format defaults to 'g:i a' |
|
723 | + * @param string $conjunction conjunction junction what's your function ? |
|
724 | + * this string joins the start date with the end date ie: Jan 01 "to" Dec 31 |
|
725 | + * @return mixed string on success, FALSE on fail |
|
726 | + * @throws ReflectionException |
|
727 | + * @throws InvalidArgumentException |
|
728 | + * @throws InvalidInterfaceException |
|
729 | + * @throws InvalidDataTypeException |
|
730 | + * @throws EE_Error |
|
731 | + */ |
|
732 | + public function time_range($tm_format = '', $conjunction = ' - ') |
|
733 | + { |
|
734 | + $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt; |
|
735 | + $start = str_replace( |
|
736 | + ' ', |
|
737 | + ' ', |
|
738 | + $this->get_i18n_datetime('DTT_EVT_start', $tm_format) |
|
739 | + ); |
|
740 | + $end = str_replace( |
|
741 | + ' ', |
|
742 | + ' ', |
|
743 | + $this->get_i18n_datetime('DTT_EVT_end', $tm_format) |
|
744 | + ); |
|
745 | + return $start !== $end ? $start . $conjunction . $end : $start; |
|
746 | + } |
|
747 | + |
|
748 | + |
|
749 | + /** |
|
750 | + * @param string $tm_format |
|
751 | + * @param string $conjunction |
|
752 | + * @throws ReflectionException |
|
753 | + * @throws InvalidArgumentException |
|
754 | + * @throws InvalidInterfaceException |
|
755 | + * @throws InvalidDataTypeException |
|
756 | + * @throws EE_Error |
|
757 | + */ |
|
758 | + public function e_time_range($tm_format = '', $conjunction = ' - ') |
|
759 | + { |
|
760 | + echo esc_html($this->time_range($tm_format, $conjunction)); |
|
761 | + } |
|
762 | + |
|
763 | + |
|
764 | + /** |
|
765 | + * This returns a range representation of the date and times. |
|
766 | + * Output is dependent on the difference (or similarity) between DTT_EVT_start and DTT_EVT_end. |
|
767 | + * Also, the return value is localized. |
|
768 | + * |
|
769 | + * @param string $dt_format |
|
770 | + * @param string $tm_format |
|
771 | + * @param string $conjunction used between two different dates or times. |
|
772 | + * ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm |
|
773 | + * @param string $separator used between the date and time formats. |
|
774 | + * ex: Dec 1, 2016{$separator}2pm |
|
775 | + * @return string |
|
776 | + * @throws ReflectionException |
|
777 | + * @throws InvalidArgumentException |
|
778 | + * @throws InvalidInterfaceException |
|
779 | + * @throws InvalidDataTypeException |
|
780 | + * @throws EE_Error |
|
781 | + */ |
|
782 | + public function date_and_time_range( |
|
783 | + $dt_format = '', |
|
784 | + $tm_format = '', |
|
785 | + $conjunction = ' - ', |
|
786 | + $separator = ' ' |
|
787 | + ) { |
|
788 | + $dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt; |
|
789 | + $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt; |
|
790 | + $full_format = $dt_format . $separator . $tm_format; |
|
791 | + // the range output depends on various conditions |
|
792 | + switch (true) { |
|
793 | + // start date timestamp and end date timestamp are the same. |
|
794 | + case ($this->get_raw('DTT_EVT_start') === $this->get_raw('DTT_EVT_end')): |
|
795 | + $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format); |
|
796 | + break; |
|
797 | + // start and end date are the same but times are different |
|
798 | + case ($this->start_date() === $this->end_date()): |
|
799 | + $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format) |
|
800 | + . $conjunction |
|
801 | + . $this->get_i18n_datetime('DTT_EVT_end', $tm_format); |
|
802 | + break; |
|
803 | + // all other conditions |
|
804 | + default: |
|
805 | + $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format) |
|
806 | + . $conjunction |
|
807 | + . $this->get_i18n_datetime('DTT_EVT_end', $full_format); |
|
808 | + break; |
|
809 | + } |
|
810 | + return $output; |
|
811 | + } |
|
812 | + |
|
813 | + |
|
814 | + /** |
|
815 | + * This echos the results of date and time range. |
|
816 | + * |
|
817 | + * @see date_and_time_range() for more details on purpose. |
|
818 | + * @param string $dt_format |
|
819 | + * @param string $tm_format |
|
820 | + * @param string $conjunction |
|
821 | + * @return void |
|
822 | + * @throws ReflectionException |
|
823 | + * @throws InvalidArgumentException |
|
824 | + * @throws InvalidInterfaceException |
|
825 | + * @throws InvalidDataTypeException |
|
826 | + * @throws EE_Error |
|
827 | + */ |
|
828 | + public function e_date_and_time_range($dt_format = '', $tm_format = '', $conjunction = ' - ') |
|
829 | + { |
|
830 | + echo esc_html($this->date_and_time_range($dt_format, $tm_format, $conjunction)); |
|
831 | + } |
|
832 | + |
|
833 | + |
|
834 | + /** |
|
835 | + * get start date and start time |
|
836 | + * |
|
837 | + * @param string $dt_format - string representation of date format defaults to 'F j, Y' |
|
838 | + * @param string $tm_format - string representation of time format defaults to 'g:i a' |
|
839 | + * @return mixed string on success, FALSE on fail |
|
840 | + * @throws ReflectionException |
|
841 | + * @throws InvalidArgumentException |
|
842 | + * @throws InvalidInterfaceException |
|
843 | + * @throws InvalidDataTypeException |
|
844 | + * @throws EE_Error |
|
845 | + */ |
|
846 | + public function start_date_and_time($dt_format = '', $tm_format = '') |
|
847 | + { |
|
848 | + return $this->_show_datetime('', 'start', $dt_format, $tm_format); |
|
849 | + } |
|
850 | + |
|
851 | + |
|
852 | + /** |
|
853 | + * @param string $dt_frmt |
|
854 | + * @param string $tm_format |
|
855 | + * @throws ReflectionException |
|
856 | + * @throws InvalidArgumentException |
|
857 | + * @throws InvalidInterfaceException |
|
858 | + * @throws InvalidDataTypeException |
|
859 | + * @throws EE_Error |
|
860 | + */ |
|
861 | + public function e_start_date_and_time($dt_frmt = '', $tm_format = '') |
|
862 | + { |
|
863 | + $this->_show_datetime('', 'start', $dt_frmt, $tm_format, true); |
|
864 | + } |
|
865 | + |
|
866 | + |
|
867 | + /** |
|
868 | + * Shows the length of the event (start to end time). |
|
869 | + * Can be shown in 'seconds','minutes','hours', or 'days'. |
|
870 | + * By default, rounds up. (So if you use 'days', and then event |
|
871 | + * only occurs for 1 hour, it will return 1 day). |
|
872 | + * |
|
873 | + * @param string $units 'seconds','minutes','hours','days' |
|
874 | + * @param bool $round_up |
|
875 | + * @return float|int|mixed |
|
876 | + * @throws ReflectionException |
|
877 | + * @throws InvalidArgumentException |
|
878 | + * @throws InvalidInterfaceException |
|
879 | + * @throws InvalidDataTypeException |
|
880 | + * @throws EE_Error |
|
881 | + */ |
|
882 | + public function length($units = 'seconds', $round_up = false) |
|
883 | + { |
|
884 | + $start = $this->get_raw('DTT_EVT_start'); |
|
885 | + $end = $this->get_raw('DTT_EVT_end'); |
|
886 | + $length_in_units = $end - $start; |
|
887 | + switch ($units) { |
|
888 | + // NOTE: We purposefully don't use "break;" in order to chain the divisions |
|
889 | + /** @noinspection PhpMissingBreakStatementInspection */ |
|
890 | + // phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment |
|
891 | + case 'days': |
|
892 | + $length_in_units /= 24; |
|
893 | + /** @noinspection PhpMissingBreakStatementInspection */ |
|
894 | + case 'hours': |
|
895 | + // fall through is intentional |
|
896 | + $length_in_units /= 60; |
|
897 | + /** @noinspection PhpMissingBreakStatementInspection */ |
|
898 | + case 'minutes': |
|
899 | + // fall through is intentional |
|
900 | + $length_in_units /= 60; |
|
901 | + case 'seconds': |
|
902 | + default: |
|
903 | + $length_in_units = ceil($length_in_units); |
|
904 | + } |
|
905 | + // phpcs:enable |
|
906 | + if ($round_up) { |
|
907 | + $length_in_units = max($length_in_units, 1); |
|
908 | + } |
|
909 | + return $length_in_units; |
|
910 | + } |
|
911 | + |
|
912 | + |
|
913 | + /** |
|
914 | + * get end date and time |
|
915 | + * |
|
916 | + * @param string $dt_frmt - string representation of date format defaults to 'F j, Y' |
|
917 | + * @param string $tm_format - string representation of time format defaults to 'g:i a' |
|
918 | + * @return mixed string on success, FALSE on fail |
|
919 | + * @throws ReflectionException |
|
920 | + * @throws InvalidArgumentException |
|
921 | + * @throws InvalidInterfaceException |
|
922 | + * @throws InvalidDataTypeException |
|
923 | + * @throws EE_Error |
|
924 | + */ |
|
925 | + public function end_date_and_time($dt_frmt = '', $tm_format = '') |
|
926 | + { |
|
927 | + return $this->_show_datetime('', 'end', $dt_frmt, $tm_format); |
|
928 | + } |
|
929 | + |
|
930 | + |
|
931 | + /** |
|
932 | + * @param string $dt_frmt |
|
933 | + * @param string $tm_format |
|
934 | + * @throws ReflectionException |
|
935 | + * @throws InvalidArgumentException |
|
936 | + * @throws InvalidInterfaceException |
|
937 | + * @throws InvalidDataTypeException |
|
938 | + * @throws EE_Error |
|
939 | + */ |
|
940 | + public function e_end_date_and_time($dt_frmt = '', $tm_format = '') |
|
941 | + { |
|
942 | + $this->_show_datetime('', 'end', $dt_frmt, $tm_format, true); |
|
943 | + } |
|
944 | + |
|
945 | + |
|
946 | + /** |
|
947 | + * get start timestamp |
|
948 | + * |
|
949 | + * @return int |
|
950 | + * @throws ReflectionException |
|
951 | + * @throws InvalidArgumentException |
|
952 | + * @throws InvalidInterfaceException |
|
953 | + * @throws InvalidDataTypeException |
|
954 | + * @throws EE_Error |
|
955 | + */ |
|
956 | + public function start() |
|
957 | + { |
|
958 | + return $this->get_raw('DTT_EVT_start'); |
|
959 | + } |
|
960 | + |
|
961 | + |
|
962 | + /** |
|
963 | + * get end timestamp |
|
964 | + * |
|
965 | + * @return int |
|
966 | + * @throws ReflectionException |
|
967 | + * @throws InvalidArgumentException |
|
968 | + * @throws InvalidInterfaceException |
|
969 | + * @throws InvalidDataTypeException |
|
970 | + * @throws EE_Error |
|
971 | + */ |
|
972 | + public function end() |
|
973 | + { |
|
974 | + return $this->get_raw('DTT_EVT_end'); |
|
975 | + } |
|
976 | + |
|
977 | + |
|
978 | + /** |
|
979 | + * get the registration limit for this datetime slot |
|
980 | + * |
|
981 | + * @return int|float int = finite limit EE_INF(float) = unlimited |
|
982 | + * @throws ReflectionException |
|
983 | + * @throws InvalidArgumentException |
|
984 | + * @throws InvalidInterfaceException |
|
985 | + * @throws InvalidDataTypeException |
|
986 | + * @throws EE_Error |
|
987 | + */ |
|
988 | + public function reg_limit() |
|
989 | + { |
|
990 | + return $this->get_raw('DTT_reg_limit'); |
|
991 | + } |
|
992 | + |
|
993 | + |
|
994 | + /** |
|
995 | + * have the tickets sold for this datetime, met or exceed the registration limit ? |
|
996 | + * |
|
997 | + * @return boolean |
|
998 | + * @throws ReflectionException |
|
999 | + * @throws InvalidArgumentException |
|
1000 | + * @throws InvalidInterfaceException |
|
1001 | + * @throws InvalidDataTypeException |
|
1002 | + * @throws EE_Error |
|
1003 | + */ |
|
1004 | + public function sold_out() |
|
1005 | + { |
|
1006 | + return $this->reg_limit() > 0 && $this->sold() >= $this->reg_limit(); |
|
1007 | + } |
|
1008 | + |
|
1009 | + |
|
1010 | + /** |
|
1011 | + * return the total number of spaces remaining at this venue. |
|
1012 | + * This only takes the venue's capacity into account, NOT the tickets available for sale |
|
1013 | + * |
|
1014 | + * @param bool $consider_tickets Whether to consider tickets remaining when determining if there are any spaces left |
|
1015 | + * Because if all tickets attached to this datetime have no spaces left, |
|
1016 | + * then this datetime IS effectively sold out. |
|
1017 | + * However, there are cases where we just want to know the spaces |
|
1018 | + * remaining for this particular datetime, hence the flag. |
|
1019 | + * @return int|float |
|
1020 | + * @throws ReflectionException |
|
1021 | + * @throws InvalidArgumentException |
|
1022 | + * @throws InvalidInterfaceException |
|
1023 | + * @throws InvalidDataTypeException |
|
1024 | + * @throws EE_Error |
|
1025 | + */ |
|
1026 | + public function spaces_remaining($consider_tickets = false) |
|
1027 | + { |
|
1028 | + // tickets remaining available for purchase |
|
1029 | + // no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF |
|
1030 | + $dtt_remaining = $this->reg_limit() - $this->sold_and_reserved(); |
|
1031 | + if (! $consider_tickets) { |
|
1032 | + return $dtt_remaining; |
|
1033 | + } |
|
1034 | + $tickets_remaining = $this->tickets_remaining(); |
|
1035 | + return min($dtt_remaining, $tickets_remaining); |
|
1036 | + } |
|
1037 | + |
|
1038 | + |
|
1039 | + /** |
|
1040 | + * Counts the total tickets available |
|
1041 | + * (from all the different types of tickets which are available for this datetime). |
|
1042 | + * |
|
1043 | + * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1044 | + * @return int |
|
1045 | + * @throws ReflectionException |
|
1046 | + * @throws InvalidArgumentException |
|
1047 | + * @throws InvalidInterfaceException |
|
1048 | + * @throws InvalidDataTypeException |
|
1049 | + * @throws EE_Error |
|
1050 | + */ |
|
1051 | + public function tickets_remaining($query_params = array()) |
|
1052 | + { |
|
1053 | + $sum = 0; |
|
1054 | + $tickets = $this->tickets($query_params); |
|
1055 | + if (! empty($tickets)) { |
|
1056 | + foreach ($tickets as $ticket) { |
|
1057 | + if ($ticket instanceof EE_Ticket) { |
|
1058 | + // get the actual amount of tickets that can be sold |
|
1059 | + $qty = $ticket->qty('saleable'); |
|
1060 | + if ($qty === EE_INF) { |
|
1061 | + return EE_INF; |
|
1062 | + } |
|
1063 | + // no negative ticket quantities plz |
|
1064 | + if ($qty > 0) { |
|
1065 | + $sum += $qty; |
|
1066 | + } |
|
1067 | + } |
|
1068 | + } |
|
1069 | + } |
|
1070 | + return $sum; |
|
1071 | + } |
|
1072 | + |
|
1073 | + |
|
1074 | + /** |
|
1075 | + * Gets the count of all the tickets available at this datetime (not ticket types) |
|
1076 | + * before any were sold |
|
1077 | + * |
|
1078 | + * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1079 | + * @return int |
|
1080 | + * @throws ReflectionException |
|
1081 | + * @throws InvalidArgumentException |
|
1082 | + * @throws InvalidInterfaceException |
|
1083 | + * @throws InvalidDataTypeException |
|
1084 | + * @throws EE_Error |
|
1085 | + */ |
|
1086 | + public function sum_tickets_initially_available($query_params = array()) |
|
1087 | + { |
|
1088 | + return $this->sum_related('Ticket', $query_params, 'TKT_qty'); |
|
1089 | + } |
|
1090 | + |
|
1091 | + |
|
1092 | + /** |
|
1093 | + * Returns the lesser-of-the two: spaces remaining at this datetime, or |
|
1094 | + * the total tickets remaining (a sum of the tickets remaining for each ticket type |
|
1095 | + * that is available for this datetime). |
|
1096 | + * |
|
1097 | + * @return int |
|
1098 | + * @throws ReflectionException |
|
1099 | + * @throws InvalidArgumentException |
|
1100 | + * @throws InvalidInterfaceException |
|
1101 | + * @throws InvalidDataTypeException |
|
1102 | + * @throws EE_Error |
|
1103 | + */ |
|
1104 | + public function total_tickets_available_at_this_datetime() |
|
1105 | + { |
|
1106 | + return $this->spaces_remaining(true); |
|
1107 | + } |
|
1108 | + |
|
1109 | + |
|
1110 | + /** |
|
1111 | + * This simply compares the internal dtt for the given string with NOW |
|
1112 | + * and determines if the date is upcoming or not. |
|
1113 | + * |
|
1114 | + * @access public |
|
1115 | + * @return boolean |
|
1116 | + * @throws ReflectionException |
|
1117 | + * @throws InvalidArgumentException |
|
1118 | + * @throws InvalidInterfaceException |
|
1119 | + * @throws InvalidDataTypeException |
|
1120 | + * @throws EE_Error |
|
1121 | + */ |
|
1122 | + public function is_upcoming() |
|
1123 | + { |
|
1124 | + return ($this->get_raw('DTT_EVT_start') > time()); |
|
1125 | + } |
|
1126 | + |
|
1127 | + |
|
1128 | + /** |
|
1129 | + * This simply compares the internal datetime for the given string with NOW |
|
1130 | + * and returns if the date is active (i.e. start and end time) |
|
1131 | + * |
|
1132 | + * @return boolean |
|
1133 | + * @throws ReflectionException |
|
1134 | + * @throws InvalidArgumentException |
|
1135 | + * @throws InvalidInterfaceException |
|
1136 | + * @throws InvalidDataTypeException |
|
1137 | + * @throws EE_Error |
|
1138 | + */ |
|
1139 | + public function is_active() |
|
1140 | + { |
|
1141 | + return ($this->get_raw('DTT_EVT_start') < time() && $this->get_raw('DTT_EVT_end') > time()); |
|
1142 | + } |
|
1143 | + |
|
1144 | + |
|
1145 | + /** |
|
1146 | + * This simply compares the internal dtt for the given string with NOW |
|
1147 | + * and determines if the date is expired or not. |
|
1148 | + * |
|
1149 | + * @return boolean |
|
1150 | + * @throws ReflectionException |
|
1151 | + * @throws InvalidArgumentException |
|
1152 | + * @throws InvalidInterfaceException |
|
1153 | + * @throws InvalidDataTypeException |
|
1154 | + * @throws EE_Error |
|
1155 | + */ |
|
1156 | + public function is_expired() |
|
1157 | + { |
|
1158 | + return ($this->get_raw('DTT_EVT_end') < time()); |
|
1159 | + } |
|
1160 | + |
|
1161 | + |
|
1162 | + /** |
|
1163 | + * This returns the active status for whether an event is active, upcoming, or expired |
|
1164 | + * |
|
1165 | + * @return int return value will be one of the EE_Datetime status constants. |
|
1166 | + * @throws ReflectionException |
|
1167 | + * @throws InvalidArgumentException |
|
1168 | + * @throws InvalidInterfaceException |
|
1169 | + * @throws InvalidDataTypeException |
|
1170 | + * @throws EE_Error |
|
1171 | + */ |
|
1172 | + public function get_active_status() |
|
1173 | + { |
|
1174 | + $total_tickets_for_this_dtt = $this->total_tickets_available_at_this_datetime(); |
|
1175 | + if ($total_tickets_for_this_dtt !== false && $total_tickets_for_this_dtt < 1) { |
|
1176 | + return EE_Datetime::sold_out; |
|
1177 | + } |
|
1178 | + if ($this->is_expired()) { |
|
1179 | + return EE_Datetime::expired; |
|
1180 | + } |
|
1181 | + if ($this->is_upcoming()) { |
|
1182 | + return EE_Datetime::upcoming; |
|
1183 | + } |
|
1184 | + if ($this->is_active()) { |
|
1185 | + return EE_Datetime::active; |
|
1186 | + } |
|
1187 | + return null; |
|
1188 | + } |
|
1189 | + |
|
1190 | + |
|
1191 | + /** |
|
1192 | + * This returns a nice display name for the datetime that is contingent on the span between the dates and times. |
|
1193 | + * |
|
1194 | + * @param boolean $use_dtt_name if TRUE then we'll use DTT->name() if its not empty. |
|
1195 | + * @return string |
|
1196 | + * @throws ReflectionException |
|
1197 | + * @throws InvalidArgumentException |
|
1198 | + * @throws InvalidInterfaceException |
|
1199 | + * @throws InvalidDataTypeException |
|
1200 | + * @throws EE_Error |
|
1201 | + */ |
|
1202 | + public function get_dtt_display_name($use_dtt_name = false) |
|
1203 | + { |
|
1204 | + if ($use_dtt_name) { |
|
1205 | + $dtt_name = $this->name(); |
|
1206 | + if (! empty($dtt_name)) { |
|
1207 | + return $dtt_name; |
|
1208 | + } |
|
1209 | + } |
|
1210 | + // first condition is to see if the months are different |
|
1211 | + if ( |
|
1212 | + date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end')) |
|
1213 | + ) { |
|
1214 | + $display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a'); |
|
1215 | + // next condition is if its the same month but different day |
|
1216 | + } else { |
|
1217 | + if ( |
|
1218 | + date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end')) |
|
1219 | + && date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end')) |
|
1220 | + ) { |
|
1221 | + $display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y'); |
|
1222 | + } else { |
|
1223 | + $display_date = $this->start_date('F j\, Y') |
|
1224 | + . ' @ ' |
|
1225 | + . $this->start_date('g:i a') |
|
1226 | + . ' - ' |
|
1227 | + . $this->end_date('g:i a'); |
|
1228 | + } |
|
1229 | + } |
|
1230 | + return $display_date; |
|
1231 | + } |
|
1232 | + |
|
1233 | + |
|
1234 | + /** |
|
1235 | + * Gets all the tickets for this datetime |
|
1236 | + * |
|
1237 | + * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1238 | + * @return EE_Base_Class[]|EE_Ticket[] |
|
1239 | + * @throws ReflectionException |
|
1240 | + * @throws InvalidArgumentException |
|
1241 | + * @throws InvalidInterfaceException |
|
1242 | + * @throws InvalidDataTypeException |
|
1243 | + * @throws EE_Error |
|
1244 | + */ |
|
1245 | + public function tickets($query_params = array()) |
|
1246 | + { |
|
1247 | + return $this->get_many_related('Ticket', $query_params); |
|
1248 | + } |
|
1249 | + |
|
1250 | + |
|
1251 | + /** |
|
1252 | + * Gets all the ticket types currently available for purchase |
|
1253 | + * |
|
1254 | + * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1255 | + * @return EE_Ticket[] |
|
1256 | + * @throws ReflectionException |
|
1257 | + * @throws InvalidArgumentException |
|
1258 | + * @throws InvalidInterfaceException |
|
1259 | + * @throws InvalidDataTypeException |
|
1260 | + * @throws EE_Error |
|
1261 | + */ |
|
1262 | + public function ticket_types_available_for_purchase($query_params = array()) |
|
1263 | + { |
|
1264 | + // first check if datetime is valid |
|
1265 | + if ($this->sold_out() || ! ($this->is_upcoming() || $this->is_active())) { |
|
1266 | + return array(); |
|
1267 | + } |
|
1268 | + if (empty($query_params)) { |
|
1269 | + $query_params = array( |
|
1270 | + array( |
|
1271 | + 'TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')), |
|
1272 | + 'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')), |
|
1273 | + 'TKT_deleted' => false, |
|
1274 | + ), |
|
1275 | + ); |
|
1276 | + } |
|
1277 | + return $this->tickets($query_params); |
|
1278 | + } |
|
1279 | + |
|
1280 | + |
|
1281 | + /** |
|
1282 | + * @return EE_Base_Class|EE_Event |
|
1283 | + * @throws ReflectionException |
|
1284 | + * @throws InvalidArgumentException |
|
1285 | + * @throws InvalidInterfaceException |
|
1286 | + * @throws InvalidDataTypeException |
|
1287 | + * @throws EE_Error |
|
1288 | + */ |
|
1289 | + public function event() |
|
1290 | + { |
|
1291 | + return $this->get_first_related('Event'); |
|
1292 | + } |
|
1293 | + |
|
1294 | + |
|
1295 | + /** |
|
1296 | + * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime |
|
1297 | + * (via the tickets). |
|
1298 | + * |
|
1299 | + * @return int |
|
1300 | + * @throws ReflectionException |
|
1301 | + * @throws InvalidArgumentException |
|
1302 | + * @throws InvalidInterfaceException |
|
1303 | + * @throws InvalidDataTypeException |
|
1304 | + * @throws EE_Error |
|
1305 | + */ |
|
1306 | + public function update_sold() |
|
1307 | + { |
|
1308 | + $count_regs_for_this_datetime = EEM_Registration::instance()->count( |
|
1309 | + array( |
|
1310 | + array( |
|
1311 | + 'STS_ID' => EEM_Registration::status_id_approved, |
|
1312 | + 'REG_deleted' => 0, |
|
1313 | + 'Ticket.Datetime.DTT_ID' => $this->ID(), |
|
1314 | + ), |
|
1315 | + ) |
|
1316 | + ); |
|
1317 | + $this->set_sold($count_regs_for_this_datetime); |
|
1318 | + $this->save(); |
|
1319 | + return $count_regs_for_this_datetime; |
|
1320 | + } |
|
1321 | + |
|
1322 | + |
|
1323 | + /** |
|
1324 | + * Adds a venue to this event |
|
1325 | + * |
|
1326 | + * @param int|EE_Venue /int $venue_id_or_obj |
|
1327 | + * @return EE_Base_Class|EE_Venue |
|
1328 | + * @throws EE_Error |
|
1329 | + * @throws ReflectionException |
|
1330 | + */ |
|
1331 | + public function add_venue($venue_id_or_obj) |
|
1332 | + { |
|
1333 | + return $this->_add_relation_to($venue_id_or_obj, 'Venue'); |
|
1334 | + } |
|
1335 | + |
|
1336 | + |
|
1337 | + /** |
|
1338 | + * Removes a venue from the event |
|
1339 | + * |
|
1340 | + * @param EE_Venue /int $venue_id_or_obj |
|
1341 | + * @return EE_Base_Class|EE_Venue |
|
1342 | + * @throws EE_Error |
|
1343 | + * @throws ReflectionException |
|
1344 | + */ |
|
1345 | + public function remove_venue($venue_id_or_obj) |
|
1346 | + { |
|
1347 | + $venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue(); |
|
1348 | + return $this->_remove_relation_to($venue_id_or_obj, 'Venue'); |
|
1349 | + } |
|
1350 | + |
|
1351 | + |
|
1352 | + /** |
|
1353 | + * Gets the venue related to the event. May provide additional $query_params if desired |
|
1354 | + * |
|
1355 | + * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1356 | + * @return int |
|
1357 | + * @throws EE_Error |
|
1358 | + * @throws ReflectionException |
|
1359 | + */ |
|
1360 | + public function venue_ID($query_params = []) |
|
1361 | + { |
|
1362 | + $venue = $this->get_first_related('Venue', $query_params); |
|
1363 | + return $venue instanceof EE_Venue |
|
1364 | + ? $venue->ID() |
|
1365 | + : 0; |
|
1366 | + } |
|
1367 | + |
|
1368 | + |
|
1369 | + /** |
|
1370 | + * Gets the venue related to the event. May provide additional $query_params if desired |
|
1371 | + * |
|
1372 | + * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1373 | + * @return EE_Base_Class|EE_Venue |
|
1374 | + * @throws EE_Error |
|
1375 | + * @throws ReflectionException |
|
1376 | + */ |
|
1377 | + public function venue($query_params = []) |
|
1378 | + { |
|
1379 | + return $this->get_first_related('Venue', $query_params); |
|
1380 | + } |
|
1381 | + |
|
1382 | + |
|
1383 | + /** |
|
1384 | + * @param EE_Base_Class|int|string $otherObjectModelObjectOrID |
|
1385 | + * @param string $relationName |
|
1386 | + * @param array $extra_join_model_fields_n_values |
|
1387 | + * @param string|null $cache_id |
|
1388 | + * @return EE_Base_Class |
|
1389 | + * @throws EE_Error |
|
1390 | + * @throws ReflectionException |
|
1391 | + * @since $VID:$ |
|
1392 | + */ |
|
1393 | + public function _add_relation_to( |
|
1394 | + $otherObjectModelObjectOrID, |
|
1395 | + $relationName, |
|
1396 | + $extra_join_model_fields_n_values = [], |
|
1397 | + $cache_id = null |
|
1398 | + ) { |
|
1399 | + // if we're adding a new relation to a ticket |
|
1400 | + if ($relationName === 'Ticket' && ! $this->hasRelation($otherObjectModelObjectOrID, $relationName)) { |
|
1401 | + /** @var EE_Ticket $ticket */ |
|
1402 | + $ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID); |
|
1403 | + $this->increaseSold($ticket->sold(), false); |
|
1404 | + $this->increaseReserved($ticket->reserved()); |
|
1405 | + $this->save(); |
|
1406 | + $otherObjectModelObjectOrID = $ticket; |
|
1407 | + } |
|
1408 | + return parent::_add_relation_to( |
|
1409 | + $otherObjectModelObjectOrID, |
|
1410 | + $relationName, |
|
1411 | + $extra_join_model_fields_n_values, |
|
1412 | + $cache_id |
|
1413 | + ); |
|
1414 | + } |
|
1415 | + |
|
1416 | + |
|
1417 | + /** |
|
1418 | + * @param EE_Base_Class|int|string $otherObjectModelObjectOrID |
|
1419 | + * @param string $relationName |
|
1420 | + * @param array $where_query |
|
1421 | + * @return bool|EE_Base_Class|null |
|
1422 | + * @throws EE_Error |
|
1423 | + * @throws ReflectionException |
|
1424 | + * @since $VID:$ |
|
1425 | + */ |
|
1426 | + public function _remove_relation_to($otherObjectModelObjectOrID, $relationName, $where_query = []) |
|
1427 | + { |
|
1428 | + if ($relationName === 'Ticket' && $this->hasRelation($otherObjectModelObjectOrID, $relationName)) { |
|
1429 | + /** @var EE_Ticket $ticket */ |
|
1430 | + $ticket = EEM_Ticket::instance()->ensure_is_obj($otherObjectModelObjectOrID); |
|
1431 | + $this->decreaseSold($ticket->sold()); |
|
1432 | + $this->decreaseReserved($ticket->reserved()); |
|
1433 | + $this->save(); |
|
1434 | + $otherObjectModelObjectOrID = $ticket; |
|
1435 | + } |
|
1436 | + return parent::_remove_relation_to( |
|
1437 | + $otherObjectModelObjectOrID, |
|
1438 | + $relationName, |
|
1439 | + $where_query |
|
1440 | + ); |
|
1441 | + } |
|
1442 | + |
|
1443 | + |
|
1444 | + /** |
|
1445 | + * Removes ALL the related things for the $relationName. |
|
1446 | + * |
|
1447 | + * @param string $relationName |
|
1448 | + * @param array $where_query_params |
|
1449 | + * @return EE_Base_Class |
|
1450 | + * @throws ReflectionException |
|
1451 | + * @throws InvalidArgumentException |
|
1452 | + * @throws InvalidInterfaceException |
|
1453 | + * @throws InvalidDataTypeException |
|
1454 | + * @throws EE_Error |
|
1455 | + * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions |
|
1456 | + */ |
|
1457 | + public function _remove_relations($relationName, $where_query_params = []) |
|
1458 | + { |
|
1459 | + if ($relationName === 'Ticket') { |
|
1460 | + $tickets = $this->tickets(); |
|
1461 | + foreach ($tickets as $ticket) { |
|
1462 | + $this->decreaseSold($ticket->sold()); |
|
1463 | + $this->decreaseReserved($ticket->reserved()); |
|
1464 | + $this->save(); |
|
1465 | + } |
|
1466 | + } |
|
1467 | + return parent::_remove_relations($relationName, $where_query_params); |
|
1468 | + } |
|
1469 | + |
|
1470 | + |
|
1471 | + /******************************************************************* |
|
1472 | 1472 | *********************** DEPRECATED METHODS ********************** |
1473 | 1473 | *******************************************************************/ |
1474 | 1474 | |
1475 | 1475 | |
1476 | - /** |
|
1477 | - * Increments sold by amount passed by $qty, and persists it immediately to the database. |
|
1478 | - * |
|
1479 | - * @deprecated 4.9.80.p |
|
1480 | - * @param int $qty |
|
1481 | - * @return boolean |
|
1482 | - * @throws ReflectionException |
|
1483 | - * @throws InvalidArgumentException |
|
1484 | - * @throws InvalidInterfaceException |
|
1485 | - * @throws InvalidDataTypeException |
|
1486 | - * @throws EE_Error |
|
1487 | - */ |
|
1488 | - public function increase_sold($qty = 1) |
|
1489 | - { |
|
1490 | - EE_Error::doing_it_wrong( |
|
1491 | - __FUNCTION__, |
|
1492 | - esc_html__('Please use EE_Datetime::increaseSold() instead', 'event_espresso'), |
|
1493 | - '4.9.80.p', |
|
1494 | - '5.0.0.p' |
|
1495 | - ); |
|
1496 | - return $this->increaseSold($qty); |
|
1497 | - } |
|
1498 | - |
|
1499 | - |
|
1500 | - /** |
|
1501 | - * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need |
|
1502 | - * to save afterwards.) |
|
1503 | - * |
|
1504 | - * @deprecated 4.9.80.p |
|
1505 | - * @param int $qty |
|
1506 | - * @return boolean |
|
1507 | - * @throws ReflectionException |
|
1508 | - * @throws InvalidArgumentException |
|
1509 | - * @throws InvalidInterfaceException |
|
1510 | - * @throws InvalidDataTypeException |
|
1511 | - * @throws EE_Error |
|
1512 | - */ |
|
1513 | - public function decrease_sold($qty = 1) |
|
1514 | - { |
|
1515 | - EE_Error::doing_it_wrong( |
|
1516 | - __FUNCTION__, |
|
1517 | - esc_html__('Please use EE_Datetime::decreaseSold() instead', 'event_espresso'), |
|
1518 | - '4.9.80.p', |
|
1519 | - '5.0.0.p' |
|
1520 | - ); |
|
1521 | - return $this->decreaseSold($qty); |
|
1522 | - } |
|
1523 | - |
|
1524 | - |
|
1525 | - /** |
|
1526 | - * Increments reserved by amount passed by $qty, and persists it immediately to the database. |
|
1527 | - * |
|
1528 | - * @deprecated 4.9.80.p |
|
1529 | - * @param int $qty |
|
1530 | - * @return boolean indicating success |
|
1531 | - * @throws ReflectionException |
|
1532 | - * @throws InvalidArgumentException |
|
1533 | - * @throws InvalidInterfaceException |
|
1534 | - * @throws InvalidDataTypeException |
|
1535 | - * @throws EE_Error |
|
1536 | - */ |
|
1537 | - public function increase_reserved($qty = 1) |
|
1538 | - { |
|
1539 | - EE_Error::doing_it_wrong( |
|
1540 | - __FUNCTION__, |
|
1541 | - esc_html__('Please use EE_Datetime::increaseReserved() instead', 'event_espresso'), |
|
1542 | - '4.9.80.p', |
|
1543 | - '5.0.0.p' |
|
1544 | - ); |
|
1545 | - return $this->increaseReserved($qty); |
|
1546 | - } |
|
1547 | - |
|
1548 | - |
|
1549 | - /** |
|
1550 | - * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database. |
|
1551 | - * |
|
1552 | - * @deprecated 4.9.80.p |
|
1553 | - * @param int $qty |
|
1554 | - * @return boolean |
|
1555 | - * @throws ReflectionException |
|
1556 | - * @throws InvalidArgumentException |
|
1557 | - * @throws InvalidInterfaceException |
|
1558 | - * @throws InvalidDataTypeException |
|
1559 | - * @throws EE_Error |
|
1560 | - */ |
|
1561 | - public function decrease_reserved($qty = 1) |
|
1562 | - { |
|
1563 | - EE_Error::doing_it_wrong( |
|
1564 | - __FUNCTION__, |
|
1565 | - esc_html__('Please use EE_Datetime::decreaseReserved() instead', 'event_espresso'), |
|
1566 | - '4.9.80.p', |
|
1567 | - '5.0.0.p' |
|
1568 | - ); |
|
1569 | - return $this->decreaseReserved($qty); |
|
1570 | - } |
|
1476 | + /** |
|
1477 | + * Increments sold by amount passed by $qty, and persists it immediately to the database. |
|
1478 | + * |
|
1479 | + * @deprecated 4.9.80.p |
|
1480 | + * @param int $qty |
|
1481 | + * @return boolean |
|
1482 | + * @throws ReflectionException |
|
1483 | + * @throws InvalidArgumentException |
|
1484 | + * @throws InvalidInterfaceException |
|
1485 | + * @throws InvalidDataTypeException |
|
1486 | + * @throws EE_Error |
|
1487 | + */ |
|
1488 | + public function increase_sold($qty = 1) |
|
1489 | + { |
|
1490 | + EE_Error::doing_it_wrong( |
|
1491 | + __FUNCTION__, |
|
1492 | + esc_html__('Please use EE_Datetime::increaseSold() instead', 'event_espresso'), |
|
1493 | + '4.9.80.p', |
|
1494 | + '5.0.0.p' |
|
1495 | + ); |
|
1496 | + return $this->increaseSold($qty); |
|
1497 | + } |
|
1498 | + |
|
1499 | + |
|
1500 | + /** |
|
1501 | + * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need |
|
1502 | + * to save afterwards.) |
|
1503 | + * |
|
1504 | + * @deprecated 4.9.80.p |
|
1505 | + * @param int $qty |
|
1506 | + * @return boolean |
|
1507 | + * @throws ReflectionException |
|
1508 | + * @throws InvalidArgumentException |
|
1509 | + * @throws InvalidInterfaceException |
|
1510 | + * @throws InvalidDataTypeException |
|
1511 | + * @throws EE_Error |
|
1512 | + */ |
|
1513 | + public function decrease_sold($qty = 1) |
|
1514 | + { |
|
1515 | + EE_Error::doing_it_wrong( |
|
1516 | + __FUNCTION__, |
|
1517 | + esc_html__('Please use EE_Datetime::decreaseSold() instead', 'event_espresso'), |
|
1518 | + '4.9.80.p', |
|
1519 | + '5.0.0.p' |
|
1520 | + ); |
|
1521 | + return $this->decreaseSold($qty); |
|
1522 | + } |
|
1523 | + |
|
1524 | + |
|
1525 | + /** |
|
1526 | + * Increments reserved by amount passed by $qty, and persists it immediately to the database. |
|
1527 | + * |
|
1528 | + * @deprecated 4.9.80.p |
|
1529 | + * @param int $qty |
|
1530 | + * @return boolean indicating success |
|
1531 | + * @throws ReflectionException |
|
1532 | + * @throws InvalidArgumentException |
|
1533 | + * @throws InvalidInterfaceException |
|
1534 | + * @throws InvalidDataTypeException |
|
1535 | + * @throws EE_Error |
|
1536 | + */ |
|
1537 | + public function increase_reserved($qty = 1) |
|
1538 | + { |
|
1539 | + EE_Error::doing_it_wrong( |
|
1540 | + __FUNCTION__, |
|
1541 | + esc_html__('Please use EE_Datetime::increaseReserved() instead', 'event_espresso'), |
|
1542 | + '4.9.80.p', |
|
1543 | + '5.0.0.p' |
|
1544 | + ); |
|
1545 | + return $this->increaseReserved($qty); |
|
1546 | + } |
|
1547 | + |
|
1548 | + |
|
1549 | + /** |
|
1550 | + * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database. |
|
1551 | + * |
|
1552 | + * @deprecated 4.9.80.p |
|
1553 | + * @param int $qty |
|
1554 | + * @return boolean |
|
1555 | + * @throws ReflectionException |
|
1556 | + * @throws InvalidArgumentException |
|
1557 | + * @throws InvalidInterfaceException |
|
1558 | + * @throws InvalidDataTypeException |
|
1559 | + * @throws EE_Error |
|
1560 | + */ |
|
1561 | + public function decrease_reserved($qty = 1) |
|
1562 | + { |
|
1563 | + EE_Error::doing_it_wrong( |
|
1564 | + __FUNCTION__, |
|
1565 | + esc_html__('Please use EE_Datetime::decreaseReserved() instead', 'event_espresso'), |
|
1566 | + '4.9.80.p', |
|
1567 | + '5.0.0.p' |
|
1568 | + ); |
|
1569 | + return $this->decreaseReserved($qty); |
|
1570 | + } |
|
1571 | 1571 | } |