Completed
Branch FET-9225-user-google-charts (0b6680)
by
unknown
624:02 queued 606:46
created

EEM_Transaction   B

Complexity

Total Complexity 11

Size/Duplication

Total Lines 271
Duplicated Lines 3.69 %

Coupling/Cohesion

Components 2
Dependencies 17
Metric Value
wmc 11
lcom 2
cbo 17
dl 10
loc 271
rs 7.8571

6 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 31 1
A get_revenue_per_day_report() 0 23 2
A get_revenue_per_event_report() 0 23 2
A get_transaction_from_reg_url_link() 0 7 2
A update_based_on_payments() 10 10 1
A delete_junk_transactions() 0 55 3

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_Base.model.php' );
3
/**
4
 *
5
 * Transaction Model
6
 *
7
 * @package			Event Espresso
8
 * @subpackage		includes/models/
9
 * @author				Brent Christensen
10
 *
11
 */
12
class EEM_Transaction extends EEM_Base {
13
14
	// private instance of the Transaction object
15
	protected static $_instance = NULL;
16
17
	/**
18
	 * Status ID(STS_ID on esp_status table) to indicate the transaction is complete,
19
	 * but payment is pending. This is the state for transactions where payment is promised
20
	 * from an offline gateway.
21
	 */
22
	//	const open_status_code = 'TPN';
23
24
	/**
25
	 * Status ID(STS_ID on esp_status table) to indicate the transaction failed,
26
	 * either due to a technical reason (server or computer crash during registration),
27
	 *  or some other reason that prevent the collection of any useful contact information from any of the registrants
28
	 */
29
	const failed_status_code = 'TFL';
30
31
	/**
32
	 * Status ID(STS_ID on esp_status table) to indicate the transaction was abandoned,
33
	 * either due to a technical reason (server or computer crash during registration),
34
	 * or due to an abandoned cart after registrant chose not to complete the registration process
35
	 * HOWEVER...
36
	 * an abandoned TXN differs from a failed TXN in that it was able to capture contact information for at least one registrant
37
	 */
38
	const abandoned_status_code = 'TAB';
39
40
	/**
41
	 * Status ID(STS_ID on esp_status table) to indicate an incomplete transaction,
42
	 * meaning that monies are still owing: TXN_paid < TXN_total
43
	 */
44
	const incomplete_status_code = 'TIN';
45
46
	/**
47
	 * Status ID (STS_ID on esp_status table) to indicate a complete transaction.
48
	 * meaning that NO monies are owing: TXN_paid == TXN_total
49
	 */
50
	const complete_status_code = 'TCM';
51
52
	/**
53
	 *  Status ID(STS_ID on esp_status table) to indicate the transaction is overpaid.
54
	 *  This is the same as complete, but site admins actually owe clients the moneys!  TXN_paid > TXN_total
55
	 */
56
	const overpaid_status_code = 'TOP';
57
58
59
60
61
62
	/**
63
	 *	private constructor to prevent direct creation
64
	 *
65
	 *	@Constructor
66
	 *	@access protected
67
	 *	@param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any incoming timezone data that gets saved).
68
	 * 		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)
69
	 *	@return EEM_Transaction
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...
70
	 */
71
	protected function __construct( $timezone ) {
72
		$this->singular_item = __('Transaction','event_espresso');
73
		$this->plural_item = __('Transactions','event_espresso');
74
75
		$this->_tables = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Transaction' => n...ransaction', 'TXN_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...
76
			'Transaction'=>new EE_Primary_Table('esp_transaction','TXN_ID')
77
		);
78
		$this->_fields = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Transaction' => a...so'), FALSE, array()))) of type array<string,array<strin...ized_Text_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...
79
			'Transaction'=>array(
80
				'TXN_ID'=>new EE_Primary_Key_Int_Field('TXN_ID', __('Transaction ID','event_espresso')),
81
				'TXN_timestamp'=>new EE_Datetime_Field('TXN_timestamp', __('date when transaction was created','event_espresso'), false, time(), $timezone ),
82
				'TXN_total'=>new EE_Money_Field('TXN_total', __('Total value of Transaction','event_espresso'), false, 0),
83
				'TXN_paid'=>new EE_Money_Field('TXN_paid', __('Amount paid towards transaction to date','event_espresso'), false, 0),
84
				'STS_ID'=>new EE_Foreign_Key_String_Field('STS_ID', __('Status ID','event_espresso'), false, EEM_Transaction::failed_status_code, 'Status'),
85
				'TXN_session_data'=>new EE_Serialized_Text_Field('TXN_session_data', __('Serialized session data','event_espresso'), true, ''),
86
				'TXN_hash_salt'=>new EE_Plain_Text_Field('TXN_hash_salt', __('Transaction Hash Salt','event_espresso'), true, ''),
87
				'PMD_ID'=>new EE_Foreign_Key_Int_Field('PMD_ID', __("Last Used Payment Method", 'event_espresso'), true, NULL, 'Payment_Method'),
88
				'TXN_reg_steps' => new EE_Serialized_Text_Field( 'TXN_reg_steps', __( 'Registration Steps', 'event_espresso' ), FALSE, array() ),
89
			)
