Completed
Branch BUG-9517-braintree-deactivatin... (7069c4)
by
unknown
514:37 queued 497:35
created

EEM_Registration   D

Complexity

Total Complexity 38

Size/Duplication

Total Lines 628
Duplicated Lines 3.5 %

Coupling/Cohesion

Components 2
Dependencies 22

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 38
lcom 2
cbo 22
dl 22
loc 628
rs 4.8631
c 1
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A reg_status_array() 0 4 2
A _get_registration_status_array() 0 18 4
B __construct() 0 42 1
A reg_statuses_that_allow_payment() 0 9 1
A get_reg_months_and_years() 0 10 1
A get_all_registrations_for_attendee() 0 6 2
A get_registration_for_reg_url_link() 0 6 2
A get_registration_for_transaction_attendee() 0 9 1
B get_registrations_per_day_report() 0 25 2
A get_registrations_per_event_report() 0 23 2
A get_primary_registration_for_transaction_ID() 0 6 2
A get_event_registration_count() 0 9 2
A delete_registrations_with_no_transaction() 0 6 1
B get_registrations_per_day_and_per_status_report() 11 53 4
B get_registrations_per_event_and_per_status_report() 11 49 4
A count_registrations_checked_into_datetime() 0 23 1
B count_registrations_checked_into_event() 0 25 1
B get_latest_registration_for_each_of_given_contacts() 0 52 5

How to fix   Duplicated Code   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

1
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
2
require_once ( EE_MODELS . 'EEM_Soft_Delete_Base.model.php' );
3
require_once ( EE_CLASSES . 'EE_Registration.class.php' );
4
/**
5
 *
6
 * Registration Model
7
 *
8
 * @package			Event Espresso
9
 * @subpackage		includes/models/
10
 * @author				Mike Nelson, Brent Christensen
11
 *
12
 * ------------------------------------------------------------------------
13
 */
14
class EEM_Registration extends EEM_Soft_Delete_Base {
15
16
  	// private instance of the Registration object
17
	protected static $_instance = NULL;
18
19
	/**
20
	 * Keys are the status IDs for registrations (eg, RAP, RCN, etc), and the values
21
	 * are status codes (eg, approved, cancelled, etc)
22
	 * @var array
23
	 */
24
	private static $_reg_status;
25
26
	/**
27
	 * The value of REG_count for a primary registrant
28
	 */
29
	const PRIMARY_REGISTRANT_COUNT = 1;
30
31
	/**
32
	 * Status ID (STS_ID on esp_status table) to indicate an INCOMPLETE registration.
33
	 * Initial status for registrations when they are first created
34
	 * Payments are NOT allowed.
35
	 * Automatically toggled to whatever the default Event registration status is upon completion of the attendee information reg step
36
	 * NO space reserved.
37
	 * Registration is NOT active
38
	 */
39
	const status_id_incomplete = 'RIC';
40
41
	/**
42
	 * Status ID (STS_ID on esp_status table) to indicate an UNAPPROVED registration.
43
	 * Payments are NOT allowed.
44
	 * Event Admin must manually toggle STS_ID for it to change
45
	 * No space reserved.
46
	 * Registration is active
47
	 */
48
	const status_id_not_approved = 'RNA';
49
50
	/**
51
	 * Status ID (STS_ID on esp_status table) to indicate registration is PENDING_PAYMENT .
52
	 * Payments are allowed.
53
	 * STS_ID will automatically be toggled to RAP if payment is made in full by the attendee
54
	 * No space reserved.
55
	 * Registration is active
56
	 */
57
	const status_id_pending_payment = 'RPP';
58
59
	/**
60
	 * Status ID (STS_ID on esp_status table) to indicate an APPROVED registration.
61
	 * the TXN may or may not be completed ( paid in full )
62
	 * Payments are allowed.
63
	 * A space IS reserved.
64
	 * Registration is active
65
	 */
66
	const status_id_approved = 'RAP';
67
68
	/**
69
	 * Status ID (STS_ID on esp_status table) to indicate a registration was CANCELLED by the attendee.
70
	 * Payments are NOT allowed.
71
	 * NO space reserved.
72
	 * Registration is NOT active
73
	 */
74
	const status_id_cancelled = 'RCN';
75
76
	/**
77
	 * Status ID (STS_ID on esp_status table) to indicate a registration was DECLINED by the Event Admin
78
	 * Payments are NOT allowed.
79
	 * No space reserved.
80
	 * Registration is NOT active
81
	 */
82
	const status_id_declined = 'RDC';
83
84
85
86
	/**
87
	 *    private constructor to prevent direct creation
88
	 *
89
	 * @Constructor
90
	 * @access protected
91
	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any incoming timezone data that gets saved).
92
	 *    Note this just sends the timezone info to the date time model field objects.  Default is NULL (and will be assumed using the set timezone in the 'timezone_string' wp option)
93
	 * @return \EEM_Registration
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
94
	 */
95
	protected function __construct( $timezone ) {
96
		$this->singular_item = __('Registration','event_espresso');
97
		$this->plural_item = __('Registrations','event_espresso');
98
99
		$this->_tables = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Registration' => ...gistration', 'REG_ID')) of type array<string,object<EE_P...ct<EE_Primary_Table>"}> is incompatible with the declared type array<integer,object<EE_Table_Base>> of property $_tables.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
