Completed
Branch BUG-9623-config-log (c144cd)
by
unknown
1199:50 queued 1181:31
created

EEM_Message   C

Complexity

Total Complexity 32

Size/Duplication

Total Lines 409
Duplicated Lines 3.91 %

Coupling/Cohesion

Components 1
Dependencies 21

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 16
loc 409
rs 5.8666
wmc 32
lcom 1
cbo 21

13 Methods

Rating   Name   Duplication   Size   Complexity  
A stati_indicating_failed_sending() 0 11 2
A __construct() 0 47 1
A create_default_object() 0 8 2
A instantiate_class_from_array_or_object() 0 8 2
A message_sent_for_attendee() 8 8 1
A message_sent_for_registration() 8 8 1
A get_one_by_token() 0 5 1
A stati_indicating_sent() 0 3 1
A stati_indicating_to_send() 0 3 1
A all_statuses() 0 14 1
B filter_by_query_params() 0 28 5
C get_pretty_label_for_results() 0 64 13
A _expected_vars_for_query_inject() 0 9 1

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
/**
3
 * Message Model
4
 *
5
 * @package			Event Espresso
6
 * @subpackage		models
7
 * @author			Darren Ethier
8
 */
9
class EEM_Message extends EEM_Base implements EEI_Query_Filter {
10
11
	// private instance of the Message object
12
	protected static $_instance = null;
13
14
15
	/**
16
	 * This priority indicates a message should be generated and sent ASAP
17
	 * @type int
18
	 */
19
	const priority_high = 10;
20
21
22
23
24
	/**
25
	 * This priority indicates a message should be generated ASAP and queued for sending.
26
	 * @type
27
	 */
28
	const priority_medium = 20;
29
30
31
32
33
	/**
34
	 * This priority indicates a message should be queued for generating.
35
	 * @type int
36
	 */
37
	const priority_low = 30;
38
39
40
41
	/**
42
	 * indicates this message was sent at the time modified
43
	 */
44
	const status_sent = 'MSN';
45
46
47
	/**
48
	 * indicates this message is waiting to be sent
49
	 */
50
	const status_idle = 'MID';
51
52
53
	/**
54
	 * indicates an attempt was a made to send this message
55
	 * at the scheduled time, but it failed at the time modified.  This differs from MDO status in that it will ALWAYs
56
	 * appear to the end user.
57
	 */
58
	const status_failed = 'MFL';
59
60
61
	/**
62
	 * indicates the message has been flagged for resending (at the time modified).
63
	 */
64
	const status_resend = 'MRS';
65
66
67
	/**
68
	 * indicates the message has been flagged for generation but has not been generated yet.  Messages always start as this
69
	 * status when added to the queue.
70
	 */
71
	const status_incomplete = 'MIC';
72
73
74
75
76
	/**
77
	 * Indicates everything was generated fine for the message, however, the messenger was unable to send.
78
	 * This status means that its possible to retry sending the message.
79
	 */
80
	const status_retry = 'MRT';
81
82
83
84
	/**
85
	 * This is for failed messages that are only displayed when `WP_DEBUG` is true.  Usually this is used for more informational
86
	 * messages that may not indicate anything is broken.
87
	 */
88
	const status_debug_only = 'MDO';
89
90
91
92
93
94
	/**
95
	 *	Private constructor to prevent direct creation.
96
	 *
97
	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and
98
	 *                         any incoming timezone data that gets saved).  Note this just sends the timezone info to the
99
	 *                         date time model field objects.  Default is null (and will be assumed using the set timezone
100
	 *                         in the 'timezone_string' wp option)
101
	 *
102
	 * @return EEM_Message
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...
103
	 */
104
	protected function __construct( $timezone = null ) {
105
		$this->singular_item = __('Message','event_espresso');
106
		$this->plural_item = __('Messages','event_espresso');
107
108
		//used for token generator
109
		EE_Registry::instance()->load_helper( 'URL' );
110
111
		$this->_tables = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Message' => new \...sp_message', 'MSG_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...
112
			'Message'=>new EE_Primary_Table('esp_message','MSG_ID')
113
		);
114
115
		$allowed_priority = array(
116
			self::priority_high => __( 'high', 'event_espresso' ),
117
			self::priority_medium => __( 'medium', 'event_espresso' ),
118
			self::priority_low => __( 'low', 'event_espresso' )
119
		);
120
121
		$this->_fields = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Message' => array...esso'), true, time()))) 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...
