Completed
Branch BETA-4.9-messages-queue-fixed (941081)
by
unknown
17:38 queued 10s
created

EEM_Line_Item   C

Complexity

Total Complexity 13

Size/Duplication

Total Lines 287
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 19
Metric Value
wmc 13
lcom 2
cbo 19
dl 0
loc 287
rs 6.875

10 Methods

Rating   Name   Duplication   Size   Complexity  
A get_object_line_items_for_transaction() 0 11 4
A get_line_item_for_registration() 0 3 1
A __construct() 0 47 1
A get_all_of_type_for_transaction() 0 7 1
A get_all_non_ticket_line_items_for_transaction() 0 10 1
A delete_line_items_with_no_transaction() 0 16 1
A get_line_item_for_transaction_object() 0 7 1
A get_existing_promotion_line_item() 0 10 1
A get_all_promotion_line_items() 0 9 1
A line_item_for_registration_query_params() 0 9 1
1
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
2
/**
3
 * Event Espresso
4
 *
5
 * Event Registration and Management Plugin for WordPress
6
 *
7
 * @ package			Event Espresso
8
 * @ author				Seth Shoultes
9
 * @ copyright		(c) 2008-2011 Event Espresso  All Rights Reserved.
10
 * @ license			http://eventespresso.com/support/terms-conditions/   * see Plugin Licensing *
11
 * @ link					http://www.eventespresso.com
12
 * @ version		 	4.0
13
 *
14
 * ------------------------------------------------------------------------
15
 *
16
 * Line Item Model. Mostly used for storing a snapshot of all the items in a transaction
17
 * as they were recorded at the time of being added to the cart.
18
 * There are different 'types' of line items: item, sub-item, tax, sub-total, and total.
19
 * Note that line items can be nested. For example, a total line item should have one-or-more
20
 * children sub-totals. Likewise, sub-totals should have one-or-more nested items or taxes
21
 * (or maybe promotions or products?). Also, items can have nested sub-items (eg. an item could be a
22
 * ticket, which has many sub-item prices which together make up the price of that ticket).
23
 * Note that line items should point to real model objects using OBJ_ID and OBJ_type (note:
24
 * there is a current limitation that they can only point to models with INT primary keys),
25
 * but this is NOT required. And in fact, the items they are related to CAN be deleted, but
26
 * the line item should still exist (in this case it merely shows that there was ONCE a model
27
 * object the line item was based off of).
28
 *
29
 * In usage, Line Items are first stored on the EE_Cart, but not saved until a user's registration is
30
 * finalized (like how the EE_Transaction is stored in the session until it is confirmed).
31
 * Many of their methods (like
32
 *
33
 *
34
 * @package			Event Espresso
35
 * @subpackage		includes/models/EEM_Line_Item.model.php
36
 * @author			Mike Nelson
37
 *
38
 * ------------------------------------------------------------------------
39
 */
