Completed
Branch FIX/fatal-error-in-ProcessTick... (711b33)
by
unknown
24:40 queued 16:48
created
core/services/commands/attendee/CreateAttendeeCommand.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -81,7 +81,7 @@
 block discarded – undo
81 81
     public function getCapCheck()
82 82
     {
83 83
         // need cap for non-AJAX admin requests
84
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
84
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
85 85
             return new CapCheck('ee_edit_contacts', 'create_new_contact');
86 86
         }
87 87
         return new PublicCapabilities('', 'create_new_contact');
Please login to merge, or discard this patch.
Indentation   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -20,62 +20,62 @@
 block discarded – undo
20 20
 class CreateAttendeeCommand extends Command implements CommandRequiresCapCheckInterface
21 21
 {
22 22
 
23
-    /**
24
-     * array of details where keys are names of EEM_Attendee model fields
25
-     *
26
-     * @var array $attendee_details
27
-     */
28
-    protected $attendee_details;
23
+	/**
24
+	 * array of details where keys are names of EEM_Attendee model fields
25
+	 *
26
+	 * @var array $attendee_details
27
+	 */
28
+	protected $attendee_details;
29 29
 
30
-    /**
31
-     * an existing registration to associate this attendee with
32
-     *
33
-     * @var EE_Registration $registration
34
-     */
35
-    protected $registration;
30
+	/**
31
+	 * an existing registration to associate this attendee with
32
+	 *
33
+	 * @var EE_Registration $registration
34
+	 */
35
+	protected $registration;
36 36
 
37 37
 
38
-    /**
39
-     * CreateAttendeeCommand constructor.
40
-     *
41
-     * @param array           $attendee_details
42
-     * @param EE_Registration $registration
43
-     */
44
-    public function __construct(array $attendee_details, EE_Registration $registration)
45
-    {
46
-        $this->attendee_details = $attendee_details;
47
-        $this->registration = $registration;
48
-    }
38
+	/**
39
+	 * CreateAttendeeCommand constructor.
40
+	 *
41
+	 * @param array           $attendee_details
42
+	 * @param EE_Registration $registration
43
+	 */
44
+	public function __construct(array $attendee_details, EE_Registration $registration)
45
+	{
46
+		$this->attendee_details = $attendee_details;
47
+		$this->registration = $registration;
48
+	}
49 49
 
50 50
 
51
-    /**
52
-     * @return array
53
-     */
54
-    public function attendeeDetails()
55
-    {
56
-        return $this->attendee_details;
57
-    }
51
+	/**
52
+	 * @return array
53
+	 */
54
+	public function attendeeDetails()
55
+	{
56
+		return $this->attendee_details;
57
+	}
58 58
 
59 59
 
60
-    /**
61
-     * @return EE_Registration
62
-     */
63
-    public function registration()
64
-    {
65
-        return $this->registration;
66
-    }
60
+	/**
61
+	 * @return EE_Registration
62
+	 */
63
+	public function registration()
64
+	{
65
+		return $this->registration;
66
+	}
67 67
 
68 68
 
69
-    /**
70
-     * @return CapCheckInterface
71
-     * @throws InvalidDataTypeException
72
-     */
73
-    public function getCapCheck()
74
-    {
75
-        // need cap for non-AJAX admin requests
76
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
77
-            return new CapCheck('ee_edit_contacts', 'create_new_contact');
78
-        }
79
-        return new PublicCapabilities('', 'create_new_contact');
80
-    }
69
+	/**
70
+	 * @return CapCheckInterface
71
+	 * @throws InvalidDataTypeException
72
+	 */
73
+	public function getCapCheck()
74
+	{
75
+		// need cap for non-AJAX admin requests
76
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
77
+			return new CapCheck('ee_edit_contacts', 'create_new_contact');
78
+		}
79
+		return new PublicCapabilities('', 'create_new_contact');
80
+	}
81 81
 }
Please login to merge, or discard this patch.
core/libraries/rest_api/controllers/Base.php 4 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -314,7 +314,7 @@
 block discarded – undo
314 314
      *
315 315
      * @param string $route
316 316
      * @param string $regex