122
			'Message'=>array(
123
				'MSG_ID'=>new EE_Primary_Key_Int_Field('MSG_ID', __('Message ID','event_espresso')),
124
				'MSG_token' => new EE_Plain_Text_Field( 'MSG_token', __('Unique Token used to represent this row in publicly viewable contexts (eg. a url).', 'event_espresso' ), false, EEH_URL::generate_unique_token() ),
125
				'GRP_ID'=>new EE_Foreign_Key_Int_Field( 'GRP_ID', __('Foreign key to the EEM_Message_Template_Group table.', 'event_espresso' ), true, 0, 'Message_Template_Group' ),
126
				'TXN_ID' => new EE_Foreign_Key_Int_Field( 'TXN_ID', __( 'Foreign key to the related EE_Transaction.  This is required to give context for regenerating the specific message', 'event_espresso' ), true, 0, 'Transaction' ),
127
				'MSG_messenger' => new EE_Plain_Text_Field('MSG_messenger', __( 'Corresponds to the EE_messenger::name used to send this message. This will also be used to attempt any resending of the message.', 'event_espresso' ), false, 'email' ),
128
				'MSG_message_type' => new EE_Plain_Text_Field( 'MSG_message_type', __( 'Corresponds to the EE_message_type::name used to generate this message.', 'event_espresso' ), false, 'receipt' ),
129
				'MSG_context' => new EE_Plain_Text_Field( 'MSG_context', __( 'Context', 'event_espresso' ), false ),
130
				'MSG_recipient_ID' => new EE_Foreign_Key_Int_Field( 'MSG_recipient_ID', __( 'Recipient ID', 'event_espresso' ), true, null, array( 'Registration', 'Attendee', 'WP_User' ) ),
0 ignored issues
show
Documentation introduced by
array('Registration', 'Attendee', 'WP_User') is of type array<integer,string,{"0..."string","2":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
131
				'MSG_recipient_type' => new EE_Any_Foreign_Model_Name_Field( 'MSG_recipient_type', __( 'Recipient Type', 'event_espresso' ), true, null, array( 'Registration', 'Attendee', 'WP_User' ) ),
0 ignored issues
show
Documentation introduced by
array('Registration', 'Attendee', 'WP_User') is of type array<integer,string,{"0..."string","2":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
132
				'MSG_content' => new EE_Maybe_Serialized_Text_Field( 'MSG_content', __( 'Content', 'event_espresso' ), true, '' ),
133
				'MSG_to' => new EE_Maybe_Serialized_Text_Field( 'MSG_to', __( 'Address To', 'event_espresso' ), true ),
134
				'MSG_from' => new EE_Maybe_Serialized_Text_Field( 'MSG_from', __( 'Address From', 'event_espresso' ), true ),
135
				'MSG_subject' => new EE_Maybe_Serialized_Text_Field( 'MSG_subject', __( 'Subject', 'event_espresso' ), true, '' ),
136
				'MSG_priority' => new EE_Enum_Integer_Field( 'MSG_priority', __( 'Priority', 'event_espresso' ), false, self::priority_low, $allowed_priority ),
137
				'STS_ID' => new EE_Foreign_Key_String_Field( 'STS_ID', __( 'Status', 'event_espresso' ), false, self::status_incomplete, 'Status' ),
138
				'MSG_created' => new EE_Datetime_Field( 'MSG_created', __( 'Created', 'event_espresso' ), false, time() ),
139
				'MSG_modified' => new EE_Datetime_Field( 'MSG_modified', __( 'Modified', 'event_espresso' ), true, time() )
140
			)
141
		);
142
		$this->_model_relations = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Attendee' => new ..._Belongs_To_Relation()) of type array<string,object<EE_B...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...
143
			'Attendee' => new EE_Belongs_To_Any_Relation(),
144
			'Registration' => new EE_Belongs_To_Any_Relation(),
145
			'WP_User' => new EE_Belongs_To_Any_Relation(),
146
			'Message_Template_Group' => new EE_Belongs_To_Relation(),
147
			'Transaction' => new EE_Belongs_To_Relation()
148
		);
149
		parent::__construct( $timezone );
0 ignored issues
show
Bug introduced by
It seems like $timezone defined by parameter $timezone on line 104 can also be of type string; however, EEM_Base::__construct() does only seem to accept null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
150
	}
151
152
153
154
	/**
155
	 * @return \EE_Message
156
	 */
157
	public function create_default_object() {
158
		/** @type EE_Message $message */
159
		$message = parent::create_default_object();
160
		if ( $message instanceof EE_Message ) {
161
			return EE_Message_Factory::set_messenger_and_message_type( $message );
162
		}
163
		return null;
164
	}
165
166
167
168
	/**
169
	 * @param mixed $cols_n_values
170
	 * @return \EE_Message
171
	 */