40
41
class EEM_Line_Item extends EEM_Base {
42
43
	/**
44
	 * Tax sub-total is just the total of all the taxes, which should be children
45
	 * of this line item. There should only ever be one tax sub-total, and it should
46
	 * be a direct child of
47
	 */
48
	const type_tax_sub_total = 'tax-sub-total';
49
50
	/**
51
	 * Tax line items indicate a tax applied to all the taxable line items.
52
	 * Should not have any children line items.
53
	 */
54
	const type_tax = 'tax';
55
56
	/**
57
	 * Indicating individual items purchased, or discounts or surcharges.
58
	 * The sum of all the regular line items  plus the tax items should equal
59
	 * the grand total.
60
	 * Possible children fo sub-line-items and cancellations.
61
	 */
62
	const type_line_item = 'line-item';
63
64
	/**
65
	 * line item indicating all the factors that make a single line item.
66
	 * Sub-line items should have NO children line items.
67
	 */
68
	const type_sub_line_item = 'sub-item';
69
70
	/**
71
	 * line item indicating a sub-total (eg total for an event, or before taxes).
72
	 * Direct children can be line items and other sub-totals
73
	 *
74
	 */
75
	const type_sub_total = 'sub-total';
76
77
	/**
78
	 * line item for teh grand total of an order. Its direct children
79
	 * should be tax subtotals and subtotals, and possibly a regular line item
80
	 * indicating a transaction-wide discount/surcharge
81
	 */
82
	const type_total = 'total';
83
84
	/**
85
	 * When a line item is cancelled, a sub-line-item of type 'cancellation'
86
	 * should be created, indicating the quantity that were cancelled
87
	 * (because a line item could have a quantity of 4, and its cancellation item
88
	 * could be for 3, indicating that there is still 1 item purchased).
89
	 * When items are refunded, a cancellation line item should be made, which points
90
	 * to teh payment model object which actually refunded the payment.
91
	 * Cancellations should NOT have any children line items.
92
	 */
93
	const type_cancellation = 'cancellation';
94
95
	// private instance of the EEM_Line_Item object
96
	protected static $_instance = NULL;
97
98
99
	/**
100
	 *        private constructor to prevent direct creation
101
	 * @Constructor
102
	 * @access protected
103
	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any incoming timezone data that gets saved).  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)
104
	 * @return \EEM_Line_Item
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...
105
	 */
106
	protected function __construct( $timezone ) {
107
		$this->singular_item = __('Line Item','event_espresso');
108
		$this->plural_item = __('Line Items','event_espresso');
109
110
		$this->_tables = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Line_Item' => new..._line_item', 'LIN_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...
111
			'Line_Item'=>new EE_Primary_Table('esp_line_item','LIN_ID')
112
		);
113
		$line_items_can_be_for = apply_filters( 'FHEE__EEM_Line_Item__line_items_can_be_for', array('Ticket','Price', 'Event' ) );
114
		$this->_fields = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Line_Item' => arr...e, time(), $timezone))) of type array<string,array<strin..._Datetime_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...
115
			'Line_Item' => array(
116
				'LIN_ID' 				=> new EE_Primary_Key_Int_Field( 'LIN_ID', __( "ID", "event_espresso" ) ),
117
				'LIN_code' 			=> new EE_Slug_Field( 'LIN_code', __( "Code for index into Cart", "event_espresso" ), TRUE ),
118
				'TXN_ID' 				=> new EE_Foreign_Key_Int_Field( 'TXN_ID', __( "Transaction ID", "event_espresso" ), TRUE, NULL, 'Transaction' ),
119
				'LIN_name' 			=> new EE_Full_HTML_Field( 'LIN_name', __( "Line Item Name", "event_espresso" ), FALSE, '' ),
120
				'LIN_desc' 			=> new EE_Full_HTML_Field( 'LIN_desc', __( "Line Item Description", "event_espresso" ), TRUE ),
121
				'LIN_unit_price' 	=> new EE_Money_Field( 'LIN_unit_price', __( "Unit Price", "event_espresso" ), FALSE, 0 ),
122
				'LIN_percent' 		=> new EE_Float_Field( 'LIN_percent', __( "Percent", "event_espresso" ), FALSE, 0 ),
123
				'LIN_is_taxable' 	=> new EE_Boolean_Field( 'LIN_is_taxable', __( "Taxable", "event_espresso" ), FALSE, FALSE ),
124
				'LIN_order' 			=> new EE_Integer_Field( 'LIN_order', __( "Order of Application towards total of parent", "event_espresso" ), FALSE, 1 ),
125
				'LIN_total' 			=> new EE_Money_Field( 'LIN_total', __( "Total (unit price x quantity)", "event_espresso" ), FALSE, 0 ),
126
				'LIN_quantity' 	=> new EE_Integer_Field( 'LIN_quantity', __( "Quantity", "event_espresso" ), TRUE, 1 ),
127
				'LIN_parent' 		=> new EE_Integer_Field( 'LIN_parent', __( "Parent ID (this item goes towards that Line Item's total)", "event_espresso" ), TRUE, NULL ),
128
				'LIN_type' 			=> new EE_Enum_Text_Field( 'LIN_type', __( "Type", "event_espresso" ), FALSE, 'line-item', array(
129
						self::type_line_item		=>  __("Line Item", "event_espresso"),
130
						self::type_sub_line_item	=>  __("Sub-Item", "event_espresso"),
131
						self::type_sub_total		=>  __("Subtotal", "event_espresso"),
132
						self::type_tax_sub_total 	=> __("Tax Subtotal", "event_espresso"),
133
						self::type_tax					=>  __("Tax", "event_espresso"),
134
						self::type_total				=>  __("Total", "event_espresso"),
135
						self::type_cancellation	=> __( 'Cancellation', 'event_espresso' )
136
					)
137
				),
138
				'OBJ_ID' 					=> new EE_Foreign_Key_Int_Field( 'OBJ_ID', __( 'ID of Item purchased.', 'event_espresso' ), TRUE, NULL, $line_items_can_be_for ),
139
				'OBJ_type'				=>new EE_Any_Foreign_Model_Name_Field( 'OBJ_type', __( "Model Name this Line Item is for", "event_espresso" ), TRUE, NULL, $line_items_can_be_for ),
140
				'LIN_timestamp' => new EE_Datetime_Field('LIN_timestamp', __('When the line item was created','event_espresso'), false, time(), $timezone ),
141
			)
142
		);