317
-     * @param array  $match_keys EXCLUDING matching the entire regex
317
+     * @param string[]  $match_keys EXCLUDING matching the entire regex
318 318
      * @return array where  $match_keys are the keys (the first value of $match_keys
319 319
      *                           becomes the first key of the return value, etc. Eg passing in $match_keys of
320 320
      *                           array( 'model', 'id' ), will, if the regex is successful, will return
Please login to merge, or discard this patch.
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -5,7 +5,6 @@
 block discarded – undo
5 5
 use WP_Error;
6 6
 use WP_REST_Response;
7 7
 use EventEspresso\core\libraries\rest_api\RestException;
8
-
9 8
 use EE_Error;
10 9
 use EED_Core_Rest_Api;
11 10
 use EEH_Inflector;
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -96,7 +96,7 @@  discard block
 block discarded – undo
96 96
      */
97 97
     protected function setDebugInfo($key, $info)
98 98
     {
99
-        $this->debug_info[ $key ] = $info;
99
+        $this->debug_info[$key] = $info;
100 100
     }
101 101
 
102 102
 
@@ -113,11 +113,11 @@  discard block
 block discarded – undo
113 113
     {
114 114
         if (is_array($value)) {
115 115
             foreach ($value as $value_key => $value_value) {
116
-                $this->setResponseHeader($header_key . '[' . $value_key . ']', $value_value);
116
+                $this->setResponseHeader($header_key.'['.$value_key.']', $value_value);
117 117
             }
118 118
         } else {
119 119
             $prefix = $use_ee_prefix ? Base::HEADER_PREFIX_FOR_EE : Base::HEADER_PREFIX_FOR_WP;
120
-            $this->response_headers[ $prefix . $header_key ] = $value;
120
+            $this->response_headers[$prefix.$header_key] = $value;
121 121
         }
122 122
     }
123 123
 
@@ -147,7 +147,7 @@  discard block
 block discarded – undo
147 147
     protected function addEeErrorsToResponse(WP_Error $wp_error_response)
148 148
     {
149 149
         $notices_during_checkin = EE_Error::get_raw_notices();
150
-        if (! empty($notices_during_checkin['errors'])) {
150
+        if ( ! empty($notices_during_checkin['errors'])) {
151 151
             foreach ($notices_during_checkin['errors'] as $error_code => $error_message) {
152 152
                 $wp_error_response->add(
153 153
                     sanitize_key($error_code),
@@ -190,7 +190,7 @@  discard block
 block discarded – undo
190 190
                 if (is_array($debug_info)) {
191 191
                     $debug_info = wp_json_encode($debug_info);
192 192
                 }
193
-                $headers[ 'X-EE4-Debug-' . ucwords($debug_key) ] = $debug_info;
193
+                $headers['X-EE4-Debug-'.ucwords($debug_key)] = $debug_info;
194 194
             }
195 195
         }
196 196
         $headers = array_merge(
@@ -249,15 +249,15 @@  discard block
 block discarded – undo
249 249
         $headers = array();
250 250
         $notices = EE_Error::get_raw_notices();
251 251
         foreach ($notices as $notice_type => $sub_notices) {
252
-            if (! is_array($sub_notices)) {
252
+            if ( ! is_array($sub_notices)) {
253 253
                 continue;
254 254
             }
255 255
             foreach ($sub_notices as $notice_code => $sub_notice) {
256
-                $headers[ 'X-EE4-Notices-'
256
+                $headers['X-EE4-Notices-'
257 257
                           . EEH_Inflector::humanize($notice_type)
258 258
                           . '['
259 259
                           . $notice_code
260
-                          . ']' ] = strip_tags($sub_notice);
260
+                          . ']'] = strip_tags($sub_notice);
261 261
             }
262 262
         }
263 263
         return apply_filters(
@@ -286,7 +286,7 @@  discard block
 block discarded – undo
286 286
         }
287 287
         $matches = $this->parseRoute(
288 288
             $route,
289
-            '~' . EED_Core_Rest_Api::ee_api_namespace_for_regex . '~',
289
+            '~'.EED_Core_Rest_Api::ee_api_namespace_for_regex.'~',
290 290
             array('version')
291 291
         );
292 292
         if (isset($matches['version'])) {
@@ -320,14 +320,14 @@  discard block
 block discarded – undo
320 320
         if (is_array($matches)) {
321 321
             // skip the overall regex match. Who cares
322 322
             for ($i = 1; $i <= count($match_keys); $i++) {
323
-                if (! isset($matches[ $i ])) {
323
+                if ( ! isset($matches[$i])) {
324 324
                     $success = false;
325 325
                 } else {
326
-                    $indexed_matches[ $match_keys[ $i - 1 ] ] = $matches[ $i ];
326
+                    $indexed_matches[$match_keys[$i - 1]] = $matches[$i];
327 327
                 }
328 328
             }
329 329
         }
330
-        if (! $success) {
330
+        if ( ! $success) {
331 331
             throw new EE_Error(
332 332
                 __('We could not parse the URL. Please contact Event Espresso Support', 'event_espresso'),
333 333
                 'endpoint_parsing_error'
Please login to merge, or discard this patch.
Indentation   +334 added lines, -334 removed lines patch added patch discarded remove patch
@@ -22,338 +22,338 @@
 block discarded – undo
22 22
 class Base
23 23
 {
24 24
 
25
-    /**
26
-     * @deprecated use all-caps version
27
-     */
28
-    // @codingStandardsIgnoreStart
29
-    const header_prefix_for_ee = 'X-EE-';
30
-    // @codingStandardsIgnoreEnd
31
-
32
-    const HEADER_PREFIX_FOR_EE = 'X-EE-';
33
-
34
-    /**
35
-     * @deprecated use all-caps version instead
36
-     */
37
-    // @codingStandardsIgnoreStart
38
-    const header_prefix_for_wp = 'X-WP-';
39
-    // @codingStandardsIgnoreEnd
40
-
41
-    const HEADER_PREFIX_FOR_WP = 'X-WP-';
42
-
43
-    /**
44
-     * Contains debug info we'll send back in the response headers
45
-     *
46
-     * @var array
47
-     */
48
-    protected $debug_info = array();
49
-
50
-    /**
51
-     * Indicates whether or not the API is in debug mode
52
-     *
53
-     * @var boolean
54
-     */
55
-    protected $debug_mode = false;
56
-
57
-    /**
58
-     * Indicates the version that was requested
59
-     *
60
-     * @var string
61
-     */
62
-    protected $requested_version;
63
-
64
-    /**
65
-     * flat array of headers to send in the response
66
-     *
67
-     * @var array
68
-     */
69
-    protected $response_headers = array();
70
-
71
-
72
-    public function __construct()
73
-    {
74
-        $this->debug_mode = EED_Core_Rest_Api::debugMode();
75
-        // we are handling a REST request. Don't show a fancy HTML error message is any error comes up
76
-        add_filter('FHEE__EE_Error__get_error__show_normal_exceptions', '__return_true');
77
-    }
78
-
79
-
80
-    /**
81
-     * Sets the version the user requested
82
-     *
83
-     * @param string $version eg '4.8'
84
-     */
85
-    public function setRequestedVersion($version)
86
-    {
87
-        $this->requested_version = $version;
88
-    }
89
-
90
-
91
-    /**
92
-     * Sets some debug info that we'll send back in headers
93
-     *
94
-     * @param string       $key
95
-     * @param string|array $info
96
-     */
97
-    protected function setDebugInfo($key, $info)
98
-    {
99
-        $this->debug_info[ $key ] = $info;
100
-    }
101
-
102
-
103
-    /**
104
-     * Sets headers for the response
105
-     *
106
-     * @param string       $header_key    , excluding the "X-EE-" part
107
-     * @param array|string $value         if an array, multiple headers will be added, one
108
-     *                                    for each key in the array
109
-     * @param boolean      $use_ee_prefix whether to use the EE prefix on the header, or fallback to
110
-     *                                    the standard WP one
111
-     */
112
-    protected function setResponseHeader($header_key, $value, $use_ee_prefix = true)
113
-    {
114
-        if (is_array($value)) {
115
-            foreach ($value as $value_key => $value_value) {
116
-                $this->setResponseHeader($header_key . '[' . $value_key . ']', $value_value);
117
-            }
118
-        } else {
119
-            $prefix = $use_ee_prefix ? Base::HEADER_PREFIX_FOR_EE : Base::HEADER_PREFIX_FOR_WP;
120
-            $this->response_headers[ $prefix . $header_key ] = $value;
121
-        }
122
-    }
123
-
124
-
125
-    /**
126
-     * Returns a flat array of headers to be added to the response
127
-     *
128
-     * @return array
129
-     */
130
-    protected function getResponseHeaders()
131
-    {
132
-        return apply_filters(
133
-            'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_response_headers',
134
-            $this->response_headers,
135
-            $this,
136
-            $this->requested_version
137
-        );
138
-    }
139
-
140
-
141
-    /**
142
-     * Adds error notices from EE_Error onto the provided \WP_Error
143
-     *
144
-     * @param WP_Error $wp_error_response
145
-     * @return WP_Error
146
-     */
147
-    protected function addEeErrorsToResponse(WP_Error $wp_error_response)
148
-    {
149
-        $notices_during_checkin = EE_Error::get_raw_notices();
150
-        if (! empty($notices_during_checkin['errors'])) {
151
-            foreach ($notices_during_checkin['errors'] as $error_code => $error_message) {
152
-                $wp_error_response->add(
153
-                    sanitize_key($error_code),
154
-                    strip_tags($error_message)
155
-                );
156
-            }
157
-        }
158
-        return $wp_error_response;
159
-    }
160
-
161
-
162
-    /**
163
-     * Sends a response, but also makes sure to attach headers that
164
-     * are handy for debugging.
165
-     * Specifically, we assume folks will want to know what exactly was the DB query that got run,
166
-     * what exactly was the Models query that got run, what capabilities came into play, what fields were omitted from
167
-     * the response, others?
168
-     *
169
-     * @param array|WP_Error|Exception|RestException $response
170
-     * @return WP_REST_Response
171
-     */
172
-    public function sendResponse($response)
173
-    {
174
-        if ($response instanceof RestException) {
175
-            $response = new WP_Error($response->getStringCode(), $response->getMessage(), $response->getData());
176
-        }
177
-        if ($response instanceof Exception) {
178
-            $code = $response->getCode() ? $response->getCode() : 'error_occurred';
179
-            $response = new WP_Error($code, $response->getMessage());
180
-        }
181
-        if ($response instanceof WP_Error) {
182
-            $response = $this->addEeErrorsToResponse($response);
183
-            $rest_response = $this->createRestResponseFromWpError($response);
184
-        } else {
185
-            $rest_response = new WP_REST_Response($response, 200);
186
-        }
187
-        $headers = array();
188
-        if ($this->debug_mode && is_array($this->debug_info)) {
189
-            foreach ($this->debug_info as $debug_key => $debug_info) {
190
-                if (is_array($debug_info)) {
191
-                    $debug_info = wp_json_encode($debug_info);
192
-                }
193
-                $headers[ 'X-EE4-Debug-' . ucwords($debug_key) ] = $debug_info;
194
-            }
195
-        }
196
-        $headers = array_merge(
197
-            $headers,
198
-            $this->getResponseHeaders(),
199
-            $this->getHeadersFromEeNotices()
200
-        );
201
-        $rest_response->set_headers($headers);
202
-        return $rest_response;
203
-    }
204
-
205
-
206
-    /**
207
-     * Converts the \WP_Error into `WP_REST_Response.
208
-     * Mostly this is just a copy-and-paste from \WP_REST_Server::error_to_response
209
-     * (which is protected)
210
-     *
211
-     * @param WP_Error $wp_error
212
-     * @return WP_REST_Response
213
-     */
214
-    protected function createRestResponseFromWpError(WP_Error $wp_error)
215
-    {
216
-        $error_data = $wp_error->get_error_data();
217
-        if (is_array($error_data) && isset($error_data['status'])) {
218
-            $status = $error_data['status'];
219
-        } else {
220
-            $status = 500;
221
-        }
222
-        $errors = array();
223
-        foreach ((array) $wp_error->errors as $code => $messages) {
224
-            foreach ((array) $messages as $message) {
225
-                $errors[] = array(
226
-                    'code'    => $code,
227
-                    'message' => $message,
228
-                    'data'    => $wp_error->get_error_data($code),
229
-                );
230
-            }
231
-        }
232
-        $data = isset($errors[0]) ? $errors[0] : array();
233
-        if (count($errors) > 1) {
234
-            // Remove the primary error.
235
-            array_shift($errors);
236
-            $data['additional_errors'] = $errors;
237
-        }
238
-        return new WP_REST_Response($data, $status);
239
-    }
240
-
241
-
242
-    /**
243
-     * Array of headers derived from EE success, attention, and error messages
244
-     *
245
-     * @return array
246
-     */
247
-    protected function getHeadersFromEeNotices()
248
-    {
249
-        $headers = array();
250
-        $notices = EE_Error::get_raw_notices();
251
-        foreach ($notices as $notice_type => $sub_notices) {
252
-            if (! is_array($sub_notices)) {
253
-                continue;
254
-            }
255
-            foreach ($sub_notices as $notice_code => $sub_notice) {
256
-                $headers[ 'X-EE4-Notices-'
257
-                          . EEH_Inflector::humanize($notice_type)
258
-                          . '['
259
-                          . $notice_code
260
-                          . ']' ] = strip_tags($sub_notice);
261
-            }
262
-        }
263
-        return apply_filters(
264
-            'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_headers_from_ee_notices__return',
265
-            $headers,
266
-            $this->requested_version,
267
-            $notices
268
-        );
269
-    }
270
-
271
-
272
-    /**
273
-     * Finds which version of the API was requested given the route, and returns it.
274
-     * eg in a request to "mysite.com/wp-json/ee/v4.8.29/events/123" this would return
275
-     * "4.8.29".
276
-     * We should know hte requested version in this model though, so if no route is
277
-     * provided just use what we set earlier
278
-     *
279
-     * @param string $route
280
-     * @return string
281
-     */
282
-    public function getRequestedVersion($route = null)
283
-    {
284
-        if ($route === null) {
285
-            return $this->requested_version;
286
-        }
287
-        $matches = $this->parseRoute(
288
-            $route,
289
-            '~' . EED_Core_Rest_Api::ee_api_namespace_for_regex . '~',
290
-            array('version')
291
-        );
292
-        if (isset($matches['version'])) {
293
-            return $matches['version'];
294
-        } else {
295
-            return EED_Core_Rest_Api::latest_rest_api_version();
296
-        }
297
-    }
298
-
299
-
300
-    /**
301
-     * Applies the regex to the route, then creates an array using the values of
302
-     * $match_keys as keys (but ignores the full pattern match). Returns the array of matches.
303
-     * For example, if you call
304
-     * parse_route( '/ee/v4.8/events', '~\/ee\/v([^/]*)\/(.*)~', array( 'version', 'model' ) )
305
-     * it will return array( 'version' => '4.8', 'model' => 'events' )
306
-     *
307
-     * @param string $route
308
-     * @param string $regex
309
-     * @param array  $match_keys EXCLUDING matching the entire regex
310
-     * @return array where  $match_keys are the keys (the first value of $match_keys
311
-     *                           becomes the first key of the return value, etc. Eg passing in $match_keys of
312
-     *                           array( 'model', 'id' ), will, if the regex is successful, will return
313
-     *                           array( 'model' => 'foo', 'id' => 'bar' )
314
-     * @throws EE_Error if it couldn't be parsed
315
-     */
316
-    public function parseRoute($route, $regex, $match_keys)
317
-    {
318
-        $indexed_matches = array();
319
-        $success = preg_match($regex, $route, $matches);
320
-        if (is_array($matches)) {
321
-            // skip the overall regex match. Who cares
322
-            for ($i = 1; $i <= count($match_keys); $i++) {
323
-                if (! isset($matches[ $i ])) {
324
-                    $success = false;
325
-                } else {
326
-                    $indexed_matches[ $match_keys[ $i - 1 ] ] = $matches[ $i ];
327
-                }
328
-            }
329
-        }
330
-        if (! $success) {
331
-            throw new EE_Error(
332
-                __('We could not parse the URL. Please contact Event Espresso Support', 'event_espresso'),
333
-                'endpoint_parsing_error'
334
-            );
335
-        }
336
-        return $indexed_matches;
337
-    }
338
-
339
-
340
-    /**
341
-     * Gets the body's params (either from JSON or parsed body), which EXCLUDES the GET params and URL params
342
-     *
343
-     * @param \WP_REST_Request $request
344
-     * @return array
345
-     */
346
-    protected function getBodyParams(\WP_REST_Request $request)
347
-    {
348
-        // $request->get_params();
349
-        return array_merge(
350
-            (array) $request->get_body_params(),
351
-            (array) $request->get_json_params()
352
-        );
353
-        // return array_diff_key(
354
-        //    $request->get_params(),
355
-        //     $request->get_url_params(),
356
-        //     $request->get_query_params()
357
-        // );
358
-    }
25
+	/**
26
+	 * @deprecated use all-caps version
27
+	 */
28
+	// @codingStandardsIgnoreStart
29
+	const header_prefix_for_ee = 'X-EE-';
30
+	// @codingStandardsIgnoreEnd
31
+
32
+	const HEADER_PREFIX_FOR_EE = 'X-EE-';
33
+
34
+	/**
35
+	 * @deprecated use all-caps version instead
36
+	 */
37
+	// @codingStandardsIgnoreStart
38
+	const header_prefix_for_wp = 'X-WP-';
39
+	// @codingStandardsIgnoreEnd
40
+
41
+	const HEADER_PREFIX_FOR_WP = 'X-WP-';
42
+
43
+	/**
44
+	 * Contains debug info we'll send back in the response headers
45
+	 *
46
+	 * @var array
47
+	 */
48
+	protected $debug_info = array();
49
+
50
+	/**
51
+	 * Indicates whether or not the API is in debug mode
52
+	 *
53
+	 * @var boolean
54
+	 */
55
+	protected $debug_mode = false;
56
+
57
+	/**
58
+	 * Indicates the version that was requested
59
+	 *
60
+	 * @var string
61
+	 */
62
+	protected $requested_version;
63
+
64
+	/**
65
+	 * flat array of headers to send in the response
66
+	 *
67
+	 * @var array
68
+	 */
69
+	protected $response_headers = array();
70
+
71
+
72
+	public function __construct()
73
+	{
74
+		$this->debug_mode = EED_Core_Rest_Api::debugMode();
75
+		// we are handling a REST request. Don't show a fancy HTML error message is any error comes up
76
+		add_filter('FHEE__EE_Error__get_error__show_normal_exceptions', '__return_true');
77
+	}
78
+
79
+
80
+	/**
81
+	 * Sets the version the user requested
82
+	 *
83
+	 * @param string $version eg '4.8'
84
+	 */
85
+	public function setRequestedVersion($version)
86
+	{
87
+		$this->requested_version = $version;
88
+	}
89
+
90
+
91
+	/**
92
+	 * Sets some debug info that we'll send back in headers
93
+	 *
94
+	 * @param string       $key
95
+	 * @param string|array $info
96
+	 */
97
+	protected function setDebugInfo($key, $info)
98
+	{
99
+		$this->debug_info[ $key ] = $info;
100
+	}
101
+
102
+
103
+	/**
104
+	 * Sets headers for the response
105
+	 *
106
+	 * @param string       $header_key    , excluding the "X-EE-" part
107
+	 * @param array|string $value         if an array, multiple headers will be added, one
108
+	 *                                    for each key in the array
109
+	 * @param boolean      $use_ee_prefix whether to use the EE prefix on the header, or fallback to
110
+	 *                                    the standard WP one
111
+	 */
112
+	protected function setResponseHeader($header_key, $value, $use_ee_prefix = true)
113
+	{
114
+		if (is_array($value)) {
115
+			foreach ($value as $value_key => $value_value) {
116
+				$this->setResponseHeader($header_key . '[' . $value_key . ']', $value_value);
117
+			}
118
+		} else {
119
+			$prefix = $use_ee_prefix ? Base::HEADER_PREFIX_FOR_EE : Base::HEADER_PREFIX_FOR_WP;
120
+			$this->response_headers[ $prefix . $header_key ] = $value;
121
+		}
122
+	}
123
+
124
+
125
+	/**
126
+	 * Returns a flat array of headers to be added to the response
127
+	 *
128
+	 * @return array
129
+	 */
130
+	protected function getResponseHeaders()
131
+	{
132
+		return apply_filters(
133
+			'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_response_headers',
134
+			$this->response_headers,
135
+			$this,
136
+			$this->requested_version
137
+		);
138
+	}
139
+
140
+
141
+	/**
142
+	 * Adds error notices from EE_Error onto the provided \WP_Error
143
+	 *
144
+	 * @param WP_Error $wp_error_response
145
+	 * @return WP_Error
146
+	 */
147
+	protected function addEeErrorsToResponse(WP_Error $wp_error_response)
148
+	{
149
+		$notices_during_checkin = EE_Error::get_raw_notices();
150
+		if (! empty($notices_during_checkin['errors'])) {
151
+			foreach ($notices_during_checkin['errors'] as $error_code => $error_message) {
152
+				$wp_error_response->add(
153
+					sanitize_key($error_code),
154
+					strip_tags($error_message)
155
+				);
156
+			}
157
+		}
158
+		return $wp_error_response;
159
+	}
160
+
161
+
162
+	/**
163
+	 * Sends a response, but also makes sure to attach headers that
164
+	 * are handy for debugging.
165
+	 * Specifically, we assume folks will want to know what exactly was the DB query that got run,
166
+	 * what exactly was the Models query that got run, what capabilities came into play, what fields were omitted from
167
+	 * the response, others?
168
+	 *
169
+	 * @param array|WP_Error|Exception|RestException $response
170
+	 * @return WP_REST_Response
171
+	 */
172
+	public function sendResponse($response)
173
+	{
174
+		if ($response instanceof RestException) {
175
+			$response = new WP_Error($response->getStringCode(), $response->getMessage(), $response->getData());
176
+		}
177
+		if ($response instanceof Exception) {
178
+			$code = $response->getCode() ? $response->getCode() : 'error_occurred';
179
+			$response = new WP_Error($code, $response->getMessage());
180
+		}
181
+		if ($response instanceof WP_Error) {
182
+			$response = $this->addEeErrorsToResponse($response);
183
+			$rest_response = $this->createRestResponseFromWpError($response);
184
+		} else {
185
+			$rest_response = new WP_REST_Response($response, 200);
186
+		}
187
+		$headers = array();
188
+		if ($this->debug_mode && is_array($this->debug_info)) {
189
+			foreach ($this->debug_info as $debug_key => $debug_info) {
190
+				if (is_array($debug_info)) {
191
+					$debug_info = wp_json_encode($debug_info);
192
+				}
193
+				$headers[ 'X-EE4-Debug-' . ucwords($debug_key) ] = $debug_info;
194
+			}
195
+		}
196
+		$headers = array_merge(
197
+			$headers,
198
+			$this->getResponseHeaders(),
199
+			$this->getHeadersFromEeNotices()
200
+		);
201
+		$rest_response->set_headers($headers);
202
+		return $rest_response;
203
+	}
204
+
205
+
206
+	/**
207
+	 * Converts the \WP_Error into `WP_REST_Response.
208
+	 * Mostly this is just a copy-and-paste from \WP_REST_Server::error_to_response
209
+	 * (which is protected)
210
+	 *
211
+	 * @param WP_Error $wp_error
212
+	 * @return WP_REST_Response
213
+	 */
214
+	protected function createRestResponseFromWpError(WP_Error $wp_error)
215
+	{
216
+		$error_data = $wp_error->get_error_data();
217
+		if (is_array($error_data) && isset($error_data['status'])) {
218
+			$status = $error_data['status'];
219
+		} else {
220
+			$status = 500;
221
+		}
222
+		$errors = array();
223
+		foreach ((array) $wp_error->errors as $code => $messages) {
224
+			foreach ((array) $messages as $message) {
225
+				$errors[] = array(
226
+					'code'    => $code,
227
+					'message' => $message,
228
+					'data'    => $wp_error->get_error_data($code),
229
+				);
230
+			}
231
+		}
232
+		$data = isset($errors[0]) ? $errors[0] : array();
233
+		if (count($errors) > 1) {
234
+			// Remove the primary error.
235
+			array_shift($errors);
236
+			$data['additional_errors'] = $errors;
237
+		}
238
+		return new WP_REST_Response($data, $status);
239
+	}
240
+
241
+
242
+	/**
243
+	 * Array of headers derived from EE success, attention, and error messages
244
+	 *
245
+	 * @return array
246
+	 */
247
+	protected function getHeadersFromEeNotices()
248
+	{
249
+		$headers = array();
250
+		$notices = EE_Error::get_raw_notices();
251
+		foreach ($notices as $notice_type => $sub_notices) {
252
+			if (! is_array($sub_notices)) {
253
+				continue;
254
+			}
255
+			foreach ($sub_notices as $notice_code => $sub_notice) {
256
+				$headers[ 'X-EE4-Notices-'
257
+						  . EEH_Inflector::humanize($notice_type)
258
+						  . '['
259
+						  . $notice_code
260
+						  . ']' ] = strip_tags($sub_notice);
261
+			}
262
+		}
263
+		return apply_filters(
264
+			'FHEE__EventEspresso\core\libraries\rest_api\controllers\Base___get_headers_from_ee_notices__return',
265
+			$headers,
266
+			$this->requested_version,
267
+			$notices
268
+		);
269
+	}
270
+
271
+
272
+	/**
273
+	 * Finds which version of the API was requested given the route, and returns it.
274
+	 * eg in a request to "mysite.com/wp-json/ee/v4.8.29/events/123" this would return
275
+	 * "4.8.29".
276
+	 * We should know hte requested version in this model though, so if no route is
277
+	 * provided just use what we set earlier
278
+	 *
279
+	 * @param string $route
280
+	 * @return string
281
+	 */
282
+	public function getRequestedVersion($route = null)
283
+	{
284
+		if ($route === null) {
285
+			return $this->requested_version;
286
+		}
287
+		$matches = $this->parseRoute(
288
+			$route,
289
+			'~' . EED_Core_Rest_Api::ee_api_namespace_for_regex . '~',
290
+			array('version')
291
+		);
292
+		if (isset($matches['version'])) {
293
+			return $matches['version'];
294
+		} else {
295
+			return EED_Core_Rest_Api::latest_rest_api_version();
296
+		}
297
+	}
298
+
299
+
300
+	/**
301
+	 * Applies the regex to the route, then creates an array using the values of
302
+	 * $match_keys as keys (but ignores the full pattern match). Returns the array of matches.
303
+	 * For example, if you call
304
+	 * parse_route( '/ee/v4.8/events', '~\/ee\/v([^/]*)\/(.*)~', array( 'version', 'model' ) )
305
+	 * it will return array( 'version' => '4.8', 'model' => 'events' )
306
+	 *
307
+	 * @param string $route
308
+	 * @param string $regex
309
+	 * @param array  $match_keys EXCLUDING matching the entire regex
310
+	 * @return array where  $match_keys are the keys (the first value of $match_keys
311
+	 *                           becomes the first key of the return value, etc. Eg passing in $match_keys of
312
+	 *                           array( 'model', 'id' ), will, if the regex is successful, will return
313
+	 *                           array( 'model' => 'foo', 'id' => 'bar' )
314
+	 * @throws EE_Error if it couldn't be parsed
315
+	 */
316
+	public function parseRoute($route, $regex, $match_keys)
317
+	{
318
+		$indexed_matches = array();
319
+		$success = preg_match($regex, $route, $matches);
320
+		if (is_array($matches)) {
321
+			// skip the overall regex match. Who cares
322
+			for ($i = 1; $i <= count($match_keys); $i++) {
323
+				if (! isset($matches[ $i ])) {
324
+					$success = false;
325
+				} else {
326
+					$indexed_matches[ $match_keys[ $i - 1 ] ] = $matches[ $i ];
327
+				}
328
+			}
329
+		}
330
+		if (! $success) {
331
+			throw new EE_Error(
332
+				__('We could not parse the URL. Please contact Event Espresso Support', 'event_espresso'),
333
+				'endpoint_parsing_error'
334
+			);
335
+		}
336
+		return $indexed_matches;
337
+	}
338
+
339
+
340
+	/**
341
+	 * Gets the body's params (either from JSON or parsed body), which EXCLUDES the GET params and URL params
342
+	 *
343
+	 * @param \WP_REST_Request $request
344
+	 * @return array
345
+	 */
346
+	protected function getBodyParams(\WP_REST_Request $request)
347
+	{
348
+		// $request->get_params();
349
+		return array_merge(
350
+			(array) $request->get_body_params(),
351
+			(array) $request->get_json_params()
352
+		);
353
+		// return array_diff_key(
354
+		//    $request->get_params(),
355
+		//     $request->get_url_params(),
356
+		//     $request->get_query_params()
357
+		// );
358
+	}
359 359
 }
Please login to merge, or discard this patch.
core/services/container/CoffeeMaker.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -69,7 +69,7 @@  discard block
 block discarded – undo
69 69
 
70 70
 
71 71
     /**
72
-     * @param $type
72
+     * @param string $type
73 73
      * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
74 74
      */
75 75
     public static function validateType($type)
@@ -127,7 +127,7 @@  discard block
 block discarded – undo
127 127
      * Examines the constructor to determine which method should be used for instantiation
128 128
      *
129 129
      * @param \ReflectionClass $reflector
130
-     * @return mixed
130
+     * @return string
131 131
      * @throws InstantiationException
132 132
      */
133 133
     protected function resolveInstantiationMethod(\ReflectionClass $reflector)
Please login to merge, or discard this patch.
Indentation   +152 added lines, -152 removed lines patch added patch discarded remove patch
@@ -18,156 +18,156 @@
 block discarded – undo
18 18
 abstract class CoffeeMaker implements CoffeeMakerInterface
19 19
 {
20 20
 
21
-    /**
22
-     * Indicates that CoffeeMaker should construct a NEW entity instance from the provided arguments (if given)
23
-     */
24
-    const BREW_NEW = 'new';
25
-
26
-    /**
27
-     * Indicates that CoffeeMaker should always return a SHARED instance
28
-     */
29
-    const BREW_SHARED = 'shared';
30
-
31
-    /**
32
-     * Indicates that CoffeeMaker should only load the file/class/interface but NOT instantiate
33
-     */
34
-    const BREW_LOAD_ONLY = 'load_only';
35
-
36
-
37
-    /**
38
-     * @var CoffeePotInterface $coffee_pot
39
-     */
40
-    private $coffee_pot;
41
-
42
-    /**
43
-     * @var DependencyInjector $injector
44
-     */
45
-    private $injector;
46
-
47
-
48
-    /**
49
-     * @return array
50
-     */
51
-    public static function getTypes()
52
-    {
53
-        return (array) apply_filters(
54
-            'FHEE__EventEspresso\core\services\container\CoffeeMaker__getTypes',
55
-            array(
56
-                CoffeeMaker::BREW_NEW,
57
-                CoffeeMaker::BREW_SHARED,
58
-                CoffeeMaker::BREW_LOAD_ONLY,
59
-            )
60
-        );
61
-    }
62
-
63
-
64
-    /**
65
-     * @param $type
66
-     * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
67
-     */
68
-    public static function validateType($type)
69
-    {
70
-        $types = CoffeeMaker::getTypes();
71
-        if (! in_array($type, $types, true)) {
72
-            throw new InvalidIdentifierException(
73
-                is_object($type) ? get_class($type) : gettype($type),
74
-                __(
75
-                    'recipe type (one of the class constants on \EventEspresso\core\services\container\CoffeeMaker)',
76
-                    'event_espresso'
77
-                )
78
-            );
79
-        }
80
-        return $type;
81
-    }
82
-
83
-
84
-    /**
85
-     * CoffeeMaker constructor.
86
-     *
87
-     * @param CoffeePotInterface $coffee_pot
88
-     * @param InjectorInterface  $injector
89
-     */
90
-    public function __construct(CoffeePotInterface $coffee_pot, InjectorInterface $injector)
91
-    {
92
-        $this->coffee_pot = $coffee_pot;
93
-        $this->injector = $injector;
94
-    }
95
-
96
-
97
-    /**
98
-     * @return \EventEspresso\core\services\container\CoffeePotInterface
99
-     */
100
-    protected function coffeePot()
101
-    {
102
-        return $this->coffee_pot;
103
-    }
104
-
105
-
106
-    /**
107
-     * @return \EventEspresso\core\services\container\DependencyInjector
108
-     */
109
-    protected function injector()
110
-    {
111
-        return $this->injector;
112
-    }
113
-
114
-
115
-    /**
116
-     * Examines the constructor to determine which method should be used for instantiation
117
-     *
118
-     * @param \ReflectionClass $reflector
119
-     * @return mixed
120
-     * @throws InstantiationException
121
-     */
122
-    protected function resolveInstantiationMethod(\ReflectionClass $reflector)
123
-    {
124
-        if ($reflector->getConstructor() === null) {
125
-            return 'NewInstance';
126
-        }
127
-        if ($reflector->isInstantiable()) {
128
-            return 'NewInstanceArgs';
129
-        }
130
-        if (method_exists($reflector->getName(), 'instance')) {
131
-            return 'instance';
132
-        }
133
-        if (method_exists($reflector->getName(), 'new_instance')) {
134
-            return 'new_instance';
135
-        }
136
-        if (method_exists($reflector->getName(), 'new_instance_from_db')) {
137
-            return 'new_instance_from_db';
138
-        }
139
-        throw new InstantiationException($reflector->getName());
140
-    }
141
-
142
-
143
-    /**
144
-     * Ensures files for classes that are not PSR-4 compatible are loaded
145
-     * and then verifies that classes exist where applicable
146
-     *
147
-     * @param RecipeInterface $recipe
148
-     * @return bool
149
-     * @throws InvalidClassException
150
-     */
151
-    protected function resolveClassAndFilepath(RecipeInterface $recipe)
152
-    {
153
-        $paths = $recipe->paths();
154
-        if (! empty($paths)) {
155
-            foreach ($paths as $path) {
156
-                if (strpos($path, '*') === false && is_readable($path)) {
157
-                    require_once($path);
158
-                }
159
-            }
160
-        }
161
-        // re: using "false" for class_exists() second param:
162
-        // if a class name is not already known to PHP, then class_exists() will run through
163
-        // all of the registered spl_autoload functions until it either finds the class,
164
-        // or gets to the end of the registered spl_autoload functions.
165
-        // When the second parameter is true, it will also attempt to load the class file,
166
-        // but it will also trigger an error if the class can not be loaded.
167
-        // We don't want that extra error in the mix, so we have set the second param to "false"
168
-        if ($recipe->type() !== CoffeeMaker::BREW_LOAD_ONLY && ! class_exists($recipe->fqcn(), false)) {
169
-            throw new InvalidClassException($recipe->identifier());
170
-        }
171
-        return true;
172
-    }
21
+	/**
22
+	 * Indicates that CoffeeMaker should construct a NEW entity instance from the provided arguments (if given)
23
+	 */
24
+	const BREW_NEW = 'new';
25
+
26
+	/**
27
+	 * Indicates that CoffeeMaker should always return a SHARED instance
28
+	 */
29
+	const BREW_SHARED = 'shared';
30
+
31
+	/**
32
+	 * Indicates that CoffeeMaker should only load the file/class/interface but NOT instantiate
33
+	 */
34
+	const BREW_LOAD_ONLY = 'load_only';
35
+
36
+
37
+	/**
38
+	 * @var CoffeePotInterface $coffee_pot
39
+	 */
40
+	private $coffee_pot;
41
+
42
+	/**
43
+	 * @var DependencyInjector $injector
44
+	 */
45
+	private $injector;
46
+
47
+
48
+	/**
49
+	 * @return array
50
+	 */
51
+	public static function getTypes()
52
+	{
53
+		return (array) apply_filters(
54
+			'FHEE__EventEspresso\core\services\container\CoffeeMaker__getTypes',
55
+			array(
56
+				CoffeeMaker::BREW_NEW,
57
+				CoffeeMaker::BREW_SHARED,
58
+				CoffeeMaker::BREW_LOAD_ONLY,
59
+			)
60
+		);
61
+	}
62
+
63
+
64
+	/**
65
+	 * @param $type
66
+	 * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
67
+	 */
68
+	public static function validateType($type)
69
+	{
70
+		$types = CoffeeMaker::getTypes();
71
+		if (! in_array($type, $types, true)) {
72
+			throw new InvalidIdentifierException(
73
+				is_object($type) ? get_class($type) : gettype($type),
74
+				__(
75
+					'recipe type (one of the class constants on \EventEspresso\core\services\container\CoffeeMaker)',
76
+					'event_espresso'
77
+				)
78
+			);
79
+		}
80
+		return $type;
81
+	}
82
+
83
+
84
+	/**
85
+	 * CoffeeMaker constructor.
86
+	 *
87
+	 * @param CoffeePotInterface $coffee_pot
88
+	 * @param InjectorInterface  $injector
89
+	 */
90
+	public function __construct(CoffeePotInterface $coffee_pot, InjectorInterface $injector)
91
+	{
92
+		$this->coffee_pot = $coffee_pot;
93
+		$this->injector = $injector;
94
+	}
95
+
96
+
97
+	/**
98
+	 * @return \EventEspresso\core\services\container\CoffeePotInterface
99
+	 */
100
+	protected function coffeePot()
101
+	{
102
+		return $this->coffee_pot;
103
+	}
104
+
105
+
106
+	/**
107
+	 * @return \EventEspresso\core\services\container\DependencyInjector
108
+	 */
109
+	protected function injector()
110
+	{
111
+		return $this->injector;
112
+	}
113
+
114
+
115
+	/**
116
+	 * Examines the constructor to determine which method should be used for instantiation
117
+	 *
118
+	 * @param \ReflectionClass $reflector
119
+	 * @return mixed
120
+	 * @throws InstantiationException
121
+	 */
122
+	protected function resolveInstantiationMethod(\ReflectionClass $reflector)
123
+	{
124
+		if ($reflector->getConstructor() === null) {
125
+			return 'NewInstance';
126
+		}
127
+		if ($reflector->isInstantiable()) {
128
+			return 'NewInstanceArgs';
129
+		}
130
+		if (method_exists($reflector->getName(), 'instance')) {
131
+			return 'instance';
132
+		}
133
+		if (method_exists($reflector->getName(), 'new_instance')) {
134
+			return 'new_instance';
135
+		}
136
+		if (method_exists($reflector->getName(), 'new_instance_from_db')) {
137
+			return 'new_instance_from_db';
138
+		}
139
+		throw new InstantiationException($reflector->getName());
140
+	}
141
+
142
+
143
+	/**
144
+	 * Ensures files for classes that are not PSR-4 compatible are loaded
145
+	 * and then verifies that classes exist where applicable
146
+	 *
147
+	 * @param RecipeInterface $recipe
148
+	 * @return bool
149
+	 * @throws InvalidClassException
150
+	 */
151
+	protected function resolveClassAndFilepath(RecipeInterface $recipe)
152
+	{
153
+		$paths = $recipe->paths();
154
+		if (! empty($paths)) {
155
+			foreach ($paths as $path) {
156
+				if (strpos($path, '*') === false && is_readable($path)) {
157
+					require_once($path);
158
+				}
159
+			}
160
+		}
161
+		// re: using "false" for class_exists() second param:
162
+		// if a class name is not already known to PHP, then class_exists() will run through
163
+		// all of the registered spl_autoload functions until it either finds the class,
164
+		// or gets to the end of the registered spl_autoload functions.
165
+		// When the second parameter is true, it will also attempt to load the class file,
166
+		// but it will also trigger an error if the class can not be loaded.
167
+		// We don't want that extra error in the mix, so we have set the second param to "false"
168
+		if ($recipe->type() !== CoffeeMaker::BREW_LOAD_ONLY && ! class_exists($recipe->fqcn(), false)) {
169
+			throw new InvalidClassException($recipe->identifier());
170
+		}
171
+		return true;
172
+	}
173 173
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -68,7 +68,7 @@  discard block
 block discarded – undo
68 68
     public static function validateType($type)
69 69
     {
70 70
         $types = CoffeeMaker::getTypes();
71
-        if (! in_array($type, $types, true)) {
71
+        if ( ! in_array($type, $types, true)) {
72 72
             throw new InvalidIdentifierException(
73 73
                 is_object($type) ? get_class($type) : gettype($type),
74 74
                 __(
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
     protected function resolveClassAndFilepath(RecipeInterface $recipe)
152 152
     {
153 153
         $paths = $recipe->paths();
154
-        if (! empty($paths)) {
154
+        if ( ! empty($paths)) {
155 155
             foreach ($paths as $path) {
156 156
                 if (strpos($path, '*') === false && is_readable($path)) {
157 157
                     require_once($path);
Please login to merge, or discard this patch.
core/services/container/CoffeeShop.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -361,7 +361,7 @@  discard block
 block discarded – undo
361 361
      * Adds instructions on how to brew objects
362 362
      *
363 363
      * @param RecipeInterface $recipe
364
-     * @return mixed
364
+     * @return boolean
365 365
      * @throws InvalidIdentifierException
366 366
      */
367 367
     public function addRecipe(RecipeInterface $recipe)
@@ -461,7 +461,7 @@  discard block
 block discarded – undo
461 461
     /**
462 462
      * Adds a service to one of the internal collections
463 463
      *
464
-     * @param        $identifier
464
+     * @param        string $identifier
465 465
      * @param array  $arguments
466 466
      * @param string $type
467 467
      * @return mixed
Please login to merge, or discard this patch.
Indentation   +565 added lines, -565 removed lines patch added patch discarded remove patch
@@ -30,569 +30,569 @@
 block discarded – undo
30 30
 {
31 31
 
32 32
 
33
-    /**
34
-     * This was the best coffee related name I could think of to represent class name "aliases"
35
-     * So classes can be found via an alias identifier,
36
-     * that is revealed when it is run through... the filters... eh? get it?
37
-     *
38
-     * @var array $filters
39
-     */
40
-    private $filters;
41
-
42
-    /**
43
-     * These are the classes that will actually build the objects (to order of course)
44
-     *
45
-     * @var array $coffee_makers
46
-     */
47
-    private $coffee_makers;
48
-
49
-    /**
50
-     * where the instantiated "singleton" objects are stored
51
-     *
52
-     * @var CollectionInterface $carafe
53
-     */
54
-    private $carafe;
55
-
56
-    /**
57
-     * collection of Recipes that instruct us how to brew objects
58
-     *
59
-     * @var CollectionInterface $recipes
60
-     */
61
-    private $recipes;
62
-
63
-    /**
64
-     * collection of closures for brewing objects
65
-     *
66
-     * @var CollectionInterface $reservoir
67
-     */
68
-    private $reservoir;
69
-
70
-
71
-    /**
72
-     * CoffeeShop constructor
73
-     *
74
-     * @throws InvalidInterfaceException
75
-     */
76
-    public function __construct()
77
-    {
78
-        // array for storing class aliases
79
-        $this->filters = array();
80
-        // create collection for storing shared services
81
-        $this->carafe = new LooseCollection('');
82
-        // create collection for storing recipes that tell us how to build services and entities
83
-        $this->recipes = new Collection('EventEspresso\core\services\container\RecipeInterface');
84
-        // create collection for storing closures for constructing new entities
85
-        $this->reservoir = new Collection('Closure');
86
-        // create collection for storing the generators that build our services and entity closures
87
-        $this->coffee_makers = new Collection('EventEspresso\core\services\container\CoffeeMakerInterface');
88
-    }
89
-
90
-
91
-    /**
92
-     * Returns true if the container can return an entry for the given identifier.
93
-     * Returns false otherwise.
94
-     * `has($identifier)` returning true does not mean that `get($identifier)` will not throw an exception.
95
-     * It does however mean that `get($identifier)` will not throw a `ServiceNotFoundException`.
96
-     *
97
-     * @param string $identifier  Identifier of the entry to look for.
98
-     *                            Typically a Fully Qualified Class Name
99
-     * @return boolean
100
-     * @throws InvalidIdentifierException
101
-     */
102
-    public function has($identifier)
103
-    {
104
-        $identifier = $this->filterIdentifier($identifier);
105
-        return $this->carafe->has($identifier);
106
-    }
107
-
108
-
109
-    /**
110
-     * finds a previously brewed (SHARED) service and returns it
111
-     *
112
-     * @param  string $identifier Identifier for the entity class to be constructed.
113
-     *                            Typically a Fully Qualified Class Name
114
-     * @return mixed
115
-     * @throws InvalidIdentifierException
116
-     * @throws ServiceNotFoundException No service was found for this identifier.
117
-     */
118
-    public function get($identifier)
119
-    {
120
-        $identifier = $this->filterIdentifier($identifier);
121
-        if ($this->carafe->has($identifier)) {
122
-            return $this->carafe->get($identifier);
123
-        }
124
-        throw new ServiceNotFoundException($identifier);
125
-    }
126
-
127
-
128
-    /**
129
-     * returns an instance of the requested entity type using the supplied arguments.
130
-     * If a shared service is requested and an instance is already in the carafe, then it will be returned.
131
-     * If it is not already in the carafe, then the service will be constructed, added to the carafe, and returned
132
-     * If the request is for a new entity and a closure exists in the reservoir for creating it,
133
-     * then a new entity will be instantiated from the closure and returned.
134
-     * If a closure does not exist, then one will be built and added to the reservoir
135
-     * before instantiating the requested entity.
136
-     *
137
-     * @param  string $identifier Identifier for the entity class to be constructed.
138
-     *                            Typically a Fully Qualified Class Name
139
-     * @param array   $arguments  an array of arguments to be passed to the entity constructor
140
-     * @param string  $type
141
-     * @return mixed
142
-     * @throws OutOfBoundsException
143
-     * @throws InstantiationException
144
-     * @throws InvalidDataTypeException
145
-     * @throws InvalidClassException
146
-     * @throws InvalidIdentifierException
147
-     * @throws ServiceExistsException
148
-     * @throws ServiceNotFoundException No service was found for this identifier.
149
-     */
150
-    public function brew($identifier, $arguments = array(), $type = '')
151
-    {
152
-        // resolve any class aliases that may exist
153
-        $identifier = $this->filterIdentifier($identifier);
154
-        // is a shared service being requested and already exists in the carafe?
155
-        $brewed = $this->getShared($identifier, $type);
156
-        // then return whatever was found
157
-        if ($brewed !== false) {
158
-            return $brewed;
159
-        }
160
-        // if the reservoir doesn't have a closure already for the requested identifier,
161
-        // then neither a shared service nor a closure for making entities has been built yet
162
-        if (! $this->reservoir->has($identifier)) {
163
-            // so let's brew something up and add it to the proper collection
164
-            $brewed = $this->makeCoffee($identifier, $arguments, $type);
165
-        }
166
-        // did the requested class only require loading, and if so, was that successful?
167
-        if ($this->brewedLoadOnly($brewed, $identifier, $type) === true) {
168
-            return true;
169
-        }
170
-        // was the brewed item a callable factory function ?
171
-        if (is_callable($brewed)) {
172
-            // then instantiate a new entity from the cached closure
173
-            return $brewed($arguments);
174
-        }
175
-        if ($brewed) {
176
-            // requested object was a shared entity, so attempt to get it from the carafe again
177
-            // because if it wasn't there before, then it should have just been brewed and added,
178
-            // but if it still isn't there, then this time the thrown ServiceNotFoundException will not be caught
179
-            return $this->get($identifier);
180
-        }
181
-        // if identifier is for a non-shared entity,
182
-        // then either a cached closure already existed, or was just brewed
183
-        return $this->brewedClosure($identifier, $arguments);
184
-    }
185
-
186
-
187
-    /**
188
-     * @param string $identifier
189
-     * @param string $type
190
-     * @return bool|mixed
191
-     * @throws InvalidIdentifierException
192
-     */
193
-    protected function getShared($identifier, $type)
194
-    {
195
-        try {
196
-            if (empty($type) || $type === CoffeeMaker::BREW_SHARED) {
197
-                // if a shared service was requested and an instance is in the carafe, then return it
198
-                return $this->get($identifier);
199
-            }
200
-        } catch (ServiceNotFoundException $e) {
201
-            // if not then we'll just catch the ServiceNotFoundException but not do anything just yet,
202
-            // and instead, attempt to build whatever was requested
203
-        }
204
-        return false;
205
-    }
206
-
207
-
208
-    /**
209
-     * @param mixed  $brewed
210
-     * @param string $identifier
211
-     * @param string $type
212
-     * @return bool
213
-     * @throws InvalidClassException
214
-     * @throws InvalidDataTypeException
215
-     * @throws InvalidIdentifierException
216
-     * @throws OutOfBoundsException
217
-     * @throws ServiceExistsException
218
-     * @throws ServiceNotFoundException
219
-     */
220
-    protected function brewedLoadOnly($brewed, $identifier, $type)
221
-    {
222
-        if ($type === CoffeeMaker::BREW_LOAD_ONLY) {
223
-            if ($brewed !== true) {
224
-                throw new ServiceNotFoundException(
225
-                    sprintf(
226
-                        esc_html__(
227
-                            'The "%1$s" class could not be loaded.',
228
-                            'event_espresso'
229
-                        ),
230
-                        $identifier
231
-                    )
232
-                );
233
-            }
234
-            return true;
235
-        }
236
-        return false;
237
-    }
238
-
239
-
240
-    /**
241
-     * @param string $identifier
242
-     * @param array  $arguments
243
-     * @return mixed
244
-     * @throws InstantiationException
245
-     */
246
-    protected function brewedClosure($identifier, array $arguments)
247
-    {
248
-        $closure = $this->reservoir->get($identifier);
249
-        if (empty($closure)) {
250
-            throw new InstantiationException(
251
-                sprintf(
252
-                    esc_html__(
253
-                        'Could not brew an instance of "%1$s".',
254
-                        'event_espresso'
255
-                    ),
256
-                    $identifier
257
-                )
258
-            );
259
-        }
260
-        return $closure($arguments);
261
-    }
262
-
263
-
264
-    /**
265
-     * @param CoffeeMakerInterface $coffee_maker
266
-     * @param string               $type
267
-     * @return bool
268
-     * @throws InvalidIdentifierException
269
-     * @throws InvalidEntityException
270
-     */
271
-    public function addCoffeeMaker(CoffeeMakerInterface $coffee_maker, $type)
272
-    {
273
-        $type = CoffeeMaker::validateType($type);
274
-        return $this->coffee_makers->add($coffee_maker, $type);
275
-    }
276
-
277
-
278
-    /**
279
-     * @param string   $identifier
280
-     * @param callable $closure
281
-     * @return callable|null
282
-     * @throws InvalidIdentifierException
283
-     * @throws InvalidDataTypeException
284
-     */
285
-    public function addClosure($identifier, $closure)
286
-    {
287
-        if (! is_callable($closure)) {
288
-            throw new InvalidDataTypeException('$closure', $closure, 'Closure');
289
-        }
290
-        $identifier = $this->processIdentifier($identifier);
291
-        if ($this->reservoir->add($closure, $identifier)) {
292
-            return $closure;
293
-        }
294
-        return null;
295
-    }
296
-
297
-
298
-    /**
299
-     * @param string $identifier
300
-     * @return boolean
301
-     * @throws InvalidIdentifierException
302
-     */
303
-    public function removeClosure($identifier)
304
-    {
305
-        $identifier = $this->processIdentifier($identifier);
306
-        if ($this->reservoir->has($identifier)) {
307
-            return $this->reservoir->remove($this->reservoir->get($identifier));
308
-        }
309
-        return false;
310
-    }
311
-
312
-
313
-    /**
314
-     * @param  string $identifier Identifier for the entity class that the service applies to
315
-     *                            Typically a Fully Qualified Class Name
316
-     * @param mixed   $service
317
-     * @return bool
318
-     * @throws \EventEspresso\core\services\container\exceptions\InvalidServiceException
319
-     * @throws InvalidIdentifierException
320
-     */
321
-    public function addService($identifier, $service)
322
-    {
323
-        $identifier = $this->processIdentifier($identifier);
324
-        $service = $this->validateService($identifier, $service);
325
-        return $this->carafe->add($service, $identifier);
326
-    }
327
-
328
-
329
-    /**
330
-     * @param string $identifier
331
-     * @return boolean
332
-     * @throws InvalidIdentifierException
333
-     */
334
-    public function removeService($identifier)
335
-    {
336
-        $identifier = $this->processIdentifier($identifier);
337
-        if ($this->carafe->has($identifier)) {
338
-            return $this->carafe->remove($this->carafe->get($identifier));
339
-        }
340
-        return false;
341
-    }
342
-
343
-
344
-    /**
345
-     * Adds instructions on how to brew objects
346
-     *
347
-     * @param RecipeInterface $recipe
348
-     * @return mixed
349
-     * @throws InvalidIdentifierException
350
-     */
351
-    public function addRecipe(RecipeInterface $recipe)
352
-    {
353
-        $this->addAliases($recipe->identifier(), $recipe->filters());
354
-        $identifier = $this->processIdentifier($recipe->identifier());
355
-        return $this->recipes->add($recipe, $identifier);
356
-    }
357
-
358
-
359
-    /**
360
-     * @param string $identifier The Recipe's identifier
361
-     * @return boolean
362
-     * @throws InvalidIdentifierException
363
-     */
364
-    public function removeRecipe($identifier)
365
-    {
366
-        $identifier = $this->processIdentifier($identifier);
367
-        if ($this->recipes->has($identifier)) {
368
-            return $this->recipes->remove($this->recipes->get($identifier));
369
-        }
370
-        return false;
371
-    }
372
-
373
-
374
-    /**
375
-     * Get instructions on how to brew objects
376
-     *
377
-     * @param  string $identifier Identifier for the entity class that the recipe applies to
378
-     *                            Typically a Fully Qualified Class Name
379
-     * @param string  $type
380
-     * @return RecipeInterface
381
-     * @throws OutOfBoundsException
382
-     * @throws InvalidIdentifierException
383
-     */
384
-    public function getRecipe($identifier, $type = '')
385
-    {
386
-        $identifier = $this->processIdentifier($identifier);
387
-        if ($this->recipes->has($identifier)) {
388
-            return $this->recipes->get($identifier);
389
-        }
390
-        $default_recipes = $this->getDefaultRecipes();
391
-        $matches = array();
392
-        foreach ($default_recipes as $wildcard => $default_recipe) {
393
-            // is the wildcard recipe prefix in the identifier ?
394
-            if (strpos($identifier, $wildcard) !== false) {
395
-                // track matches and use the number of wildcard characters matched for the key
396
-                $matches[ strlen($wildcard) ] = $default_recipe;
397
-            }
398
-        }
399
-        if (count($matches) > 0) {
400
-            // sort our recipes by the number of wildcard characters matched
401
-            ksort($matches);
402
-            // then grab the last recipe form the list, since it had the most matching characters
403
-            $match = array_pop($matches);
404
-            // since we are using a default recipe, we need to set it's identifier and fqcn
405
-            return $this->copyDefaultRecipe($match, $identifier, $type);
406
-        }
407
-        if ($this->recipes->has(Recipe::DEFAULT_ID)) {
408
-            // since we are using a default recipe, we need to set it's identifier and fqcn
409
-            return $this->copyDefaultRecipe($this->recipes->get(Recipe::DEFAULT_ID), $identifier, $type);
410
-        }
411
-        throw new OutOfBoundsException(
412
-            sprintf(
413
-                __('Could not brew coffee because no recipes were found for class "%1$s".', 'event_espresso'),
414
-                $identifier
415
-            )
416
-        );
417
-    }
418
-
419
-
420
-    /**
421
-     * adds class name aliases to list of filters
422
-     *
423
-     * @param  string       $identifier Identifier for the entity class that the alias applies to
424
-     *                                  Typically a Fully Qualified Class Name
425
-     * @param  array|string $aliases
426
-     * @return void
427
-     * @throws InvalidIdentifierException
428
-     */
429
-    public function addAliases($identifier, $aliases)
430
-    {
431
-        if (empty($aliases)) {
432
-            return;
433
-        }
434
-        $identifier = $this->processIdentifier($identifier);
435
-        foreach ((array) $aliases as $alias) {
436
-            $this->filters[ $this->processIdentifier($alias) ] = $identifier;
437
-        }
438
-    }
439
-
440
-
441
-    /**
442
-     * Adds a service to one of the internal collections
443
-     *
444
-     * @param        $identifier
445
-     * @param array  $arguments
446
-     * @param string $type
447
-     * @return mixed
448
-     * @throws InvalidDataTypeException
449
-     * @throws InvalidClassException
450
-     * @throws OutOfBoundsException
451
-     * @throws InvalidIdentifierException
452
-     * @throws ServiceExistsException
453
-     */
454
-    private function makeCoffee($identifier, $arguments = array(), $type = '')
455
-    {
456
-        if ((empty($type) || $type === CoffeeMaker::BREW_SHARED) && $this->has($identifier)) {
457
-            throw new ServiceExistsException($identifier);
458
-        }
459
-        $identifier = $this->filterIdentifier($identifier);
460
-        $recipe = $this->getRecipe($identifier, $type);
461
-        $type = ! empty($type) ? $type : $recipe->type();
462
-        $coffee_maker = $this->getCoffeeMaker($type);
463
-        return $coffee_maker->brew($recipe, $arguments);
464
-    }
465
-
466
-
467
-    /**
468
-     * filters alias identifiers to find the real class name
469
-     *
470
-     * @param  string $identifier Identifier for the entity class that the filter applies to
471
-     *                            Typically a Fully Qualified Class Name
472
-     * @return string
473
-     * @throws InvalidIdentifierException
474
-     */
475
-    private function filterIdentifier($identifier)
476
-    {
477
-        $identifier = $this->processIdentifier($identifier);
478
-        return isset($this->filters[ $identifier ]) && ! empty($this->filters[ $identifier ])
479
-            ? $this->filters[ $identifier ]
480
-            : $identifier;
481
-    }
482
-
483
-
484
-    /**
485
-     * verifies and standardizes identifiers
486
-     *
487
-     * @param  string $identifier Identifier for the entity class
488
-     *                            Typically a Fully Qualified Class Name
489
-     * @return string
490
-     * @throws InvalidIdentifierException
491
-     */
492
-    private function processIdentifier($identifier)
493
-    {
494
-        if (! is_string($identifier)) {
495
-            throw new InvalidIdentifierException(
496
-                is_object($identifier) ? get_class($identifier) : gettype($identifier),
497
-                '\Fully\Qualified\ClassName'
498
-            );
499
-        }
500
-        return ltrim($identifier, '\\');
501
-    }
502
-
503
-
504
-    /**
505
-     * @param string $type
506
-     * @return CoffeeMakerInterface
507
-     * @throws OutOfBoundsException
508
-     * @throws InvalidDataTypeException
509
-     * @throws InvalidClassException
510
-     */
511
-    private function getCoffeeMaker($type)
512
-    {
513
-        if (! $this->coffee_makers->has($type)) {
514
-            throw new OutOfBoundsException(
515
-                __('The requested coffee maker is either missing or invalid.', 'event_espresso')
516
-            );
517
-        }
518
-        return $this->coffee_makers->get($type);
519
-    }
520
-
521
-
522
-    /**
523
-     * Retrieves all recipes that use a wildcard "*" in their identifier
524
-     * This allows recipes to be set up for handling
525
-     * legacy classes that do not support PSR-4 autoloading.
526
-     * for example:
527
-     * using "EEM_*" for a recipe identifier would target all legacy models like EEM_Attendee
528
-     *
529
-     * @return array
530
-     */
531
-    private function getDefaultRecipes()
532
-    {
533
-        $default_recipes = array();
534
-        $this->recipes->rewind();
535
-        while ($this->recipes->valid()) {
536
-            $identifier = $this->recipes->getInfo();
537
-            // does this recipe use a wildcard ? (but is NOT the global default)
538
-            if ($identifier !== Recipe::DEFAULT_ID && strpos($identifier, '*') !== false) {
539
-                // strip the wildcard and use identifier as key
540
-                $default_recipes[ str_replace('*', '', $identifier) ] = $this->recipes->current();
541
-            }
542
-            $this->recipes->next();
543
-        }
544
-        return $default_recipes;
545
-    }
546
-
547
-
548
-    /**
549
-     * clones a default recipe and then copies details
550
-     * from the incoming request to it so that it can be used
551
-     *
552
-     * @param RecipeInterface $default_recipe
553
-     * @param string          $identifier
554
-     * @param string          $type
555
-     * @return RecipeInterface
556
-     */
557
-    private function copyDefaultRecipe(RecipeInterface $default_recipe, $identifier, $type = '')
558
-    {
559
-        $recipe = clone $default_recipe;
560
-        if (! empty($type)) {
561
-            $recipe->setType($type);
562
-        }
563
-        // is this the base default recipe ?
564
-        if ($default_recipe->identifier() === Recipe::DEFAULT_ID) {
565
-            $recipe->setIdentifier($identifier);
566
-            $recipe->setFqcn($identifier);
567
-            return $recipe;
568
-        }
569
-        $recipe->setIdentifier($identifier);
570
-        foreach ($default_recipe->paths() as $path) {
571
-            $path = str_replace('*', $identifier, $path);
572
-            if (is_readable($path)) {
573
-                $recipe->setPaths($path);
574
-            }
575
-        }
576
-        $recipe->setFqcn($identifier);
577
-        return $recipe;
578
-    }
579
-
580
-
581
-    /**
582
-     * @param  string $identifier Identifier for the entity class that the service applies to
583
-     *                            Typically a Fully Qualified Class Name
584
-     * @param mixed   $service
585
-     * @return mixed
586
-     * @throws InvalidServiceException
587
-     */
588
-    private function validateService($identifier, $service)
589
-    {
590
-        if (! is_object($service)) {
591
-            throw new InvalidServiceException(
592
-                $identifier,
593
-                $service
594
-            );
595
-        }
596
-        return $service;
597
-    }
33
+	/**
34
+	 * This was the best coffee related name I could think of to represent class name "aliases"
35
+	 * So classes can be found via an alias identifier,
36
+	 * that is revealed when it is run through... the filters... eh? get it?
37
+	 *
38
+	 * @var array $filters
39
+	 */
40
+	private $filters;
41
+
42
+	/**
43
+	 * These are the classes that will actually build the objects (to order of course)
44
+	 *
45
+	 * @var array $coffee_makers
46
+	 */
47
+	private $coffee_makers;
48
+
49
+	/**
50
+	 * where the instantiated "singleton" objects are stored
51
+	 *
52
+	 * @var CollectionInterface $carafe
53
+	 */
54
+	private $carafe;
55
+
56
+	/**
57
+	 * collection of Recipes that instruct us how to brew objects
58
+	 *
59
+	 * @var CollectionInterface $recipes
60
+	 */
61
+	private $recipes;
62
+
63
+	/**
64
+	 * collection of closures for brewing objects
65
+	 *
66
+	 * @var CollectionInterface $reservoir
67
+	 */
68
+	private $reservoir;
69
+
70
+
71
+	/**
72
+	 * CoffeeShop constructor
73
+	 *
74
+	 * @throws InvalidInterfaceException
75
+	 */
76
+	public function __construct()
77
+	{
78
+		// array for storing class aliases
79
+		$this->filters = array();
80
+		// create collection for storing shared services
81
+		$this->carafe = new LooseCollection('');
82
+		// create collection for storing recipes that tell us how to build services and entities
83
+		$this->recipes = new Collection('EventEspresso\core\services\container\RecipeInterface');
84
+		// create collection for storing closures for constructing new entities
85
+		$this->reservoir = new Collection('Closure');
86
+		// create collection for storing the generators that build our services and entity closures
87
+		$this->coffee_makers = new Collection('EventEspresso\core\services\container\CoffeeMakerInterface');
88
+	}
89
+
90
+
91
+	/**
92
+	 * Returns true if the container can return an entry for the given identifier.
93
+	 * Returns false otherwise.
94
+	 * `has($identifier)` returning true does not mean that `get($identifier)` will not throw an exception.
95
+	 * It does however mean that `get($identifier)` will not throw a `ServiceNotFoundException`.
96
+	 *
97
+	 * @param string $identifier  Identifier of the entry to look for.
98
+	 *                            Typically a Fully Qualified Class Name
99
+	 * @return boolean
100
+	 * @throws InvalidIdentifierException
101
+	 */
102
+	public function has($identifier)
103
+	{
104
+		$identifier = $this->filterIdentifier($identifier);
105
+		return $this->carafe->has($identifier);
106
+	}
107
+
108
+
109
+	/**
110
+	 * finds a previously brewed (SHARED) service and returns it
111
+	 *
112
+	 * @param  string $identifier Identifier for the entity class to be constructed.
113
+	 *                            Typically a Fully Qualified Class Name
114
+	 * @return mixed
115
+	 * @throws InvalidIdentifierException
116
+	 * @throws ServiceNotFoundException No service was found for this identifier.
117
+	 */
118
+	public function get($identifier)
119
+	{
120
+		$identifier = $this->filterIdentifier($identifier);
121
+		if ($this->carafe->has($identifier)) {
122
+			return $this->carafe->get($identifier);
123
+		}
124
+		throw new ServiceNotFoundException($identifier);
125
+	}
126
+
127
+
128
+	/**
129
+	 * returns an instance of the requested entity type using the supplied arguments.
130
+	 * If a shared service is requested and an instance is already in the carafe, then it will be returned.
131
+	 * If it is not already in the carafe, then the service will be constructed, added to the carafe, and returned
132
+	 * If the request is for a new entity and a closure exists in the reservoir for creating it,
133
+	 * then a new entity will be instantiated from the closure and returned.
134
+	 * If a closure does not exist, then one will be built and added to the reservoir
135
+	 * before instantiating the requested entity.
136
+	 *
137
+	 * @param  string $identifier Identifier for the entity class to be constructed.
138
+	 *                            Typically a Fully Qualified Class Name
139
+	 * @param array   $arguments  an array of arguments to be passed to the entity constructor
140
+	 * @param string  $type
141
+	 * @return mixed
142
+	 * @throws OutOfBoundsException
143
+	 * @throws InstantiationException
144
+	 * @throws InvalidDataTypeException
145
+	 * @throws InvalidClassException
146
+	 * @throws InvalidIdentifierException
147
+	 * @throws ServiceExistsException
148
+	 * @throws ServiceNotFoundException No service was found for this identifier.
149
+	 */
150
+	public function brew($identifier, $arguments = array(), $type = '')
151
+	{
152
+		// resolve any class aliases that may exist
153
+		$identifier = $this->filterIdentifier($identifier);
154
+		// is a shared service being requested and already exists in the carafe?
155
+		$brewed = $this->getShared($identifier, $type);
156
+		// then return whatever was found
157
+		if ($brewed !== false) {
158
+			return $brewed;
159
+		}
160
+		// if the reservoir doesn't have a closure already for the requested identifier,
161
+		// then neither a shared service nor a closure for making entities has been built yet
162
+		if (! $this->reservoir->has($identifier)) {
163
+			// so let's brew something up and add it to the proper collection
164
+			$brewed = $this->makeCoffee($identifier, $arguments, $type);
165
+		}
166
+		// did the requested class only require loading, and if so, was that successful?
167
+		if ($this->brewedLoadOnly($brewed, $identifier, $type) === true) {
168
+			return true;
169
+		}
170
+		// was the brewed item a callable factory function ?
171
+		if (is_callable($brewed)) {
172
+			// then instantiate a new entity from the cached closure
173
+			return $brewed($arguments);
174
+		}
175
+		if ($brewed) {
176
+			// requested object was a shared entity, so attempt to get it from the carafe again
177
+			// because if it wasn't there before, then it should have just been brewed and added,
178
+			// but if it still isn't there, then this time the thrown ServiceNotFoundException will not be caught
179
+			return $this->get($identifier);
180
+		}
181
+		// if identifier is for a non-shared entity,
182
+		// then either a cached closure already existed, or was just brewed
183
+		return $this->brewedClosure($identifier, $arguments);
184
+	}
185
+
186
+
187
+	/**
188
+	 * @param string $identifier
189
+	 * @param string $type
190
+	 * @return bool|mixed
191
+	 * @throws InvalidIdentifierException
192
+	 */
193
+	protected function getShared($identifier, $type)
194
+	{
195
+		try {
196
+			if (empty($type) || $type === CoffeeMaker::BREW_SHARED) {
197
+				// if a shared service was requested and an instance is in the carafe, then return it
198
+				return $this->get($identifier);
199
+			}
200
+		} catch (ServiceNotFoundException $e) {
201
+			// if not then we'll just catch the ServiceNotFoundException but not do anything just yet,
202
+			// and instead, attempt to build whatever was requested
203
+		}
204
+		return false;
205
+	}
206
+
207
+
208
+	/**
209
+	 * @param mixed  $brewed
210
+	 * @param string $identifier
211
+	 * @param string $type
212
+	 * @return bool
213
+	 * @throws InvalidClassException
214
+	 * @throws InvalidDataTypeException
215
+	 * @throws InvalidIdentifierException
216
+	 * @throws OutOfBoundsException
217
+	 * @throws ServiceExistsException
218
+	 * @throws ServiceNotFoundException
219
+	 */
220
+	protected function brewedLoadOnly($brewed, $identifier, $type)
221
+	{
222
+		if ($type === CoffeeMaker::BREW_LOAD_ONLY) {
223
+			if ($brewed !== true) {
224
+				throw new ServiceNotFoundException(
225
+					sprintf(
226
+						esc_html__(
227
+							'The "%1$s" class could not be loaded.',
228
+							'event_espresso'
229
+						),
230
+						$identifier
231
+					)
232
+				);
233
+			}
234
+			return true;
235
+		}
236
+		return false;
237
+	}
238
+
239
+
240
+	/**
241
+	 * @param string $identifier
242
+	 * @param array  $arguments
243
+	 * @return mixed
244
+	 * @throws InstantiationException
245
+	 */
246
+	protected function brewedClosure($identifier, array $arguments)
247
+	{
248
+		$closure = $this->reservoir->get($identifier);
249
+		if (empty($closure)) {
250
+			throw new InstantiationException(
251
+				sprintf(
252
+					esc_html__(
253
+						'Could not brew an instance of "%1$s".',
254
+						'event_espresso'
255
+					),
256
+					$identifier
257
+				)
258
+			);
259
+		}
260
+		return $closure($arguments);
261
+	}
262
+
263
+
264
+	/**
265
+	 * @param CoffeeMakerInterface $coffee_maker
266
+	 * @param string               $type
267
+	 * @return bool
268
+	 * @throws InvalidIdentifierException
269
+	 * @throws InvalidEntityException
270
+	 */
271
+	public function addCoffeeMaker(CoffeeMakerInterface $coffee_maker, $type)
272
+	{
273
+		$type = CoffeeMaker::validateType($type);
274
+		return $this->coffee_makers->add($coffee_maker, $type);
275
+	}
276
+
277
+
278
+	/**
279
+	 * @param string   $identifier
280
+	 * @param callable $closure
281
+	 * @return callable|null
282
+	 * @throws InvalidIdentifierException
283
+	 * @throws InvalidDataTypeException
284
+	 */
285
+	public function addClosure($identifier, $closure)
286
+	{
287
+		if (! is_callable($closure)) {
288
+			throw new InvalidDataTypeException('$closure', $closure, 'Closure');
289
+		}
290
+		$identifier = $this->processIdentifier($identifier);
291
+		if ($this->reservoir->add($closure, $identifier)) {
292
+			return $closure;
293
+		}
294
+		return null;
295
+	}
296
+
297
+
298
+	/**
299
+	 * @param string $identifier
300
+	 * @return boolean
301
+	 * @throws InvalidIdentifierException
302
+	 */
303
+	public function removeClosure($identifier)
304
+	{
305
+		$identifier = $this->processIdentifier($identifier);
306
+		if ($this->reservoir->has($identifier)) {
307
+			return $this->reservoir->remove($this->reservoir->get($identifier));
308
+		}
309
+		return false;
310
+	}
311
+
312
+
313
+	/**
314
+	 * @param  string $identifier Identifier for the entity class that the service applies to
315
+	 *                            Typically a Fully Qualified Class Name
316
+	 * @param mixed   $service
317
+	 * @return bool
318
+	 * @throws \EventEspresso\core\services\container\exceptions\InvalidServiceException
319
+	 * @throws InvalidIdentifierException
320
+	 */
321
+	public function addService($identifier, $service)
322
+	{
323
+		$identifier = $this->processIdentifier($identifier);
324
+		$service = $this->validateService($identifier, $service);
325
+		return $this->carafe->add($service, $identifier);
326
+	}
327
+
328
+
329
+	/**
330
+	 * @param string $identifier
331
+	 * @return boolean
332
+	 * @throws InvalidIdentifierException
333
+	 */
334
+	public function removeService($identifier)
335
+	{
336
+		$identifier = $this->processIdentifier($identifier);
337
+		if ($this->carafe->has($identifier)) {
338
+			return $this->carafe->remove($this->carafe->get($identifier));
339
+		}
340
+		return false;
341
+	}
342
+
343
+
344
+	/**
345
+	 * Adds instructions on how to brew objects
346
+	 *
347
+	 * @param RecipeInterface $recipe
348
+	 * @return mixed
349
+	 * @throws InvalidIdentifierException
350
+	 */
351
+	public function addRecipe(RecipeInterface $recipe)
352
+	{
353
+		$this->addAliases($recipe->identifier(), $recipe->filters());
354
+		$identifier = $this->processIdentifier($recipe->identifier());
355
+		return $this->recipes->add($recipe, $identifier);
356
+	}
357
+
358
+
359
+	/**
360
+	 * @param string $identifier The Recipe's identifier
361
+	 * @return boolean
362
+	 * @throws InvalidIdentifierException
363
+	 */
364
+	public function removeRecipe($identifier)
365
+	{
366
+		$identifier = $this->processIdentifier($identifier);
367
+		if ($this->recipes->has($identifier)) {
368
+			return $this->recipes->remove($this->recipes->get($identifier));
369
+		}
370
+		return false;
371
+	}
372
+
373
+
374
+	/**
375
+	 * Get instructions on how to brew objects
376
+	 *
377
+	 * @param  string $identifier Identifier for the entity class that the recipe applies to
378
+	 *                            Typically a Fully Qualified Class Name
379
+	 * @param string  $type
380
+	 * @return RecipeInterface
381
+	 * @throws OutOfBoundsException
382
+	 * @throws InvalidIdentifierException
383
+	 */
384
+	public function getRecipe($identifier, $type = '')
385
+	{
386
+		$identifier = $this->processIdentifier($identifier);
387
+		if ($this->recipes->has($identifier)) {
388
+			return $this->recipes->get($identifier);
389
+		}
390
+		$default_recipes = $this->getDefaultRecipes();
391
+		$matches = array();
392
+		foreach ($default_recipes as $wildcard => $default_recipe) {
393
+			// is the wildcard recipe prefix in the identifier ?
394
+			if (strpos($identifier, $wildcard) !== false) {
395
+				// track matches and use the number of wildcard characters matched for the key
396
+				$matches[ strlen($wildcard) ] = $default_recipe;
397
+			}
398
+		}
399
+		if (count($matches) > 0) {
400
+			// sort our recipes by the number of wildcard characters matched
401
+			ksort($matches);
402
+			// then grab the last recipe form the list, since it had the most matching characters
403
+			$match = array_pop($matches);
404
+			// since we are using a default recipe, we need to set it's identifier and fqcn
405
+			return $this->copyDefaultRecipe($match, $identifier, $type);
406
+		}
407
+		if ($this->recipes->has(Recipe::DEFAULT_ID)) {
408
+			// since we are using a default recipe, we need to set it's identifier and fqcn
409
+			return $this->copyDefaultRecipe($this->recipes->get(Recipe::DEFAULT_ID), $identifier, $type);
410
+		}
411
+		throw new OutOfBoundsException(
412
+			sprintf(
413
+				__('Could not brew coffee because no recipes were found for class "%1$s".', 'event_espresso'),
414
+				$identifier
415
+			)
416
+		);
417
+	}
418
+
419
+
420
+	/**
421
+	 * adds class name aliases to list of filters
422
+	 *
423
+	 * @param  string       $identifier Identifier for the entity class that the alias applies to
424
+	 *                                  Typically a Fully Qualified Class Name
425
+	 * @param  array|string $aliases
426
+	 * @return void
427
+	 * @throws InvalidIdentifierException
428
+	 */
429
+	public function addAliases($identifier, $aliases)
430
+	{
431
+		if (empty($aliases)) {
432
+			return;
433
+		}
434
+		$identifier = $this->processIdentifier($identifier);
435
+		foreach ((array) $aliases as $alias) {
436
+			$this->filters[ $this->processIdentifier($alias) ] = $identifier;
437
+		}
438
+	}
439
+
440
+
441
+	/**
442
+	 * Adds a service to one of the internal collections
443
+	 *
444
+	 * @param        $identifier
445
+	 * @param array  $arguments
446
+	 * @param string $type
447
+	 * @return mixed
448
+	 * @throws InvalidDataTypeException
449
+	 * @throws InvalidClassException
450
+	 * @throws OutOfBoundsException
451
+	 * @throws InvalidIdentifierException
452
+	 * @throws ServiceExistsException
453
+	 */
454
+	private function makeCoffee($identifier, $arguments = array(), $type = '')
455
+	{
456
+		if ((empty($type) || $type === CoffeeMaker::BREW_SHARED) && $this->has($identifier)) {
457
+			throw new ServiceExistsException($identifier);
458
+		}
459
+		$identifier = $this->filterIdentifier($identifier);
460
+		$recipe = $this->getRecipe($identifier, $type);
461
+		$type = ! empty($type) ? $type : $recipe->type();
462
+		$coffee_maker = $this->getCoffeeMaker($type);
463
+		return $coffee_maker->brew($recipe, $arguments);
464
+	}
465
+
466
+
467
+	/**
468
+	 * filters alias identifiers to find the real class name
469
+	 *
470
+	 * @param  string $identifier Identifier for the entity class that the filter applies to
471
+	 *                            Typically a Fully Qualified Class Name
472
+	 * @return string
473
+	 * @throws InvalidIdentifierException
474
+	 */
475
+	private function filterIdentifier($identifier)
476
+	{
477
+		$identifier = $this->processIdentifier($identifier);
478
+		return isset($this->filters[ $identifier ]) && ! empty($this->filters[ $identifier ])
479
+			? $this->filters[ $identifier ]
480
+			: $identifier;
481
+	}
482
+
483
+
484
+	/**
485
+	 * verifies and standardizes identifiers
486
+	 *
487
+	 * @param  string $identifier Identifier for the entity class
488
+	 *                            Typically a Fully Qualified Class Name
489
+	 * @return string
490
+	 * @throws InvalidIdentifierException
491
+	 */
492
+	private function processIdentifier($identifier)
493
+	{
494
+		if (! is_string($identifier)) {
495
+			throw new InvalidIdentifierException(
496
+				is_object($identifier) ? get_class($identifier) : gettype($identifier),
497
+				'\Fully\Qualified\ClassName'
498
+			);
499
+		}
500
+		return ltrim($identifier, '\\');
501
+	}
502
+
503
+
504
+	/**
505
+	 * @param string $type
506
+	 * @return CoffeeMakerInterface
507
+	 * @throws OutOfBoundsException
508
+	 * @throws InvalidDataTypeException
509
+	 * @throws InvalidClassException
510
+	 */
511
+	private function getCoffeeMaker($type)
512
+	{
513
+		if (! $this->coffee_makers->has($type)) {
514
+			throw new OutOfBoundsException(
515
+				__('The requested coffee maker is either missing or invalid.', 'event_espresso')
516
+			);
517
+		}
518
+		return $this->coffee_makers->get($type);
519
+	}
520
+
521
+
522
+	/**
523
+	 * Retrieves all recipes that use a wildcard "*" in their identifier
524
+	 * This allows recipes to be set up for handling
525
+	 * legacy classes that do not support PSR-4 autoloading.
526
+	 * for example:
527
+	 * using "EEM_*" for a recipe identifier would target all legacy models like EEM_Attendee
528
+	 *
529
+	 * @return array
530
+	 */
531
+	private function getDefaultRecipes()
532
+	{
533
+		$default_recipes = array();
534
+		$this->recipes->rewind();
535
+		while ($this->recipes->valid()) {
536
+			$identifier = $this->recipes->getInfo();
537
+			// does this recipe use a wildcard ? (but is NOT the global default)
538
+			if ($identifier !== Recipe::DEFAULT_ID && strpos($identifier, '*') !== false) {
539
+				// strip the wildcard and use identifier as key
540
+				$default_recipes[ str_replace('*', '', $identifier) ] = $this->recipes->current();
541
+			}
542
+			$this->recipes->next();
543
+		}
544
+		return $default_recipes;
545
+	}
546
+
547
+
548
+	/**
549
+	 * clones a default recipe and then copies details
550
+	 * from the incoming request to it so that it can be used
551
+	 *
552
+	 * @param RecipeInterface $default_recipe
553
+	 * @param string          $identifier
554
+	 * @param string          $type
555
+	 * @return RecipeInterface
556
+	 */
557
+	private function copyDefaultRecipe(RecipeInterface $default_recipe, $identifier, $type = '')
558
+	{
559
+		$recipe = clone $default_recipe;
560
+		if (! empty($type)) {
561
+			$recipe->setType($type);
562
+		}
563
+		// is this the base default recipe ?
564
+		if ($default_recipe->identifier() === Recipe::DEFAULT_ID) {
565
+			$recipe->setIdentifier($identifier);
566
+			$recipe->setFqcn($identifier);
567
+			return $recipe;
568
+		}
569
+		$recipe->setIdentifier($identifier);
570
+		foreach ($default_recipe->paths() as $path) {
571
+			$path = str_replace('*', $identifier, $path);
572
+			if (is_readable($path)) {
573
+				$recipe->setPaths($path);
574
+			}
575
+		}
576
+		$recipe->setFqcn($identifier);
577
+		return $recipe;
578
+	}
579
+
580
+
581
+	/**
582
+	 * @param  string $identifier Identifier for the entity class that the service applies to
583
+	 *                            Typically a Fully Qualified Class Name
584
+	 * @param mixed   $service
585
+	 * @return mixed
586
+	 * @throws InvalidServiceException
587
+	 */
588
+	private function validateService($identifier, $service)
589
+	{
590
+		if (! is_object($service)) {
591
+			throw new InvalidServiceException(
592
+				$identifier,
593
+				$service
594
+			);
595
+		}
596
+		return $service;
597
+	}
598 598
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
         }
160 160
         // if the reservoir doesn't have a closure already for the requested identifier,
161 161
         // then neither a shared service nor a closure for making entities has been built yet
162
-        if (! $this->reservoir->has($identifier)) {
162
+        if ( ! $this->reservoir->has($identifier)) {
163 163
             // so let's brew something up and add it to the proper collection
164 164
             $brewed = $this->makeCoffee($identifier, $arguments, $type);
165 165
         }
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
      */
285 285
     public function addClosure($identifier, $closure)
286 286
     {
287
-        if (! is_callable($closure)) {
287
+        if ( ! is_callable($closure)) {
288 288
             throw new InvalidDataTypeException('$closure', $closure, 'Closure');
289 289
         }
290 290
         $identifier = $this->processIdentifier($identifier);
@@ -393,7 +393,7 @@  discard block
 block discarded – undo
393 393
             // is the wildcard recipe prefix in the identifier ?
394 394
             if (strpos($identifier, $wildcard) !== false) {
395 395
                 // track matches and use the number of wildcard characters matched for the key
396
-                $matches[ strlen($wildcard) ] = $default_recipe;
396
+                $matches[strlen($wildcard)] = $default_recipe;
397 397
             }
398 398
         }
399 399
         if (count($matches) > 0) {
@@ -433,7 +433,7 @@  discard block
 block discarded – undo
433 433
         }
434 434
         $identifier = $this->processIdentifier($identifier);
435 435
         foreach ((array) $aliases as $alias) {
436
-            $this->filters[ $this->processIdentifier($alias) ] = $identifier;
436
+            $this->filters[$this->processIdentifier($alias)] = $identifier;
437 437
         }
438 438
     }
439 439
 
@@ -475,8 +475,8 @@  discard block
 block discarded – undo
475 475
     private function filterIdentifier($identifier)
476 476
     {
477 477
         $identifier = $this->processIdentifier($identifier);
478
-        return isset($this->filters[ $identifier ]) && ! empty($this->filters[ $identifier ])
479
-            ? $this->filters[ $identifier ]
478
+        return isset($this->filters[$identifier]) && ! empty($this->filters[$identifier])
479
+            ? $this->filters[$identifier]
480 480
             : $identifier;
481 481
     }
482 482
 
@@ -491,7 +491,7 @@  discard block
 block discarded – undo
491 491
      */
492 492
     private function processIdentifier($identifier)
493 493
     {
494
-        if (! is_string($identifier)) {
494
+        if ( ! is_string($identifier)) {
495 495
             throw new InvalidIdentifierException(
496 496
                 is_object($identifier) ? get_class($identifier) : gettype($identifier),
497 497
                 '\Fully\Qualified\ClassName'
@@ -510,7 +510,7 @@  discard block
 block discarded – undo
510 510
      */
511 511
     private function getCoffeeMaker($type)
512 512
     {
513
-        if (! $this->coffee_makers->has($type)) {
513
+        if ( ! $this->coffee_makers->has($type)) {
514 514
             throw new OutOfBoundsException(
515 515
                 __('The requested coffee maker is either missing or invalid.', 'event_espresso')
516 516
             );
@@ -537,7 +537,7 @@  discard block
 block discarded – undo
537 537
             // does this recipe use a wildcard ? (but is NOT the global default)
538 538
             if ($identifier !== Recipe::DEFAULT_ID && strpos($identifier, '*') !== false) {
539 539
                 // strip the wildcard and use identifier as key
540
-                $default_recipes[ str_replace('*', '', $identifier) ] = $this->recipes->current();
540
+                $default_recipes[str_replace('*', '', $identifier)] = $this->recipes->current();
541 541
             }
542 542
             $this->recipes->next();
543 543
         }
@@ -557,7 +557,7 @@  discard block
 block discarded – undo
557 557
     private function copyDefaultRecipe(RecipeInterface $default_recipe, $identifier, $type = '')
558 558
     {
559 559
         $recipe = clone $default_recipe;
560
-        if (! empty($type)) {
560
+        if ( ! empty($type)) {
561 561
             $recipe->setType($type);
562 562
         }
563 563
         // is this the base default recipe ?
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
      */
588 588
     private function validateService($identifier, $service)
589 589
     {
590
-        if (! is_object($service)) {
590
+        if ( ! is_object($service)) {
591 591
             throw new InvalidServiceException(
592 592
                 $identifier,
593 593
                 $service
Please login to merge, or discard this patch.
core/interfaces/line_items/EEI_Line_Item_Display.interface.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -9,12 +9,12 @@
 block discarded – undo
9 9
 interface EEI_Line_Item_Display
10 10
 {
11 11
 
12
-    /**
13
-     * @param EE_Line_Item $line_item
14
-     * @param array        $options
15
-     * @return mixed
16
-     */
17
-    public function display_line_item(EE_Line_Item $line_item, $options = array());
12
+	/**
13
+	 * @param EE_Line_Item $line_item
14
+	 * @param array        $options
15
+	 * @return mixed
16
+	 */
17
+	public function display_line_item(EE_Line_Item $line_item, $options = array());
18 18
 
19 19
 }
20 20
 
Please login to merge, or discard this patch.
form_sections/strategies/normalization/EE_Int_Normalization.strategy.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -17,7 +17,7 @@
 block discarded – undo
17 17
 
18 18
     /**
19 19
      * @param string $value_to_normalize
20
-     * @return int|mixed|string
20
+     * @return null|integer
21 21
      * @throws \EE_Validation_Error
22 22
      */
23 23
     public function normalize($value_to_normalize)
Please login to merge, or discard this patch.
Indentation   +74 added lines, -74 removed lines patch added patch discarded remove patch
@@ -10,88 +10,88 @@
 block discarded – undo
10 10
 class EE_Int_Normalization extends EE_Normalization_Strategy_Base
11 11
 {
12 12
 
13
-    /*
13
+	/*
14 14
      * regex pattern that matches for the following:
15 15
      *      * optional negative sign
16 16
      *      * one or more digits
17 17
      */
18
-    const REGEX = '/^(-?)(\d+)(?:\.0+)?$/';
18
+	const REGEX = '/^(-?)(\d+)(?:\.0+)?$/';
19 19
 
20 20
 
21 21
 
22
-    /**
23
-     * @param string $value_to_normalize
24
-     * @return int|mixed|string
25
-     * @throws \EE_Validation_Error
26
-     */
27
-    public function normalize($value_to_normalize)
28
-    {
29
-        if ($value_to_normalize === null) {
30
-            return null;
31
-        }
32
-        if (is_int($value_to_normalize) || is_float($value_to_normalize)) {
33
-            return (int) $value_to_normalize;
34
-        }
35
-        if (! is_string($value_to_normalize)) {
36
-            throw new EE_Validation_Error(
37
-                sprintf(
38
-                    __('The value "%s" must be a string submitted for normalization, it was %s', 'event_espresso'),
39
-                    print_r($value_to_normalize, true),
40
-                    gettype($value_to_normalize)
41
-                )
42
-            );
43
-        }
44
-        $value_to_normalize = filter_var(
45
-            $value_to_normalize,
46
-            FILTER_SANITIZE_NUMBER_FLOAT,
47
-            FILTER_FLAG_ALLOW_FRACTION
48
-        );
49
-        if ($value_to_normalize === '') {
50
-            return null;
51
-        }
52
-        $matches = array();
53
-        if (preg_match(EE_Int_Normalization::REGEX, $value_to_normalize, $matches)) {
54
-            if (count($matches) === 3) {
55
-                // if first match is the negative sign,
56
-                // then the number needs to be multiplied by -1 to remain negative
57
-                return $matches[1] === '-'
58
-                    ? (int) $matches[2] * -1
59
-                    : (int) $matches[2];
60
-            }
61
-        }
62
-        // find if this input has a int validation strategy
63
-        // in which case, use its message
64
-        $validation_error_message = null;
65
-        foreach ($this->_input->get_validation_strategies() as $validation_strategy) {
66
-            if ($validation_strategy instanceof EE_Int_Validation_Strategy) {
67
-                $validation_error_message = $validation_strategy->get_validation_error_message();
68
-            }
69
-        }
70
-        // this really shouldn't ever happen because fields with a int normalization strategy
71
-        // should also have a int validation strategy, but in case it doesn't use the default
72
-        if (! $validation_error_message) {
73
-            $default_validation_strategy = new EE_Int_Validation_Strategy();
74
-            $validation_error_message = $default_validation_strategy->get_validation_error_message();
75
-        }
76
-        throw new EE_Validation_Error($validation_error_message, 'numeric_only');
77
-    }
22
+	/**
23
+	 * @param string $value_to_normalize
24
+	 * @return int|mixed|string
25
+	 * @throws \EE_Validation_Error
26
+	 */
27
+	public function normalize($value_to_normalize)
28
+	{
29
+		if ($value_to_normalize === null) {
30
+			return null;
31
+		}
32
+		if (is_int($value_to_normalize) || is_float($value_to_normalize)) {
33
+			return (int) $value_to_normalize;
34
+		}
35
+		if (! is_string($value_to_normalize)) {
36
+			throw new EE_Validation_Error(
37
+				sprintf(
38
+					__('The value "%s" must be a string submitted for normalization, it was %s', 'event_espresso'),
39
+					print_r($value_to_normalize, true),
40
+					gettype($value_to_normalize)
41
+				)
42
+			);
43
+		}
44
+		$value_to_normalize = filter_var(
45
+			$value_to_normalize,
46
+			FILTER_SANITIZE_NUMBER_FLOAT,
47
+			FILTER_FLAG_ALLOW_FRACTION
48
+		);
49
+		if ($value_to_normalize === '') {
50
+			return null;
51
+		}
52
+		$matches = array();
53
+		if (preg_match(EE_Int_Normalization::REGEX, $value_to_normalize, $matches)) {
54
+			if (count($matches) === 3) {
55
+				// if first match is the negative sign,
56
+				// then the number needs to be multiplied by -1 to remain negative
57
+				return $matches[1] === '-'
58
+					? (int) $matches[2] * -1
59
+					: (int) $matches[2];
60
+			}
61
+		}
62
+		// find if this input has a int validation strategy
63
+		// in which case, use its message
64
+		$validation_error_message = null;
65
+		foreach ($this->_input->get_validation_strategies() as $validation_strategy) {
66
+			if ($validation_strategy instanceof EE_Int_Validation_Strategy) {
67
+				$validation_error_message = $validation_strategy->get_validation_error_message();
68
+			}
69
+		}
70
+		// this really shouldn't ever happen because fields with a int normalization strategy
71
+		// should also have a int validation strategy, but in case it doesn't use the default
72
+		if (! $validation_error_message) {
73
+			$default_validation_strategy = new EE_Int_Validation_Strategy();
74
+			$validation_error_message = $default_validation_strategy->get_validation_error_message();
75
+		}
76
+		throw new EE_Validation_Error($validation_error_message, 'numeric_only');
77
+	}
78 78
 
79 79
 
80 80
 
81
-    /**
82
-     * Converts the int into a string for use in teh html form
83
-     *
84
-     * @param int $normalized_value
85
-     * @return string
86
-     */
87
-    public function unnormalize($normalized_value)
88
-    {
89
-        if ($normalized_value === null || $normalized_value === '') {
90
-            return '';
91
-        }
92
-        if (empty($normalized_value)) {
93
-            return '0';
94
-        }
95
-        return "$normalized_value";
96
-    }
81
+	/**
82
+	 * Converts the int into a string for use in teh html form
83
+	 *
84
+	 * @param int $normalized_value
85
+	 * @return string
86
+	 */
87
+	public function unnormalize($normalized_value)
88
+	{
89
+		if ($normalized_value === null || $normalized_value === '') {
90
+			return '';
91
+		}
92
+		if (empty($normalized_value)) {
93
+			return '0';
94
+		}
95
+		return "$normalized_value";
96
+	}
97 97
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -32,7 +32,7 @@  discard block
 block discarded – undo
32 32
         if (is_int($value_to_normalize) || is_float($value_to_normalize)) {
33 33
             return (int) $value_to_normalize;
34 34
         }
35
-        if (! is_string($value_to_normalize)) {
35
+        if ( ! is_string($value_to_normalize)) {
36 36
             throw new EE_Validation_Error(
37 37
                 sprintf(
38 38
                     __('The value "%s" must be a string submitted for normalization, it was %s', 'event_espresso'),
@@ -69,7 +69,7 @@  discard block
 block discarded – undo
69 69
         }
70 70
         // this really shouldn't ever happen because fields with a int normalization strategy
71 71
         // should also have a int validation strategy, but in case it doesn't use the default
72
-        if (! $validation_error_message) {
72
+        if ( ! $validation_error_message) {
73 73
             $default_validation_strategy = new EE_Int_Validation_Strategy();
74 74
             $validation_error_message = $default_validation_strategy->get_validation_error_message();
75 75
         }
Please login to merge, or discard this patch.
core/db_models/EEM_Event.model.php 4 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -217,7 +217,7 @@
 block discarded – undo
217 217
 
218 218
     /**
219 219
      * Used to override the default for the additional limit field.
220
-     * @param $additional_limit
220
+     * @param integer $additional_limit
221 221
      */
222 222
     public static function set_default_additional_limit($additional_limit)
223 223
     {
Please login to merge, or discard this patch.
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -2,7 +2,6 @@
 block discarded – undo
2 2
 
3 3
 use EventEspresso\core\exceptions\InvalidDataTypeException;
4 4
 use EventEspresso\core\exceptions\InvalidInterfaceException;
5
-use EventEspresso\core\services\orm\ModelFieldFactory;
6 5
 
7 6
 /**
8 7
  * EEM_Event Model
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -278,7 +278,7 @@  discard block
 block discarded – undo
278 278
             'WP_User'                => new EE_Belongs_To_Relation(),
279 279
         );
280 280
         // this model is generally available for reading
281
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
281
+        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
282 282
         $this->model_chain_to_password = '';
283 283
         parent::__construct($timezone);
284 284
     }
@@ -371,7 +371,7 @@  discard block
 block discarded – undo
371 371
      */
372 372
     public function get_all_event_question_groups($EVT_ID = 0)
373 373
     {
374
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
374
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
375 375
             EE_Error::add_error(
376 376
                 esc_html__(
377 377
                     'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
@@ -405,7 +405,7 @@  discard block
 block discarded – undo
405 405
      */
406 406
     public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
407 407
     {
408
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
408
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
409 409
             EE_Error::add_error(
410 410
                 esc_html__(
411 411
                     // @codingStandardsIgnoreStart
@@ -448,7 +448,7 @@  discard block
 block discarded – undo
448 448
      */
449 449
     public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
450 450
     {
451
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
451
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
452 452
             EE_Error::add_error(
453 453
                 esc_html__(
454 454
                     'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
@@ -861,11 +861,11 @@  discard block
 block discarded – undo
861 861
         $questions = array();
862 862
         // get all question groups for event
863 863
         $qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
864
-        if (! empty($qgs)) {
864
+        if ( ! empty($qgs)) {
865 865
             foreach ($qgs as $qg) {
866 866
                 $qsts = $qg->questions();
867
-                $questions[ $qg->ID() ] = $qg->model_field_array();
868
-                $questions[ $qg->ID() ]['QSG_questions'] = array();
867
+                $questions[$qg->ID()] = $qg->model_field_array();
868
+                $questions[$qg->ID()]['QSG_questions'] = array();
869 869
                 foreach ($qsts as $qst) {
870 870
                     if ($qst->is_system_question()) {
871 871
                         continue;
@@ -879,26 +879,26 @@  discard block
 block discarded – undo
879 879
                     $answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
880 880
                     $qst_name = $qstn_id = $qst->ID();
881 881
                     $ans_id = $answer->ID();
882
-                    $qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
882
+                    $qst_name = ! empty($ans_id) ? '['.$qst_name.']['.$ans_id.']' : '['.$qst_name.']';
883 883
                     $input_name = '';
884 884
                     $input_id = sanitize_key($qst->display_text());
885 885
                     $input_class = '';
886
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
887
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
886
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()] = $qst->model_field_array();
887
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_name'] = 'qstn'
888 888
                                                                                            . $input_name
889 889
                                                                                            . $qst_name;
890
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
891
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
892
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
893
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
894
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
890
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_id'] = $input_id.'-'.$qstn_id;
891
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_class'] = $input_class;
892
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'] = array();
893
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['qst_obj'] = $qst;
894
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['ans_obj'] = $answer;
895 895
                     // leave responses as-is, don't convert stuff into html entities please!
896
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
896
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['htmlentities'] = false;
897 897
                     if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
898 898
                         $QSOs = $qst->options(true, $answer->value());
899 899
                         if (is_array($QSOs)) {
900 900
                             foreach ($QSOs as $QSO_ID => $QSO) {
901
-                                $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
901
+                                $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'][$QSO_ID] = $QSO->model_field_array();
902 902
                             }
903 903
                         }
904 904
                     }
Please login to merge, or discard this patch.
Indentation   +909 added lines, -909 removed lines patch added patch discarded remove patch
@@ -15,913 +15,913 @@
 block discarded – undo
15 15
 class EEM_Event extends EEM_CPT_Base
16 16
 {
17 17
 
18
-    /**
19
-     * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
20
-     * event
21
-     */
22
-    const sold_out = 'sold_out';
23
-
24
-    /**
25
-     * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
26
-     * date)
27
-     */
28
-    const postponed = 'postponed';
29
-
30
-    /**
31
-     * constant used by status(), indicating that the event will no longer occur
32
-     */
33
-    const cancelled = 'cancelled';
34
-
35
-
36
-    /**
37
-     * @var string
38
-     */
39
-    protected static $_default_reg_status;
40
-
41
-
42
-    /**
43
-     * This is the default for the additional limit field.
44
-     * @var int
45
-     */
46
-    protected static $_default_additional_limit = 10;
47
-
48
-
49
-    /**
50
-     * private instance of the Event object
51
-     *
52
-     * @var EEM_Event
53
-     */
54
-    protected static $_instance;
55
-
56
-
57
-
58
-
59
-    /**
60
-     * Adds a relationship to Term_Taxonomy for each CPT_Base
61
-     *
62
-     * @param string $timezone
63
-     * @throws \EE_Error
64
-     */
65
-    protected function __construct($timezone = null)
66
-    {
67
-        EE_Registry::instance()->load_model('Registration');
68
-        $this->singular_item = esc_html__('Event', 'event_espresso');
69
-        $this->plural_item = esc_html__('Events', 'event_espresso');
70
-        // to remove Cancelled events from the frontend, copy the following filter to your functions.php file
71
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
72
-        // to remove Postponed events from the frontend, copy the following filter to your functions.php file
73
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
74
-        // to remove Sold Out events from the frontend, copy the following filter to your functions.php file
75
-        //  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
76
-        $this->_custom_stati = apply_filters(
77
-            'AFEE__EEM_Event__construct___custom_stati',
78
-            array(
79
-                EEM_Event::cancelled => array(
80
-                    'label'  => esc_html__('Cancelled', 'event_espresso'),
81
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
82
-                ),
83
-                EEM_Event::postponed => array(
84
-                    'label'  => esc_html__('Postponed', 'event_espresso'),
85
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
86
-                ),
87
-                EEM_Event::sold_out  => array(
88
-                    'label'  => esc_html__('Sold Out', 'event_espresso'),
89
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
90
-                ),
91
-            )
92
-        );
93
-        self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
94
-            : self::$_default_reg_status;
95
-        $this->_tables = array(
96
-            'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
97
-            'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
98
-        );
99
-        $this->_fields = array(
100
-            'Event_CPT'  => array(
101
-                'EVT_ID'         => new EE_Primary_Key_Int_Field(
102
-                    'ID',
103
-                    esc_html__('Post ID for Event', 'event_espresso')
104
-                ),
105
-                'EVT_name'       => new EE_Plain_Text_Field(
106
-                    'post_title',
107
-                    esc_html__('Event Name', 'event_espresso'),
108
-                    false,
109
-                    ''
110
-                ),
111
-                'EVT_desc'       => new EE_Post_Content_Field(
112
-                    'post_content',
113
-                    esc_html__('Event Description', 'event_espresso'),
114
-                    false,
115
-                    ''
116
-                ),
117
-                'EVT_slug'       => new EE_Slug_Field(
118
-                    'post_name',
119
-                    esc_html__('Event Slug', 'event_espresso'),
120
-                    false,
121
-                    ''
122
-                ),
123
-                'EVT_created'    => new EE_Datetime_Field(
124
-                    'post_date',
125
-                    esc_html__('Date/Time Event Created', 'event_espresso'),
126
-                    false,
127
-                    EE_Datetime_Field::now
128
-                ),
129
-                'EVT_short_desc' => new EE_Simple_HTML_Field(
130
-                    'post_excerpt',
131
-                    esc_html__('Event Short Description', 'event_espresso'),
132
-                    false,
133
-                    ''
134
-                ),
135
-                'EVT_modified'   => new EE_Datetime_Field(
136
-                    'post_modified',
137
-                    esc_html__('Date/Time Event Modified', 'event_espresso'),
138
-                    false,
139
-                    EE_Datetime_Field::now
140
-                ),
141
-                'EVT_wp_user'    => new EE_WP_User_Field(
142
-                    'post_author',
143
-                    esc_html__('Event Creator ID', 'event_espresso'),
144
-                    false
145
-                ),
146
-                'parent'         => new EE_Integer_Field(
147
-                    'post_parent',
148
-                    esc_html__('Event Parent ID', 'event_espresso'),
149
-                    false,
150
-                    0
151
-                ),
152
-                'EVT_order'      => new EE_Integer_Field(
153
-                    'menu_order',
154
-                    esc_html__('Event Menu Order', 'event_espresso'),
155
-                    false,
156
-                    1
157
-                ),
158
-                'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
159
-                // EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
160
-                'status'         => new EE_WP_Post_Status_Field(
161
-                    'post_status',
162
-                    esc_html__('Event Status', 'event_espresso'),
163
-                    false,
164
-                    'draft',
165
-                    $this->_custom_stati
166
-                ),
167
-                'password' => new EE_Password_Field(
168
-                    'post_password',
169
-                    __('Password', 'event_espresso'),
170
-                    false,
171
-                    '',
172
-                    array(
173
-                        'EVT_desc',
174
-                        'EVT_short_desc',
175
-                        'EVT_display_desc',
176
-                        'EVT_display_ticket_selector',
177
-                        'EVT_visible_on',
178
-                        'EVT_additional_limit',
179
-                        'EVT_default_registration_status',
180
-                        'EVT_member_only',
181
-                        'EVT_phone',
182
-                        'EVT_allow_overflow',
183
-                        'EVT_timezone_string',
184
-                        'EVT_external_URL',
185
-                        'EVT_donations'
186
-                    )
187
-                )
188
-            ),
189
-            'Event_Meta' => array(
190
-                'EVTM_ID'                         => new EE_DB_Only_Float_Field(
191
-                    'EVTM_ID',
192
-                    esc_html__('Event Meta Row ID', 'event_espresso'),
193
-                    false
194
-                ),
195
-                'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
196
-                    'EVT_ID',
197
-                    esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
198
-                    false
199
-                ),
200
-                'EVT_display_desc'                => new EE_Boolean_Field(
201
-                    'EVT_display_desc',
202
-                    esc_html__('Display Description Flag', 'event_espresso'),
203
-                    false,
204
-                    true
205
-                ),
206
-                'EVT_display_ticket_selector'     => new EE_Boolean_Field(
207
-                    'EVT_display_ticket_selector',
208
-                    esc_html__('Display Ticket Selector Flag', 'event_espresso'),
209
-                    false,
210
-                    true
211
-                ),
212
-                'EVT_visible_on'                  => new EE_Datetime_Field(
213
-                    'EVT_visible_on',
214
-                    esc_html__('Event Visible Date', 'event_espresso'),
215
-                    true,
216
-                    EE_Datetime_Field::now
217
-                ),
218
-                'EVT_additional_limit'            => new EE_Integer_Field(
219
-                    'EVT_additional_limit',
220
-                    esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
221
-                    true,
222
-                    self::$_default_additional_limit
223
-                ),
224
-                'EVT_default_registration_status' => new EE_Enum_Text_Field(
225
-                    'EVT_default_registration_status',
226
-                    esc_html__('Default Registration Status on this Event', 'event_espresso'),
227
-                    false,
228
-                    EEM_Event::$_default_reg_status,
229
-                    EEM_Registration::reg_status_array()
230
-                ),
231
-                'EVT_member_only'                 => new EE_Boolean_Field(
232
-                    'EVT_member_only',
233
-                    esc_html__('Member-Only Event Flag', 'event_espresso'),
234
-                    false,
235
-                    false
236
-                ),
237
-                'EVT_phone'                       => new EE_Plain_Text_Field(
238
-                    'EVT_phone',
239
-                    esc_html__('Event Phone Number', 'event_espresso'),
240
-                    false,
241
-                    ''
242
-                ),
243
-                'EVT_allow_overflow'              => new EE_Boolean_Field(
244
-                    'EVT_allow_overflow',
245
-                    esc_html__('Allow Overflow on Event', 'event_espresso'),
246
-                    false,
247
-                    false
248
-                ),
249
-                'EVT_timezone_string'             => new EE_Plain_Text_Field(
250
-                    'EVT_timezone_string',
251
-                    esc_html__('Timezone (name) for Event times', 'event_espresso'),
252
-                    false,
253
-                    ''
254
-                ),
255
-                'EVT_external_URL'                => new EE_Plain_Text_Field(
256
-                    'EVT_external_URL',
257
-                    esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
258
-                    true
259
-                ),
260
-                'EVT_donations'                   => new EE_Boolean_Field(
261
-                    'EVT_donations',
262
-                    esc_html__('Accept Donations?', 'event_espresso'),
263
-                    false,
264
-                    false
265
-                ),
266
-            ),
267
-        );
268
-        $this->_model_relations = array(
269
-            'Registration'           => new EE_Has_Many_Relation(),
270
-            'Datetime'               => new EE_Has_Many_Relation(),
271
-            'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
272
-            'Event_Question_Group'   => new EE_Has_Many_Relation(),
273
-            'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
274
-            'Term_Relationship'      => new EE_Has_Many_Relation(),
275
-            'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
276
-            'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
277
-            'Attendee'               => new EE_HABTM_Relation('Registration'),
278
-            'WP_User'                => new EE_Belongs_To_Relation(),
279
-        );
280
-        // this model is generally available for reading
281
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
282
-        $this->model_chain_to_password = '';
283
-        parent::__construct($timezone);
284
-    }
285
-
286
-
287
-
288
-    /**
289
-     * @param string $default_reg_status
290
-     */
291
-    public static function set_default_reg_status($default_reg_status)
292
-    {
293
-        self::$_default_reg_status = $default_reg_status;
294
-        // if EEM_Event has already been instantiated,
295
-        // then we need to reset the `EVT_default_reg_status` field to use the new default.
296
-        if (self::$_instance instanceof EEM_Event) {
297
-            $default_reg_status = new EE_Enum_Text_Field(
298
-                'EVT_default_registration_status',
299
-                esc_html__('Default Registration Status on this Event', 'event_espresso'),
300
-                false,
301
-                $default_reg_status,
302
-                EEM_Registration::reg_status_array()
303
-            );
304
-            $default_reg_status->_construct_finalize(
305
-                'Event_Meta',
306
-                'EVT_default_registration_status',
307
-                'EEM_Event'
308
-            );
309
-            self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
310
-        }
311
-    }
312
-
313
-
314
-    /**
315
-     * Used to override the default for the additional limit field.
316
-     * @param $additional_limit
317
-     */
318
-    public static function set_default_additional_limit($additional_limit)
319
-    {
320
-        self::$_default_additional_limit = (int) $additional_limit;
321
-        if (self::$_instance instanceof EEM_Event) {
322
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
323
-                'EVT_additional_limit',
324
-                __('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
325
-                true,
326
-                self::$_default_additional_limit
327
-            );
328
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
329
-                'Event_Meta',
330
-                'EVT_additional_limit',
331
-                'EEM_Event'
332
-            );
333
-        }
334
-    }
335
-
336
-
337
-    /**
338
-     * Return what is currently set as the default additional limit for the event.
339
-     * @return int
340
-     */
341
-    public static function get_default_additional_limit()
342
-    {
343
-        return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
344
-    }
345
-
346
-
347
-    /**
348
-     * get_question_groups
349
-     *
350
-     * @return array
351
-     * @throws \EE_Error
352
-     */
353
-    public function get_all_question_groups()
354
-    {
355
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
356
-            array(
357
-                array('QSG_deleted' => false),
358
-                'order_by' => array('QSG_order' => 'ASC'),
359
-            )
360
-        );
361
-    }
362
-
363
-
364
-
365
-    /**
366
-     * get_question_groups
367
-     *
368
-     * @param int $EVT_ID
369
-     * @return array|bool
370
-     * @throws \EE_Error
371
-     */
372
-    public function get_all_event_question_groups($EVT_ID = 0)
373
-    {
374
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
375
-            EE_Error::add_error(
376
-                esc_html__(
377
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
378
-                    'event_espresso'
379
-                ),
380
-                __FILE__,
381
-                __FUNCTION__,
382
-                __LINE__
383
-            );
384
-            return false;
385
-        }
386
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
387
-            array(
388
-                array('EVT_ID' => $EVT_ID),
389
-            )
390
-        );
391
-    }
392
-
393
-
394
-    /**
395
-     * get_question_groups
396
-     *
397
-     * @param int $EVT_ID
398
-     * @param boolean $for_primary_attendee
399
-     * @return array|bool
400
-     * @throws EE_Error
401
-     * @throws InvalidArgumentException
402
-     * @throws ReflectionException
403
-     * @throws InvalidDataTypeException
404
-     * @throws InvalidInterfaceException
405
-     */
406
-    public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
407
-    {
408
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
409
-            EE_Error::add_error(
410
-                esc_html__(
411
-                    // @codingStandardsIgnoreStart
412
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
413
-                    // @codingStandardsIgnoreEnd
414
-                    'event_espresso'
415
-                ),
416
-                __FILE__,
417
-                __FUNCTION__,
418
-                __LINE__
419
-            );
420
-            return false;
421
-        }
422
-        $query_params = [
423
-            [
424
-                'EVT_ID' => $EVT_ID,
425
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true
426
-            ]
427
-        ];
428
-        if ($for_primary_attendee) {
429
-            $query_params[0]['EQG_primary'] = true;
430
-        } else {
431
-            $query_params[0]['EQG_additional'] = true;
432
-        }
433
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
434
-    }
435
-
436
-
437
-    /**
438
-     * get_question_groups
439
-     *
440
-     * @param int $EVT_ID
441
-     * @param EE_Registration $registration
442
-     * @return array|bool
443
-     * @throws EE_Error
444
-     * @throws InvalidArgumentException
445
-     * @throws InvalidDataTypeException
446
-     * @throws InvalidInterfaceException
447
-     * @throws ReflectionException
448
-     */
449
-    public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
450
-    {
451
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
452
-            EE_Error::add_error(
453
-                esc_html__(
454
-                    'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
455
-                    'event_espresso'
456
-                ),
457
-                __FILE__,
458
-                __FUNCTION__,
459
-                __LINE__
460
-            );
461
-            return false;
462
-        }
463
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
464
-            [
465
-                [
466
-                    'Event_Question_Group.EVT_ID'      => $EVT_ID,
467
-                    'Event_Question_Group.'
468
-                        . EEM_Event_Question_Group::instance()->fieldNameForContext(
469
-                            $registration->is_primary_registrant()
470
-                        ) => true
471
-                ],
472
-                'order_by' => ['QSG_order' => 'ASC'],
473
-            ]
474
-        );
475
-    }
476
-
477
-
478
-
479
-    /**
480
-     * get_question_target_db_column
481
-     *
482
-     * @param string $QSG_IDs csv list of $QSG IDs
483
-     * @return array|bool
484
-     * @throws \EE_Error
485
-     */
486
-    public function get_questions_in_groups($QSG_IDs = '')
487
-    {
488
-        if (empty($QSG_IDs)) {
489
-            EE_Error::add_error(
490
-                esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
491
-                __FILE__,
492
-                __FUNCTION__,
493
-                __LINE__
494
-            );
495
-            return false;
496
-        }
497
-        return EE_Registry::instance()->load_model('Question')->get_all(
498
-            array(
499
-                array(
500
-                    'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
501
-                    'QST_deleted'           => false,
502
-                    'QST_admin_only'        => is_admin(),
503
-                ),
504
-                'order_by' => 'QST_order',
505
-            )
506
-        );
507
-    }
508
-
509
-
510
-
511
-    /**
512
-     * get_options_for_question
513
-     *
514
-     * @param string $QST_IDs csv list of $QST IDs
515
-     * @return array|bool
516
-     * @throws \EE_Error
517
-     */
518
-    public function get_options_for_question($QST_IDs)
519
-    {
520
-        if (empty($QST_IDs)) {
521
-            EE_Error::add_error(
522
-                esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
523
-                __FILE__,
524
-                __FUNCTION__,
525
-                __LINE__
526
-            );
527
-            return false;
528
-        }
529
-        return EE_Registry::instance()->load_model('Question_Option')->get_all(
530
-            array(
531
-                array(
532
-                    'Question.QST_ID' => array('IN', $QST_IDs),
533
-                    'QSO_deleted'     => false,
534
-                ),
535
-                'order_by' => 'QSO_ID',
536
-            )
537
-        );
538
-    }
539
-
540
-
541
-
542
-
543
-
544
-
545
-
546
-    /**
547
-     * Gets all events that are published
548
-     * and have event start time earlier than now and an event end time later than now
549
-     *
550
-     * @param  array $query_params An array of query params to further filter on
551
-     *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
552
-     * @param bool   $count        whether to return the count or not (default FALSE)
553
-     * @return EE_Event[]|int
554
-     * @throws \EE_Error
555
-     */
556
-    public function get_active_events($query_params, $count = false)
557
-    {
558
-        if (array_key_exists(0, $query_params)) {
559
-            $where_params = $query_params[0];
560
-            unset($query_params[0]);
561
-        } else {
562
-            $where_params = array();
563
-        }
564
-        // if we have count make sure we don't include group by
565
-        if ($count && isset($query_params['group_by'])) {
566
-            unset($query_params['group_by']);
567
-        }
568
-        // let's add specific query_params for active_events
569
-        // keep in mind this will override any sent status in the query AND any date queries.
570
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
571
-        // if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
572
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
573
-            $where_params['Datetime.DTT_EVT_start******'] = array(
574
-                '<',
575
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
576
-            );
577
-        } else {
578
-            $where_params['Datetime.DTT_EVT_start'] = array(
579
-                '<',
580
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
581
-            );
582
-        }
583
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
584
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
585
-                '>',
586
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
587
-            );
588
-        } else {
589
-            $where_params['Datetime.DTT_EVT_end'] = array(
590
-                '>',
591
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
592
-            );
593
-        }
594
-        $query_params[0] = $where_params;
595
-        // don't use $query_params with count()
596
-        // because we don't want to include additional query clauses like "GROUP BY"
597
-        return $count
598
-            ? $this->count(array($where_params), 'EVT_ID', true)
599
-            : $this->get_all($query_params);
600
-    }
601
-
602
-
603
-
604
-    /**
605
-     * get all events that are published and have an event start time later than now
606
-     *
607
-     * @param  array $query_params An array of query params to further filter on
608
-     *                             (Note that status and DTT_EVT_start will be overridden)
609
-     * @param bool   $count        whether to return the count or not (default FALSE)
610
-     * @return EE_Event[]|int
611
-     * @throws \EE_Error
612
-     */
613
-    public function get_upcoming_events($query_params, $count = false)
614
-    {
615
-        if (array_key_exists(0, $query_params)) {
616
-            $where_params = $query_params[0];
617
-            unset($query_params[0]);
618
-        } else {
619
-            $where_params = array();
620
-        }
621
-        // if we have count make sure we don't include group by
622
-        if ($count && isset($query_params['group_by'])) {
623
-            unset($query_params['group_by']);
624
-        }
625
-        // let's add specific query_params for active_events
626
-        // keep in mind this will override any sent status in the query AND any date queries.
627
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
628
-        // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
629
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
630
-            $where_params['Datetime.DTT_EVT_start*****'] = array(
631
-                '>',
632
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
633
-            );
634
-        } else {
635
-            $where_params['Datetime.DTT_EVT_start'] = array(
636
-                '>',
637
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
638
-            );
639
-        }
640
-        $query_params[0] = $where_params;
641
-        // don't use $query_params with count()
642
-        // because we don't want to include additional query clauses like "GROUP BY"
643
-        return $count
644
-            ? $this->count(array($where_params), 'EVT_ID', true)
645
-            : $this->get_all($query_params);
646
-    }
647
-
648
-
649
-
650
-    /**
651
-     * Gets all events that are published
652
-     * and have an event end time later than now
653
-     *
654
-     * @param  array $query_params An array of query params to further filter on
655
-     *                             (note that status and DTT_EVT_end will be overridden)
656
-     * @param bool   $count        whether to return the count or not (default FALSE)
657
-     * @return EE_Event[]|int
658
-     * @throws \EE_Error
659
-     */
660
-    public function get_active_and_upcoming_events($query_params, $count = false)
661
-    {
662
-        if (array_key_exists(0, $query_params)) {
663
-            $where_params = $query_params[0];
664
-            unset($query_params[0]);
665
-        } else {
666
-            $where_params = array();
667
-        }
668
-        // if we have count make sure we don't include group by
669
-        if ($count && isset($query_params['group_by'])) {
670
-            unset($query_params['group_by']);
671
-        }
672
-        // let's add specific query_params for active_events
673
-        // keep in mind this will override any sent status in the query AND any date queries.
674
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
675
-        // add where params for DTT_EVT_end
676
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
677
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
678
-                '>',
679
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
680
-            );
681
-        } else {
682
-            $where_params['Datetime.DTT_EVT_end'] = array(
683
-                '>',
684
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
685
-            );
686
-        }
687
-        $query_params[0] = $where_params;
688
-        // don't use $query_params with count()
689
-        // because we don't want to include additional query clauses like "GROUP BY"
690
-        return $count
691
-            ? $this->count(array($where_params), 'EVT_ID', true)
692
-            : $this->get_all($query_params);
693
-    }
694
-
695
-
696
-
697
-    /**
698
-     * This only returns events that are expired.
699
-     * They may still be published but all their datetimes have expired.
700
-     *
701
-     * @param  array $query_params An array of query params to further filter on
702
-     *                             (note that status and DTT_EVT_end will be overridden)
703
-     * @param bool   $count        whether to return the count or not (default FALSE)
704
-     * @return EE_Event[]|int
705
-     * @throws \EE_Error
706
-     */
707
-    public function get_expired_events($query_params, $count = false)
708
-    {
709
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
710
-        // if we have count make sure we don't include group by
711
-        if ($count && isset($query_params['group_by'])) {
712
-            unset($query_params['group_by']);
713
-        }
714
-        // let's add specific query_params for active_events
715
-        // keep in mind this will override any sent status in the query AND any date queries.
716
-        if (isset($where_params['status'])) {
717
-            unset($where_params['status']);
718
-        }
719
-        $exclude_query = $query_params;
720
-        if (isset($exclude_query[0])) {
721
-            unset($exclude_query[0]);
722
-        }
723
-        $exclude_query[0] = array(
724
-            'Datetime.DTT_EVT_end' => array(
725
-                '>',
726
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
727
-            ),
728
-        );
729
-        // first get all events that have datetimes where its not expired.
730
-        $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
731
-        $event_ids = array_keys($event_ids);
732
-        // if we have any additional query_params, let's add them to the 'AND' condition
733
-        $and_condition = array(
734
-            'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
735
-            'EVT_ID'               => array('NOT IN', $event_ids),
736
-        );
737
-        if (isset($where_params['OR'])) {
738
-            $and_condition['OR'] = $where_params['OR'];
739
-            unset($where_params['OR']);
740
-        }
741
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
742
-            $and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
743
-            unset($where_params['Datetime.DTT_EVT_end']);
744
-        }
745
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
746
-            $and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
747
-            unset($where_params['Datetime.DTT_EVT_start']);
748
-        }
749
-        // merge remaining $where params with the and conditions.
750
-        $where_params['AND'] = array_merge($and_condition, $where_params);
751
-        $query_params[0] = $where_params;
752
-        // don't use $query_params with count()
753
-        // because we don't want to include additional query clauses like "GROUP BY"
754
-        return $count
755
-            ? $this->count(array($where_params), 'EVT_ID', true)
756
-            : $this->get_all($query_params);
757
-    }
758
-
759
-
760
-
761
-    /**
762
-     * This basically just returns the events that do not have the publish status.
763
-     *
764
-     * @param  array   $query_params An array of query params to further filter on
765
-     *                               (note that status will be overwritten)
766
-     * @param  boolean $count        whether to return the count or not (default FALSE)
767
-     * @return EE_Event[]|int
768
-     * @throws \EE_Error
769
-     */
770
-    public function get_inactive_events($query_params, $count = false)
771
-    {
772
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
773
-        // let's add in specific query_params for inactive events.
774
-        if (isset($where_params['status'])) {
775
-            unset($where_params['status']);
776
-        }
777
-        // if we have count make sure we don't include group by
778
-        if ($count && isset($query_params['group_by'])) {
779
-            unset($query_params['group_by']);
780
-        }
781
-        // if we have any additional query_params, let's add them to the 'AND' condition
782
-        $where_params['AND']['status'] = array('!=', 'publish');
783
-        if (isset($where_params['OR'])) {
784
-            $where_params['AND']['OR'] = $where_params['OR'];
785
-            unset($where_params['OR']);
786
-        }
787
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
788
-            $where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
789
-            unset($where_params['Datetime.DTT_EVT_end']);
790
-        }
791
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
792
-            $where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
793
-            unset($where_params['Datetime.DTT_EVT_start']);
794
-        }
795
-        $query_params[0] = $where_params;
796
-        // don't use $query_params with count()
797
-        // because we don't want to include additional query clauses like "GROUP BY"
798
-        return $count
799
-            ? $this->count(array($where_params), 'EVT_ID', true)
800
-            : $this->get_all($query_params);
801
-    }
802
-
803
-
804
-
805
-    /**
806
-     * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
807
-     * because we don't want to override any existing global default prices but instead insert NEW prices that get
808
-     * attached to the event. See parent for param descriptions
809
-     *
810
-     * @param        $id_or_obj
811
-     * @param        $other_model_id_or_obj
812
-     * @param string $relationName
813
-     * @param array  $where_query
814
-     * @return EE_Base_Class
815
-     * @throws EE_Error
816
-     */
817
-    public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
818
-    {
819
-        if ($relationName === 'Price') {
820
-            // let's get the PRC object for the given ID to make sure that we aren't dealing with a default
821
-            $prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
822
-            // if EVT_ID = 0, then this is a default
823
-            if ((int) $prc_chk->get('EVT_ID') === 0) {
824
-                // let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
825
-                $prc_chk->set('PRC_ID', 0);
826
-            }
827
-            // run parent
828
-            return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
829
-        }
830
-        // otherwise carry on as normal
831
-        return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
832
-    }
833
-
834
-
835
-
836
-    /******************** DEPRECATED METHODS ********************/
837
-
838
-
839
-
840
-    /**
841
-     * _get_question_target_db_column
842
-     *
843
-     * @deprecated as of 4.8.32.rc.001. Instead consider using
844
-     *             EE_Registration_Custom_Questions_Form located in
845
-     *             admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
846
-     * @access     public
847
-     * @param    EE_Registration $registration (so existing answers for registration are included)
848
-     * @param    int             $EVT_ID       so all question groups are included for event (not just answers from
849
-     *                                         registration).
850
-     * @throws EE_Error
851
-     * @return    array
852
-     */
853
-    public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
854
-    {
855
-        if (empty($EVT_ID)) {
856
-            throw new EE_Error(__(
857
-                'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
858
-                'event_espresso'
859
-            ));
860
-        }
861
-        $questions = array();
862
-        // get all question groups for event
863
-        $qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
864
-        if (! empty($qgs)) {
865
-            foreach ($qgs as $qg) {
866
-                $qsts = $qg->questions();
867
-                $questions[ $qg->ID() ] = $qg->model_field_array();
868
-                $questions[ $qg->ID() ]['QSG_questions'] = array();
869
-                foreach ($qsts as $qst) {
870
-                    if ($qst->is_system_question()) {
871
-                        continue;
872
-                    }
873
-                    $answer = EEM_Answer::instance()->get_one(array(
874
-                        array(
875
-                            'QST_ID' => $qst->ID(),
876
-                            'REG_ID' => $registration->ID(),
877
-                        ),
878
-                    ));
879
-                    $answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
880
-                    $qst_name = $qstn_id = $qst->ID();
881
-                    $ans_id = $answer->ID();
882
-                    $qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
883
-                    $input_name = '';
884
-                    $input_id = sanitize_key($qst->display_text());
885
-                    $input_class = '';
886
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
887
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
888
-                                                                                           . $input_name
889
-                                                                                           . $qst_name;
890
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
891
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
892
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
893
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
894
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
895
-                    // leave responses as-is, don't convert stuff into html entities please!
896
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
897
-                    if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
898
-                        $QSOs = $qst->options(true, $answer->value());
899
-                        if (is_array($QSOs)) {
900
-                            foreach ($QSOs as $QSO_ID => $QSO) {
901
-                                $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
902
-                            }
903
-                        }
904
-                    }
905
-                }
906
-            }
907
-        }
908
-        return $questions;
909
-    }
910
-
911
-
912
-    /**
913
-     * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
914
-     *                             or an stdClass where each property is the name of a column,
915
-     * @return EE_Base_Class
916
-     * @throws \EE_Error
917
-     */
918
-    public function instantiate_class_from_array_or_object($cols_n_values)
919
-    {
920
-        $classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
921
-        if ($classInstance instanceof EE_Event) {
922
-            // events have their timezone defined in the DB, so use it immediately
923
-            $this->set_timezone($classInstance->get_timezone());
924
-        }
925
-        return $classInstance;
926
-    }
18
+	/**
19
+	 * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
20
+	 * event
21
+	 */
22
+	const sold_out = 'sold_out';
23
+
24
+	/**
25
+	 * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
26
+	 * date)
27
+	 */
28
+	const postponed = 'postponed';
29
+
30
+	/**
31
+	 * constant used by status(), indicating that the event will no longer occur
32
+	 */
33
+	const cancelled = 'cancelled';
34
+
35
+
36
+	/**
37
+	 * @var string
38
+	 */
39
+	protected static $_default_reg_status;
40
+
41
+
42
+	/**
43
+	 * This is the default for the additional limit field.
44
+	 * @var int
45
+	 */
46
+	protected static $_default_additional_limit = 10;
47
+
48
+
49
+	/**
50
+	 * private instance of the Event object
51
+	 *
52
+	 * @var EEM_Event
53
+	 */
54
+	protected static $_instance;
55
+
56
+
57
+
58
+
59
+	/**
60
+	 * Adds a relationship to Term_Taxonomy for each CPT_Base
61
+	 *
62
+	 * @param string $timezone
63
+	 * @throws \EE_Error
64
+	 */
65
+	protected function __construct($timezone = null)
66
+	{
67
+		EE_Registry::instance()->load_model('Registration');
68
+		$this->singular_item = esc_html__('Event', 'event_espresso');
69
+		$this->plural_item = esc_html__('Events', 'event_espresso');
70
+		// to remove Cancelled events from the frontend, copy the following filter to your functions.php file
71
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
72
+		// to remove Postponed events from the frontend, copy the following filter to your functions.php file
73
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
74
+		// to remove Sold Out events from the frontend, copy the following filter to your functions.php file
75
+		//  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
76
+		$this->_custom_stati = apply_filters(
77
+			'AFEE__EEM_Event__construct___custom_stati',
78
+			array(
79
+				EEM_Event::cancelled => array(
80
+					'label'  => esc_html__('Cancelled', 'event_espresso'),
81
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
82
+				),
83
+				EEM_Event::postponed => array(
84
+					'label'  => esc_html__('Postponed', 'event_espresso'),
85
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
86
+				),
87
+				EEM_Event::sold_out  => array(
88
+					'label'  => esc_html__('Sold Out', 'event_espresso'),
89
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
90
+				),
91
+			)
92
+		);
93
+		self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
94
+			: self::$_default_reg_status;
95
+		$this->_tables = array(
96
+			'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
97
+			'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
98
+		);
99
+		$this->_fields = array(
100
+			'Event_CPT'  => array(
101
+				'EVT_ID'         => new EE_Primary_Key_Int_Field(
102
+					'ID',
103
+					esc_html__('Post ID for Event', 'event_espresso')
104
+				),
105
+				'EVT_name'       => new EE_Plain_Text_Field(
106
+					'post_title',
107
+					esc_html__('Event Name', 'event_espresso'),
108
+					false,
109
+					''
110
+				),
111
+				'EVT_desc'       => new EE_Post_Content_Field(
112
+					'post_content',
113
+					esc_html__('Event Description', 'event_espresso'),
114
+					false,
115
+					''
116
+				),
117
+				'EVT_slug'       => new EE_Slug_Field(
118
+					'post_name',
119
+					esc_html__('Event Slug', 'event_espresso'),
120
+					false,
121
+					''
122
+				),
123
+				'EVT_created'    => new EE_Datetime_Field(
124
+					'post_date',
125
+					esc_html__('Date/Time Event Created', 'event_espresso'),
126
+					false,
127
+					EE_Datetime_Field::now
128
+				),
129
+				'EVT_short_desc' => new EE_Simple_HTML_Field(
130
+					'post_excerpt',
131
+					esc_html__('Event Short Description', 'event_espresso'),
132
+					false,
133
+					''
134
+				),
135
+				'EVT_modified'   => new EE_Datetime_Field(
136
+					'post_modified',
137
+					esc_html__('Date/Time Event Modified', 'event_espresso'),
138
+					false,
139
+					EE_Datetime_Field::now
140
+				),
141
+				'EVT_wp_user'    => new EE_WP_User_Field(
142
+					'post_author',
143
+					esc_html__('Event Creator ID', 'event_espresso'),
144
+					false
145
+				),
146
+				'parent'         => new EE_Integer_Field(
147
+					'post_parent',
148
+					esc_html__('Event Parent ID', 'event_espresso'),
149
+					false,
150
+					0
151
+				),
152
+				'EVT_order'      => new EE_Integer_Field(
153
+					'menu_order',
154
+					esc_html__('Event Menu Order', 'event_espresso'),
155
+					false,
156
+					1
157
+				),
158
+				'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
159
+				// EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
160
+				'status'         => new EE_WP_Post_Status_Field(
161
+					'post_status',
162
+					esc_html__('Event Status', 'event_espresso'),
163
+					false,
164
+					'draft',
165
+					$this->_custom_stati
166
+				),
167
+				'password' => new EE_Password_Field(
168
+					'post_password',
169
+					__('Password', 'event_espresso'),
170
+					false,
171
+					'',
172
+					array(
173
+						'EVT_desc',
174
+						'EVT_short_desc',
175
+						'EVT_display_desc',
176
+						'EVT_display_ticket_selector',
177
+						'EVT_visible_on',
178
+						'EVT_additional_limit',
179
+						'EVT_default_registration_status',
180
+						'EVT_member_only',
181
+						'EVT_phone',
182
+						'EVT_allow_overflow',
183
+						'EVT_timezone_string',
184
+						'EVT_external_URL',
185
+						'EVT_donations'
186
+					)
187
+				)
188
+			),
189
+			'Event_Meta' => array(
190
+				'EVTM_ID'                         => new EE_DB_Only_Float_Field(
191
+					'EVTM_ID',
192
+					esc_html__('Event Meta Row ID', 'event_espresso'),
193
+					false
194
+				),
195
+				'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
196
+					'EVT_ID',
197
+					esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
198
+					false
199
+				),
200
+				'EVT_display_desc'                => new EE_Boolean_Field(
201
+					'EVT_display_desc',
202
+					esc_html__('Display Description Flag', 'event_espresso'),
203
+					false,
204
+					true
205
+				),
206
+				'EVT_display_ticket_selector'     => new EE_Boolean_Field(
207
+					'EVT_display_ticket_selector',
208
+					esc_html__('Display Ticket Selector Flag', 'event_espresso'),
209
+					false,
210
+					true
211
+				),
212
+				'EVT_visible_on'                  => new EE_Datetime_Field(
213
+					'EVT_visible_on',
214
+					esc_html__('Event Visible Date', 'event_espresso'),
215
+					true,
216
+					EE_Datetime_Field::now
217
+				),
218
+				'EVT_additional_limit'            => new EE_Integer_Field(
219
+					'EVT_additional_limit',
220
+					esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
221
+					true,
222
+					self::$_default_additional_limit
223
+				),
224
+				'EVT_default_registration_status' => new EE_Enum_Text_Field(
225
+					'EVT_default_registration_status',
226
+					esc_html__('Default Registration Status on this Event', 'event_espresso'),
227
+					false,
228
+					EEM_Event::$_default_reg_status,
229
+					EEM_Registration::reg_status_array()
230
+				),
231
+				'EVT_member_only'                 => new EE_Boolean_Field(
232
+					'EVT_member_only',
233
+					esc_html__('Member-Only Event Flag', 'event_espresso'),
234
+					false,
235
+					false
236
+				),
237
+				'EVT_phone'                       => new EE_Plain_Text_Field(
238
+					'EVT_phone',
239
+					esc_html__('Event Phone Number', 'event_espresso'),
240
+					false,
241
+					''
242
+				),
243
+				'EVT_allow_overflow'              => new EE_Boolean_Field(
244
+					'EVT_allow_overflow',
245
+					esc_html__('Allow Overflow on Event', 'event_espresso'),
246
+					false,
247
+					false
248
+				),
249
+				'EVT_timezone_string'             => new EE_Plain_Text_Field(
250
+					'EVT_timezone_string',
251
+					esc_html__('Timezone (name) for Event times', 'event_espresso'),
252
+					false,
253
+					''
254
+				),
255
+				'EVT_external_URL'                => new EE_Plain_Text_Field(
256
+					'EVT_external_URL',
257
+					esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
258
+					true
259
+				),
260
+				'EVT_donations'                   => new EE_Boolean_Field(
261
+					'EVT_donations',
262
+					esc_html__('Accept Donations?', 'event_espresso'),
263
+					false,
264
+					false
265
+				),
266
+			),
267
+		);
268
+		$this->_model_relations = array(
269
+			'Registration'           => new EE_Has_Many_Relation(),
270
+			'Datetime'               => new EE_Has_Many_Relation(),
271
+			'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
272
+			'Event_Question_Group'   => new EE_Has_Many_Relation(),
273
+			'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
274
+			'Term_Relationship'      => new EE_Has_Many_Relation(),
275
+			'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
276
+			'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
277
+			'Attendee'               => new EE_HABTM_Relation('Registration'),
278
+			'WP_User'                => new EE_Belongs_To_Relation(),
279
+		);
280
+		// this model is generally available for reading
281
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
282
+		$this->model_chain_to_password = '';
283
+		parent::__construct($timezone);
284
+	}
285
+
286
+
287
+
288
+	/**
289
+	 * @param string $default_reg_status
290
+	 */
291
+	public static function set_default_reg_status($default_reg_status)
292
+	{
293
+		self::$_default_reg_status = $default_reg_status;
294
+		// if EEM_Event has already been instantiated,
295
+		// then we need to reset the `EVT_default_reg_status` field to use the new default.
296
+		if (self::$_instance instanceof EEM_Event) {
297
+			$default_reg_status = new EE_Enum_Text_Field(
298
+				'EVT_default_registration_status',
299
+				esc_html__('Default Registration Status on this Event', 'event_espresso'),
300
+				false,
301
+				$default_reg_status,
302
+				EEM_Registration::reg_status_array()
303
+			);
304
+			$default_reg_status->_construct_finalize(
305
+				'Event_Meta',
306
+				'EVT_default_registration_status',
307
+				'EEM_Event'
308
+			);
309
+			self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
310
+		}
311
+	}
312
+
313
+
314
+	/**
315
+	 * Used to override the default for the additional limit field.
316
+	 * @param $additional_limit
317
+	 */
318
+	public static function set_default_additional_limit($additional_limit)
319
+	{
320
+		self::$_default_additional_limit = (int) $additional_limit;
321
+		if (self::$_instance instanceof EEM_Event) {
322
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
323
+				'EVT_additional_limit',
324
+				__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
325
+				true,
326
+				self::$_default_additional_limit
327
+			);
328
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
329
+				'Event_Meta',
330
+				'EVT_additional_limit',
331
+				'EEM_Event'
332
+			);
333
+		}
334
+	}
335
+
336
+
337
+	/**
338
+	 * Return what is currently set as the default additional limit for the event.
339
+	 * @return int
340
+	 */
341
+	public static function get_default_additional_limit()
342
+	{
343
+		return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
344
+	}
345
+
346
+
347
+	/**
348
+	 * get_question_groups
349
+	 *
350
+	 * @return array
351
+	 * @throws \EE_Error
352
+	 */
353
+	public function get_all_question_groups()
354
+	{
355
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
356
+			array(
357
+				array('QSG_deleted' => false),
358
+				'order_by' => array('QSG_order' => 'ASC'),
359
+			)
360
+		);
361
+	}
362
+
363
+
364
+
365
+	/**
366
+	 * get_question_groups
367
+	 *
368
+	 * @param int $EVT_ID
369
+	 * @return array|bool
370
+	 * @throws \EE_Error
371
+	 */
372
+	public function get_all_event_question_groups($EVT_ID = 0)
373
+	{
374
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
375
+			EE_Error::add_error(
376
+				esc_html__(
377
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
378
+					'event_espresso'
379
+				),
380
+				__FILE__,
381
+				__FUNCTION__,
382
+				__LINE__
383
+			);
384
+			return false;
385
+		}
386
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
387
+			array(
388
+				array('EVT_ID' => $EVT_ID),
389
+			)
390
+		);
391
+	}
392
+
393
+
394
+	/**
395
+	 * get_question_groups
396
+	 *
397
+	 * @param int $EVT_ID
398
+	 * @param boolean $for_primary_attendee
399
+	 * @return array|bool
400
+	 * @throws EE_Error
401
+	 * @throws InvalidArgumentException
402
+	 * @throws ReflectionException
403
+	 * @throws InvalidDataTypeException
404
+	 * @throws InvalidInterfaceException
405
+	 */
406
+	public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
407
+	{
408
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
409
+			EE_Error::add_error(
410
+				esc_html__(
411
+					// @codingStandardsIgnoreStart
412
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
413
+					// @codingStandardsIgnoreEnd
414
+					'event_espresso'
415
+				),
416
+				__FILE__,
417
+				__FUNCTION__,
418
+				__LINE__
419
+			);
420
+			return false;
421
+		}
422
+		$query_params = [
423
+			[
424
+				'EVT_ID' => $EVT_ID,
425
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true
426
+			]
427
+		];
428
+		if ($for_primary_attendee) {
429
+			$query_params[0]['EQG_primary'] = true;
430
+		} else {
431
+			$query_params[0]['EQG_additional'] = true;
432
+		}
433
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
434
+	}
435
+
436
+
437
+	/**
438
+	 * get_question_groups
439
+	 *
440
+	 * @param int $EVT_ID
441
+	 * @param EE_Registration $registration
442
+	 * @return array|bool
443
+	 * @throws EE_Error
444
+	 * @throws InvalidArgumentException
445
+	 * @throws InvalidDataTypeException
446
+	 * @throws InvalidInterfaceException
447
+	 * @throws ReflectionException
448
+	 */
449
+	public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
450
+	{
451
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
452
+			EE_Error::add_error(
453
+				esc_html__(
454
+					'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
455
+					'event_espresso'
456
+				),
457
+				__FILE__,
458
+				__FUNCTION__,
459
+				__LINE__
460
+			);
461
+			return false;
462
+		}
463
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
464
+			[
465
+				[
466
+					'Event_Question_Group.EVT_ID'      => $EVT_ID,
467
+					'Event_Question_Group.'
468
+						. EEM_Event_Question_Group::instance()->fieldNameForContext(
469
+							$registration->is_primary_registrant()
470
+						) => true
471
+				],
472
+				'order_by' => ['QSG_order' => 'ASC'],
473
+			]
474
+		);
475
+	}
476
+
477
+
478
+
479
+	/**
480
+	 * get_question_target_db_column
481
+	 *
482
+	 * @param string $QSG_IDs csv list of $QSG IDs
483
+	 * @return array|bool
484
+	 * @throws \EE_Error
485
+	 */
486
+	public function get_questions_in_groups($QSG_IDs = '')
487
+	{
488
+		if (empty($QSG_IDs)) {
489
+			EE_Error::add_error(
490
+				esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
491
+				__FILE__,
492
+				__FUNCTION__,
493
+				__LINE__
494
+			);
495
+			return false;
496
+		}
497
+		return EE_Registry::instance()->load_model('Question')->get_all(
498
+			array(
499
+				array(
500
+					'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
501
+					'QST_deleted'           => false,
502
+					'QST_admin_only'        => is_admin(),
503
+				),
504
+				'order_by' => 'QST_order',
505
+			)
506
+		);
507
+	}
508
+
509
+
510
+
511
+	/**
512
+	 * get_options_for_question
513
+	 *
514
+	 * @param string $QST_IDs csv list of $QST IDs
515
+	 * @return array|bool
516
+	 * @throws \EE_Error
517
+	 */
518
+	public function get_options_for_question($QST_IDs)
519
+	{
520
+		if (empty($QST_IDs)) {
521
+			EE_Error::add_error(
522
+				esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
523
+				__FILE__,
524
+				__FUNCTION__,
525
+				__LINE__
526
+			);
527
+			return false;
528
+		}
529
+		return EE_Registry::instance()->load_model('Question_Option')->get_all(
530
+			array(
531
+				array(
532
+					'Question.QST_ID' => array('IN', $QST_IDs),
533
+					'QSO_deleted'     => false,
534
+				),
535
+				'order_by' => 'QSO_ID',
536
+			)
537
+		);
538
+	}
539
+
540
+
541
+
542
+
543
+
544
+
545
+
546
+	/**
547
+	 * Gets all events that are published
548
+	 * and have event start time earlier than now and an event end time later than now
549
+	 *
550
+	 * @param  array $query_params An array of query params to further filter on
551
+	 *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
552
+	 * @param bool   $count        whether to return the count or not (default FALSE)
553
+	 * @return EE_Event[]|int
554
+	 * @throws \EE_Error
555
+	 */
556
+	public function get_active_events($query_params, $count = false)
557
+	{
558
+		if (array_key_exists(0, $query_params)) {
559
+			$where_params = $query_params[0];
560
+			unset($query_params[0]);
561
+		} else {
562
+			$where_params = array();
563
+		}
564
+		// if we have count make sure we don't include group by
565
+		if ($count && isset($query_params['group_by'])) {
566
+			unset($query_params['group_by']);
567
+		}
568
+		// let's add specific query_params for active_events
569
+		// keep in mind this will override any sent status in the query AND any date queries.
570
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
571
+		// if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
572
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
573
+			$where_params['Datetime.DTT_EVT_start******'] = array(
574
+				'<',
575
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
576
+			);
577
+		} else {
578
+			$where_params['Datetime.DTT_EVT_start'] = array(
579
+				'<',
580
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
581
+			);
582
+		}
583
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
584
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
585
+				'>',
586
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
587
+			);
588
+		} else {
589
+			$where_params['Datetime.DTT_EVT_end'] = array(
590
+				'>',
591
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
592
+			);
593
+		}
594
+		$query_params[0] = $where_params;
595
+		// don't use $query_params with count()
596
+		// because we don't want to include additional query clauses like "GROUP BY"
597
+		return $count
598
+			? $this->count(array($where_params), 'EVT_ID', true)
599
+			: $this->get_all($query_params);
600
+	}
601
+
602
+
603
+
604
+	/**
605
+	 * get all events that are published and have an event start time later than now
606
+	 *
607
+	 * @param  array $query_params An array of query params to further filter on
608
+	 *                             (Note that status and DTT_EVT_start will be overridden)
609
+	 * @param bool   $count        whether to return the count or not (default FALSE)
610
+	 * @return EE_Event[]|int
611
+	 * @throws \EE_Error
612
+	 */
613
+	public function get_upcoming_events($query_params, $count = false)
614
+	{
615
+		if (array_key_exists(0, $query_params)) {
616
+			$where_params = $query_params[0];
617
+			unset($query_params[0]);
618
+		} else {
619
+			$where_params = array();
620
+		}
621
+		// if we have count make sure we don't include group by
622
+		if ($count && isset($query_params['group_by'])) {
623
+			unset($query_params['group_by']);
624
+		}
625
+		// let's add specific query_params for active_events
626
+		// keep in mind this will override any sent status in the query AND any date queries.
627
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
628
+		// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
629
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
630
+			$where_params['Datetime.DTT_EVT_start*****'] = array(
631
+				'>',
632
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
633
+			);
634
+		} else {
635
+			$where_params['Datetime.DTT_EVT_start'] = array(
636
+				'>',
637
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
638
+			);
639
+		}
640
+		$query_params[0] = $where_params;
641
+		// don't use $query_params with count()
642
+		// because we don't want to include additional query clauses like "GROUP BY"
643
+		return $count
644
+			? $this->count(array($where_params), 'EVT_ID', true)
645
+			: $this->get_all($query_params);
646
+	}
647
+
648
+
649
+
650
+	/**
651
+	 * Gets all events that are published
652
+	 * and have an event end time later than now
653
+	 *
654
+	 * @param  array $query_params An array of query params to further filter on
655
+	 *                             (note that status and DTT_EVT_end will be overridden)
656
+	 * @param bool   $count        whether to return the count or not (default FALSE)
657
+	 * @return EE_Event[]|int
658
+	 * @throws \EE_Error
659
+	 */
660
+	public function get_active_and_upcoming_events($query_params, $count = false)
661
+	{
662
+		if (array_key_exists(0, $query_params)) {
663
+			$where_params = $query_params[0];
664
+			unset($query_params[0]);
665
+		} else {
666
+			$where_params = array();
667
+		}
668
+		// if we have count make sure we don't include group by
669
+		if ($count && isset($query_params['group_by'])) {
670
+			unset($query_params['group_by']);
671
+		}
672
+		// let's add specific query_params for active_events
673
+		// keep in mind this will override any sent status in the query AND any date queries.
674
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
675
+		// add where params for DTT_EVT_end
676
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
677
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
678
+				'>',
679
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
680
+			);
681
+		} else {
682
+			$where_params['Datetime.DTT_EVT_end'] = array(
683
+				'>',
684
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
685
+			);
686
+		}
687
+		$query_params[0] = $where_params;
688
+		// don't use $query_params with count()
689
+		// because we don't want to include additional query clauses like "GROUP BY"
690
+		return $count
691
+			? $this->count(array($where_params), 'EVT_ID', true)
692
+			: $this->get_all($query_params);
693
+	}
694
+
695
+
696
+
697
+	/**
698
+	 * This only returns events that are expired.
699
+	 * They may still be published but all their datetimes have expired.
700
+	 *
701
+	 * @param  array $query_params An array of query params to further filter on
702
+	 *                             (note that status and DTT_EVT_end will be overridden)
703
+	 * @param bool   $count        whether to return the count or not (default FALSE)
704
+	 * @return EE_Event[]|int
705
+	 * @throws \EE_Error
706
+	 */
707
+	public function get_expired_events($query_params, $count = false)
708
+	{
709
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
710
+		// if we have count make sure we don't include group by
711
+		if ($count && isset($query_params['group_by'])) {
712
+			unset($query_params['group_by']);
713
+		}
714
+		// let's add specific query_params for active_events
715
+		// keep in mind this will override any sent status in the query AND any date queries.
716
+		if (isset($where_params['status'])) {
717
+			unset($where_params['status']);
718
+		}
719
+		$exclude_query = $query_params;
720
+		if (isset($exclude_query[0])) {
721
+			unset($exclude_query[0]);
722
+		}
723
+		$exclude_query[0] = array(
724
+			'Datetime.DTT_EVT_end' => array(
725
+				'>',
726
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
727
+			),
728
+		);
729
+		// first get all events that have datetimes where its not expired.
730
+		$event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
731
+		$event_ids = array_keys($event_ids);
732
+		// if we have any additional query_params, let's add them to the 'AND' condition
733
+		$and_condition = array(
734
+			'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
735
+			'EVT_ID'               => array('NOT IN', $event_ids),
736
+		);
737
+		if (isset($where_params['OR'])) {
738
+			$and_condition['OR'] = $where_params['OR'];
739
+			unset($where_params['OR']);
740
+		}
741
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
742
+			$and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
743
+			unset($where_params['Datetime.DTT_EVT_end']);
744
+		}
745
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
746
+			$and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
747
+			unset($where_params['Datetime.DTT_EVT_start']);
748
+		}
749
+		// merge remaining $where params with the and conditions.
750
+		$where_params['AND'] = array_merge($and_condition, $where_params);
751
+		$query_params[0] = $where_params;
752
+		// don't use $query_params with count()
753
+		// because we don't want to include additional query clauses like "GROUP BY"
754
+		return $count
755
+			? $this->count(array($where_params), 'EVT_ID', true)
756
+			: $this->get_all($query_params);
757
+	}
758
+
759
+
760
+
761
+	/**
762
+	 * This basically just returns the events that do not have the publish status.
763
+	 *
764
+	 * @param  array   $query_params An array of query params to further filter on
765
+	 *                               (note that status will be overwritten)
766
+	 * @param  boolean $count        whether to return the count or not (default FALSE)
767
+	 * @return EE_Event[]|int
768
+	 * @throws \EE_Error
769
+	 */
770
+	public function get_inactive_events($query_params, $count = false)
771
+	{
772
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
773
+		// let's add in specific query_params for inactive events.
774
+		if (isset($where_params['status'])) {
775
+			unset($where_params['status']);
776
+		}
777
+		// if we have count make sure we don't include group by
778
+		if ($count && isset($query_params['group_by'])) {
779
+			unset($query_params['group_by']);
780
+		}
781
+		// if we have any additional query_params, let's add them to the 'AND' condition
782
+		$where_params['AND']['status'] = array('!=', 'publish');
783
+		if (isset($where_params['OR'])) {
784
+			$where_params['AND']['OR'] = $where_params['OR'];
785
+			unset($where_params['OR']);
786
+		}
787
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
788
+			$where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
789
+			unset($where_params['Datetime.DTT_EVT_end']);
790
+		}
791
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
792
+			$where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
793
+			unset($where_params['Datetime.DTT_EVT_start']);
794
+		}
795
+		$query_params[0] = $where_params;
796
+		// don't use $query_params with count()
797
+		// because we don't want to include additional query clauses like "GROUP BY"
798
+		return $count
799
+			? $this->count(array($where_params), 'EVT_ID', true)
800
+			: $this->get_all($query_params);
801
+	}
802
+
803
+
804
+
805
+	/**
806
+	 * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
807
+	 * because we don't want to override any existing global default prices but instead insert NEW prices that get
808
+	 * attached to the event. See parent for param descriptions
809
+	 *
810
+	 * @param        $id_or_obj
811
+	 * @param        $other_model_id_or_obj
812
+	 * @param string $relationName
813
+	 * @param array  $where_query
814
+	 * @return EE_Base_Class
815
+	 * @throws EE_Error
816
+	 */
817
+	public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
818
+	{
819
+		if ($relationName === 'Price') {
820
+			// let's get the PRC object for the given ID to make sure that we aren't dealing with a default
821
+			$prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
822
+			// if EVT_ID = 0, then this is a default
823
+			if ((int) $prc_chk->get('EVT_ID') === 0) {
824
+				// let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
825
+				$prc_chk->set('PRC_ID', 0);
826
+			}
827
+			// run parent
828
+			return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
829
+		}
830
+		// otherwise carry on as normal
831
+		return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
832
+	}
833
+
834
+
835
+
836
+	/******************** DEPRECATED METHODS ********************/
837
+
838
+
839
+
840
+	/**
841
+	 * _get_question_target_db_column
842
+	 *
843
+	 * @deprecated as of 4.8.32.rc.001. Instead consider using
844
+	 *             EE_Registration_Custom_Questions_Form located in
845
+	 *             admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
846
+	 * @access     public
847
+	 * @param    EE_Registration $registration (so existing answers for registration are included)
848
+	 * @param    int             $EVT_ID       so all question groups are included for event (not just answers from
849
+	 *                                         registration).
850
+	 * @throws EE_Error
851
+	 * @return    array
852
+	 */
853
+	public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
854
+	{
855
+		if (empty($EVT_ID)) {
856
+			throw new EE_Error(__(
857
+				'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
858
+				'event_espresso'
859
+			));
860
+		}
861
+		$questions = array();
862
+		// get all question groups for event
863
+		$qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
864
+		if (! empty($qgs)) {
865
+			foreach ($qgs as $qg) {
866
+				$qsts = $qg->questions();
867
+				$questions[ $qg->ID() ] = $qg->model_field_array();
868
+				$questions[ $qg->ID() ]['QSG_questions'] = array();
869
+				foreach ($qsts as $qst) {
870
+					if ($qst->is_system_question()) {
871
+						continue;
872
+					}
873
+					$answer = EEM_Answer::instance()->get_one(array(
874
+						array(
875
+							'QST_ID' => $qst->ID(),
876
+							'REG_ID' => $registration->ID(),
877
+						),
878
+					));
879
+					$answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
880
+					$qst_name = $qstn_id = $qst->ID();
881
+					$ans_id = $answer->ID();
882
+					$qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
883
+					$input_name = '';
884
+					$input_id = sanitize_key($qst->display_text());
885
+					$input_class = '';
886
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
887
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
888
+																						   . $input_name
889
+																						   . $qst_name;
890
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
891
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
892
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
893
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
894
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
895
+					// leave responses as-is, don't convert stuff into html entities please!
896
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
897
+					if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
898
+						$QSOs = $qst->options(true, $answer->value());
899
+						if (is_array($QSOs)) {
900
+							foreach ($QSOs as $QSO_ID => $QSO) {
901
+								$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
902
+							}
903
+						}
904
+					}
905
+				}
906
+			}
907
+		}
908
+		return $questions;
909
+	}
910
+
911
+
912
+	/**
913
+	 * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
914
+	 *                             or an stdClass where each property is the name of a column,
915
+	 * @return EE_Base_Class
916
+	 * @throws \EE_Error
917
+	 */
918
+	public function instantiate_class_from_array_or_object($cols_n_values)
919
+	{
920
+		$classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
921
+		if ($classInstance instanceof EE_Event) {
922
+			// events have their timezone defined in the DB, so use it immediately
923
+			$this->set_timezone($classInstance->get_timezone());
924
+		}
925
+		return $classInstance;
926
+	}
927 927
 }
Please login to merge, or discard this patch.
events/help_tabs/events_default_settings_max_tickets.help_tab.php 1 patch
Indentation   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@
 block discarded – undo
1 1
 <p>
2 2
     <?php esc_html_e(
3
-        'Use this to control what the default will be for maximum tickets on an order when creating a new event.',
4
-        'event_espresso'
5
-    ); ?>
3
+		'Use this to control what the default will be for maximum tickets on an order when creating a new event.',
4
+		'event_espresso'
5
+	); ?>
6 6
 </p>
7 7
\ No newline at end of file
Please login to merge, or discard this patch.
core/services/notices/ConvertNoticesToEeErrors.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -43,7 +43,7 @@
 block discarded – undo
43 43
             $error_string = esc_html__('The following errors occurred:', 'event_espresso');
44 44
             foreach ($notices->getError() as $notice) {
45 45
                 if ($this->getThrowExceptions()) {
46
-                    $error_string .= '<br />' . $notice->message();
46
+                    $error_string .= '<br />'.$notice->message();
47 47
                 } else {
48 48
                     EE_Error::add_error(
49 49
                         $notice->message(),
Please login to merge, or discard this patch.
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -19,56 +19,56 @@
 block discarded – undo
19 19
 class ConvertNoticesToEeErrors extends NoticeConverter
20 20
 {
21 21
 
22
-    /**
23
-     * Converts Notice objects into EE_Error notifications
24
-     *
25
-     * @param NoticesContainerInterface $notices
26
-     * @throws EE_Error
27
-     */
28
-    public function process(NoticesContainerInterface $notices)
29
-    {
30
-        $this->setNotices($notices);
31
-        $notices = $this->getNotices();
32
-        if ($notices->hasAttention()) {
33
-            foreach ($notices->getAttention() as $notice) {
34
-                EE_Error::add_attention(
35
-                    $notice->message(),
36
-                    $notice->file(),
37
-                    $notice->func(),
38
-                    $notice->line()
39
-                );
40
-            }
41
-        }
42
-        if ($notices->hasError()) {
43
-            $error_string = esc_html__('The following errors occurred:', 'event_espresso');
44
-            foreach ($notices->getError() as $notice) {
45
-                if ($this->getThrowExceptions()) {
46
-                    $error_string .= '<br />' . $notice->message();
47
-                } else {
48
-                    EE_Error::add_error(
49
-                        $notice->message(),
50
-                        $notice->file(),
51
-                        $notice->func(),
52
-                        $notice->line()
53
-                    );
54
-                }
55
-            }
56
-            if ($this->getThrowExceptions()) {
57
-                throw new EE_Error($error_string);
58
-            }
59
-        }
60
-        if ($notices->hasSuccess()) {
61
-            foreach ($notices->getSuccess() as $notice) {
62
-                EE_Error::add_success(
63
-                    $notice->message(),
64
-                    $notice->file(),
65
-                    $notice->func(),
66
-                    $notice->line()
67
-                );
68
-            }
69
-        }
70
-        $this->clearNotices();
71
-    }
22
+	/**
23
+	 * Converts Notice objects into EE_Error notifications
24
+	 *
25
+	 * @param NoticesContainerInterface $notices
26
+	 * @throws EE_Error
27
+	 */
28
+	public function process(NoticesContainerInterface $notices)
29
+	{
30
+		$this->setNotices($notices);
31
+		$notices = $this->getNotices();
32
+		if ($notices->hasAttention()) {
33
+			foreach ($notices->getAttention() as $notice) {
34
+				EE_Error::add_attention(
35
+					$notice->message(),
36
+					$notice->file(),
37
+					$notice->func(),
38
+					$notice->line()
39
+				);
40
+			}
41
+		}
42
+		if ($notices->hasError()) {
43
+			$error_string = esc_html__('The following errors occurred:', 'event_espresso');
44
+			foreach ($notices->getError() as $notice) {
45
+				if ($this->getThrowExceptions()) {
46
+					$error_string .= '<br />' . $notice->message();
47
+				} else {
48
+					EE_Error::add_error(
49
+						$notice->message(),
50
+						$notice->file(),
51
+						$notice->func(),
52
+						$notice->line()
53
+					);
54
+				}
55
+			}
56
+			if ($this->getThrowExceptions()) {
57
+				throw new EE_Error($error_string);
58
+			}
59
+		}
60
+		if ($notices->hasSuccess()) {
61
+			foreach ($notices->getSuccess() as $notice) {
62
+				EE_Error::add_success(
63
+					$notice->message(),
64
+					$notice->file(),
65
+					$notice->func(),
66
+					$notice->line()
67
+				);
68
+			}
69
+		}
70
+		$this->clearNotices();
71
+	}
72 72
 
73 73
 
74 74
 }
Please login to merge, or discard this patch.