90
		);
91
		$this->_model_relations = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Registration' => ..._Belongs_To_Relation()) of type array<string,object<EE_H...Belongs_To_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...
92
			'Registration'=>new EE_Has_Many_Relation(),
93
			'Payment'=>new EE_Has_Many_Relation(),
94
			'Status'=>new EE_Belongs_To_Relation(),
95
			'Line_Item'=>new EE_Has_Many_Relation(false),//you can delete a transaction without needing to delete its line items
96
			'Payment_Method'=>new EE_Belongs_To_Relation(),
97
		);
98
		$this->_model_chain_to_wp_user = 'Registration.Event';
99
		parent::__construct( $timezone );
100
101
	}
102
103
	/**
104
	 *        get the revenue per day  for the Transaction Admin page Reports Tab
105
	 *
106
	 * @access        public
107
	 * @param string $period
108
	 * @return \stdClass[]
109
	 */
110
	public function get_revenue_per_day_report( $period = '-1 month' ) {
111
		$sql_date = $this->convert_datetime_for_query( 'TXN_timestamp', date( 'Y-m-d H:i:s', strtotime( $period ) ), 'Y-m-d H:i:s', 'UTC' );
112
113
		$offset = get_option( 'gmt_offset' );
114
		$query_interval = $offset < 0
115
			? 'DATE_SUB(TXN_timestamp, INTERVAL ' . $offset*-1 . ' HOUR)'
116
			: 'DATE_ADD(TXN_timestamp, INTERVAL ' . $offset . ' HOUR)';
117
118
		$results = $this->_get_all_wpdb_results(
119
			array(
120
				array(
121
				'TXN_timestamp' => array( '>=', $sql_date ) ),
122
				'group_by' => 'txnDate',
123
				'order_by' => array( 'TXN_timestamp' => 'ASC' )
124
			),
125
			OBJECT,
126
			array(
127
				'txnDate' => array( 'DATE(' . $query_interval . ')', '%s' ),
128
				'revenue' => array( 'SUM(Transaction.TXN_paid)', '%d' )
129
			)
130
		);
131
		return $results;
132
	}
133
134
135
136
	/**
137
	 *        get the revenue per event  for the Transaction Admin page Reports Tab
138
	 *
139
	 * @access        public
140
	 * @param string $period
141
	 * @throws \EE_Error
142
	 * @return mixed
143
	 */
144
	public function get_revenue_per_event_report( $period = '-1 month' ) {
145
		$date_sql = EEM_Registration::instance()->convert_datetime_for_query( 'REG_date', date( 'Y-m-d H:i:s', strtotime( $period ) ), 'Y-m-d H:i:s', 'UTC' );
146
		$where = array( 'Registration.REG_date' => array( '>=', $date_sql ) );
147
148
		if ( ! EE_Registry::instance()->CAP->current_user_can( 'ee_read_others_registrations', 'revenue_per_event_report' ) ) {
149
			$where ['Registration.Event.EVT_wp_user'] = get_current_user_id();
150
		}
151
152
		$results = $this->_get_all_wpdb_results(
153
			array(
154
				$where,
155
				'group_by' => array( 'Registration.Event.EVT_name' ),
156
				'order_by' => 'Registration.Event.EVT_name',
157
				'limit' => array( 0, 24 )
158
			),
159
			OBJECT,
160
			array(
161
				'event_name' => array( 'Registration___Event_CPT.post_title', '%s' ),
162
				'revenue' => array( 'SUM(TXN_PAID)', '%d' )
163
			)
164
		);
165
		return $results;
166
	}
167
168
169
170
171
172
173
	/**
174
	 * Gets the current transaction given the reg_url_link, or assumes the reg_url_link is in the
175
	 * $_REQUEST global variable. Either way, tries to find the current transaction (through
176
	 * the registration pointed to by reg_url_link), if not returns null
177
	 * @param string $reg_url_link
178
	 * @return EE_Transaction
179
	 */