100
			'Registration'=>new EE_Primary_Table('esp_registration','REG_ID')
101
		);
102
		$this->_fields = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Registration' => ...esso'), false, false))) of type array<string,array<strin...shed_Flag_Field>\"}>"}> is incompatible with the declared type array<integer,object<EE_Model_Field_Base>> of property $_fields.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
103
			'Registration'=>array(
104
				'REG_ID'=>new EE_Primary_Key_Int_Field('REG_ID', __('Registration ID','event_espresso')),
105
				'EVT_ID'=>new EE_Foreign_Key_Int_Field('EVT_ID', __('Event ID','event_espresso'), false, 0, 'Event'),
106
				'ATT_ID'=>new EE_Foreign_Key_Int_Field('ATT_ID', __('Attendee ID','event_espresso'), false, 0, 'Attendee'),
107
				'TXN_ID'=>new EE_Foreign_Key_Int_Field('TXN_ID', __('Transaction ID','event_espresso'), false, 0, 'Transaction'),
108
				'TKT_ID'=>new EE_Foreign_Key_Int_Field('TKT_ID', __('Ticket ID','event_espresso'), false, 0, 'Ticket'),
109
				'STS_ID'=>new EE_Foreign_Key_String_Field('STS_ID', __('Status ID','event_espresso'), false, EEM_Registration::status_id_incomplete, 'Status'),
110
				'REG_date'=>new EE_Datetime_Field('REG_date', __('Time registration occurred','event_espresso'), false, time(), $timezone ),
111
				'REG_final_price'=>new EE_Money_Field('REG_final_price', __('Registration\'s share of the transaction total','event_espresso'), false, 0),
112
				'REG_paid'=>new EE_Money_Field('REG_paid', __('Amount paid to date towards registration','event_espresso'), false, 0),
113
				'REG_session'=>new EE_Plain_Text_Field('REG_session', __('Session ID of registration','event_espresso'), false, ''),
114
				'REG_code'=>new EE_Plain_Text_Field('REG_code', __('Unique Code for this registration','event_espresso'), false, ''),
115
				'REG_url_link'=>new EE_Plain_Text_Field('REG_url_link', __('String to be used in URL for identifying registration','event_espresso'), false, ''),
116
				'REG_count'=>new EE_Integer_Field('REG_count', __('Count of this registration in the group registration ','event_espresso'), true, 1),
117
				'REG_group_size'=>new EE_Integer_Field('REG_group_size', __('Number of registrations on this group','event_espresso'), false, 1),
118
				'REG_att_is_going'=>new EE_Boolean_Field('REG_att_is_going', __('Flag indicating the registrant plans on attending','event_espresso'), false, false),
119
				'REG_deleted' => new EE_Trashed_Flag_Field('REG_deleted', __('Flag indicating if registration has been archived or not.', 'event_espresso'), false, false )
120
			)
121
		);
122
		$this->_model_relations = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Event' => new \EE...Registration_Payment')) of type array<string,object<EE_B...t<EE_HABTM_Relation>"}> is incompatible with the declared type array<integer,object<EE_Model_Relation_Base>> of property $_model_relations.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
123
			'Event'=>new EE_Belongs_To_Relation(),
124
			'Attendee'=>new EE_Belongs_To_Relation(),
125
			'Transaction'=>new EE_Belongs_To_Relation(),
126
			'Ticket'=>new EE_Belongs_To_Relation(),
