Completed
Branch BUG-9871-email-validation (e62b1a)
by
unknown
350:41 queued 333:27
created

EEM_Event::instance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 5

Duplication

Lines 12
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 12
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
2
require_once( EE_MODELS . 'EEM_CPT_Base.model.php');
3
/**
4
 *
5
 * EEM_Event Model
6
 *
7
 * extends EEM_CPT_Base which extends EEM_Base
8
 *
9
 * @package			Event Espresso
10
 * @subpackage		includes/models/
11
 * @author				Michael Nelson, Brent Christensen
12
 *
13
 */
14
class EEM_Event  extends EEM_CPT_Base{
15
16
	/**
17
	 * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the event
18
	 */
19
	const sold_out = 'sold_out';
20
21
	/**
22
	 * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later date)
23
	 */
24
	const postponed = 'postponed';
25
26
	/**
27
	 * constant used by status(), indicating that the event will no longer occur
28
	 */
29
	const cancelled = 'cancelled';
30
31
32
33
	/**
34
	 * @var string
35
	 */
36
	protected static $_default_reg_status = NULL;
37
38
39
	/**
40
	 * private instance of the Event object
41
	 * @var EEM_Event
42
	 */
43
	protected static $_instance = NULL;
44
45
46
47
	/**
48
	 *        This function is a singleton method used to instantiate the EEM_Event object
49
	 *
50
	 * @access public
51
	 * @param string $timezone
52
	 * @return EEM_Event
53
	 */
54 View Code Duplication
	public static function instance( $timezone = NULL ){
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...
55
56
		// check if instance of EEM_Event already exists
57
		if ( ! self::$_instance instanceof EEM_Event ) {
58
			// instantiate Espresso_model
59
			self::$_instance = new self( $timezone );
60
		}
61
		//we might have a timezone set, let set_timezone decide what to do with it
62
		self::$_instance->set_timezone( $timezone );
63
		// EEM_Event object
64
		return self::$_instance;
65
	}
66
67
68
	/**
69
	 * Adds a relationship to Term_Taxonomy for each CPT_Base
70
	 * @param string $timezone
71
	 * @return EEM_Event
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...
72
	 */
73
	protected function __construct($timezone = null){
74
75
		EE_Registry::instance()->load_model( 'Registration' );
76
77
		$this->singular_item = __('Event','event_espresso');
78
		$this->plural_item = __('Events','event_espresso');
79
80
		// to remove Cancelled events from the frontend, copy the following filter to your functions.php file
81
		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
82
		// to remove Postponed events from the frontend, copy the following filter to your functions.php file
83
		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
84
		// to remove Sold Out events from the frontend, copy the following filter to your functions.php file
85
		//	add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
86
87
		$this->_custom_stati = apply_filters(
88
			'AFEE__EEM_Event__construct___custom_stati',
89
			array(
90
				EEM_Event::cancelled => array(
91
					'label' => __('Cancelled', 'event_espresso'),
92
					'public' => apply_filters( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', TRUE )
93
				),
94
				EEM_Event::postponed => array(
95
					'label' => __('Postponed', 'event_espresso'),
96
					'public' => apply_filters( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', TRUE )
97
				),
98
				EEM_Event::sold_out => array(
99
					'label' => __('Sold Out', 'event_espresso'),
100
					'public' => apply_filters( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', TRUE )
101
				)
102
			)
103
		);
104
105
		self::$_default_reg_status = empty( self::$_default_reg_status ) ? EEM_Registration::status_id_pending_payment : self::$_default_reg_status;
106
107
		$this->_tables = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Event_CPT' => new..., 'EVTM_ID', 'EVT_ID')) of type array<string,object<EE_P...<EE_Secondary_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...
108
			'Event_CPT'=>new EE_Primary_Table( 'posts','ID' ),
109
			'Event_Meta'=> new EE_Secondary_Table( 'esp_event_meta', 'EVTM_ID', 'EVT_ID' )
110
		);
111
112
		$this->_fields = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('Event_CPT' => arr...esso'), FALSE, FALSE))) of type array<string,array<strin...E_Boolean_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...
113
			'Event_CPT'=>array(
114
				'EVT_ID'=>new EE_Primary_Key_Int_Field( 'ID', __( 'Post ID for Event','event_espresso' )),
115
				'EVT_name'=>new EE_Plain_Text_Field( 'post_title', __( 'Event Name','event_espresso' ), FALSE, '' ),
116
				'EVT_desc'=>new EE_Post_Content_Field( 'post_content', __( 'Event Description', 'event_espresso' ), FALSE, '' ),
117
				'EVT_slug'=>new EE_Slug_Field( 'post_name', __( 'Event Slug', 'event_espresso' ), FALSE, '' ),
118
				'EVT_created'=>new EE_Datetime_Field( 'post_date', __( 'Date/Time Event Created', 'event_espresso' ), FALSE, time()),
119
				'EVT_short_desc'=>new EE_Simple_HTML_Field( 'post_excerpt', __( 'Event Short Description', 'event_espresso' ), FALSE,'' ),
120
				'EVT_modified'=>new EE_Datetime_Field( 'post_modified', __( 'Date/Time Event Modified', 'event_espresso' ), FALSE, time()),
121
				'EVT_wp_user'=>new EE_WP_User_Field( 'post_author', __( 'Event Creator ID', 'event_espresso'), FALSE),
122
				'parent'=>new EE_Integer_Field( 'post_parent', __( 'Event Parent ID', 'event_espresso' ), FALSE, 0 ),
123
				'EVT_order'=>new EE_Integer_Field( 'menu_order', __( 'Event Menu Order', 'event_espresso' ), FALSE, 1 ),
124
				'post_type'=>new EE_WP_Post_Type_Field('espresso_events'),// EE_Plain_Text_Field( 'post_type', __( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
125
				'status' => new EE_WP_Post_Status_Field( 'post_status', __( 'Event Status', 'event_espresso' ), FALSE, 'draft', $this->_custom_stati )
126
			),
127
			'Event_Meta'=>array(
128
				'EVTM_ID'=> new EE_DB_Only_Float_Field( 'EVTM_ID', __( 'Event Meta Row ID','event_espresso' ), FALSE ),
129
				'EVT_ID_fk'=>new EE_DB_Only_Int_Field( 'EVT_ID', __( 'Foreign key to Event ID from Event Meta table', 'event_espresso' ), FALSE ),
130
				'EVT_display_desc'=>new EE_Boolean_Field( 'EVT_display_desc', __( 'Display Description Flag', 'event_espresso' ), FALSE, 1 ),
131
				'EVT_display_ticket_selector'=>new EE_Boolean_Field( 'EVT_display_ticket_selector', __( 'Display Ticket Selector Flag', 'event_espresso' ), FALSE, 1 ),
132
				'EVT_visible_on'=>new EE_Datetime_Field( 'EVT_visible_on', __( 'Event Visible Date', 'event_espresso' ), TRUE, time()),
133
				'EVT_additional_limit'=>new EE_Integer_Field( 'EVT_additional_limit', __( 'Limit of Additional Registrations on Same Transaction', 'event_espresso' ), TRUE, 10 ),
134
				'EVT_default_registration_status'=>new EE_Enum_Text_Field(
135
					'EVT_default_registration_status', __( 'Default Registration Status on this Event', 'event_espresso' ), FALSE, EEM_Event::$_default_reg_status, EEM_Registration::reg_status_array()
136
				),
137
				'EVT_member_only'=>new EE_Boolean_Field( 'EVT_member_only', __( 'Member-Only Event Flag', 'event_espresso' ), FALSE, FALSE ),
138
				'EVT_phone'=> new EE_Plain_Text_Field('EVT_phone', __( 'Event Phone Number', 'event_espresso' ), FALSE ),
139
				'EVT_allow_overflow'=>new EE_Boolean_Field(  'EVT_allow_overflow', __( 'Allow Overflow on Event', 'event_espresso' ), FALSE, FALSE ),
140
				'EVT_timezone_string'=>new EE_Plain_Text_Field( 'EVT_timezone_string', __( 'Timezone (name) for Event times', 'event_espresso' ), FALSE ),
141
				'EVT_external_URL'=>new EE_Plain_Text_Field( 'EVT_external_URL', __( 'URL of Event Page if hosted elsewhere', 'event_espresso' ), TRUE ),
142
				'EVT_donations'=>new EE_Boolean_Field( 'EVT_donations', __( 'Accept Donations?', 'event_espresso' ), FALSE, FALSE )
143
144
			));
145
146
		$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...
147
			'Registration'=>new EE_Has_Many_Relation(),
148
			'Datetime'=>new EE_Has_Many_Relation(),
149
			'Question_Group'=>new EE_HABTM_Relation('Event_Question_Group'),
0 ignored issues
show
Documentation introduced by
'Event_Question_Group' is of type string, but the function expects a boolean.

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...
150
			'Venue'=>new EE_HABTM_Relation('Event_Venue'),
0 ignored issues
show
Documentation introduced by
'Event_Venue' is of type string, but the function expects a boolean.

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...
151
			'Term_Taxonomy'=>new EE_HABTM_Relation('Term_Relationship'),
0 ignored issues
show
Documentation introduced by
'Term_Relationship' is of type string, but the function expects a boolean.

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...
152
			'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
0 ignored issues
show
Documentation introduced by
'Event_Message_Template' is of type string, but the function expects a boolean.

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...
153
			'Attendee'=>new EE_HABTM_Relation('Registration'),
0 ignored issues
show
Documentation introduced by
'Registration' is of type string, but the function expects a boolean.

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...
154
			'WP_User' => new EE_Belongs_To_Relation(),
155
		);
156
		//this model is generally available for reading
157
		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
158
		parent::__construct( $timezone );
159
	}
160
161
162
163
	/**
164
	 * @param string $default_reg_status
165
	 */
166
	public static function set_default_reg_status( $default_reg_status ) {
167
		self::$_default_reg_status = $default_reg_status;
168
		//if EEM_Event has already been instantiated, then we need to reset the `EVT_default_reg_status` field to use the new default.
169
		if ( self::$_instance instanceof EEM_Event ) {
170
			self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = new EE_Enum_Text_Field(
171
				'EVT_default_registration_status', __( 'Default Registration Status on this Event', 'event_espresso' ), false, $default_reg_status, EEM_Registration::reg_status_array()
172
			);
173
			self::$_instance->_fields['Event_Meta']['EVT_default_registration_status']->_construct_finalize( 'Event_Meta', 'EVT_default_registration_status', 'EEM_Event' );
174
		}
175
	}
176
177
178
179
	/**
180
	*		get_question_groups
181
	*
182
	* 		@access		public
183
	*		@return 		array
184
	*/
185
	public function get_all_question_groups() {
186
		return EE_Registry::instance()->load_model( 'Question_Group' )->get_all( array(
187
			array( 'QSG_deleted' => FALSE ),
188
			'order_by' => array( 'QSG_order' => 'ASC' )
189
		));
190
	}
191
192
193
194
195
196
197
	/**
198
	*		get_question_groups
199
	*
200
	* 		@access		public
201
	* 		@param		int $EVT_ID
202
	*		@return 		array
203
	*/
204 View Code Duplication
	public function get_all_event_question_groups( $EVT_ID = 0 ) {
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...
205
		if ( ! isset( $EVT_ID) || ! absint( $EVT_ID )) {
206
			EE_Error::add_error( __( 'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
207
			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_Event::get_all_event_question_groups of type array.

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...
208
		}
209
		return EE_Registry::instance()->load_model( 'Event_Question_Group' )->get_all( array(
210
			array( 'EVT_ID' => $EVT_ID )
211
		));
212
	}
213
214
215
216
217
218
	/**
219
	*		get_question_groups
220
	*
221
	* 		@access		public
222
	* 		@param		int $EVT_ID
223
	* 		@param		boolean	$for_primary_attendee
224
	*		@return 		array
225
	*/
226 View Code Duplication
	public function get_event_question_groups( $EVT_ID = 0, $for_primary_attendee = TRUE ) {
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...
227
		if ( ! isset( $EVT_ID) || ! absint( $EVT_ID )) {
228
			EE_Error::add_error( __( 'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
229
			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_Event::get_event_question_groups of type array.

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...
230
		}
231
		return EE_Registry::instance()->load_model( 'Event_Question_Group' )->get_all( array(
232
			array( 'EVT_ID' => $EVT_ID, 'EQG_primary' => $for_primary_attendee )
233
		));
234
	}
235
236
237
238
239
240
241
	/**
242
	*		get_question_groups
243
	*
244
	* 		@access		public
245
	* 		@param		int $EVT_ID
246
	* 		@param		EE_Registration 	$registration
247
	*		@return 		array
248
	*/
249
	public function get_question_groups_for_event( $EVT_ID = 0, EE_Registration $registration ) {
250
251
		if ( ! isset( $EVT_ID) || ! absint( $EVT_ID )) {
252
			EE_Error::add_error( __( 'An error occurred. No Question Groups could be retrieved because an Event ID was not received.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
253
			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_Event::get_question_groups_for_event of type array.

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...
254
		}
255
256
		$where_params = array(
257
			'Event_Question_Group.EVT_ID' => $EVT_ID,
258
			'Event_Question_Group.EQG_primary' => $registration->count() == 1 ? TRUE : FALSE,
259
			'QSG_deleted' => FALSE
260
		);
261
262
		return EE_Registry::instance()->load_model( 'Question_Group' )->get_all( array(
263
			$where_params,
264
			'order_by' => array('QSG_order' => 'ASC')
265
		));
266
267
	}
268
269
270
271
272
273
274
275
	/**
276
	*		get_question_target_db_column
277
	*
278
	* 		@access		public
279
	* 		@param		string		$QSG_IDs  csv list of $QSG IDs
280
	*		@return 		array
281
	*/
282 View Code Duplication
	public function get_questions_in_groups( $QSG_IDs = '' ) {
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...
283
284
		if ( empty( $QSG_IDs )) {
285
			EE_Error::add_error( __( 'An error occurred. No Question Group IDs were received.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
286
			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_Event::get_questions_in_groups of type array.

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...
287
		}
288
289
		return EE_Registry::instance()->load_model( 'Question' )->get_all( array(
290
			array(
291
				'Question_Group.QSG_ID' => array( 'IN', $QSG_IDs ),
292
				'QST_deleted' => FALSE,
293
				'QST_admin_only' => is_admin()
294
			),
295
			'order_by' => 'QST_order'
296
		));
297
298
	}
299
300
301
302
303
304
305
306
	/**
307
	*		get_options_for_question
308
	*
309
	* 		@access		public
310
	* 		@param		string		$QST_IDs  csv list of $QST IDs
311
	*		@return 		array
312
	*/
313 View Code Duplication
	public function get_options_for_question( $QST_IDs ) {
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...
314
315
		if ( empty( $QST_IDs )) {
316
			EE_Error::add_error( __( 'An error occurred. No Question IDs were received.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
317
			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_Event::get_options_for_question of type array.

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...
318
		}
319
320
		return EE_Registry::instance()->load_model( 'Question_Option' )->get_all( array(
321
			array(
322
				'Question.QST_ID' => array( 'IN', $QST_IDs ),
323
				'QSO_deleted' => FALSE
324
			),
325
			'order_by' => 'QSO_ID'
326
		));
327
328
	}
329
330
331
332
	/**
333
	 *        _get_question_target_db_column
334
	 *	@deprecated as of 4.8.32.rc.001. Instead consider using
335
	 * EE_Registration_Custom_Questions_Form located in admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
336
	 * @access 	public
337
	 * @param 	EE_Registration $registration (so existing answers for registration are included)
338
	 * @param 	int 	$EVT_ID 	so all question groups are included for event (not just answers from registration).
339
	 * @throws EE_Error
340
	 * @return 	array
341
	 */
342
	public function assemble_array_of_groups_questions_and_options( EE_Registration $registration, $EVT_ID = 0 ) {
343
344
		if ( empty( $EVT_ID ) ) {
345
			throw new EE_Error( __( 'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.', 'event_espresso' ) );
346
		}
347
348
		$questions = array();
349
350
		// get all question groups for event
351
		$qgs = $this->get_question_groups_for_event( $EVT_ID, $registration );
352
		if ( !empty( $qgs ) ) {
353
			foreach ( $qgs as $qg ) {
354
			 	$qsts = $qg->questions();
355
			 	$questions[ $qg->ID() ] = $qg->model_field_array();
356
			 	$questions[ $qg->ID() ]['QSG_questions'] = array();
357
			 	foreach ( $qsts as $qst ) {
358
			 		if ( $qst->is_system_question() )
359
			 			continue;
360
			 		$answer = EEM_Answer::instance()->get_one( array( array( 'QST_ID' => $qst->ID(), 'REG_ID' => $registration->ID() ) ) );
361
			 		$answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
362
			 		$qst_name = $qstn_id = $qst->ID();
363
			 		$ans_id = $answer->ID();
364
			 		$qst_name = !empty( $ans_id ) ?  '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
365
			 		$input_name = '';
366
			 		$input_id = sanitize_key( $qst->display_text() );
367
			 		$input_class = '';
368
			 		$questions[$qg->ID()]['QSG_questions'][$qst->ID()] = $qst->model_field_array();
369
		 			$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn' . $input_name . $qst_name;
370
					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
371
					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
372
					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
373
					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
374
					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
375
					//leave responses as-is, don't convert stuff into html entities please!
376
					$questions[ $qg->ID() ][ 'QSG_questions'][ $qst->ID() ][ 'htmlentities' ] = false;
377
					if ( $qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN' ) {
378
						$QSOs = $qst->options(TRUE,$answer->value());
0 ignored issues
show
Documentation Bug introduced by
The method value does not exist on object<EE_Base_Class>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
379
						if ( is_array( $QSOs ) ) {
380
							foreach ( $QSOs as $QSO_ID => $QSO ) {
381
								$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
382
							}
383
						}
384
					}
385
386
			 	}
387
			}
388
		}
389
		return $questions;
390
	}
391
392
393
394
395
396
397
398
	/**
399
	*		_get_question_target_db_column
400
	*
401
	* 		@access		private
402
	* 		@param		$QST
403
	*		@return 		string		string
404
	*/
405
	private function _generate_question_input_name( $QST ) {
406
407
		if ( $QST->QST_system ) {
408
			$qst_name = $QST->QST_system;
409
/*			switch( $QST->QST_system ) {
410
411
				case 1 :
412
						$qst_name = $QST->QST_ID . '-fname';
413
					break;
414
415
				case 2 :
416
						$qst_name = $QST->QST_ID . '-lname';
417
					break;
418
419
				case 3 :
420
						$qst_name = $QST->QST_ID . '-email';
421
					break;
422
423
				case 4 :
424
						$qst_name = $QST->QST_ID . '-address';
425
					break;
426
427
				case 5 :
428
						$qst_name = $QST->QST_ID . '-address2';
429
					break;
430
431
				case  6  :
432
						$qst_name = $QST->QST_ID . '-city';
433
					break;
434
435
				case 7 :
436
						$qst_name = $QST->QST_ID . '-state';
437
					break;
438
439
				case 8 :
440
						$qst_name = $QST->QST_ID . '-zip';
441
					break;
442
443
				case 9 :
444
						$qst_name = $QST->QST_ID . '-country';
445
					break;
446
447
				case 10 :
448
						$qst_name = $QST->QST_ID . '-phone-' . $QST->QST_ID;
449
					break;
450
451
			}*/
452
453
		} else {
454
			//$qst_name = $QST->QST_ID . '-' . str_replace( array( ' ', '-', '.' ), '_', strtolower( $QST->QST_display_text ));
455
			$qst_name = $QST->QST_ID;
456
		}
457
		return $qst_name;
458
	}
459
460
461
462
463
464
465
466
	/**
467
	 * Gets all events that are published and have event start time earlier than now and an event end time later than now
468
	 *
469
	 * @access public
470
	 * @param  array  $query_params An array of query params to further filter on (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
471
	 * @param bool    $count whether to return the count or not (default FALSE)
472
	 * @return array 	EE_Event objects
473
	 */
474
	public function get_active_events( $query_params, $count = FALSE ) {
475 View Code Duplication
		if ( array_key_exists( 0, $query_params ) ) {
476
			$where_params = $query_params[0];
477
			unset( $query_params[0] );
478
		} else {
479
			$where_params = array();
480
		}
481
482
		//if we have count make sure we don't include group by
483
		if ( $count && isset( $query_params['group_by'] ) ) {
484
			unset( $query_params['group_by'] );
485
		}
486
487
		//let's add specific query_params for active_events - keep in mind this will override any sent status in the query AND any date queries.
488
		$where_params['status'] = 'publish';
489
		//if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
490 View Code Duplication
		if ( isset( $where_params['Datetime.DTT_EVT_start'] ) ) {
491
			$where_params['Datetime.DTT_EVT_start******'] = array('<',  EEM_Datetime::instance()->current_time_for_query( 'DTT_EVT_start' ) );
492
		} else {
493
			$where_params['Datetime.DTT_EVT_start'] = array('<',  EEM_Datetime::instance()->current_time_for_query( 'DTT_EVT_start' ) );
494
		}
495
496 View Code Duplication
		if ( isset( $where_params['Datetime.DTT_EVT_end'] ) ) {
497
			$where_params['Datetime.DTT_EVT_end*****'] = array('>', EEM_Datetime::instance()->current_time_for_query( 'DTT_EVT_end' ) );
498
		} else {
499
			$where_params['Datetime.DTT_EVT_end'] = array('>', EEM_Datetime::instance()->current_time_for_query( 'DTT_EVT_end' ) );
500
		}
501
		$query_params[0] = $where_params;
502
		// don't use $query_params with count() because we don't want to include additional query clauses like "GROUP BY"
503
		return $count ? $this->count( array( $where_params ), 'EVT_ID', true ) : $this->get_all( $query_params );
504
	}
505
506
507
508
509
510
	/**
511
	 * get all events that are published and have an event start time later than now
512
	 *
513
	 * @access public
514
	 * @param  array 	$query_params An array of query params to further filter on (Note that status and DTT_EVT_start will be overridden)
515
	 * @param bool    $count whether to return the count or not (default FALSE)
516
	 * @return array               EE_Event objects
517
	 */
518
	public function get_upcoming_events( $query_params, $count = FALSE ) {
519 View Code Duplication
		if ( array_key_exists( 0, $query_params ) ) {
520
			$where_params = $query_params[0];
521
			unset( $query_params[0] );
522
		} else {
523
			$where_params = array();
524
		}
525
526
		//if we have count make sure we don't include group by
527
		if ( $count && isset( $query_params['group_by'] ) ) {
528
			unset( $query_params['group_by'] );
529
		}
530
531
		//let's add specific query_params for active_events - keep in mind this will override any sent status in the query AND any date queries.
532
		$where_params['status'] = 'publish';
533
		//if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
534 View Code Duplication
		if ( isset( $where_params['Datetime.DTT_EVT_start'] ) ) {
535
			$where_params['Datetime.DTT_EVT_start*****'] = array('>', EEM_Datetime::instance()->current_time_for_query( 'DTT_EVT_start' ) );
536
		} else {
537
			$where_params['Datetime.DTT_EVT_start'] = array('>', EEM_Datetime::instance()->current_time_for_query( 'DTT_EVT_start' ) );
538
		}
539
		$query_params[0] = $where_params;
540
		// don't use $query_params with count() because we don't want to include additional query clauses like "GROUP BY"
541
		return $count ? $this->count( array( $where_params ), 'EVT_ID', true ) : $this->get_all( $query_params );
542
	}
543
544
545
	/**
546
	 * This only returns events that are expired.  They may still be published but all their datetimes have expired.
547
	 *
548
	 * @access public
549
	 * @param  array  $query_params An array of query params to further filter on (note that status and DTT_EVT_end will be overridden)
550
	 * @param bool    $count whether to return the count or not (default FALSE)
551
	 * @return array 	EE_Event objects
552
	 */
553
	public function get_expired_events( $query_params, $count = FALSE ) {
554
555
		$where_params = isset( $query_params[0] ) ? $query_params[0] : array();
556
557
		//if we have count make sure we don't include group by
558
		if ( $count && isset( $query_params['group_by'] ) ) {
559
			unset( $query_params['group_by'] );
560
		}
561
562
		//let's add specific query_params for active_events - keep in mind this will override any sent status in the query AND any date queries.
563
		if ( isset( $where_params['status'] ) ) {
564
			unset( $where_params['status'] );
565
		}
566
		$exclude_query = $query_params;
567
		if ( isset( $exclude_query[0] ) ) {
568
			unset( $exclude_query[0] );
569
		}
570
		$exclude_query[0] = array( 'Datetime.DTT_EVT_end' => array( '>', EEM_Datetime::instance()->current_time_for_query( 'DTT_EVT_end' ) ) );
571
		//first get all events that have datetimes where its not expired.
572
		$event_ids = $this->_get_all_wpdb_results( $exclude_query, OBJECT_K, 'Event_CPT.ID' );
573
		$event_ids = array_keys( $event_ids );
574
575
		//if we have any additional query_params, let's add them to the 'AND' condition
576
		$and_condition = array(
577
			'Datetime.DTT_EVT_end' => array( '<', EEM_Datetime::instance()->current_time_for_query( 'DTT_EVT_end' ) ),
578
			'EVT_ID' =>  array( 'NOT IN', $event_ids )
579
			);
580
581 View Code Duplication
		if ( isset( $where_params['OR'] ) ) {
582
			$and_condition['OR'] = $where_params['OR'];
583
			unset( $where_params['OR'] );
584
		}
585
586 View Code Duplication
		if ( isset( $where_params['Datetime.DTT_EVT_end'] ) ) {
587
			$and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
588
			unset( $where_params['Datetime.DTT_EVT_end'] );
589
		}
590
591 View Code Duplication
		if ( isset( $where_params['Datetime.DTT_EVT_start'] ) ) {
592
			$and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
593
			unset( $where_params['Datetime.DTT_EVT_start'] );
594
		}
595
596
		//merge remaining $where params with the and conditions.
597
		$where_params['AND'] = array_merge( $and_condition, $where_params );
598
		$query_params[0] = $where_params;
599
		// don't use $query_params with count() because we don't want to include additional query clauses like "GROUP BY"
600
		return $count ? $this->count( array( $where_params ), 'EVT_ID', true ) : $this->get_all( $query_params );
601
	}
602
603
604
605
	/**
606
	 * This basically just returns the events that do not have the publish status.
607
	 * @param  array  $query_params  An array of query params to further filter on (note that status will be overwritten)
608
	 * @param  boolean $count        whether to return the count or not (default FALSE)
609
	 * @return EE_Event[]            array of EE_Event objects
610
	 */
611
	public function get_inactive_events( $query_params, $count = FALSE ) {
612
		$where_params = isset( $query_params[0] ) ? $query_params[0] : array();
613
614
		//let's add in specific query_params for inactive events.
615
		if ( isset( $where_params['status'] ) ) {
616
			unset( $where_params['status'] );
617
		}
618
619
		//if we have count make sure we don't include group by
620
		if ( $count && isset( $query_params['group_by'] ) ) {
621
			unset( $query_params['group_by'] );
622
		}
623
624
		//if we have any additional query_params, let's add them to the 'AND' condition
625
		$where_params['AND']['status'] = array( '!=', 'publish' );
626
627 View Code Duplication
		if ( isset( $where_params['OR'] ) ) {
628
			$where_params['AND']['OR'] = $where_params['OR'];
629
			unset( $where_params['OR'] );
630
		}
631
632 View Code Duplication
		if ( isset( $where_params['Datetime.DTT_EVT_end'] ) ) {
633
			$where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
634
			unset( $where_params['Datetime.DTT_EVT_end'] );
635
		}
636
637 View Code Duplication
		if ( isset( $where_params['Datetime.DTT_EVT_start'] ) ) {
638
			$where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
639
			unset( $where_params['Datetime.DTT_EVT_start'] );
640
		}
641
642
		$query_params[0] = $where_params;
643
		// don't use $query_params with count() because we don't want to include additional query clauses like "GROUP BY"
644
		return $count ? $this->count( array( $where_params ), 'EVT_ID', true ) : $this->get_all( $query_params );
645
	}
646
647
648
	/**
649
	 * This is just injecting into the parent add_relationship_to so we do special handling on price relationships because we don't want to override any existing global default prices but instead insert NEW prices that get attached to the event.
650
	 * See parent for param descriptions
651
	 */
652
	public function add_relationship_to($id_or_obj,$other_model_id_or_obj, $relationName, $where_query = array()){
653
654
		if ( $relationName == 'Price' ) {
655
			//let's get the PRC object for the given ID to make sure that we aren't dealing with a default
656
			$prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
657
			//if EVT_ID = 0, then this is a default
658
			if ( $prc_chk->get('EVT_ID') == 0 ) {
659
				//let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
660
				$prc_chk->set('PRC_ID', 0);
661
			}
662
663
			//run parent
664
			return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
665
		}
666
667
		//otherwise carry on as normal
668
		return parent::add_relationship_to($id_or_obj,$other_model_id_or_obj, $relationName, $where_query);
669
	}
670
671
672
673
}
674
// End of file EEM_Event.model.php
675
// Location: /includes/models/EEM_Event.model.php
676