143
		$this->_model_relations = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Transaction' => n...ongs_To_Any_Relation()) of type array<string,object<EE_B...ngs_To_Any_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...
144
			'Transaction'	=>new EE_Belongs_To_Relation(),
145
			'Ticket'				=>new EE_Belongs_To_Any_Relation(),
146
			'Price'				=>new EE_Belongs_To_Any_Relation(),
147
			'Event' => new EE_Belongs_To_Any_Relation()
148
		);
149
		$this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
150
		$this->_caps_slug = 'transactions';
151
		parent::__construct( $timezone );
152
	}
153
154
155
156
	/**
157
	 * Gets all the line items for this transaction of the given type
158
	 * @param string $line_item_type like one of EEM_Line_Item::type_*
159
	 * @param EE_Transaction|int $transaction
160
	 * @return EE_Line_Item[]
161
	 */
162
	public function get_all_of_type_for_transaction( $line_item_type, $transaction ){
163
		$transaction = EEM_Transaction::instance()->ensure_is_ID( $transaction );
164
		return $this->get_all( array( array(
165
			'LIN_type' => $line_item_type,
166
			'TXN_ID' => $transaction
167
		)));
168
	}
169
170
171
172
	/**
173
	 * Gets all line items unrelated to tickets that are normal line items
174
	 * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
175
	 * @param EE_Transaction|int $transaction
176
	 * @return \EE_Base_Class[]
177
	 */
178
	public function get_all_non_ticket_line_items_for_transaction( $transaction ) {
179
		$transaction = EEM_Transaction::instance()->ensure_is_ID( $transaction );
180
		return $this->get_all( array( array(
181
			'LIN_type' => self::type_line_item,
182
			'TXN_ID' => $transaction,
183
			'OR' => array(
184
				'OBJ_type*notticket' => array( '!=', 'Ticket'),
185
				'OBJ_type*null' => array( 'IS_NULL' ))
186
		)));
187
	}
188
189
	/**
190
	 * Deletes line items with no transaction who have passed the transaction cutoff time.
191
	 * This needs to be very efficient
192
	 * because if there are spam bots afoot there will be LOTS of line items
193
	 * @return int count of how many deleted
194
	 */
195
	public function delete_line_items_with_no_transaction(){
196
		/** @type WPDB $wpdb */
197
		global $wpdb;
198
		$time_to_leave_alone = apply_filters(
199
			'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone', WEEK_IN_SECONDS
200
		);
201
		$query = $wpdb->prepare(
202
				'DELETE li
203
				FROM ' . $this->table() . ' li
204
				LEFT JOIN ' . EEM_Transaction::instance()->table(). ' t ON li.TXN_ID = t.TXN_ID
205
				WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s',
206
				// use GMT time because that's what TXN_timestamps are in
207
				gmdate(  'Y-m-d H:i:s', time() - $time_to_leave_alone )
208
				);
209
		return $wpdb->query( $query );
210
	}
211
212
213
214
	/**
215
	 * get_line_item_for_transaction_object
216
	 * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
217
	 *
218
	 * @param int $TXN_ID
219
	 * @param \EE_Base_Class $object
220
	 * @return EE_Line_Item[]
221
	 */