127
			'Status'=>new EE_Belongs_To_Relation(),
128
			'Answer'=>new EE_Has_Many_Relation(),
129
			'Checkin'=>new EE_Has_Many_Relation(),
130
			'Registration_Payment' => new EE_Has_Many_Relation(),
131
			'Payment'=>new EE_HABTM_Relation( 'Registration_Payment' ),
132
		);
133
		$this->_model_chain_to_wp_user = 'Event';
134
135
		parent::__construct( $timezone );
136
	}
137
138
139
140
	/**
141
	 * 	reg_statuses_that_allow_payment
142
	 * 	a filterable list of registration statuses that allow a registrant to make a payment
143
	 *
144
	 *	@access public
145
	 *	@return array
146
	 */
147
	public static function reg_statuses_that_allow_payment() {
148
		return apply_filters(
149
			'FHEE__EEM_Registration__reg_statuses_that_allow_payment',
150
			array(
151
				EEM_Registration::status_id_approved,
152
				EEM_Registration::status_id_pending_payment,
153
			)
154
		);
155
	}
156
157
158
159
	/**
160
	 * 		get list of registration statuses
161
	 *
162
	 *
163
	 *		@access public
164
	 *		@param array $exclude The status ids to exclude from the returned results
165
	 *		@param bool  $translated If true will return the values as singular localized strings
166
	 *		@return array
167
	 */
168
	public static function reg_status_array( $exclude = array(), $translated = FALSE ) {
169
		EEM_Registration::instance()->_get_registration_status_array( $exclude );
170
		return $translated ? EEM_Status::instance()->localized_status( self::$_reg_status, FALSE, 'sentence') : self::$_reg_status;
171
	}
172
173
174
175
	/**
176
	 * 	get list of registration statuses
177
	 * @access private
178
	 * @param array $exclude
179
	 * @return array
180
	 */
181
	private function _get_registration_status_array( $exclude = array() ) {
182
		//in the very rare circumstance that we are deleting a model's table's data
183
		//and the table hasn't actually been created, this could have an error
184
		/** @type WPDB $wpdb */
185
		global $wpdb;
186
		EE_Registry::instance()->load_helper( 'Activation' );
187
		if( EEH_Activation::table_exists( $wpdb->prefix . 'esp_status' ) ){
188
			$SQL = 'SELECT STS_ID, STS_code FROM '. $wpdb->prefix . 'esp_status WHERE STS_type = "registration"';
189
			$results = $wpdb->get_results( $SQL );
190
			self::$_reg_status = array();
191
			foreach ( $results as $status ) {
192
				if ( ! in_array( $status->STS_ID, $exclude )) {
193
					self::$_reg_status[ $status->STS_ID ] = $status->STS_code;
194
				}
195
			}
196
		}
197
198
	}
199
200
201
202
203
	/**
204
	 * This returns a wpdb->results array of all registration date month and years matching the incoming query params and grouped by month and year.
205
	 * @param  array  $where_params Array of query_params as described in the comments for EEM_Base::get_all()
206
	 * @return wpdb results array
207
	 */
208
	public function get_reg_months_and_years( $where_params ) {
209
		$query_params[0] = $where_params;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$query_params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $query_params = array(); before regardless.

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

Let’s take a look at an example:

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

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

    // do something with $myArray
}

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

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

Loading history...
210
		$query_params['group_by'] = array('reg_year', 'reg_month');
211
		$query_params['order_by'] = array( 'REG_date' => 'DESC' );
212
		$columns_to_select = array(
213
			'reg_year' => array('YEAR(REG_date)', '%s'),
214
			'reg_month' => array('MONTHNAME(REG_date)', '%s')
215
			);
216
		return $this->_get_all_wpdb_results( $query_params, OBJECT, $columns_to_select );
217
	}
218
219
220
221
222
	/**
223
	*		retrieve ALL registrations for a particular Attendee from db
224
	* 		@access		public
225
	* 		@param		int		$ATT_ID
226
	*		@return 	EE_Registration[]
227
	*/
228
	public function get_all_registrations_for_attendee( $ATT_ID = 0 ) {
229
		if ( ! $ATT_ID ) {
230
			return FALSE;
231
		}
232
		return $this->get_all( array( array( 'ATT_ID' => $ATT_ID )));
233
	}