172
	public function instantiate_class_from_array_or_object( $cols_n_values ) {
173
		/** @type EE_Message $message */
174
		$message = parent::instantiate_class_from_array_or_object( $cols_n_values );
175
		if ( $message instanceof EE_Message ) {
176
			return EE_Message_Factory::set_messenger_and_message_type( $message );
177
		}
178
		return null;
179
	}
180
181
182
183
	/**
184
	 * Returns whether or not a message of that type was sent for a given attendee.
185
	 * @param EE_Attendee|int $attendee
186
	 * @param string $message_type the message type slug
187
	 * @return boolean
188
	 */
189 View Code Duplication
	public function message_sent_for_attendee( $attendee, $message_type ) {
0 ignored issues
show
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...
190
		$attendee_ID = EEM_Attendee::instance()->ensure_is_ID( $attendee );
191
		return $this->exists( array( array(
192
			'Attendee.ATT_ID' => $attendee_ID,
193
			'MSG_message_type' => $message_type,
194
			'STS_ID' => array( 'IN', $this->stati_indicating_sent() )
195
		) ) );
196
	}
197
198
199
200
201
	/**
202
	 * Returns whether or not a message of that type was sent for a given registration
203
	 * @param EE_Registration|int $registration
204
	 * @param string $message_type the message type slug
205
	 * @return boolean
206
	 */
207 View Code Duplication
	public function message_sent_for_registration( $registration, $message_type ) {
0 ignored issues
show
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...
208
		$registrationID = EEM_Registration::instance()->ensure_is_ID( $registration );
209
		return $this->exists( array( array(
210
			'Registration.REG_ID' => $registrationID,
211
			'MSG_message_type' => $message_type,
212
			'STS_ID' => array( 'IN', $this->stati_indicating_sent() )
213
		) ) );
214
	}
215
216
217
218
219
	/**
220
	 * This retrieves an EE_Message object from the db matching the given token string.
221
	 * @param string $token
222
	 * @return EE_Message
223
	 */
224
	public function get_one_by_token( $token ) {
225
		return $this->get_one( array( array(
226
			'MSG_token' => $token
227
		) ) );
228
	}
229
230
231
	/**
232
	 * Returns stati that indicate the message HAS been sent
233
	 * @return array of strings for possible stati
234
	 */
235
	public function stati_indicating_sent(){
236
		return apply_filters( 'FHEE__EEM_Message__stati_indicating_sent', array( self::status_sent ) );
237
	}
238
239
240
241
242
	/**
243
	 * Returns stati that indicate the message is waiting to be sent.
244
	 * @return array of strings for possible stati.
245
	 */
246
	public function stati_indicating_to_send() {
247
		return apply_filters( 'FHEE__EEM_Message__stati_indicating_to_send', array( self::status_idle, self::status_resend ) );
248
	}
249
250
251
	/**
252
	 * Returns stati that indicate the message has failed sending
253
	 * @return array  array of strings for possible stati.
254
	 */
255
	public function stati_indicating_failed_sending() {
256
		$failed_stati = array(
257
			self::status_failed,
258
			self::status_retry,
259
		);
260
		//if WP_DEBUG is set, then let's include debug_only fails
261
		if ( WP_DEBUG ) {
262
			$failed_stati[] = self::status_debug_only;
263
		}
264
		return apply_filters( 'FHEE__EEM_Message__stati_indicating_failed_sending', $failed_stati );
265
	}
266
267
268
269
270
	/**
271
	 * Returns filterable array of all EEM_Message statuses.
272
	 * @return array
273
	 */
274
	public function all_statuses() {
275
		return apply_filters(
276
			'FHEE__EEM_Message__all_statuses',
277
			array(
278
				EEM_Message::status_sent,
279
				EEM_Message::status_incomplete,
280
				EEM_Message::status_idle,
281
				EEM_Message::status_resend,
282
				EEM_Message::status_retry,
283
				EEM_Message::status_failed,
284
				EEM_Message::status_debug_only,
285
			)
286
		);
287
	}
288
289
	/**
290
	 * Detects any specific query variables in the request and uses those to setup appropriate
291
	 * filter for any queries.
292
	 * @return array
293
	 */