180
	public function get_transaction_from_reg_url_link( $reg_url_link = '' ){
181
		return $this->get_one( array(
182
			array(
183
				'Registration.REG_url_link' => ! empty( $reg_url_link ) ? $reg_url_link : EE_Registry::instance()->REQ->get( 'e_reg_url_link', '' )
184
			)
185
		));
186
	}
187
188
189
190
191
192
193
194
	/**
195
	 * Updates the provided EE_Transaction with all the applicable payments
196
	 * (or fetch the EE_Transaction from its ID)
197
	 *
198
	 * @deprecated
199
	 * @param EE_Transaction | int $transaction_obj_or_id
200
	 * @param boolean $save_txn whether or not to save the transaction during this function call
201
	 * @return boolean
202
	 */
203 View Code Duplication
	public function update_based_on_payments( $transaction_obj_or_id, $save_txn = TRUE ){
0 ignored issues
show
Unused Code introduced by
The parameter $save_txn is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
204
		EE_Error::doing_it_wrong(
205
			__CLASS__ . '::' . __FUNCTION__,
206
			sprintf( __( 'This method is deprecated. Please use "%s" instead', 'event_espresso' ), 'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()' ),
207
			'4.6.0'
208
		);
209
		/** @type EE_Transaction_Processor $transaction_processor */
210
		$transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
211
		return  $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment( $this->ensure_is_obj( $transaction_obj_or_id ));
0 ignored issues
show
Compatibility introduced by
$this->ensure_is_obj($transaction_obj_or_id) of type object<EE_Base_Class> is not a sub-type of object<EE_Transaction>. It seems like you assume a child class of the class EE_Base_Class to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
212
	}
213
214
	/**
215
	 * Deletes "junk" transactions that were probably added by bots. There might be TONS
216
	 * of these, so we are very careful to NOT select (which the models do even when deleting),
217
	 * and so we only use wpdb directly and NOT do any joins.
218
	 * The downside to this approach is that is addons are listening for object deletions
219
	 * on EEM_Base::delete() they won't be notified of this.
220
	 * @global WPDB $wpdb
221
	 * @return mixed
222
	 */
223
	public function delete_junk_transactions() {
224
		/** @type WPDB $wpdb */
225
		global $wpdb;
226
		$deleted = false;
227
		$time_to_leave_alone = apply_filters(
228
			'FHEE__EEM_Transaction__delete_junk_transactions__time_to_leave_alone', WEEK_IN_SECONDS
229
		);
230
231
232
		/**
233
		 * This allows code to filter the query arguments used for retrieving the transaction IDs to delete.
234
		 * Useful for plugins that want to exclude transactions matching certain query parameters.
235
		 * The query parameters should be in the format accepted by the EEM_Base model queries.
236
		 */
237
		$ids_query = apply_filters(
238
			'FHEE__EEM_Transaction__delete_junk_transactions__initial_query_args',
239
			array(
240
				0 => array(
241
					'STS_ID' => EEM_Transaction::failed_status_code,
242
					'TXN_timestamp' => array( '<', time() - $time_to_leave_alone )
243
				)
244
			),
245
			$time_to_leave_alone
246
		);
247
248
249
		/**
250
		 * This filter is for when code needs to filter the list of transaction ids that represent transactions
251
		 * about to be deleted based on some other criteria that isn't easily done via the query args filter.
252
		 */
253
		$txn_ids = apply_filters(
254
			'FHEE__EEM_Transaction__delete_junk_transactions__transaction_ids_to_delete',
255
			EEM_Transaction::instance()->get_col( $ids_query, 'TXN_ID' ),
256
			$time_to_leave_alone
257
		);
258
259
		//now that we have the ids to delete, let's get deletin'
260
		//Why no wpdb->prepare?  Because the data is trusted.  We got the ids from the original query to get them FROM
261
		//the db (which is sanitized) so no need to prepare them again.
262
		if ( $txn_ids ) {
263
			$query   = '
264
				DELETE
265
				FROM ' . $this->table() . '
266
				WHERE
267
					TXN_ID IN ( ' . implode( ",", $txn_ids ) . ')';
268
			$deleted = $wpdb->query( $query );
269
		}
270
		if ( $deleted ) {
271
			/**
272
			 * Allows code to do something after the transactions have been deleted.
273
			 */
274
			do_action( 'AHEE__EEM_Transaction__delete_junk_transactions__successful_deletion', $txn_ids );
275
		}
276
		return $deleted;
277
	}
278
279
280
281
282
}
283
// End of file EEM_Transaction.model.php
284
// Location: /includes/models/EEM_Transaction.model.php
285