234
235
236
237
	/**
238
	 * Gets a registration given their REG_url_link. Yes, this should usually
239
	 * be passed via a GET parameter.
240
	 * @param string $REG_url_link
241
	 * @return EE_Registration
242
	 */
243
	public function get_registration_for_reg_url_link($REG_url_link){
244
		if(!$REG_url_link){
245
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by EEM_Registration::get_re...ration_for_reg_url_link of type EE_Registration|null.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
246
		}
247
		return $this->get_one(array(array('REG_url_link'=>$REG_url_link)));
248
	}
249
250
251
252
253
	/**
254
	*		retrieve registration for a specific transaction attendee from db
255
	*
256
	* 		@access		public
257
	* 		@param	int	$TXN_ID
258
	* 		@param    int		$ATT_ID
259
	* 		@param    int		$att_nmbr 	in case the ATT_ID is the same for multiple registrations (same details used) then the attendee number is required
260
	*		@return 		mixed		array on success, FALSE on fail
261
	*/
262
	public function get_registration_for_transaction_attendee( $TXN_ID = 0, $ATT_ID = 0, $att_nmbr = 0 ) {
263
		return $this->get_one(array(
264
			array(
265
				'TXN_ID'=>$TXN_ID,
266
				'ATT_ID'=>$ATT_ID
267
			),
268
			'limit'=>array( min( ( $att_nmbr-1 ), 0 ), 1 )
269
		));
270
	}
271
272
273
	/**
274
	*		get the number of registrations per day  for the Registration Admin page Reports Tab.
275
	 *		(doesn't utilize models because it's a fairly specialized query)
276
	* 		@access		public
277
	 *		@param $period string which can be passed to php's strtotime function (eg "-1 month")
278
	 *		@return stdClass[] with properties regDate and total
279
	*/
280
	public function get_registrations_per_day_report( $period = '-1 month' ) {
281
282
		$sql_date = $this->convert_datetime_for_query( 'REG_date', date("Y-m-d H:i:s", strtotime($period) ), 'Y-m-d H:i:s', 'UTC' );
283
		$where = array( 'REG_date' => array( '>=', $sql_date ), 'STS_ID' => array( '!=', EEM_Registration::status_id_incomplete ) );
284
285
		if ( ! EE_Registry::instance()->CAP->current_user_can( 'ee_read_others_registrations', 'reg_per_day_report' ) ) {
286
			$where['Event.EVT_wp_user'] = get_current_user_id();
287
		}
288
289
		EE_Registry::instance()->load_helper( 'DTT_Helper' );
290
		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset( $this->get_timezone(), 'REG_date' );
291
292
		$results = $this->_get_all_wpdb_results(
293
				array(
294
					$where,
295
					'group_by'=>'regDate',
296
					'order_by'=>array('REG_date'=>'ASC')
297
				),
298
				OBJECT,
299
				array(
300
					'regDate'=>array( 'DATE(' . $query_interval . ')','%s'),
301
					'total'=>array('count(REG_ID)','%d')
302
				));
303
		return $results;
304
	}
305
306
307
	/**
308
	 * Get the number of registrations per day including the count of registrations for each Registration Status.
309
	 * Note: EEM_Registration::status_id_incomplete registrations are excluded from the results.
310
	 *
311
	 * @param string $period
312
	 *
313
	 * @return stdClass[] with properties Registration_REG_date and a column for each registration status as the STS_ID
314
	 *                    (i.e. RAP)
315
	 */