294
	public function filter_by_query_params() {
295
		// expected possible query_vars, the key in this array matches an expected key in the request,
296
		// the value, matches the corresponding EEM_Base child reference.
297
		$expected_vars = $this->_expected_vars_for_query_inject();
298
		$query_params[0] = array();
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...
299
		foreach ( $expected_vars as $request_key => $model_name ) {
300
			$request_value = EE_Registry::instance()->REQ->get( $request_key );
301
			if ( $request_value ) {
302
				//special case
303
				switch ( $request_key ) {
304
					case '_REG_ID' :
305
						$query_params[0]['AND**filter_by']['OR**filter_by_REG_ID'] = array(
306
							'Transaction.Registration.REG_ID' => $request_value,
307
						);
308
						break;
309
					case 'EVT_ID' :
310
						$query_params[0]['AND**filter_by']['OR**filter_by_EVT_ID'] = array(
311
							'Transaction.Registration.EVT_ID' => $request_value,
312
						);
313
						break;
314
					default :
315
						$query_params[0]['AND**filter_by'][ 'OR**filter_by_' . $request_key ][ $model_name . '.' . $request_key ] = $request_value;
316
						break;
317
				}
318
			}
319
		}
320
		return $query_params;
321
	}
322
323
324
325
326
327
	public function get_pretty_label_for_results() {
328
		$expected_vars = $this->_expected_vars_for_query_inject();
329
		$pretty_label = '';
330
		$label_parts = array();
331
		foreach ( $expected_vars as $request_key => $model_name ) {
332
			$model = EE_Registry::instance()->load_model( $model_name );
333
			if ( $model_field_value = EE_Registry::instance()->REQ->get( $request_key ) ) {
334
				switch ( $request_key ) {
335
					case '_REG_ID' :
336
						$label_parts[] = sprintf(
337
							esc_html__( 'Registration with the ID: %s', 'event_espresso' ),
338
							$model_field_value
339
						);
340
						break;
341
					case 'ATT_ID' :
342
						/** @var EE_Attendee $attendee */
343
						$attendee = $model->get_one_by_ID( $model_field_value );
344
						$label_parts[] = $attendee instanceof EE_Attendee
345
							? sprintf( esc_html__( 'Attendee %s', 'event_espresso' ), $attendee->full_name() )
346
							: sprintf( esc_html__( 'Attendee ID: %s', 'event_espresso' ), $model_field_value );
347
						break;
348
					case 'ID' :
349
						/** @var EE_WP_User $wpUser */
350
						$wpUser = $model->get_one_by_ID( $model_field_value );
351
						$label_parts[] = $wpUser instanceof EE_WP_User
352
							? sprintf( esc_html__( 'WP User: %s', 'event_espresso' ), $wpUser->name() )
353
							: sprintf( esc_html__( 'WP User ID: %s', 'event_espresso' ), $model_field_value );
354
						break;
355
					case 'TXN_ID' :
356
						$label_parts[] = sprintf(
357
							esc_html__( 'Transaction with the ID: %s', 'event_espresso' ),
358
							$model_field_value
359
						);
360
						break;
361
					case 'EVT_ID' :
362
						/** @var EE_Event $Event */
363
						$Event = $model->get_one_by_ID( $model_field_value );
364
						$label_parts[] = $Event instanceof EE_Event
365
							? sprintf( esc_html__( 'for the Event: %s', 'event_espresso' ), $Event->name() )
366
							: sprintf( esc_html__( 'for the Event with ID: %s', 'event_espresso' ), $model_field_value );
367
						break;
368
				}
369
			}
370
		}
371
372
		if ( $label_parts ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $label_parts of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
373
374
			//prepend to the last element of $label_parts an "and".
375
			if ( count( $label_parts ) > 1 ) {
376
				$label_parts_index_to_prepend                 = count( $label_parts ) - 1;
377
				$label_parts[ $label_parts_index_to_prepend ] = 'and' . $label_parts[ $label_parts_index_to_prepend ];
378
			}
379
380
			$pretty_label .= sprintf(
381
				esc_html_x(
382
					'Showing messages for %s',
383
					'A label for the messages returned in a query that are filtered by items in the query. This could be Transaction, Event, Attendee, Registration, or WP_User.',
384
					'event_espresso'
385
				),
386
				implode( ', ', $label_parts )
387
			);
388
		}
389
		return $pretty_label;
390
	}
391
392
393
394
395
	/**
396
	 * This returns the array of expected variables for the EEI_Query_Filter methods being implemented
397
	 * The array is in the format:
398
	 *
399
	 * array(
400
	 *  {$field_name} => {$model_name}
401
	 * );
402
	 *
403
	 * @since 4.9.0
404
	 * @return array
405
	 */
406
	protected function _expected_vars_for_query_inject() {
407
		return array(
408
			'_REG_ID' => 'Registration',
409
			'ATT_ID' => 'Attendee',
410
			'ID' => 'WP_User',
411
			'TXN_ID' => 'Transaction',
412
			'EVT_ID' => 'Event',
413
		);
414
	}
415
416
417
}
418
// End of file EEM_Message.model.php
419
// Location: /includes/models/EEM_Message.model.php
420