222
	public function get_line_item_for_transaction_object( $TXN_ID, EE_Base_Class $object ){
223
		return $this->get_all( array( array(
224
			'TXN_ID' 		=> $TXN_ID,
225
			'OBJ_type' 	=> str_replace( 'EE_', '', get_class( $object )),
226
			'OBJ_ID' 		=> $object->ID()
227
		)));
228
	}
229
230
231
232
	/**
233
	 * get_object_line_items_for_transaction
234
	 * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
235
	 *
236
	 * @param int $TXN_ID
237
	 * @param string $OBJ_type
238
	 * @param array $OBJ_IDs
239
	 * @return EE_Line_Item[]
240
	 */
241
	public function get_object_line_items_for_transaction( $TXN_ID, $OBJ_type = 'Event', $OBJ_IDs = array() ){
242
		$query_params = array(
243
			'OBJ_type' 	=> $OBJ_type,
244
			// if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
245
			'OBJ_ID' 		=> is_array( $OBJ_IDs ) && ! isset( $OBJ_IDs['IN'] ) ? array( 'IN', $OBJ_IDs ) : $OBJ_IDs
246
		);
247
		if ( $TXN_ID ) {
248
			$query_params['TXN_ID'] = $TXN_ID;
249
		}
250
		return $this->get_all( array( $query_params ));
251
	}
252
253
254
255
	/**
256
	 * get_existing_promotion_line_item
257
	 * searches the cart for existing line items for the specified promotion
258
	 *
259
	 * @since   1.0.0
260
	 *
261
	 * @param EE_Line_Item $parent_line_item
262
	 * @param EE_Promotion $promotion
263
	 * @return EE_Line_Item
264
	 */
265
	public function get_existing_promotion_line_item( EE_Line_Item $parent_line_item, EE_Promotion $promotion ) {
266
		return $this->get_one( array(
267
			array(
268
				'TXN_ID' 			=> $parent_line_item->TXN_ID(),
269
				'LIN_parent' 	=> $parent_line_item->ID(),
270
				'OBJ_type' 		=> 'Promotion',
271
				'OBJ_ID' 			=> $promotion->ID()
272
			)
273
		));
274
	}
275
276
277
278
	/**
279
	 * get_all_promotion_line_items
280
	 * searches the cart for any and all existing promotion line items
281
	 *
282
	 * @since   1.0.0
283
	 *
284
	 * @param EE_Line_Item $parent_line_item
285
	 * @return EE_Line_Item[]
286
	 */
287
	public function get_all_promotion_line_items( EE_Line_Item $parent_line_item ) {
288
		return $this->get_all( array(
289
			array(
290
				'TXN_ID' 			=> $parent_line_item->TXN_ID(),
291
				'LIN_parent' 	=> $parent_line_item->ID(),
292
				'OBJ_type' 		=> 'Promotion'
293
			)
294
		));
295
	}
296
297
	/**
298
	 * Gets the registration's corresponding line item.
299
	 * Note: basically does NOT support having multiple line items for a single ticket,
300
	 * which would happen if some of the registrations had a price modifier while others didn't.
301
	 * In order to support that, we'd probably need a LIN_ID on registrations or something.
302
	 * @param EE_Registration $registration
303
	 * @return EEM_Line_ITem
304
	 */
305
	public function get_line_item_for_registration( EE_Registration $registration ) {
306
		return $this->get_one( $this->line_item_for_registration_query_params( $registration ));
307
	}
308
309
	/**
310
	 * Gets the query params used to retrieve a specific line item for the given registration
311
	 * @param EE_Registration $registration
312
	 * @param array $original_query_params any extra query params you'd like to be merged with
313
	 * @return array like EEM_Base::get_all()'s $query_params
314
	 */
315
	public function line_item_for_registration_query_params( EE_Registration $registration, $original_query_params = array() ) {
316
		return array_replace_recursive( $original_query_params, array(
317
			array(
318
				'OBJ_ID' => $registration->ticket_ID(),
319
				'OBJ_type' => 'Ticket',
320
				'TXN_ID' => $registration->transaction_ID()
321
			)
322
		) );
323
	}
324
325
326
327
}