316
	public function get_registrations_per_day_and_per_status_report( $period = '-1 month' ) {
317
		global $wpdb;
318
		$registration_table = $wpdb->prefix . 'esp_registration';
319
		$event_table = $wpdb->posts;
320
		$sql_date = date("Y-m-d H:i:s", strtotime($period) );
321
322
		//prepare the query interval for displaying offset
323
		EE_Registry::instance()->load_helper( 'DTT_Helper' );
324
		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset( $this->get_timezone(), 'dates.REG_date' );
325
326
		//inner date query
327
		$inner_date_query = "SELECT DISTINCT REG_date from $registration_table ";
328
		$inner_where = " WHERE";
329
		//exclude events not authored by user if permissions in effect
330 View Code Duplication
		if ( ! EE_Registry::instance()->CAP->current_user_can( 'ee_read_others_registrations', 'reg_per_event_report' ) ) {
331
			$inner_date_query .= "LEFT JOIN $event_table ON ID = EVT_ID";
332
			$inner_where .= " post_author = " . get_current_user_id() . " AND";
333
		}
334
		$inner_where .= " REG_date >= '$sql_date'";
335
		$inner_date_query .= $inner_where;
336
337
		//start main query
338
		$select = "SELECT DATE($query_interval) as Registration_REG_date, ";
339
		$join = '';
340
		$join_parts = array();
341
		$select_parts = array();
342
343
		//loop through registration stati to do parts for each status.
344 View Code Duplication
		foreach ( EEM_Registration::reg_status_array() as $STS_ID => $STS_code ) {
345
			if ( $STS_ID === EEM_Registration::status_id_incomplete ) {
346
				continue;
347
			}
348
			$select_parts[] = "COUNT($STS_code.REG_ID) as $STS_ID";
349
			$join_parts[] = "$registration_table AS $STS_code ON $STS_code.REG_date = dates.REG_date AND $STS_code.STS_ID = '$STS_ID'";
350
		}
351
352
		//setup the selects
353
		$select .= implode(', ', $select_parts );
354
		$select .= " FROM ($inner_date_query) AS dates LEFT JOIN ";
355
356
		//setup the joins
357
		$join .= implode( " LEFT JOIN ", $join_parts );
358
359
		//now let's put it all together
360
		$query = $select . $join . ' GROUP BY Registration_REG_date';
361
362
		//and execute it
363
		$results = $wpdb->get_results(
364
			$query,
365
			ARRAY_A
366
		);
367
		return $results;
368
	}
369
370
371
372
373
374
375
	/**
376
	*		get the number of registrations per event  for the Registration Admin page Reports Tab
377
	* 		@access		public
378
	 * @param $period string which can be passed to php's strtotime function (eg "-1 month")
379
	 *		@return stdClass[] each with properties event_name, reg_limit, and total
380
	*/
381
	public function get_registrations_per_event_report( $period = '-1 month' ) {
382
383
		$date_sql = $this->convert_datetime_for_query( 'REG_date', date( "Y-m-d H:i:s", strtotime( $period )), 'Y-m-d H:i:s', 'UTC' );
384
		$where = array( 'REG_date' => array( '>=', $date_sql ), 'STS_ID' => array( '!=', EEM_Registration::status_id_incomplete ) );
385
386
		if ( ! EE_Registry::instance()->CAP->current_user_can( 'ee_read_others_registrations', 'reg_per_event_report' ) ) {
387
			$where['Event.EVT_wp_user'] = get_current_user_id();
388
		}
389
		$results = $this->_get_all_wpdb_results(array(
390
			$where,
391
			'group_by'=>'Event.EVT_name',
392
			'order_by'=>'Event.EVT_name',
393
			'limit'=>array(0,24)),
394
			OBJECT,
395
			array(
396
				'event_name'=>array('Event_CPT.post_title','%s'),
397
				'total'=>array('COUNT(REG_ID)','%s')
398
			)
399
		);
400
401
		return $results;
402
403
	}
404
405
406
	/**
407
	 * Get the number of registrations per event grouped by registration status.
408
	 * Note: EEM_Registration::status_id_incomplete registrations are excluded from the results.
409
	 *
410
	 * @param string $period
411
	 *
412
	 * @return stdClass[] with properties `Registration_Event` and a column for each registration status as the STS_ID
413
	 *                    (i.e. RAP)
414
	 */
415
	public function get_registrations_per_event_and_per_status_report( $period = '-1 month' ) {
416
		global $wpdb;
417
		$registration_table = $wpdb->prefix . 'esp_registration';
418
		$event_table = $wpdb->posts;
419
		$sql_date = date("Y-m-d H:i:s", strtotime($period) );
420
421
		//inner date query
422
		$inner_date_query = "SELECT DISTINCT EVT_ID, REG_date from $registration_table ";
423
		$inner_where = " WHERE";
424
		//exclude events not authored by user if permissions in effect
425 View Code Duplication
		if ( ! EE_Registry::instance()->CAP->current_user_can( 'ee_read_others_registrations', 'reg_per_event_report' ) ) {
426
			$inner_date_query .= "LEFT JOIN $event_table ON ID = EVT_ID";
427
			$inner_where .= " post_author = " . get_current_user_id() . " AND";
428
		}
429
		$inner_where .= " REG_date >= '$sql_date'";
430
		$inner_date_query .= $inner_where;
431
432
		//build main query
433
		$select = "SELECT Event.post_title as Registration_Event, ";
434
		$join = '';
435
		$join_parts = array();
436
		$select_parts = array();
437
438
		//loop through registration stati to do parts for each status.
439 View Code Duplication
		foreach ( EEM_Registration::reg_status_array() as $STS_ID => $STS_code ) {
440
			if ( $STS_ID === EEM_Registration::status_id_incomplete ) {
441
				continue;
442
			}
443
			$select_parts[] = "COUNT($STS_code.REG_ID) as $STS_ID";
444
			$join_parts[] = "$registration_table AS $STS_code ON $STS_code.EVT_ID = dates.EVT_ID AND $STS_code.STS_ID = '$STS_ID' AND $STS_code.REG_date = dates.REG_date";
445
		}
446
447
		//setup the selects
448
		$select .= implode( ', ', $select_parts );
449
		$select .= " FROM ($inner_date_query) AS dates LEFT JOIN $event_table as Event ON Event.ID = dates.EVT_ID LEFT JOIN ";
450
451
		//setup remaining joins
452
		$join .= implode( " LEFT JOIN ", $join_parts );
453
454
		//now put it all together
455
		$query = $select . $join . ' GROUP BY Registration_Event';
456
457
		//and execute
458
		$results = $wpdb->get_results(
459
			$query,
460
			ARRAY_A
461
		);
462
		return $results;
463
	}
464
465
466
	/**
467
	 * Returns the EE_Registration of the primary attendee on the transaction id provided
468
	 * @param int $TXN_ID
469
	 * @return EE_Registration
470
	 */
471
	public function get_primary_registration_for_transaction_ID( $TXN_ID = 0){
472
		if( ! $TXN_ID ){
473
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by EEM_Registration::get_pr...tion_for_transaction_ID of type EE_Registration|null.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
474
		}
475
		return $this->get_one(array(array('TXN_ID'=>$TXN_ID,'REG_count'=>  EEM_Registration::PRIMARY_REGISTRANT_COUNT)));
476
	}
477
478
479
	/**
480
	 *		get_event_registration_count
481
	 *
482
	 *		@access public
483
	 *		@param int $EVT_ID
484
	 *		@param boolean $for_incomplete_payments
485
	 *		@return int
486
	 */
487
	public function get_event_registration_count ( $EVT_ID, $for_incomplete_payments = FALSE ) {
488
		// we only count approved registrations towards registration limits
489
		$query_params = array( array( 'EVT_ID' => $EVT_ID, 'STS_ID' => self::status_id_approved ) );
490
		if( $for_incomplete_payments ){
491
			$query_params[0]['Transaction.STS_ID']=array('!=',  EEM_Transaction::complete_status_code);
492
		}
493
494
		return $this->count($query_params);
495
	}
496
497
	/**
498
	 * Deletes all registrations with no transactions. Note that this needs to be very efficient
499
	 * and so it uses wpdb directly
500
	 * @global WPDB $wpdb
501
	 * @return int number deleted
502
	 */
503
	public function delete_registrations_with_no_transaction() {
504
		/** @type WPDB $wpdb */
505
		global $wpdb;
506
		return $wpdb->query(
507
				'DELETE r FROM ' . $this->table() . ' r LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON r.TXN_ID = t.TXN_ID WHERE t.TXN_ID IS NULL' );
508
	}
509
510
	/**
511
	 *  Count registrations checked into (or out of) a datetime
512
	 *
513
	 * @param int $DTT_ID datetime ID
514
	 * @param boolean $checked_in whether to count registrations checked IN or OUT
515
	 * @return int
516
	 */
517
	public function count_registrations_checked_into_datetime( $DTT_ID, $checked_in = true) {
518
		global $wpdb;
519
		//subquery to get latest checkin
520
		$query = $wpdb->prepare(
521
			'SELECT '
522
				. 'COUNT( DISTINCT checkins.REG_ID ) '
523
			. 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
524
				. '( SELECT '
525
					. 'max( CHK_timestamp ) AS latest_checkin, '
526
					. 'REG_ID AS REG_ID '
527
				. 'FROM ' . EEM_Checkin::instance()->table() . ' '
528
				. 'WHERE DTT_ID=%d '
529
				. 'GROUP BY REG_ID'
530
			. ') AS most_recent_checkin_per_reg '
531
			. 'ON checkins.REG_ID=most_recent_checkin_per_reg.REG_ID '
532
				. 'AND checkins.CHK_timestamp = most_recent_checkin_per_reg.latest_checkin '
533
			. 'WHERE '
534
				. 'checkins.CHK_in=%d',
535
			$DTT_ID,
536
			$checked_in
537
		);
538
		return (int)$wpdb->get_var( $query );
539
	}
540
541
	/**
542
	 *  Count registrations checked into (or out of) an event.
543
	 *
544
	 * @param int $EVT_ID event ID
545
	 * @param boolean $checked_in whether to count registrations checked IN or OUT
546
	 * @return int
547
	 */
548
	public function count_registrations_checked_into_event( $EVT_ID, $checked_in = true ) {
549
		global $wpdb;
550
		//subquery to get latest checkin
551
		$query = $wpdb->prepare(
552
			'SELECT '
553
				. 'COUNT( DISTINCT checkins.REG_ID ) '
554
			. 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
555
				. '( SELECT '
556
					. 'max( CHK_timestamp ) AS latest_checkin, '
557
					. 'REG_ID AS REG_ID '
558
				. 'FROM ' . EEM_Checkin::instance()->table() . ' AS c '
559
				. 'INNER JOIN ' . EEM_Datetime::instance()->table() . ' AS d '
560
				. 'ON c.DTT_ID=d.DTT_ID '
561
				. 'WHERE d.EVT_ID=%d '
562
				. 'GROUP BY REG_ID'
563
			. ') AS most_recent_checkin_per_reg '
564
			. 'ON checkins.REG_ID=most_recent_checkin_per_reg.REG_ID '
565
				. 'AND checkins.CHK_timestamp = most_recent_checkin_per_reg.latest_checkin '
566
			. 'WHERE '
567
				. 'checkins.CHK_in=%d',
568
			$EVT_ID,
569
			$checked_in
570
		);
571
		return (int)$wpdb->get_var( $query );
572
	}
573
574
575
576
577
578
	/**
579
	 * The purpose of this method is to retrieve an array of
580
	 * EE_Registration objects that represent the latest registration
581
	 * for each ATT_ID given in the function argument.
582
	 *
583
	 * @param array $attendee_ids
584
	 * @return EE_Registration[]
585
	 */
586
	public function get_latest_registration_for_each_of_given_contacts( $attendee_ids = array() ) {
587
		//first do a native wp_query to get the latest REG_ID's matching these attendees.
588
		global $wpdb;
589
		$registration_table = $wpdb->prefix . 'esp_registration';
590
		$attendee_table = $wpdb->posts;
591
		$attendee_ids = is_array( $attendee_ids )
592
			? array_map( 'absint', $attendee_ids )
593
			: array( (int) $attendee_ids );
594
		$attendee_ids = implode( ',', $attendee_ids );
595
596
597
		//first we do a query to get the registration ids
598
		// (because a group by before order by causes the order by to be ignored.)
599
		$registration_id_query = "
600
			SELECT registrations.registration_ids as registration_id
601
			FROM (
602
				SELECT
603
					Attendee.ID as attendee_ids,
604
					Registration.REG_ID as registration_ids
605
				FROM $registration_table AS Registration
606
				JOIN $attendee_table AS Attendee
607
					ON Registration.ATT_ID = Attendee.ID
608
					AND Attendee.ID IN ( $attendee_ids )
609
				ORDER BY Registration.REG_ID DESC
610
			  ) AS registrations
611
			  GROUP BY registrations.attendee_ids
612
		";
613
614
		$registration_ids = $wpdb->get_results(
615
			$registration_id_query,
616
			ARRAY_A
617
		);
618
619
		if ( empty( $registration_ids ) ) {
620
			return array();
621
		}
622
623
		$ids_for_model_query = array();
624
		//let's flatten the ids so they can be used in the model query.
625
		foreach ( $registration_ids as $registration_id ) {
626
			if ( isset( $registration_id['registration_id'] ) ) {
627
				$ids_for_model_query[] = $registration_id['registration_id'];
628
			}
629
		}
630
631
		//construct query
632
		$_where = array(
633
			'REG_ID' => array( 'IN', $ids_for_model_query )
634
		);
635
636
		return $this->get_all( array( $_where ) );
637
	}
638
639
640
641
}
642
// End of file EEM_Registration.model.php
643
// Location: /includes/models/EEM_Registration.model.php
644