Completed
Branch FET/extract-doc-block-from-eem... (b14d68)
by
unknown
08:28 queued 21s
created
core/db_models/EEM_Change_Log.model.php 1 patch
Indentation   +227 added lines, -227 removed lines patch added patch discarded remove patch
@@ -11,93 +11,93 @@  discard block
 block discarded – undo
11 11
 class EEM_Change_Log extends EEM_Base
12 12
 {
13 13
 
14
-    /**
15
-     * the related object was created log type
16
-     */
17
-    const type_create = 'create';
18
-    /**
19
-     * the related object was updated (changed, or soft-deleted)
20
-     */
21
-    const type_update = 'update';
22
-    /**
23
-     * the related object was deleted permanently
24
-     */
25
-    const type_delete = 'delete';
26
-    /**
27
-     * the related item had something worth noting happen on it, but
28
-     * only for the purposes of debugging problems
29
-     */
30
-    const type_debug = 'debug';
31
-    /**
32
-     * the related item had an error occur on it
33
-     */
34
-    const type_error = 'error';
35
-    /**
36
-     * the related item is regarding some gateway interaction, like an IPN
37
-     * or request to process a payment
38
-     */
39
-    const type_gateway = 'gateway';
14
+	/**
15
+	 * the related object was created log type
16
+	 */
17
+	const type_create = 'create';
18
+	/**
19
+	 * the related object was updated (changed, or soft-deleted)
20
+	 */
21
+	const type_update = 'update';
22
+	/**
23
+	 * the related object was deleted permanently
24
+	 */
25
+	const type_delete = 'delete';
26
+	/**
27
+	 * the related item had something worth noting happen on it, but
28
+	 * only for the purposes of debugging problems
29
+	 */
30
+	const type_debug = 'debug';
31
+	/**
32
+	 * the related item had an error occur on it
33
+	 */
34
+	const type_error = 'error';
35
+	/**
36
+	 * the related item is regarding some gateway interaction, like an IPN
37
+	 * or request to process a payment
38
+	 */
39
+	const type_gateway = 'gateway';
40 40
 
41
-    /**
42
-     * private instance of the EEM_Change_Log object
43
-     *
44
-     * @access private
45
-     * @var EEM_Change_Log $_instance
46
-     */
47
-    protected static $_instance = null;
41
+	/**
42
+	 * private instance of the EEM_Change_Log object
43
+	 *
44
+	 * @access private
45
+	 * @var EEM_Change_Log $_instance
46
+	 */
47
+	protected static $_instance = null;
48 48
 
49 49
 
50
-    /**
51
-     * constructor
52
-     *
53
-     * @access protected
54
-     * @param null $timezone
55
-     * @throws EE_Error
56
-     */
57
-    protected function __construct($timezone = null)
58
-    {
59
-        global $current_user;
60
-        $this->singular_item       = esc_html__('Log', 'event_espresso');
61
-        $this->plural_item         = esc_html__('Logs', 'event_espresso');
62
-        $this->_tables             = array(
63
-            'Log' => new EE_Primary_Table('esp_log', 'LOG_ID'),
64
-        );
65
-        $models_this_can_attach_to = array_keys(EE_Registry::instance()->non_abstract_db_models);
66
-        $this->_fields             = array(
67
-            'Log' => array(
68
-                'LOG_ID'      => new EE_Primary_Key_Int_Field('LOG_ID', esc_html__('Log ID', 'event_espresso')),
69
-                'LOG_time'    => new EE_Datetime_Field(
70
-                    'LOG_time',
71
-                    esc_html__("Log Time", 'event_espresso'),
72
-                    false,
73
-                    EE_Datetime_Field::now
74
-                ),
75
-                'OBJ_ID'      => new EE_Foreign_Key_String_Field(
76
-                    'OBJ_ID',
77
-                    esc_html__("Object ID (int or string)", 'event_espresso'),
78
-                    true,
79
-                    null,
80
-                    $models_this_can_attach_to
81
-                ),
82
-                'OBJ_type'    => new EE_Any_Foreign_Model_Name_Field(
83
-                    'OBJ_type',
84
-                    esc_html__("Object Type", 'event_espresso'),
85
-                    true,
86
-                    null,
87
-                    $models_this_can_attach_to
88
-                ),
89
-                'LOG_type'    => new EE_Plain_Text_Field(
90
-                    'LOG_type',
91
-                    esc_html__("Type of log entry", "event_espresso"),
92
-                    false,
93
-                    self::type_debug
94
-                ),
95
-                'LOG_message' => new EE_Maybe_Serialized_Text_Field(
96
-                    'LOG_message',
97
-                    esc_html__("Log Message (body)", 'event_espresso'),
98
-                    true
99
-                ),
100
-                /*
50
+	/**
51
+	 * constructor
52
+	 *
53
+	 * @access protected
54
+	 * @param null $timezone
55
+	 * @throws EE_Error
56
+	 */
57
+	protected function __construct($timezone = null)
58
+	{
59
+		global $current_user;
60
+		$this->singular_item       = esc_html__('Log', 'event_espresso');
61
+		$this->plural_item         = esc_html__('Logs', 'event_espresso');
62
+		$this->_tables             = array(
63
+			'Log' => new EE_Primary_Table('esp_log', 'LOG_ID'),
64
+		);
65
+		$models_this_can_attach_to = array_keys(EE_Registry::instance()->non_abstract_db_models);
66
+		$this->_fields             = array(
67
+			'Log' => array(
68
+				'LOG_ID'      => new EE_Primary_Key_Int_Field('LOG_ID', esc_html__('Log ID', 'event_espresso')),
69
+				'LOG_time'    => new EE_Datetime_Field(
70
+					'LOG_time',
71
+					esc_html__("Log Time", 'event_espresso'),
72
+					false,
73
+					EE_Datetime_Field::now
74
+				),
75
+				'OBJ_ID'      => new EE_Foreign_Key_String_Field(
76
+					'OBJ_ID',
77
+					esc_html__("Object ID (int or string)", 'event_espresso'),
78
+					true,
79
+					null,
80
+					$models_this_can_attach_to
81
+				),
82
+				'OBJ_type'    => new EE_Any_Foreign_Model_Name_Field(
83
+					'OBJ_type',
84
+					esc_html__("Object Type", 'event_espresso'),
85
+					true,
86
+					null,
87
+					$models_this_can_attach_to
88
+				),
89
+				'LOG_type'    => new EE_Plain_Text_Field(
90
+					'LOG_type',
91
+					esc_html__("Type of log entry", "event_espresso"),
92
+					false,
93
+					self::type_debug
94
+				),
95
+				'LOG_message' => new EE_Maybe_Serialized_Text_Field(
96
+					'LOG_message',
97
+					esc_html__("Log Message (body)", 'event_espresso'),
98
+					true
99
+				),
100
+				/*
101 101
                  * Note: when querying for a change log's user, the OBJ_ID and OBJ_type fields are used,
102 102
                  * not the LOG_wp_user field. E.g.,
103 103
                  * `EEM_Change_Log::instance()->get_all(array(array('WP_User.ID'=>1)))` will actually return
@@ -106,158 +106,158 @@  discard block
 block discarded – undo
106 106
                  *  If you want the latter, you can't use the model's magic joining. E.g, you would need to do
107 107
                  * `EEM_Change_Log::instance()->get_all(array(array('LOG_wp_user' => 1)))`.
108 108
                  */
109
-                'LOG_wp_user' => new EE_WP_User_Field(
110
-                    'LOG_wp_user',
111
-                    esc_html__("User who was logged in while this occurred", 'event_espresso'),
112
-                    true
113
-                ),
114
-            ),
115
-        );
116
-        $this->_model_relations    = array();
117
-        foreach ($models_this_can_attach_to as $model) {
118
-            if ($model != 'Change_Log') {
119
-                $this->_model_relations[ $model ] = new EE_Belongs_To_Any_Relation();
120
-            }
121
-        }
122
-        // use completely custom caps for this
123
-        $this->_cap_restriction_generators = false;
124
-        // caps-wise this is all-or-nothing: if you have the default role you can access anything, otherwise nothing
125
-        foreach ($this->_cap_contexts_to_cap_action_map as $cap_context => $action) {
126
-            $this->_cap_restrictions[ $cap_context ][ EE_Restriction_Generator_Base::get_default_restrictions_cap() ]
127
-                = new EE_Return_None_Where_Conditions();
128
-        }
129
-        parent::__construct($timezone);
130
-    }
109
+				'LOG_wp_user' => new EE_WP_User_Field(
110
+					'LOG_wp_user',
111
+					esc_html__("User who was logged in while this occurred", 'event_espresso'),
112
+					true
113
+				),
114
+			),
115
+		);
116
+		$this->_model_relations    = array();
117
+		foreach ($models_this_can_attach_to as $model) {
118
+			if ($model != 'Change_Log') {
119
+				$this->_model_relations[ $model ] = new EE_Belongs_To_Any_Relation();
120
+			}
121
+		}
122
+		// use completely custom caps for this
123
+		$this->_cap_restriction_generators = false;
124
+		// caps-wise this is all-or-nothing: if you have the default role you can access anything, otherwise nothing
125
+		foreach ($this->_cap_contexts_to_cap_action_map as $cap_context => $action) {
126
+			$this->_cap_restrictions[ $cap_context ][ EE_Restriction_Generator_Base::get_default_restrictions_cap() ]
127
+				= new EE_Return_None_Where_Conditions();
128
+		}
129
+		parent::__construct($timezone);
130
+	}
131 131
 
132
-    /**
133
-     * @param string        $log_type !see the acceptable values of LOG_type in EEM__Change_Log::__construct
134
-     * @param mixed         $message  array|string of the message you want to record
135
-     * @param EE_Base_Class $related_model_obj
136
-     * @return EE_Change_Log
137
-     * @throws EE_Error
138
-     */
139
-    public function log($log_type, $message, $related_model_obj)
140
-    {
141
-        if ($related_model_obj instanceof EE_Base_Class) {
142
-            $obj_id   = $related_model_obj->ID();
143
-            $obj_type = $related_model_obj->get_model()->get_this_model_name();
144
-        } else {
145
-            $obj_id   = null;
146
-            $obj_type = null;
147
-        }
148
-        /** @var EE_Change_Log $log */
149
-        $log = EE_Change_Log::new_instance(array(
150
-            'LOG_type'    => $log_type,
151
-            'LOG_message' => $message,
152
-            'OBJ_ID'      => $obj_id,
153
-            'OBJ_type'    => $obj_type,
154
-        ));
155
-        $log->save();
156
-        return $log;
157
-    }
132
+	/**
133
+	 * @param string        $log_type !see the acceptable values of LOG_type in EEM__Change_Log::__construct
134
+	 * @param mixed         $message  array|string of the message you want to record
135
+	 * @param EE_Base_Class $related_model_obj
136
+	 * @return EE_Change_Log
137
+	 * @throws EE_Error
138
+	 */
139
+	public function log($log_type, $message, $related_model_obj)
140
+	{
141
+		if ($related_model_obj instanceof EE_Base_Class) {
142
+			$obj_id   = $related_model_obj->ID();
143
+			$obj_type = $related_model_obj->get_model()->get_this_model_name();
144
+		} else {
145
+			$obj_id   = null;
146
+			$obj_type = null;
147
+		}
148
+		/** @var EE_Change_Log $log */
149
+		$log = EE_Change_Log::new_instance(array(
150
+			'LOG_type'    => $log_type,
151
+			'LOG_message' => $message,
152
+			'OBJ_ID'      => $obj_id,
153
+			'OBJ_type'    => $obj_type,
154
+		));
155
+		$log->save();
156
+		return $log;
157
+	}
158 158
 
159 159
 
160
-    /**
161
-     * Adds a gateway log for the specified object, given its ID and type
162
-     *
163
-     * @param string $message
164
-     * @param mixed  $related_obj_id
165
-     * @param string $related_obj_type
166
-     * @throws EE_Error
167
-     * @return EE_Change_Log
168
-     */
169
-    public function gateway_log($message, $related_obj_id, $related_obj_type)
170
-    {
171
-        if (! EE_Registry::instance()->is_model_name($related_obj_type)) {
172
-            throw new EE_Error(
173
-                sprintf(
174
-                    esc_html__(
175
-                        "'%s' is not a model name. A model name must be provided when making a gateway log. Eg, 'Payment', 'Payment_Method', etc",
176
-                        "event_espresso"
177
-                    ),
178
-                    $related_obj_type
179
-                )
180
-            );
181
-        }
182
-        /** @var EE_Change_Log $log */
183
-        $log = EE_Change_Log::new_instance(array(
184
-            'LOG_type'    => EEM_Change_Log::type_gateway,
185
-            'LOG_message' => $message,
186
-            'OBJ_ID'      => $related_obj_id,
187
-            'OBJ_type'    => $related_obj_type,
188
-        ));
189
-        $log->save();
190
-        return $log;
191
-    }
160
+	/**
161
+	 * Adds a gateway log for the specified object, given its ID and type
162
+	 *
163
+	 * @param string $message
164
+	 * @param mixed  $related_obj_id
165
+	 * @param string $related_obj_type
166
+	 * @throws EE_Error
167
+	 * @return EE_Change_Log
168
+	 */
169
+	public function gateway_log($message, $related_obj_id, $related_obj_type)
170
+	{
171
+		if (! EE_Registry::instance()->is_model_name($related_obj_type)) {
172
+			throw new EE_Error(
173
+				sprintf(
174
+					esc_html__(
175
+						"'%s' is not a model name. A model name must be provided when making a gateway log. Eg, 'Payment', 'Payment_Method', etc",
176
+						"event_espresso"
177
+					),
178
+					$related_obj_type
179
+				)
180
+			);
181
+		}
182
+		/** @var EE_Change_Log $log */
183
+		$log = EE_Change_Log::new_instance(array(
184
+			'LOG_type'    => EEM_Change_Log::type_gateway,
185
+			'LOG_message' => $message,
186
+			'OBJ_ID'      => $related_obj_id,
187
+			'OBJ_type'    => $related_obj_type,
188
+		));
189
+		$log->save();
190
+		return $log;
191
+	}
192 192
 
193 193
 
194
-    /**
195
-     * Just gets the bare-bones wpdb results as an array in cases where efficiency is essential
196
-     *
197
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
198
-     * @return array of arrays
199
-     * @throws EE_Error
200
-     */
201
-    public function get_all_efficiently($query_params)
202
-    {
203
-        return $this->_get_all_wpdb_results($query_params);
204
-    }
194
+	/**
195
+	 * Just gets the bare-bones wpdb results as an array in cases where efficiency is essential
196
+	 *
197
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
198
+	 * @return array of arrays
199
+	 * @throws EE_Error
200
+	 */
201
+	public function get_all_efficiently($query_params)
202
+	{
203
+		return $this->_get_all_wpdb_results($query_params);
204
+	}
205 205
 
206 206
 
207
-    /**
208
-     * Executes a database query to delete gateway logs. Does not affect model objects, so if you attempt to use
209
-     * models after this, they may be out-of-sync with the database
210
-     *
211
-     * @param DateTime $datetime
212
-     * @return false|int
213
-     * @throws EE_Error
214
-     */
215
-    public function delete_gateway_logs_older_than(DateTime $datetime)
216
-    {
217
-        global $wpdb;
218
-        return $wpdb->query(
219
-            $wpdb->prepare(
220
-                'DELETE FROM ' . $this->table() . ' WHERE LOG_type = %s AND LOG_time < %s',
221
-                EEM_Change_Log::type_gateway,
222
-                $datetime->format(EE_Datetime_Field::mysql_timestamp_format)
223
-            )
224
-        );
225
-    }
207
+	/**
208
+	 * Executes a database query to delete gateway logs. Does not affect model objects, so if you attempt to use
209
+	 * models after this, they may be out-of-sync with the database
210
+	 *
211
+	 * @param DateTime $datetime
212
+	 * @return false|int
213
+	 * @throws EE_Error
214
+	 */
215
+	public function delete_gateway_logs_older_than(DateTime $datetime)
216
+	{
217
+		global $wpdb;
218
+		return $wpdb->query(
219
+			$wpdb->prepare(
220
+				'DELETE FROM ' . $this->table() . ' WHERE LOG_type = %s AND LOG_time < %s',
221
+				EEM_Change_Log::type_gateway,
222
+				$datetime->format(EE_Datetime_Field::mysql_timestamp_format)
223
+			)
224
+		);
225
+	}
226 226
 
227 227
 
228
-    /**
229
-     * Returns the map of type to pretty label for identifiers used for `LOG_type`.  Client code can register their own
230
-     * map vai the given filter.
231
-     *
232
-     * @return array
233
-     */
234
-    public static function get_pretty_label_map_for_registered_types()
235
-    {
236
-        return apply_filters(
237
-            'FHEE__EEM_Change_Log__get_pretty_label_map_for_registered_types',
238
-            array(
239
-                self::type_create=>  esc_html__("Create", "event_espresso"),
240
-                self::type_update=>  esc_html__("Update", "event_espresso"),
241
-                self::type_delete => esc_html__("Delete", "event_espresso"),
242
-                self::type_debug=>  esc_html__("Debug", "event_espresso"),
243
-                self::type_error=>  esc_html__("Error", "event_espresso"),
244
-                self::type_gateway=> esc_html__("Gateway Interaction (IPN or Direct Payment)", 'event_espresso')
245
-            )
246
-        );
247
-    }
228
+	/**
229
+	 * Returns the map of type to pretty label for identifiers used for `LOG_type`.  Client code can register their own
230
+	 * map vai the given filter.
231
+	 *
232
+	 * @return array
233
+	 */
234
+	public static function get_pretty_label_map_for_registered_types()
235
+	{
236
+		return apply_filters(
237
+			'FHEE__EEM_Change_Log__get_pretty_label_map_for_registered_types',
238
+			array(
239
+				self::type_create=>  esc_html__("Create", "event_espresso"),
240
+				self::type_update=>  esc_html__("Update", "event_espresso"),
241
+				self::type_delete => esc_html__("Delete", "event_espresso"),
242
+				self::type_debug=>  esc_html__("Debug", "event_espresso"),
243
+				self::type_error=>  esc_html__("Error", "event_espresso"),
244
+				self::type_gateway=> esc_html__("Gateway Interaction (IPN or Direct Payment)", 'event_espresso')
245
+			)
246
+		);
247
+	}
248 248
 
249 249
 
250
-    /**
251
-     * Return the pretty (localized) label for the given log type identifier.
252
-     * @param string $type_identifier
253
-     * @return string
254
-     */
255
-    public static function get_pretty_label_for_type($type_identifier)
256
-    {
257
-        $type_identifier_map = self::get_pretty_label_map_for_registered_types();
258
-        // we fallback to the incoming type identifier if there is no localized label for it.
259
-        return isset($type_identifier_map[ $type_identifier ])
260
-            ? $type_identifier_map[ $type_identifier ]
261
-            : $type_identifier;
262
-    }
250
+	/**
251
+	 * Return the pretty (localized) label for the given log type identifier.
252
+	 * @param string $type_identifier
253
+	 * @return string
254
+	 */
255
+	public static function get_pretty_label_for_type($type_identifier)
256
+	{
257
+		$type_identifier_map = self::get_pretty_label_map_for_registered_types();
258
+		// we fallback to the incoming type identifier if there is no localized label for it.
259
+		return isset($type_identifier_map[ $type_identifier ])
260
+			? $type_identifier_map[ $type_identifier ]
261
+			: $type_identifier;
262
+	}
263 263
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Term_Relationship.model.php 1 patch
Indentation   +223 added lines, -223 removed lines patch added patch discarded remove patch
@@ -9,233 +9,233 @@
 block discarded – undo
9 9
 class EEM_Term_Relationship extends EEM_Base
10 10
 {
11 11
 
12
-    // private instance of the Attendee object
13
-    protected static $_instance = null;
14
-
15
-
16
-
17
-    /**
18
-     * EEM_Term_Relationship constructor.
19
-     *
20
-     * @param string $timezone
21
-     */
22
-    protected function __construct($timezone = null)
23
-    {
24
-        $this->singular_item = __('Term Relationship', 'event_espresso');
25
-        $this->plural_item = __('Term Relationships', 'event_espresso');
26
-        $this->_tables = array(
27
-            'Term_Relationship' => new EE_Primary_Table('term_relationships'),
28
-        );
29
-        $models_this_can_attach_to = array_keys(EE_Registry::instance()->cpt_models());
30
-        $this->_fields = array(
31
-            'Term_Relationship' => array(
32
-                'object_id'        => new EE_Foreign_Key_Int_Field(
33
-                    'object_id',
34
-                    __('Object(Post) ID', 'event_espresso'),
35
-                    false,
36
-                    0,
37
-                    $models_this_can_attach_to
38
-                ),
39
-                'term_taxonomy_id' => new EE_Foreign_Key_Int_Field(
40
-                    'term_taxonomy_id',
41
-                    __(
42
-                        'Term (in context of a taxonomy) ID',
43
-                        'event_espresso'
44
-                    ),
45
-                    false,
46
-                    0,
47
-                    'Term_Taxonomy'
48
-                ),
49
-                'term_order'       => new EE_Integer_Field(
50
-                    'term_order',
51
-                    __('Term Order', 'event_espresso'),
52
-                    false,
53
-                    0
54
-                ),
55
-            ),
56
-        );
57
-        $this->_model_relations = array(
58
-            'Term_Taxonomy' => new EE_Belongs_To_Relation(),
59
-        );
60
-        foreach ($models_this_can_attach_to as $model_name) {
61
-            $this->_model_relations[ $model_name ] = new EE_Belongs_To_Relation();
62
-        }
63
-        $this->_wp_core_model = true;
64
-        $this->_indexes = array(
65
-            'PRIMARY' => new EE_Primary_Key_Index(array('object_id', 'term_taxonomy_id')),
66
-        );
67
-        $path_to_event_model = 'Event.';
68
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public(
69
-            $path_to_event_model
70
-        );
71
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
72
-            new EE_Restriction_Generator_Event_Related_Protected(
73
-                $path_to_event_model
74
-            );
75
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ] = new EE_Restriction_Generator_Event_Related_Protected(
76
-            $path_to_event_model
77
-        );
78
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ] =
79
-            new EE_Restriction_Generator_Event_Related_Protected(
80
-                $path_to_event_model,
81
-                EEM_Base::caps_edit
82
-            );
83
-        $path_to_tax_model = 'Term_Taxonomy.';
84
-        // add cap restrictions for editing term relations to the "ee_assign_*"
85
-        // and for deleting term relations too
86
-        $cap_contexts_affected = array(EEM_Base::caps_edit, EEM_Base::caps_delete);
87
-        foreach ($cap_contexts_affected as $cap_context_affected) {
88
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_category'] =
89
-                new EE_Default_Where_Conditions(
90
-                    array(
91
-                        $path_to_tax_model . 'taxonomy*ee_assign_event_category' => array(
92
-                            '!=',
93
-                            'espresso_event_categories',
94
-                        ),
95
-                    )
96
-                );
97
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_venue_category'] =
98
-                new EE_Default_Where_Conditions(
99
-                    array(
100
-                        $path_to_tax_model . 'taxonomy*ee_assign_venue_category' => array(
101
-                            '!=',
102
-                            'espresso_venue_categories',
103
-                        ),
104
-                    )
105
-                );
106
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_type'] = new EE_Default_Where_Conditions(
107
-                array(
108
-                    $path_to_tax_model . 'taxonomy*ee_assign_event_type' => array('!=', 'espresso_event_type'),
109
-                )
110
-            );
111
-        }
112
-        parent::__construct($timezone);
113
-        add_filter(
114
-            'FHEE__Read__create_model_query_params',
115
-            array('EEM_Term_Relationship', 'rest_api_query_params'),
116
-            10,
117
-            3
118
-        );
119
-    }
120
-
121
-
122
-    /**
123
-     * Makes sure all term-taxonomy counts are correct
124
-     *
125
-     * @param int   $term_taxonomy_id the id of the term taxonomy to update. If NULL, updates ALL
126
-     * @global wpdb $wpdb
127
-     * @return int the number of rows affected
128
-     * @throws EE_Error
129
-     */
130
-    public function update_term_taxonomy_counts($term_taxonomy_id = null)
131
-    {
132
-        // because this uses a subquery and sometimes assigning to column to be another column's
133
-        // value, we just write the SQL directly.
134
-        global $wpdb;
135
-
136
-        $query = "
12
+	// private instance of the Attendee object
13
+	protected static $_instance = null;
14
+
15
+
16
+
17
+	/**
18
+	 * EEM_Term_Relationship constructor.
19
+	 *
20
+	 * @param string $timezone
21
+	 */
22
+	protected function __construct($timezone = null)
23
+	{
24
+		$this->singular_item = __('Term Relationship', 'event_espresso');
25
+		$this->plural_item = __('Term Relationships', 'event_espresso');
26
+		$this->_tables = array(
27
+			'Term_Relationship' => new EE_Primary_Table('term_relationships'),
28
+		);
29
+		$models_this_can_attach_to = array_keys(EE_Registry::instance()->cpt_models());
30
+		$this->_fields = array(
31
+			'Term_Relationship' => array(
32
+				'object_id'        => new EE_Foreign_Key_Int_Field(
33
+					'object_id',
34
+					__('Object(Post) ID', 'event_espresso'),
35
+					false,
36
+					0,
37
+					$models_this_can_attach_to
38
+				),
39
+				'term_taxonomy_id' => new EE_Foreign_Key_Int_Field(
40
+					'term_taxonomy_id',
41
+					__(
42
+						'Term (in context of a taxonomy) ID',
43
+						'event_espresso'
44
+					),
45
+					false,
46
+					0,
47
+					'Term_Taxonomy'
48
+				),
49
+				'term_order'       => new EE_Integer_Field(
50
+					'term_order',
51
+					__('Term Order', 'event_espresso'),
52
+					false,
53
+					0
54
+				),
55
+			),
56
+		);
57
+		$this->_model_relations = array(
58
+			'Term_Taxonomy' => new EE_Belongs_To_Relation(),
59
+		);
60
+		foreach ($models_this_can_attach_to as $model_name) {
61
+			$this->_model_relations[ $model_name ] = new EE_Belongs_To_Relation();
62
+		}
63
+		$this->_wp_core_model = true;
64
+		$this->_indexes = array(
65
+			'PRIMARY' => new EE_Primary_Key_Index(array('object_id', 'term_taxonomy_id')),
66
+		);
67
+		$path_to_event_model = 'Event.';
68
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public(
69
+			$path_to_event_model
70
+		);
71
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
72
+			new EE_Restriction_Generator_Event_Related_Protected(
73
+				$path_to_event_model
74
+			);
75
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ] = new EE_Restriction_Generator_Event_Related_Protected(
76
+			$path_to_event_model
77
+		);
78
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ] =
79
+			new EE_Restriction_Generator_Event_Related_Protected(
80
+				$path_to_event_model,
81
+				EEM_Base::caps_edit
82
+			);
83
+		$path_to_tax_model = 'Term_Taxonomy.';
84
+		// add cap restrictions for editing term relations to the "ee_assign_*"
85
+		// and for deleting term relations too
86
+		$cap_contexts_affected = array(EEM_Base::caps_edit, EEM_Base::caps_delete);
87
+		foreach ($cap_contexts_affected as $cap_context_affected) {
88
+			$this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_category'] =
89
+				new EE_Default_Where_Conditions(
90
+					array(
91
+						$path_to_tax_model . 'taxonomy*ee_assign_event_category' => array(
92
+							'!=',
93
+							'espresso_event_categories',
94
+						),
95
+					)
96
+				);
97
+			$this->_cap_restrictions[ $cap_context_affected ]['ee_assign_venue_category'] =
98
+				new EE_Default_Where_Conditions(
99
+					array(
100
+						$path_to_tax_model . 'taxonomy*ee_assign_venue_category' => array(
101
+							'!=',
102
+							'espresso_venue_categories',
103
+						),
104
+					)
105
+				);
106
+			$this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_type'] = new EE_Default_Where_Conditions(
107
+				array(
108
+					$path_to_tax_model . 'taxonomy*ee_assign_event_type' => array('!=', 'espresso_event_type'),
109
+				)
110
+			);
111
+		}
112
+		parent::__construct($timezone);
113
+		add_filter(
114
+			'FHEE__Read__create_model_query_params',
115
+			array('EEM_Term_Relationship', 'rest_api_query_params'),
116
+			10,
117
+			3
118
+		);
119
+	}
120
+
121
+
122
+	/**
123
+	 * Makes sure all term-taxonomy counts are correct
124
+	 *
125
+	 * @param int   $term_taxonomy_id the id of the term taxonomy to update. If NULL, updates ALL
126
+	 * @global wpdb $wpdb
127
+	 * @return int the number of rows affected
128
+	 * @throws EE_Error
129
+	 */
130
+	public function update_term_taxonomy_counts($term_taxonomy_id = null)
131
+	{
132
+		// because this uses a subquery and sometimes assigning to column to be another column's
133
+		// value, we just write the SQL directly.
134
+		global $wpdb;
135
+
136
+		$query = "
137 137
                 UPDATE {$wpdb->term_taxonomy} AS tt 
138 138
                 SET count = (
139 139
                     select count(*) as proper_count from {$wpdb->term_relationships} AS tr 
140 140
                     WHERE tt.term_taxonomy_id = tr.term_taxonomy_id
141 141
                 )";
142 142
 
143
-        if ($term_taxonomy_id) {
144
-            $query .= ' WHERE tt.term_taxonomy_id = %d';
145
-            $query = $wpdb->prepare(
146
-                $query,
147
-                $term_taxonomy_id
148
-            );
149
-        }
150
-        $rows_affected = $this->_do_wpdb_query(
151
-            'query',
152
-            array(
153
-                $query,
154
-            )
155
-        );
156
-        return $rows_affected;
157
-    }
158
-
159
-
160
-
161
-    /**
162
-     * Overrides the parent to also make sure term-taxonomy counts are up-to-date after
163
-     * inserting
164
-     *
165
-     * @param array $field_n_values @see EEM_Base::insert
166
-     * @return boolean
167
-     */
168
-    public function insert($field_n_values)
169
-    {
170
-        $return = parent::insert($field_n_values);
171
-        if (isset($field_n_values['term_taxonomy_id'])) {
172
-            $this->update_term_taxonomy_counts($field_n_values['term_taxonomy_id']);
173
-        }
174
-        return $return;
175
-    }
176
-
177
-
178
-
179
-    /**
180
-     * Overrides parent so that after an update, we also check the term_taxonomy_counts are
181
-     * all ok
182
-     *
183
-     * @param array   $fields_n_values         see EEM_Base::update
184
-     * @param array   $query_params            @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
185
-     * @param boolean $keep_model_objs_in_sync if TRUE, makes sure we ALSO update model objects
186
-     *                                         in this model's entity map according to $fields_n_values that match
187
-     *                                         $query_params. This obviously has some overhead, so you can disable it
188
-     *                                         by setting this to FALSE, but be aware that model objects being used
189
-     *                                         could get out-of-sync with the database
190
-     * @return int
191
-     */
192
-    public function update($fields_n_values, $query_params, $keep_model_objs_in_sync = true)
193
-    {
194
-        $count = parent::update($fields_n_values, $query_params, $keep_model_objs_in_sync);
195
-        if ($count) {
196
-            $this->update_term_taxonomy_counts();
197
-        }
198
-        return $count;
199
-    }
200
-
201
-
202
-
203
-    /**
204
-     * Overrides parent so that after running this, we also double-check
205
-     * the term taxonomy counts are up-to-date
206
-     *
207
-     * @param array   $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
208
-     * @param boolean $allow_blocking
209
-     * @return int @see EEM_Base::delete
210
-     */
211
-    public function delete($query_params, $allow_blocking = true)
212
-    {
213
-        $count = parent::delete($query_params, $allow_blocking);
214
-        if ($count) {
215
-            $this->update_term_taxonomy_counts();
216
-        }
217
-        return $count;
218
-    }
219
-
220
-
221
-
222
-    /**
223
-     * Makes sure that during REST API queries, we only return term relationships
224
-     * for term taxonomies which should be shown in the rest api
225
-     *
226
-     * @param array    $model_query_params
227
-     * @param array    $querystring_query_params
228
-     * @param EEM_Base $model
229
-     * @return array
230
-     */
231
-    public static function rest_api_query_params($model_query_params, $querystring_query_params, $model)
232
-    {
233
-        if ($model === EEM_Term_Relationship::instance()) {
234
-            $taxonomies = get_taxonomies(array('show_in_rest' => true));
235
-            if (! empty($taxonomies)) {
236
-                $model_query_params[0]['Term_Taxonomy.taxonomy'] = array('IN', $taxonomies);
237
-            }
238
-        }
239
-        return $model_query_params;
240
-    }
143
+		if ($term_taxonomy_id) {
144
+			$query .= ' WHERE tt.term_taxonomy_id = %d';
145
+			$query = $wpdb->prepare(
146
+				$query,
147
+				$term_taxonomy_id
148
+			);
149
+		}
150
+		$rows_affected = $this->_do_wpdb_query(
151
+			'query',
152
+			array(
153
+				$query,
154
+			)
155
+		);
156
+		return $rows_affected;
157
+	}
158
+
159
+
160
+
161
+	/**
162
+	 * Overrides the parent to also make sure term-taxonomy counts are up-to-date after
163
+	 * inserting
164
+	 *
165
+	 * @param array $field_n_values @see EEM_Base::insert
166
+	 * @return boolean
167
+	 */
168
+	public function insert($field_n_values)
169
+	{
170
+		$return = parent::insert($field_n_values);
171
+		if (isset($field_n_values['term_taxonomy_id'])) {
172
+			$this->update_term_taxonomy_counts($field_n_values['term_taxonomy_id']);
173
+		}
174
+		return $return;
175
+	}
176
+
177
+
178
+
179
+	/**
180
+	 * Overrides parent so that after an update, we also check the term_taxonomy_counts are
181
+	 * all ok
182
+	 *
183
+	 * @param array   $fields_n_values         see EEM_Base::update
184
+	 * @param array   $query_params            @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
185
+	 * @param boolean $keep_model_objs_in_sync if TRUE, makes sure we ALSO update model objects
186
+	 *                                         in this model's entity map according to $fields_n_values that match
187
+	 *                                         $query_params. This obviously has some overhead, so you can disable it
188
+	 *                                         by setting this to FALSE, but be aware that model objects being used
189
+	 *                                         could get out-of-sync with the database
190
+	 * @return int
191
+	 */
192
+	public function update($fields_n_values, $query_params, $keep_model_objs_in_sync = true)
193
+	{
194
+		$count = parent::update($fields_n_values, $query_params, $keep_model_objs_in_sync);
195
+		if ($count) {
196
+			$this->update_term_taxonomy_counts();
197
+		}
198
+		return $count;
199
+	}
200
+
201
+
202
+
203
+	/**
204
+	 * Overrides parent so that after running this, we also double-check
205
+	 * the term taxonomy counts are up-to-date
206
+	 *
207
+	 * @param array   $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
208
+	 * @param boolean $allow_blocking
209
+	 * @return int @see EEM_Base::delete
210
+	 */
211
+	public function delete($query_params, $allow_blocking = true)
212
+	{
213
+		$count = parent::delete($query_params, $allow_blocking);
214
+		if ($count) {
215
+			$this->update_term_taxonomy_counts();
216
+		}
217
+		return $count;
218
+	}
219
+
220
+
221
+
222
+	/**
223
+	 * Makes sure that during REST API queries, we only return term relationships
224
+	 * for term taxonomies which should be shown in the rest api
225
+	 *
226
+	 * @param array    $model_query_params
227
+	 * @param array    $querystring_query_params
228
+	 * @param EEM_Base $model
229
+	 * @return array
230
+	 */
231
+	public static function rest_api_query_params($model_query_params, $querystring_query_params, $model)
232
+	{
233
+		if ($model === EEM_Term_Relationship::instance()) {
234
+			$taxonomies = get_taxonomies(array('show_in_rest' => true));
235
+			if (! empty($taxonomies)) {
236
+				$model_query_params[0]['Term_Taxonomy.taxonomy'] = array('IN', $taxonomies);
237
+			}
238
+		}
239
+		return $model_query_params;
240
+	}
241 241
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Datetime.model.php 1 patch
Indentation   +655 added lines, -655 removed lines patch added patch discarded remove patch
@@ -9,659 +9,659 @@
 block discarded – undo
9 9
 class EEM_Datetime extends EEM_Soft_Delete_Base
10 10
 {
11 11
 
12
-    /**
13
-     * @var EEM_Datetime $_instance
14
-     */
15
-    protected static $_instance;
16
-
17
-
18
-    /**
19
-     * private constructor to prevent direct creation
20
-     *
21
-     * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
22
-     *                         (and any incoming timezone data that gets saved).
23
-     *                         Note this just sends the timezone info to the date time model field objects.
24
-     *                         Default is NULL
25
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
26
-     * @throws EE_Error
27
-     * @throws InvalidArgumentException
28
-     * @throws InvalidArgumentException
29
-     */
30
-    protected function __construct($timezone)
31
-    {
32
-        $this->singular_item           = esc_html__('Datetime', 'event_espresso');
33
-        $this->plural_item             = esc_html__('Datetimes', 'event_espresso');
34
-        $this->_tables                 = array(
35
-            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
36
-        );
37
-        $this->_fields                 = array(
38
-            'Datetime' => array(
39
-                'DTT_ID'          => new EE_Primary_Key_Int_Field(
40
-                    'DTT_ID',
41
-                    esc_html__('Datetime ID', 'event_espresso')
42
-                ),
43
-                'EVT_ID'          => new EE_Foreign_Key_Int_Field(
44
-                    'EVT_ID',
45
-                    esc_html__('Event ID', 'event_espresso'),
46
-                    false,
47
-                    0,
48
-                    'Event'
49
-                ),
50
-                'DTT_name'        => new EE_Plain_Text_Field(
51
-                    'DTT_name',
52
-                    esc_html__('Datetime Name', 'event_espresso'),
53
-                    false,
54
-                    ''
55
-                ),
56
-                'DTT_description' => new EE_Post_Content_Field(
57
-                    'DTT_description',
58
-                    esc_html__('Description for Datetime', 'event_espresso'),
59
-                    false,
60
-                    ''
61
-                ),
62
-                'DTT_EVT_start'   => new EE_Datetime_Field(
63
-                    'DTT_EVT_start',
64
-                    esc_html__('Start time/date of Event', 'event_espresso'),
65
-                    false,
66
-                    EE_Datetime_Field::now,
67
-                    $timezone
68
-                ),
69
-                'DTT_EVT_end'     => new EE_Datetime_Field(
70
-                    'DTT_EVT_end',
71
-                    esc_html__('End time/date of Event', 'event_espresso'),
72
-                    false,
73
-                    EE_Datetime_Field::now,
74
-                    $timezone
75
-                ),
76
-                'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
77
-                    'DTT_reg_limit',
78
-                    esc_html__('Registration Limit for this time', 'event_espresso'),
79
-                    true,
80
-                    EE_INF
81
-                ),
82
-                'DTT_sold'        => new EE_Integer_Field(
83
-                    'DTT_sold',
84
-                    esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
85
-                    true,
86
-                    0
87
-                ),
88
-                'DTT_reserved'    => new EE_Integer_Field(
89
-                    'DTT_reserved',
90
-                    esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
91
-                    false,
92
-                    0
93
-                ),
94
-                'DTT_is_primary'  => new EE_Boolean_Field(
95
-                    'DTT_is_primary',
96
-                    esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
97
-                    false,
98
-                    false
99
-                ),
100
-                'DTT_order'       => new EE_Integer_Field(
101
-                    'DTT_order',
102
-                    esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
103
-                    false,
104
-                    0
105
-                ),
106
-                'DTT_parent'      => new EE_Integer_Field(
107
-                    'DTT_parent',
108
-                    esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
109
-                    true,
110
-                    0
111
-                ),
112
-                'DTT_deleted'     => new EE_Trashed_Flag_Field(
113
-                    'DTT_deleted',
114
-                    esc_html__('Flag indicating datetime is archived', 'event_espresso'),
115
-                    false,
116
-                    false
117
-                ),
118
-            ),
119
-        );
120
-        $this->_model_relations        = array(
121
-            'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
122
-            'Event'   => new EE_Belongs_To_Relation(),
123
-            'Checkin' => new EE_Has_Many_Relation(),
124
-        );
125
-        $this->_model_chain_to_wp_user = 'Event';
126
-        // this model is generally available for reading
127
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
128
-            'Event'
129
-        );
130
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
131
-            'Event'
132
-        );
133
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
134
-            'Event'
135
-        );
136
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
137
-            'Event',
138
-            EEM_Base::caps_edit
139
-        );
140
-        parent::__construct($timezone);
141
-    }
142
-
143
-
144
-    /**
145
-     * create new blank datetime
146
-     *
147
-     * @access public
148
-     * @return EE_Datetime[] array on success, FALSE on fail
149
-     * @throws EE_Error
150
-     */
151
-    public function create_new_blank_datetime()
152
-    {
153
-        // makes sure timezone is always set.
154
-        $timezone_string = $this->get_timezone();
155
-        $blank_datetime  = EE_Datetime::new_instance(
156
-            array(
157
-                'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
158
-                'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
159
-                'DTT_order'     => 1,
160
-                'DTT_reg_limit' => EE_INF,
161
-            ),
162
-            $timezone_string
163
-        );
164
-        $blank_datetime->set_start_time(
165
-            $this->convert_datetime_for_query(
166
-                'DTT_EVT_start',
167
-                '8am',
168
-                'ga',
169
-                $timezone_string
170
-            )
171
-        );
172
-        $blank_datetime->set_end_time(
173
-            $this->convert_datetime_for_query(
174
-                'DTT_EVT_end',
175
-                '5pm',
176
-                'ga',
177
-                $timezone_string
178
-            )
179
-        );
180
-        return array($blank_datetime);
181
-    }
182
-
183
-
184
-    /**
185
-     * get event start date from db
186
-     *
187
-     * @access public
188
-     * @param  int $EVT_ID
189
-     * @return EE_Datetime[] array on success, FALSE on fail
190
-     * @throws EE_Error
191
-     */
192
-    public function get_all_event_dates($EVT_ID = 0)
193
-    {
194
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
195
-            return $this->create_new_blank_datetime();
196
-        }
197
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
198
-        if (empty($results)) {
199
-            return $this->create_new_blank_datetime();
200
-        }
201
-        return $results;
202
-    }
203
-
204
-
205
-    /**
206
-     * get all datetimes attached to an event ordered by the DTT_order field
207
-     *
208
-     * @public
209
-     * @param  int    $EVT_ID     event id
210
-     * @param boolean $include_expired
211
-     * @param boolean $include_deleted
212
-     * @param  int    $limit      If included then limit the count of results by
213
-     *                            the given number
214
-     * @return EE_Datetime[]
215
-     * @throws EE_Error
216
-     */
217
-    public function get_datetimes_for_event_ordered_by_DTT_order(
218
-        $EVT_ID,
219
-        $include_expired = true,
220
-        $include_deleted = true,
221
-        $limit = null
222
-    ) {
223
-        // sanitize EVT_ID
224
-        $EVT_ID         = absint($EVT_ID);
225
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
226
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
227
-        $where_params = array('Event.EVT_ID' => $EVT_ID);
228
-        $query_params = ! empty($limit)
229
-            ? array(
230
-                $where_params,
231
-                'limit'                    => $limit,
232
-                'order_by'                 => array('DTT_order' => 'ASC'),
233
-                'default_where_conditions' => 'none',
234
-            )
235
-            : array(
236
-                $where_params,
237
-                'order_by'                 => array('DTT_order' => 'ASC'),
238
-                'default_where_conditions' => 'none',
239
-            );
240
-        if (! $include_expired) {
241
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
242
-        }
243
-        if ($include_deleted) {
244
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
245
-        }
246
-        /** @var EE_Datetime[] $result */
247
-        $result = $this->get_all($query_params);
248
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
249
-        return $result;
250
-    }
251
-
252
-
253
-    /**
254
-     * Gets the datetimes for the event (with the given limit), and orders them by "importance".
255
-     * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
256
-     * and then the earlier datetimes are the most important.
257
-     * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
258
-     *
259
-     * @param int $EVT_ID
260
-     * @param int $limit
261
-     * @return EE_Datetime[]|EE_Base_Class[]
262
-     * @throws EE_Error
263
-     */
264
-    public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
265
-    {
266
-        return $this->get_all(
267
-            array(
268
-                array('Event.EVT_ID' => $EVT_ID),
269
-                'limit'                    => $limit,
270
-                'order_by'                 => array('DTT_EVT_start' => 'ASC'),
271
-                'default_where_conditions' => 'none',
272
-            )
273
-        );
274
-    }
275
-
276
-
277
-    /**
278
-     * @param int     $EVT_ID
279
-     * @param boolean $include_expired
280
-     * @param boolean $include_deleted
281
-     * @return EE_Datetime
282
-     * @throws EE_Error
283
-     */
284
-    public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
285
-    {
286
-        $results = $this->get_datetimes_for_event_ordered_by_start_time(
287
-            $EVT_ID,
288
-            $include_expired,
289
-            $include_deleted,
290
-            1
291
-        );
292
-        if ($results) {
293
-            return array_shift($results);
294
-        }
295
-        return null;
296
-    }
297
-
298
-
299
-    /**
300
-     * Gets the 'primary' datetime for an event.
301
-     *
302
-     * @param int  $EVT_ID
303
-     * @param bool $try_to_exclude_expired
304
-     * @param bool $try_to_exclude_deleted
305
-     * @return \EE_Datetime
306
-     * @throws EE_Error
307
-     */
308
-    public function get_primary_datetime_for_event(
309
-        $EVT_ID,
310
-        $try_to_exclude_expired = true,
311
-        $try_to_exclude_deleted = true
312
-    ) {
313
-        if ($try_to_exclude_expired) {
314
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
315
-            if ($non_expired) {
316
-                return $non_expired;
317
-            }
318
-        }
319
-        if ($try_to_exclude_deleted) {
320
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
321
-            if ($expired_even) {
322
-                return $expired_even;
323
-            }
324
-        }
325
-        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
326
-    }
327
-
328
-
329
-    /**
330
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
331
-     * only by start date
332
-     *
333
-     * @param int     $EVT_ID
334
-     * @param boolean $include_expired
335
-     * @param boolean $include_deleted
336
-     * @param int     $limit
337
-     * @return EE_Datetime[]
338
-     * @throws EE_Error
339
-     */
340
-    public function get_datetimes_for_event_ordered_by_start_time(
341
-        $EVT_ID,
342
-        $include_expired = true,
343
-        $include_deleted = true,
344
-        $limit = null
345
-    ) {
346
-        // sanitize EVT_ID
347
-        $EVT_ID         = absint($EVT_ID);
348
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
349
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
350
-        $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
351
-        if (! $include_expired) {
352
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
353
-        }
354
-        if ($include_deleted) {
355
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
356
-        }
357
-        if ($limit) {
358
-            $query_params['limit'] = $limit;
359
-        }
360
-        /** @var EE_Datetime[] $result */
361
-        $result = $this->get_all($query_params);
362
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
363
-        return $result;
364
-    }
365
-
366
-
367
-    /**
368
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
369
-     * only by start date
370
-     *
371
-     * @param int     $TKT_ID
372
-     * @param boolean $include_expired
373
-     * @param boolean $include_deleted
374
-     * @param int     $limit
375
-     * @return EE_Datetime[]
376
-     * @throws EE_Error
377
-     */
378
-    public function get_datetimes_for_ticket_ordered_by_start_time(
379
-        $TKT_ID,
380
-        $include_expired = true,
381
-        $include_deleted = true,
382
-        $limit = null
383
-    ) {
384
-        // sanitize TKT_ID
385
-        $TKT_ID         = absint($TKT_ID);
386
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
387
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
388
-        $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
389
-        if (! $include_expired) {
390
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
391
-        }
392
-        if ($include_deleted) {
393
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
394
-        }
395
-        if ($limit) {
396
-            $query_params['limit'] = $limit;
397
-        }
398
-        /** @var EE_Datetime[] $result */
399
-        $result = $this->get_all($query_params);
400
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
401
-        return $result;
402
-    }
403
-
404
-
405
-    /**
406
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
407
-     * datetimes.
408
-     *
409
-     * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
410
-     * @param  boolean  $include_expired whether to include expired datetimes or not
411
-     * @param  boolean  $include_deleted whether to include trashed datetimes or not.
412
-     * @param  int|null $limit           if null, no limit, if int then limit results by
413
-     *                                   that number
414
-     * @return EE_Datetime[]
415
-     * @throws EE_Error
416
-     */
417
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
418
-        $TKT_ID,
419
-        $include_expired = true,
420
-        $include_deleted = true,
421
-        $limit = null
422
-    ) {
423
-        // sanitize id.
424
-        $TKT_ID         = absint($TKT_ID);
425
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
426
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
427
-        $where_params = array('Ticket.TKT_ID' => $TKT_ID);
428
-        $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
429
-        if (! $include_expired) {
430
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
431
-        }
432
-        if ($include_deleted) {
433
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
434
-        }
435
-        if ($limit) {
436
-            $query_params['limit'] = $limit;
437
-        }
438
-        /** @var EE_Datetime[] $result */
439
-        $result = $this->get_all($query_params);
440
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
441
-        return $result;
442
-    }
443
-
444
-
445
-    /**
446
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
447
-     * reason it doesn't exist, we consider the earliest event the most important)
448
-     *
449
-     * @param int $EVT_ID
450
-     * @return EE_Datetime
451
-     * @throws EE_Error
452
-     */
453
-    public function get_most_important_datetime_for_event($EVT_ID)
454
-    {
455
-        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
456
-        if ($results) {
457
-            return array_shift($results);
458
-        }
459
-        return null;
460
-    }
461
-
462
-
463
-    /**
464
-     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
465
-     * grouped by month and year.
466
-     *
467
-     * @param  array  $where_params      @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
468
-     * @param  string $evt_active_status A string representing the evt active status to filter the months by.
469
-     *                                   Can be:
470
-     *                                   - '' = no filter
471
-     *                                   - upcoming = Published events with at least one upcoming datetime.
472
-     *                                   - expired = Events with all datetimes expired.
473
-     *                                   - active = Events that are published and have at least one datetime that
474
-     *                                   starts before now and ends after now.
475
-     *                                   - inactive = Events that are either not published.
476
-     * @return EE_Base_Class[]
477
-     * @throws EE_Error
478
-     * @throws InvalidArgumentException
479
-     * @throws InvalidArgumentException
480
-     */
481
-    public function get_dtt_months_and_years($where_params, $evt_active_status = '')
482
-    {
483
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
484
-        $current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
485
-        switch ($evt_active_status) {
486
-            case 'upcoming':
487
-                $where_params['Event.status'] = 'publish';
488
-                // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
489
-                if (isset($where_params['DTT_EVT_start'])) {
490
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
491
-                }
492
-                $where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
493
-                break;
494
-            case 'expired':
495
-                if (isset($where_params['Event.status'])) {
496
-                    unset($where_params['Event.status']);
497
-                }
498
-                // get events to exclude
499
-                $exclude_query[0] = array_merge(
500
-                    $where_params,
501
-                    array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end))
502
-                );
503
-                // first get all events that have datetimes where its not expired.
504
-                $event_ids = $this->_get_all_wpdb_results(
505
-                    $exclude_query,
506
-                    OBJECT_K,
507
-                    'Datetime.EVT_ID'
508
-                );
509
-                $event_ids = array_keys($event_ids);
510
-                if (isset($where_params['DTT_EVT_end'])) {
511
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
512
-                }
513
-                $where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
514
-                $where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
515
-                break;
516
-            case 'active':
517
-                $where_params['Event.status'] = 'publish';
518
-                if (isset($where_params['DTT_EVT_start'])) {
519
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
520
-                }
521
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
522
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
523
-                }
524
-                $where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
525
-                $where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
526
-                break;
527
-            case 'inactive':
528
-                if (isset($where_params['Event.status'])) {
529
-                    unset($where_params['Event.status']);
530
-                }
531
-                if (isset($where_params['OR'])) {
532
-                    $where_params['AND']['OR'] = $where_params['OR'];
533
-                }
534
-                if (isset($where_params['DTT_EVT_end'])) {
535
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
536
-                    unset($where_params['DTT_EVT_end']);
537
-                }
538
-                if (isset($where_params['DTT_EVT_start'])) {
539
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
540
-                    unset($where_params['DTT_EVT_start']);
541
-                }
542
-                $where_params['AND']['Event.status'] = array('!=', 'publish');
543
-                break;
544
-        }
545
-        $query_params[0]          = $where_params;
546
-        $query_params['group_by'] = array('dtt_year', 'dtt_month');
547
-        $query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
548
-        $query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset(
549
-            $this->get_timezone(),
550
-            'DTT_EVT_start'
551
-        );
552
-        $columns_to_select        = array(
553
-            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
554
-            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
555
-            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
556
-        );
557
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
558
-    }
559
-
560
-
561
-    /**
562
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
563
-     * for the tickets for each datetime)
564
-     *
565
-     * @param EE_Base_Class[]|EE_Datetime[] $datetimes
566
-     * @throws EE_Error
567
-     */
568
-    public function update_sold($datetimes)
569
-    {
570
-        EE_Error::doing_it_wrong(
571
-            __FUNCTION__,
572
-            esc_html__(
573
-                'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
574
-                'event_espresso'
575
-            ),
576
-            '4.9.32.rc.005'
577
-        );
578
-        foreach ($datetimes as $datetime) {
579
-            $datetime->update_sold();
580
-        }
581
-    }
582
-
583
-
584
-    /**
585
-     *    Gets the total number of tickets available at a particular datetime
586
-     *    (does NOT take into account the datetime's spaces available)
587
-     *
588
-     * @param int   $DTT_ID
589
-     * @param array $query_params
590
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
591
-     *             tickets attached to datetime then FALSE is returned.
592
-     */
593
-    public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
594
-    {
595
-        $datetime = $this->get_one_by_ID($DTT_ID);
596
-        if ($datetime instanceof EE_Datetime) {
597
-            return $datetime->tickets_remaining($query_params);
598
-        }
599
-        return 0;
600
-    }
601
-
602
-
603
-    /**
604
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
605
-     *
606
-     * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
607
-     *                                 stati you want counts for as values in the array.  An empty array returns counts
608
-     *                                 for all valid stati.
609
-     * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
610
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
611
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
612
-     * @throws EE_Error
613
-     *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
614
-     *                                 EE_Datetime::expired
615
-     */
616
-    public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
617
-    {
618
-        // only accept where conditions for this query.
619
-        $_where            = isset($query_params[0]) ? $query_params[0] : array();
620
-        $status_query_args = array(
621
-            EE_Datetime::active   => array_merge(
622
-                $_where,
623
-                array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
624
-            ),
625
-            EE_Datetime::upcoming => array_merge(
626
-                $_where,
627
-                array('DTT_EVT_start' => array('>', time()))
628
-            ),
629
-            EE_Datetime::expired  => array_merge(
630
-                $_where,
631
-                array('DTT_EVT_end' => array('<', time()))
632
-            ),
633
-        );
634
-        if (! empty($stati_to_include)) {
635
-            foreach (array_keys($status_query_args) as $status) {
636
-                if (! in_array($status, $stati_to_include, true)) {
637
-                    unset($status_query_args[ $status ]);
638
-                }
639
-            }
640
-        }
641
-        // loop through and query counts for each stati.
642
-        $status_query_results = array();
643
-        foreach ($status_query_args as $status => $status_where_conditions) {
644
-            $status_query_results[ $status ] = EEM_Datetime::count(
645
-                array($status_where_conditions),
646
-                'DTT_ID',
647
-                true
648
-            );
649
-        }
650
-        return $status_query_results;
651
-    }
652
-
653
-
654
-    /**
655
-     * Returns the specific count for a given Datetime status matching any given query_params.
656
-     *
657
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
658
-     * @param array  $query_params
659
-     * @return int
660
-     * @throws EE_Error
661
-     */
662
-    public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
663
-    {
664
-        $count = $this->get_datetime_counts_by_status(array($status), $query_params);
665
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
666
-    }
12
+	/**
13
+	 * @var EEM_Datetime $_instance
14
+	 */
15
+	protected static $_instance;
16
+
17
+
18
+	/**
19
+	 * private constructor to prevent direct creation
20
+	 *
21
+	 * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
22
+	 *                         (and any incoming timezone data that gets saved).
23
+	 *                         Note this just sends the timezone info to the date time model field objects.
24
+	 *                         Default is NULL
25
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
26
+	 * @throws EE_Error
27
+	 * @throws InvalidArgumentException
28
+	 * @throws InvalidArgumentException
29
+	 */
30
+	protected function __construct($timezone)
31
+	{
32
+		$this->singular_item           = esc_html__('Datetime', 'event_espresso');
33
+		$this->plural_item             = esc_html__('Datetimes', 'event_espresso');
34
+		$this->_tables                 = array(
35
+			'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
36
+		);
37
+		$this->_fields                 = array(
38
+			'Datetime' => array(
39
+				'DTT_ID'          => new EE_Primary_Key_Int_Field(
40
+					'DTT_ID',
41
+					esc_html__('Datetime ID', 'event_espresso')
42
+				),
43
+				'EVT_ID'          => new EE_Foreign_Key_Int_Field(
44
+					'EVT_ID',
45
+					esc_html__('Event ID', 'event_espresso'),
46
+					false,
47
+					0,
48
+					'Event'
49
+				),
50
+				'DTT_name'        => new EE_Plain_Text_Field(
51
+					'DTT_name',
52
+					esc_html__('Datetime Name', 'event_espresso'),
53
+					false,
54
+					''
55
+				),
56
+				'DTT_description' => new EE_Post_Content_Field(
57
+					'DTT_description',
58
+					esc_html__('Description for Datetime', 'event_espresso'),
59
+					false,
60
+					''
61
+				),
62
+				'DTT_EVT_start'   => new EE_Datetime_Field(
63
+					'DTT_EVT_start',
64
+					esc_html__('Start time/date of Event', 'event_espresso'),
65
+					false,
66
+					EE_Datetime_Field::now,
67
+					$timezone
68
+				),
69
+				'DTT_EVT_end'     => new EE_Datetime_Field(
70
+					'DTT_EVT_end',
71
+					esc_html__('End time/date of Event', 'event_espresso'),
72
+					false,
73
+					EE_Datetime_Field::now,
74
+					$timezone
75
+				),
76
+				'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
77
+					'DTT_reg_limit',
78
+					esc_html__('Registration Limit for this time', 'event_espresso'),
79
+					true,
80
+					EE_INF
81
+				),
82
+				'DTT_sold'        => new EE_Integer_Field(
83
+					'DTT_sold',
84
+					esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
85
+					true,
86
+					0
87
+				),
88
+				'DTT_reserved'    => new EE_Integer_Field(
89
+					'DTT_reserved',
90
+					esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
91
+					false,
92
+					0
93
+				),
94
+				'DTT_is_primary'  => new EE_Boolean_Field(
95
+					'DTT_is_primary',
96
+					esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
97
+					false,
98
+					false
99
+				),
100
+				'DTT_order'       => new EE_Integer_Field(
101
+					'DTT_order',
102
+					esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
103
+					false,
104
+					0
105
+				),
106
+				'DTT_parent'      => new EE_Integer_Field(
107
+					'DTT_parent',
108
+					esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
109
+					true,
110
+					0
111
+				),
112
+				'DTT_deleted'     => new EE_Trashed_Flag_Field(
113
+					'DTT_deleted',
114
+					esc_html__('Flag indicating datetime is archived', 'event_espresso'),
115
+					false,
116
+					false
117
+				),
118
+			),
119
+		);
120
+		$this->_model_relations        = array(
121
+			'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
122
+			'Event'   => new EE_Belongs_To_Relation(),
123
+			'Checkin' => new EE_Has_Many_Relation(),
124
+		);
125
+		$this->_model_chain_to_wp_user = 'Event';
126
+		// this model is generally available for reading
127
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
128
+			'Event'
129
+		);
130
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
131
+			'Event'
132
+		);
133
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
134
+			'Event'
135
+		);
136
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
137
+			'Event',
138
+			EEM_Base::caps_edit
139
+		);
140
+		parent::__construct($timezone);
141
+	}
142
+
143
+
144
+	/**
145
+	 * create new blank datetime
146
+	 *
147
+	 * @access public
148
+	 * @return EE_Datetime[] array on success, FALSE on fail
149
+	 * @throws EE_Error
150
+	 */
151
+	public function create_new_blank_datetime()
152
+	{
153
+		// makes sure timezone is always set.
154
+		$timezone_string = $this->get_timezone();
155
+		$blank_datetime  = EE_Datetime::new_instance(
156
+			array(
157
+				'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
158
+				'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
159
+				'DTT_order'     => 1,
160
+				'DTT_reg_limit' => EE_INF,
161
+			),
162
+			$timezone_string
163
+		);
164
+		$blank_datetime->set_start_time(
165
+			$this->convert_datetime_for_query(
166
+				'DTT_EVT_start',
167
+				'8am',
168
+				'ga',
169
+				$timezone_string
170
+			)
171
+		);
172
+		$blank_datetime->set_end_time(
173
+			$this->convert_datetime_for_query(
174
+				'DTT_EVT_end',
175
+				'5pm',
176
+				'ga',
177
+				$timezone_string
178
+			)
179
+		);
180
+		return array($blank_datetime);
181
+	}
182
+
183
+
184
+	/**
185
+	 * get event start date from db
186
+	 *
187
+	 * @access public
188
+	 * @param  int $EVT_ID
189
+	 * @return EE_Datetime[] array on success, FALSE on fail
190
+	 * @throws EE_Error
191
+	 */
192
+	public function get_all_event_dates($EVT_ID = 0)
193
+	{
194
+		if (! $EVT_ID) { // on add_new_event event_id gets set to 0
195
+			return $this->create_new_blank_datetime();
196
+		}
197
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
198
+		if (empty($results)) {
199
+			return $this->create_new_blank_datetime();
200
+		}
201
+		return $results;
202
+	}
203
+
204
+
205
+	/**
206
+	 * get all datetimes attached to an event ordered by the DTT_order field
207
+	 *
208
+	 * @public
209
+	 * @param  int    $EVT_ID     event id
210
+	 * @param boolean $include_expired
211
+	 * @param boolean $include_deleted
212
+	 * @param  int    $limit      If included then limit the count of results by
213
+	 *                            the given number
214
+	 * @return EE_Datetime[]
215
+	 * @throws EE_Error
216
+	 */
217
+	public function get_datetimes_for_event_ordered_by_DTT_order(
218
+		$EVT_ID,
219
+		$include_expired = true,
220
+		$include_deleted = true,
221
+		$limit = null
222
+	) {
223
+		// sanitize EVT_ID
224
+		$EVT_ID         = absint($EVT_ID);
225
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
226
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
227
+		$where_params = array('Event.EVT_ID' => $EVT_ID);
228
+		$query_params = ! empty($limit)
229
+			? array(
230
+				$where_params,
231
+				'limit'                    => $limit,
232
+				'order_by'                 => array('DTT_order' => 'ASC'),
233
+				'default_where_conditions' => 'none',
234
+			)
235
+			: array(
236
+				$where_params,
237
+				'order_by'                 => array('DTT_order' => 'ASC'),
238
+				'default_where_conditions' => 'none',
239
+			);
240
+		if (! $include_expired) {
241
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
242
+		}
243
+		if ($include_deleted) {
244
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
245
+		}
246
+		/** @var EE_Datetime[] $result */
247
+		$result = $this->get_all($query_params);
248
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
249
+		return $result;
250
+	}
251
+
252
+
253
+	/**
254
+	 * Gets the datetimes for the event (with the given limit), and orders them by "importance".
255
+	 * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
256
+	 * and then the earlier datetimes are the most important.
257
+	 * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
258
+	 *
259
+	 * @param int $EVT_ID
260
+	 * @param int $limit
261
+	 * @return EE_Datetime[]|EE_Base_Class[]
262
+	 * @throws EE_Error
263
+	 */
264
+	public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
265
+	{
266
+		return $this->get_all(
267
+			array(
268
+				array('Event.EVT_ID' => $EVT_ID),
269
+				'limit'                    => $limit,
270
+				'order_by'                 => array('DTT_EVT_start' => 'ASC'),
271
+				'default_where_conditions' => 'none',
272
+			)
273
+		);
274
+	}
275
+
276
+
277
+	/**
278
+	 * @param int     $EVT_ID
279
+	 * @param boolean $include_expired
280
+	 * @param boolean $include_deleted
281
+	 * @return EE_Datetime
282
+	 * @throws EE_Error
283
+	 */
284
+	public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
285
+	{
286
+		$results = $this->get_datetimes_for_event_ordered_by_start_time(
287
+			$EVT_ID,
288
+			$include_expired,
289
+			$include_deleted,
290
+			1
291
+		);
292
+		if ($results) {
293
+			return array_shift($results);
294
+		}
295
+		return null;
296
+	}
297
+
298
+
299
+	/**
300
+	 * Gets the 'primary' datetime for an event.
301
+	 *
302
+	 * @param int  $EVT_ID
303
+	 * @param bool $try_to_exclude_expired
304
+	 * @param bool $try_to_exclude_deleted
305
+	 * @return \EE_Datetime
306
+	 * @throws EE_Error
307
+	 */
308
+	public function get_primary_datetime_for_event(
309
+		$EVT_ID,
310
+		$try_to_exclude_expired = true,
311
+		$try_to_exclude_deleted = true
312
+	) {
313
+		if ($try_to_exclude_expired) {
314
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
315
+			if ($non_expired) {
316
+				return $non_expired;
317
+			}
318
+		}
319
+		if ($try_to_exclude_deleted) {
320
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
321
+			if ($expired_even) {
322
+				return $expired_even;
323
+			}
324
+		}
325
+		return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
326
+	}
327
+
328
+
329
+	/**
330
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
331
+	 * only by start date
332
+	 *
333
+	 * @param int     $EVT_ID
334
+	 * @param boolean $include_expired
335
+	 * @param boolean $include_deleted
336
+	 * @param int     $limit
337
+	 * @return EE_Datetime[]
338
+	 * @throws EE_Error
339
+	 */
340
+	public function get_datetimes_for_event_ordered_by_start_time(
341
+		$EVT_ID,
342
+		$include_expired = true,
343
+		$include_deleted = true,
344
+		$limit = null
345
+	) {
346
+		// sanitize EVT_ID
347
+		$EVT_ID         = absint($EVT_ID);
348
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
349
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
350
+		$query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
351
+		if (! $include_expired) {
352
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
353
+		}
354
+		if ($include_deleted) {
355
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
356
+		}
357
+		if ($limit) {
358
+			$query_params['limit'] = $limit;
359
+		}
360
+		/** @var EE_Datetime[] $result */
361
+		$result = $this->get_all($query_params);
362
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
363
+		return $result;
364
+	}
365
+
366
+
367
+	/**
368
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
369
+	 * only by start date
370
+	 *
371
+	 * @param int     $TKT_ID
372
+	 * @param boolean $include_expired
373
+	 * @param boolean $include_deleted
374
+	 * @param int     $limit
375
+	 * @return EE_Datetime[]
376
+	 * @throws EE_Error
377
+	 */
378
+	public function get_datetimes_for_ticket_ordered_by_start_time(
379
+		$TKT_ID,
380
+		$include_expired = true,
381
+		$include_deleted = true,
382
+		$limit = null
383
+	) {
384
+		// sanitize TKT_ID
385
+		$TKT_ID         = absint($TKT_ID);
386
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
387
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
388
+		$query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
389
+		if (! $include_expired) {
390
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
391
+		}
392
+		if ($include_deleted) {
393
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
394
+		}
395
+		if ($limit) {
396
+			$query_params['limit'] = $limit;
397
+		}
398
+		/** @var EE_Datetime[] $result */
399
+		$result = $this->get_all($query_params);
400
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
401
+		return $result;
402
+	}
403
+
404
+
405
+	/**
406
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
407
+	 * datetimes.
408
+	 *
409
+	 * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
410
+	 * @param  boolean  $include_expired whether to include expired datetimes or not
411
+	 * @param  boolean  $include_deleted whether to include trashed datetimes or not.
412
+	 * @param  int|null $limit           if null, no limit, if int then limit results by
413
+	 *                                   that number
414
+	 * @return EE_Datetime[]
415
+	 * @throws EE_Error
416
+	 */
417
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
418
+		$TKT_ID,
419
+		$include_expired = true,
420
+		$include_deleted = true,
421
+		$limit = null
422
+	) {
423
+		// sanitize id.
424
+		$TKT_ID         = absint($TKT_ID);
425
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
426
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
427
+		$where_params = array('Ticket.TKT_ID' => $TKT_ID);
428
+		$query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
429
+		if (! $include_expired) {
430
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
431
+		}
432
+		if ($include_deleted) {
433
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
434
+		}
435
+		if ($limit) {
436
+			$query_params['limit'] = $limit;
437
+		}
438
+		/** @var EE_Datetime[] $result */
439
+		$result = $this->get_all($query_params);
440
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
441
+		return $result;
442
+	}
443
+
444
+
445
+	/**
446
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
447
+	 * reason it doesn't exist, we consider the earliest event the most important)
448
+	 *
449
+	 * @param int $EVT_ID
450
+	 * @return EE_Datetime
451
+	 * @throws EE_Error
452
+	 */
453
+	public function get_most_important_datetime_for_event($EVT_ID)
454
+	{
455
+		$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
456
+		if ($results) {
457
+			return array_shift($results);
458
+		}
459
+		return null;
460
+	}
461
+
462
+
463
+	/**
464
+	 * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
465
+	 * grouped by month and year.
466
+	 *
467
+	 * @param  array  $where_params      @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
468
+	 * @param  string $evt_active_status A string representing the evt active status to filter the months by.
469
+	 *                                   Can be:
470
+	 *                                   - '' = no filter
471
+	 *                                   - upcoming = Published events with at least one upcoming datetime.
472
+	 *                                   - expired = Events with all datetimes expired.
473
+	 *                                   - active = Events that are published and have at least one datetime that
474
+	 *                                   starts before now and ends after now.
475
+	 *                                   - inactive = Events that are either not published.
476
+	 * @return EE_Base_Class[]
477
+	 * @throws EE_Error
478
+	 * @throws InvalidArgumentException
479
+	 * @throws InvalidArgumentException
480
+	 */
481
+	public function get_dtt_months_and_years($where_params, $evt_active_status = '')
482
+	{
483
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
484
+		$current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
485
+		switch ($evt_active_status) {
486
+			case 'upcoming':
487
+				$where_params['Event.status'] = 'publish';
488
+				// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
489
+				if (isset($where_params['DTT_EVT_start'])) {
490
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
491
+				}
492
+				$where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
493
+				break;
494
+			case 'expired':
495
+				if (isset($where_params['Event.status'])) {
496
+					unset($where_params['Event.status']);
497
+				}
498
+				// get events to exclude
499
+				$exclude_query[0] = array_merge(
500
+					$where_params,
501
+					array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end))
502
+				);
503
+				// first get all events that have datetimes where its not expired.
504
+				$event_ids = $this->_get_all_wpdb_results(
505
+					$exclude_query,
506
+					OBJECT_K,
507
+					'Datetime.EVT_ID'
508
+				);
509
+				$event_ids = array_keys($event_ids);
510
+				if (isset($where_params['DTT_EVT_end'])) {
511
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
512
+				}
513
+				$where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
514
+				$where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
515
+				break;
516
+			case 'active':
517
+				$where_params['Event.status'] = 'publish';
518
+				if (isset($where_params['DTT_EVT_start'])) {
519
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
520
+				}
521
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
522
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
523
+				}
524
+				$where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
525
+				$where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
526
+				break;
527
+			case 'inactive':
528
+				if (isset($where_params['Event.status'])) {
529
+					unset($where_params['Event.status']);
530
+				}
531
+				if (isset($where_params['OR'])) {
532
+					$where_params['AND']['OR'] = $where_params['OR'];
533
+				}
534
+				if (isset($where_params['DTT_EVT_end'])) {
535
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
536
+					unset($where_params['DTT_EVT_end']);
537
+				}
538
+				if (isset($where_params['DTT_EVT_start'])) {
539
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
540
+					unset($where_params['DTT_EVT_start']);
541
+				}
542
+				$where_params['AND']['Event.status'] = array('!=', 'publish');
543
+				break;
544
+		}
545
+		$query_params[0]          = $where_params;
546
+		$query_params['group_by'] = array('dtt_year', 'dtt_month');
547
+		$query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
548
+		$query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset(
549
+			$this->get_timezone(),
550
+			'DTT_EVT_start'
551
+		);
552
+		$columns_to_select        = array(
553
+			'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
554
+			'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
555
+			'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
556
+		);
557
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
558
+	}
559
+
560
+
561
+	/**
562
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
563
+	 * for the tickets for each datetime)
564
+	 *
565
+	 * @param EE_Base_Class[]|EE_Datetime[] $datetimes
566
+	 * @throws EE_Error
567
+	 */
568
+	public function update_sold($datetimes)
569
+	{
570
+		EE_Error::doing_it_wrong(
571
+			__FUNCTION__,
572
+			esc_html__(
573
+				'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
574
+				'event_espresso'
575
+			),
576
+			'4.9.32.rc.005'
577
+		);
578
+		foreach ($datetimes as $datetime) {
579
+			$datetime->update_sold();
580
+		}
581
+	}
582
+
583
+
584
+	/**
585
+	 *    Gets the total number of tickets available at a particular datetime
586
+	 *    (does NOT take into account the datetime's spaces available)
587
+	 *
588
+	 * @param int   $DTT_ID
589
+	 * @param array $query_params
590
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
591
+	 *             tickets attached to datetime then FALSE is returned.
592
+	 */
593
+	public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
594
+	{
595
+		$datetime = $this->get_one_by_ID($DTT_ID);
596
+		if ($datetime instanceof EE_Datetime) {
597
+			return $datetime->tickets_remaining($query_params);
598
+		}
599
+		return 0;
600
+	}
601
+
602
+
603
+	/**
604
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
605
+	 *
606
+	 * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
607
+	 *                                 stati you want counts for as values in the array.  An empty array returns counts
608
+	 *                                 for all valid stati.
609
+	 * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
610
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
611
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
612
+	 * @throws EE_Error
613
+	 *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
614
+	 *                                 EE_Datetime::expired
615
+	 */
616
+	public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
617
+	{
618
+		// only accept where conditions for this query.
619
+		$_where            = isset($query_params[0]) ? $query_params[0] : array();
620
+		$status_query_args = array(
621
+			EE_Datetime::active   => array_merge(
622
+				$_where,
623
+				array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
624
+			),
625
+			EE_Datetime::upcoming => array_merge(
626
+				$_where,
627
+				array('DTT_EVT_start' => array('>', time()))
628
+			),
629
+			EE_Datetime::expired  => array_merge(
630
+				$_where,
631
+				array('DTT_EVT_end' => array('<', time()))
632
+			),
633
+		);
634
+		if (! empty($stati_to_include)) {
635
+			foreach (array_keys($status_query_args) as $status) {
636
+				if (! in_array($status, $stati_to_include, true)) {
637
+					unset($status_query_args[ $status ]);
638
+				}
639
+			}
640
+		}
641
+		// loop through and query counts for each stati.
642
+		$status_query_results = array();
643
+		foreach ($status_query_args as $status => $status_where_conditions) {
644
+			$status_query_results[ $status ] = EEM_Datetime::count(
645
+				array($status_where_conditions),
646
+				'DTT_ID',
647
+				true
648
+			);
649
+		}
650
+		return $status_query_results;
651
+	}
652
+
653
+
654
+	/**
655
+	 * Returns the specific count for a given Datetime status matching any given query_params.
656
+	 *
657
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
658
+	 * @param array  $query_params
659
+	 * @return int
660
+	 * @throws EE_Error
661
+	 */
662
+	public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
663
+	{
664
+		$count = $this->get_datetime_counts_by_status(array($status), $query_params);
665
+		return ! empty($count[ $status ]) ? $count[ $status ] : 0;
666
+	}
667 667
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Currency.model.php 1 patch
Indentation   +59 added lines, -59 removed lines patch added patch discarded remove patch
@@ -11,66 +11,66 @@
 block discarded – undo
11 11
  */
12 12
 class EEM_Currency extends EEM_Base
13 13
 {
14
-        // private instance of the Attendee object
15
-    protected static $_instance = null;
14
+		// private instance of the Attendee object
15
+	protected static $_instance = null;
16 16
 
17
-    protected function __construct($timezone = null)
18
-    {
19
-        $this->singular_item = __('Currency', 'event_espresso');
20
-        $this->plural_item = __('Currencies', 'event_espresso');
21
-        $this->_tables = array(
22
-            'Currency'=> new EE_Primary_Table('esp_currency', 'CUR_code')
23
-        );
24
-        $this->_fields = array(
25
-            'Currency'=>array(
26
-                'CUR_code'=> new EE_Primary_Key_String_Field('CUR_code', __('Currency Code', 'event_espresso')),
27
-                'CUR_single' => new EE_Plain_Text_Field('CUR_single', __('Currency Name Singular', 'event_espresso'), false),
28
-                'CUR_plural' => new EE_Plain_Text_Field('CUR_plural', __('Currency Name Plural', 'event_espresso'), false),
29
-                'CUR_sign' => new EE_Plain_Text_Field('CUR_sign', __('Currency Sign', 'event_espresso'), false),
30
-                'CUR_dec_plc' => new EE_Integer_Field('CUR_dec_plc', __('Currency Decimal Places', 'event_espresso'), false, 2),
31
-                'CUR_active'=>new EE_Boolean_Field('CUR_active', __('Active?', 'event_espresso'), false, true),
32
-            ));
33
-        $this->_model_relations = array(
34
-            'Payment_Method'=>new EE_HABTM_Relation('Currency_Payment_Method'),
35
-        );
36
-        // this model is generally available for reading
37
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
17
+	protected function __construct($timezone = null)
18
+	{
19
+		$this->singular_item = __('Currency', 'event_espresso');
20
+		$this->plural_item = __('Currencies', 'event_espresso');
21
+		$this->_tables = array(
22
+			'Currency'=> new EE_Primary_Table('esp_currency', 'CUR_code')
23
+		);
24
+		$this->_fields = array(
25
+			'Currency'=>array(
26
+				'CUR_code'=> new EE_Primary_Key_String_Field('CUR_code', __('Currency Code', 'event_espresso')),
27
+				'CUR_single' => new EE_Plain_Text_Field('CUR_single', __('Currency Name Singular', 'event_espresso'), false),
28
+				'CUR_plural' => new EE_Plain_Text_Field('CUR_plural', __('Currency Name Plural', 'event_espresso'), false),
29
+				'CUR_sign' => new EE_Plain_Text_Field('CUR_sign', __('Currency Sign', 'event_espresso'), false),
30
+				'CUR_dec_plc' => new EE_Integer_Field('CUR_dec_plc', __('Currency Decimal Places', 'event_espresso'), false, 2),
31
+				'CUR_active'=>new EE_Boolean_Field('CUR_active', __('Active?', 'event_espresso'), false, true),
32
+			));
33
+		$this->_model_relations = array(
34
+			'Payment_Method'=>new EE_HABTM_Relation('Currency_Payment_Method'),
35
+		);
36
+		// this model is generally available for reading
37
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
38 38
 
39
-        parent::__construct($timezone);
40
-    }
39
+		parent::__construct($timezone);
40
+	}
41 41
 
42
-    /**
43
-     * Gets all thea ctive currencies, and orders them by their singular name, and then their code
44
-     * (may be overridden)
45
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
46
-     * @return EE_Currency[]
47
-     */
48
-    public function get_all_active($query_params = array())
49
-    {
50
-        $query_params[0]['CUR_active'] = true;
51
-        if (! isset($query_params['order_by'])) {
52
-            $query_params['order_by'] = array('CUR_code'=>'ASC','CUR_single'=>'ASC');
53
-        }
54
-        return $this->get_all($query_params);
55
-    }
56
-    /**
57
-     * Gets all the currencies which can be used by that payment method type
58
-     * @param EE_PMT_Base $payment_method_type
59
-     * @return EE_Currency[]
60
-     */
61
-    public function get_all_currencies_usable_by($payment_method_type)
62
-    {
63
-        if ($payment_method_type instanceof EE_PMT_Base &&
64
-                $payment_method_type->get_gateway()) {
65
-            $currencies_supported = $payment_method_type->get_gateway()->currencies_supported();
66
-        } else {
67
-            $currencies_supported = EE_Gateway::all_currencies_supported;
68
-        }
69
-        if ($currencies_supported == EE_Gateway::all_currencies_supported || empty($currencies_supported)) {
70
-            $currencies = $this->get_all_active();
71
-        } else {
72
-            $currencies = $this->get_all_active(array(array('CUR_code'=>array('IN',$currencies_supported))));
73
-        }
74
-        return $currencies;
75
-    }
42
+	/**
43
+	 * Gets all thea ctive currencies, and orders them by their singular name, and then their code
44
+	 * (may be overridden)
45
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
46
+	 * @return EE_Currency[]
47
+	 */
48
+	public function get_all_active($query_params = array())
49
+	{
50
+		$query_params[0]['CUR_active'] = true;
51
+		if (! isset($query_params['order_by'])) {
52
+			$query_params['order_by'] = array('CUR_code'=>'ASC','CUR_single'=>'ASC');
53
+		}
54
+		return $this->get_all($query_params);
55
+	}
56
+	/**
57
+	 * Gets all the currencies which can be used by that payment method type
58
+	 * @param EE_PMT_Base $payment_method_type
59
+	 * @return EE_Currency[]
60
+	 */
61
+	public function get_all_currencies_usable_by($payment_method_type)
62
+	{
63
+		if ($payment_method_type instanceof EE_PMT_Base &&
64
+				$payment_method_type->get_gateway()) {
65
+			$currencies_supported = $payment_method_type->get_gateway()->currencies_supported();
66
+		} else {
67
+			$currencies_supported = EE_Gateway::all_currencies_supported;
68
+		}
69
+		if ($currencies_supported == EE_Gateway::all_currencies_supported || empty($currencies_supported)) {
70
+			$currencies = $this->get_all_active();
71
+		} else {
72
+			$currencies = $this->get_all_active(array(array('CUR_code'=>array('IN',$currencies_supported))));
73
+		}
74
+		return $currencies;
75
+	}
76 76
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Payment_Method.model.php 1 patch
Indentation   +376 added lines, -376 removed lines patch added patch discarded remove patch
@@ -20,381 +20,381 @@
 block discarded – undo
20 20
 class EEM_Payment_Method extends EEM_Base
21 21
 {
22 22
 
23
-    const scope_cart = 'CART';
24
-
25
-    const scope_admin = 'ADMIN';
26
-
27
-    const scope_api = 'API';
28
-
29
-    /**
30
-     *
31
-     * @type EEM_Payment_Method
32
-     */
33
-    protected static $_instance = null;
34
-
35
-
36
-
37
-    /**
38
-     * private constructor to prevent direct creation
39
-     * @Constructor
40
-     * @access   protected
41
-     * @return EEM_Payment_Method
42
-     */
43
-    protected function __construct($timezone = null)
44
-    {
45
-        $this->singlular_item = __('Payment Method', 'event_espresso');
46
-        $this->plural_item = __('Payment Methods', 'event_espresso');
47
-        $this->_tables = array( 'Payment_Method' => new EE_Primary_Table('esp_payment_method', 'PMD_ID') );
48
-        $this->_fields = array(
49
-            'Payment_Method' => array(
50
-                'PMD_ID' => new EE_Primary_Key_Int_Field('PMD_ID', __("ID", 'event_espresso')),
51
-                'PMD_type' => new EE_Plain_Text_Field('PMD_type', __("Payment Method Type", 'event_espresso'), false, 'Admin_Only'),
52
-                'PMD_name' => new EE_Plain_Text_Field('PMD_name', __("Name", 'event_espresso'), false),
53
-                'PMD_desc' => new EE_Post_Content_Field('PMD_desc', __("Description", 'event_espresso'), false, ''),
54
-                'PMD_admin_name' => new EE_Plain_Text_Field('PMD_admin_name', __("Admin-Only Name", 'event_espresso'), true),
55
-                'PMD_admin_desc' => new EE_Post_Content_Field('PMD_admin_desc', __("Admin-Only Description", 'event_espresso'), true),
56
-                'PMD_slug' => new EE_Slug_Field('PMD_slug', __("Slug", 'event_espresso'), false),
57
-                'PMD_order' => new EE_Integer_Field('PMD_order', __("Order", 'event_espresso'), false, 0),
58
-                'PMD_debug_mode' => new EE_Boolean_Field('PMD_debug_mode', __("Debug Mode On?", 'event_espresso'), false, false),
59
-                'PMD_wp_user' => new EE_WP_User_Field('PMD_wp_user', __("Payment Method Creator ID", 'event_espresso'), false),
60
-                'PMD_open_by_default' => new EE_Boolean_Field('PMD_open_by_default', __("Open by Default?", 'event_espresso'), false, false), 'PMD_button_url' => new EE_Plain_Text_Field('PMD_button_url', __("Button URL", 'event_espresso'), true, ''),
61
-                'PMD_scope' => new EE_Serialized_Text_Field('PMD_scope', __("Usable From?", 'event_espresso'), false, array()), // possible values currently are 'CART','ADMIN','API'
62
-        ) );
63
-        $this->_model_relations = array(
23
+	const scope_cart = 'CART';
24
+
25
+	const scope_admin = 'ADMIN';
26
+
27
+	const scope_api = 'API';
28
+
29
+	/**
30
+	 *
31
+	 * @type EEM_Payment_Method
32
+	 */
33
+	protected static $_instance = null;
34
+
35
+
36
+
37
+	/**
38
+	 * private constructor to prevent direct creation
39
+	 * @Constructor
40
+	 * @access   protected
41
+	 * @return EEM_Payment_Method
42
+	 */
43
+	protected function __construct($timezone = null)
44
+	{
45
+		$this->singlular_item = __('Payment Method', 'event_espresso');
46
+		$this->plural_item = __('Payment Methods', 'event_espresso');
47
+		$this->_tables = array( 'Payment_Method' => new EE_Primary_Table('esp_payment_method', 'PMD_ID') );
48
+		$this->_fields = array(
49
+			'Payment_Method' => array(
50
+				'PMD_ID' => new EE_Primary_Key_Int_Field('PMD_ID', __("ID", 'event_espresso')),
51
+				'PMD_type' => new EE_Plain_Text_Field('PMD_type', __("Payment Method Type", 'event_espresso'), false, 'Admin_Only'),
52
+				'PMD_name' => new EE_Plain_Text_Field('PMD_name', __("Name", 'event_espresso'), false),
53
+				'PMD_desc' => new EE_Post_Content_Field('PMD_desc', __("Description", 'event_espresso'), false, ''),
54
+				'PMD_admin_name' => new EE_Plain_Text_Field('PMD_admin_name', __("Admin-Only Name", 'event_espresso'), true),
55
+				'PMD_admin_desc' => new EE_Post_Content_Field('PMD_admin_desc', __("Admin-Only Description", 'event_espresso'), true),
56
+				'PMD_slug' => new EE_Slug_Field('PMD_slug', __("Slug", 'event_espresso'), false),
57
+				'PMD_order' => new EE_Integer_Field('PMD_order', __("Order", 'event_espresso'), false, 0),
58
+				'PMD_debug_mode' => new EE_Boolean_Field('PMD_debug_mode', __("Debug Mode On?", 'event_espresso'), false, false),
59
+				'PMD_wp_user' => new EE_WP_User_Field('PMD_wp_user', __("Payment Method Creator ID", 'event_espresso'), false),
60
+				'PMD_open_by_default' => new EE_Boolean_Field('PMD_open_by_default', __("Open by Default?", 'event_espresso'), false, false), 'PMD_button_url' => new EE_Plain_Text_Field('PMD_button_url', __("Button URL", 'event_espresso'), true, ''),
61
+				'PMD_scope' => new EE_Serialized_Text_Field('PMD_scope', __("Usable From?", 'event_espresso'), false, array()), // possible values currently are 'CART','ADMIN','API'
62
+		) );
63
+		$this->_model_relations = array(
64 64
  //         'Event'=>new EE_HABTM_Relation('Event_Payment_Method'),
65
-            'Payment' => new EE_Has_Many_Relation(),
66
-            'Currency' => new EE_HABTM_Relation('Currency_Payment_Method'),
67
-            'Transaction' => new EE_Has_Many_Relation(),
68
-            'WP_User' => new EE_Belongs_To_Relation(),
69
-        );
70
-        parent::__construct($timezone);
71
-    }
72
-
73
-
74
-
75
-    /**
76
-     * Gets one by the slug provided
77
-     * @param string $slug
78
-     * @return EE_Payment_Method
79
-     */
80
-    public function get_one_by_slug($slug)
81
-    {
82
-        return $this->get_one(array( array( 'PMD_slug' => $slug ) ));
83
-    }
84
-
85
-
86
-
87
-    /**
88
-     * Gets all the acceptable scopes for payment methods.
89
-     * Keys are their names as store din the DB, and values are nice names for displaying them
90
-     * @return array
91
-     */
92
-    public function scopes()
93
-    {
94
-        return apply_filters(
95
-            'FHEE__EEM_Payment_Method__scopes',
96
-            array(
97
-                self::scope_cart        => __("Front-end Registration Page", 'event_espresso'),
98
-                self::scope_admin   => __("Admin Registration Page (no online processing)", 'event_espresso')
99
-            )
100
-        );
101
-    }
102
-
103
-
104
-
105
-    /**
106
-     * Determines if this is an valid scope
107
-     * @param string $scope like one of EEM_Payment_Method::instance()->scopes()
108
-     * @return boolean
109
-     */
110
-    public function is_valid_scope($scope)
111
-    {
112
-        $scopes = $this->scopes();
113
-        if (isset($scopes[ $scope ])) {
114
-            return true;
115
-        } else {
116
-            return false;
117
-        }
118
-    }
119
-
120
-
121
-
122
-    /**
123
-     * Gets all active payment methods
124
-     * @param string $scope one of
125
-     * @param array  $query_params
126
-     * @throws EE_Error
127
-     * @return EE_Payment_Method[]
128
-     */
129
-    public function get_all_active($scope = null, $query_params = array())
130
-    {
131
-        if (! isset($query_params['order_by']) && ! isset($query_params['order'])) {
132
-            $query_params['order_by'] = array( 'PMD_order' => 'ASC', 'PMD_ID' => 'ASC' );
133
-        }
134
-        return $this->get_all($this->_get_query_params_for_all_active($scope, $query_params));
135
-    }
136
-
137
-    /**
138
-     * Counts all active gateways in the specified scope
139
-     * @param string $scope one of EEM_Payment_Method::scope_*
140
-     * @param array $query_params
141
-     * @return int
142
-     */
143
-    public function count_active($scope = null, $query_params = array())
144
-    {
145
-        return $this->count($this->_get_query_params_for_all_active($scope, $query_params));
146
-    }
147
-
148
-    /**
149
-     * Creates the $query_params that can be passed into any EEM_Payment_Method as their $query_params
150
-     * argument to get all active for a given scope
151
-     * @param string $scope one of the constants EEM_Payment_Method::scope_*
152
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
153
-     * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
154
-     * @throws EE_Error
155
-     */
156
-    protected function _get_query_params_for_all_active($scope = null, $query_params = array())
157
-    {
158
-        if ($scope) {
159
-            if ($this->is_valid_scope($scope)) {
160
-                return array_replace_recursive(array( array( 'PMD_scope' => array( 'LIKE', "%$scope%" ) ) ), $query_params);
161
-            } else {
162
-                throw new EE_Error(sprintf(__("'%s' is not a valid scope for a payment method", "event_espresso"), $scope));
163
-            }
164
-        } else {
165
-            $acceptable_scopes = array();
166
-            $count = 0;
167
-            foreach ($this->scopes() as $scope_name => $desc) {
168
-                $count++;
169
-                $acceptable_scopes[ 'PMD_scope*' . $count ] = array( 'LIKE', '%' . $scope_name . '%' );
170
-            }
171
-            return array_replace_recursive(array( array( 'OR*active_scope' => $acceptable_scopes ) ), $query_params);
172
-        }
173
-    }
174
-
175
-    /**
176
-     * Creates the $query_params that can be passed into any EEM_Payment_Method as their $query_params
177
-     * argument to get all active for a given scope
178
-     * @param string $scope one of the constants EEM_Payment_Method::scope_*
179
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
180
-     * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
181
-     * @throws EE_Error
182
-     */
183
-    public function get_query_params_for_all_active($scope = null, $query_params = array())
184
-    {
185
-        return $this->_get_query_params_for_all_active($scope, $query_params);
186
-    }
187
-
188
-
189
-    /**
190
-     * Gets one active payment method. see @get_all_active for documentation
191
-     * @param string $scope
192
-     * @param array  $query_params
193
-     * @return EE_Payment_Method
194
-     */
195
-    public function get_one_active($scope = null, $query_params = array())
196
-    {
197
-        return $this->get_one($this->_get_query_params_for_all_active($scope, $query_params));
198
-    }
199
-
200
-
201
-
202
-    /**
203
-     * Gets one payment method of that type, regardless of whether its active or not
204
-     * @param string $type
205
-     * @return EE_Payment_Method
206
-     */
207
-    public function get_one_of_type($type)
208
-    {
209
-        return $this->get_one(array( array( 'PMD_type' => $type ) ));
210
-    }
211
-
212
-
213
-
214
-    /**
215
-     * Overrides parent ot also check by the slug
216
-     * @see EEM_Base::ensure_is_obj()
217
-     * @param string|int|EE_Payment_Method $base_class_obj_or_id
218
-     * @param boolean                      $ensure_is_in_db
219
-     * @return EE_Payment_Method
220
-     * @throws EE_Error
221
-     */
222
-    public function ensure_is_obj($base_class_obj_or_id, $ensure_is_in_db = false)
223
-    {
224
-        // first: check if it's a slug
225
-        if (is_string($base_class_obj_or_id)) {
226
-            $obj = $this->get_one_by_slug($base_class_obj_or_id);
227
-            if ($obj) {
228
-                return $obj;
229
-            }
230
-        }
231
-        // ok so it wasn't a slug we were passed. try the usual then (ie, it's an object or an ID)
232
-        try {
233
-            return parent::ensure_is_obj($base_class_obj_or_id, $ensure_is_in_db);
234
-        } catch (EE_Error $e) {
235
-            // handle it outside the catch
236
-        }
237
-        throw new EE_Error(sprintf(__("'%s' is neither a Payment Method ID, slug, nor object.", "event_espresso"), $base_class_obj_or_id));
238
-    }
239
-
240
-
241
-
242
-    /**
243
-     * Gets the ID of this object, or if its a string finds the object's id
244
-     * associated with that slug
245
-     * @param mixed $base_obj_or_id_or_slug
246
-     * @return int
247
-     */
248
-    public function ensure_is_ID($base_obj_or_id_or_slug)
249
-    {
250
-        if (is_string($base_obj_or_id_or_slug)) {
251
-            // assume it's a slug
252
-            $base_obj_or_id_or_slug = $this->get_one_by_slug($base_obj_or_id_or_slug);
253
-        }
254
-        return parent::ensure_is_ID($base_obj_or_id_or_slug);
255
-    }
256
-
257
-
258
-
259
-    /**
260
-     * Verifies the button urls on all the passed payment methods have a valid button url. If not, resets them to their default.
261
-     * @param EE_Payment_Method[] $payment_methods. If NULL is provided defaults to all payment methods active in the cart
262
-     */
263
-    public function verify_button_urls($payment_methods = null)
264
-    {
265
-        $payment_methods = is_array($payment_methods) ? $payment_methods : $this->get_all_active(EEM_Payment_Method::scope_cart);
266
-        foreach ($payment_methods as $payment_method) {
267
-            try {
268
-                $current_button_url = $payment_method->button_url();
269
-                $buttons_urls_to_try = apply_filters('FHEE__EEM_Payment_Method__verify_button_urls__button_urls_to_try', array(
270
-                    'current_ssl' => str_replace("http://", "https://", $current_button_url),
271
-                    'current' => str_replace("https://", "http://", $current_button_url),
272
-                    'default_ssl' => str_replace("http://", "https://", $payment_method->type_obj()->default_button_url()),
273
-                    'default' => str_replace("https://", "http://", $payment_method->type_obj()->default_button_url()),
274
-                ));
275
-                foreach ($buttons_urls_to_try as $button_url_to_try) {
276
-                    if ((// this is the current url and it exists, regardless of SSL issues
277
-                                $button_url_to_try == $current_button_url &&
278
-                                EEH_URL::remote_file_exists(
279
-                                    $button_url_to_try,
280
-                                    array(
281
-                                            'sslverify' => false,
282
-                                            'limit_response_size' => 4095,// we don't really care for a full response, but we do want headers at least. Lets just ask for a one block
283
-                                            )
284
-                                )
285
-                            )
286
-                            ||
287
-                            (// this is NOT the current url and it exists with a working SSL cert
288
-                                $button_url_to_try != $current_button_url &&
289
-                                EEH_URL::remote_file_exists($button_url_to_try)
290
-                            ) ) {
291
-                        if ($current_button_url != $button_url_to_try) {
292
-                            $payment_method->save(array( 'PMD_button_url' => $button_url_to_try ));
293
-                            EE_Error::add_attention(sprintf(__("Payment Method %s's button url was set to %s, because the old image either didnt exist or SSL was recently enabled.", "event_espresso"), $payment_method->name(), $button_url_to_try));
294
-                        }
295
-                        // this image exists. So if wasn't set before, now it is;
296
-                        // or if it was already set, we have nothing to do
297
-                        break;
298
-                    }
299
-                }
300
-            } catch (EE_Error $e) {
301
-                $payment_method->set_active(false);
302
-            }
303
-        }
304
-    }
305
-
306
-
307
-
308
-    /**
309
-     * Overrides parent to not only turn wpdb results into EE_Payment_Method objects,
310
-     * but also verifies the payment method type of each is a usable object. If not,
311
-     * deactivate it, sets a notification, and deactivates it
312
-     *
313
-     * @param array $rows
314
-     * @return EE_Payment_Method[]
315
-     * @throws InvalidDataTypeException
316
-     */
317
-    protected function _create_objects($rows = array())
318
-    {
319
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
320
-        $payment_methods = parent::_create_objects($rows);
321
-        /* @var $payment_methods EE_Payment_Method[] */
322
-        $usable_payment_methods = array();
323
-        foreach ($payment_methods as $key => $payment_method) {
324
-            if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($payment_method->type())) {
325
-                $usable_payment_methods[ $key ] = $payment_method;
326
-                // some payment methods enqueue their scripts in EE_PMT_*::__construct
327
-                // which is kinda a no-no (just because it's being constructed doesn't mean we need to enqueue
328
-                // its scripts). but for backwards-compat we should continue to do that
329
-                $payment_method->type_obj();
330
-            } elseif ($payment_method->active()) {
331
-                // only deactivate and notify the admin if the payment is active somewhere
332
-                $payment_method->deactivate();
333
-                $payment_method->save();
334
-                do_action(
335
-                    'AHEE__EEM_Payment_Method___create_objects_auto_deactivated_payment_method',
336
-                    $payment_method
337
-                );
338
-                new PersistentAdminNotice(
339
-                    'auto-deactivated-' . $payment_method->type(),
340
-                    sprintf(
341
-                        __(
342
-                            'The payment method %1$s was automatically deactivated because it appears its associated Event Espresso Addon was recently deactivated.%2$sIt can be reactivated on the %3$sPlugins admin page%4$s, then you can reactivate the payment method.',
343
-                            'event_espresso'
344
-                        ),
345
-                        $payment_method->admin_name(),
346
-                        '<br />',
347
-                        '<a href="' . admin_url('plugins.php') . '">',
348
-                        '</a>'
349
-                    ),
350
-                    true
351
-                );
352
-            }
353
-        }
354
-        return $usable_payment_methods;
355
-    }
356
-
357
-
358
-
359
-    /**
360
-     * Gets all the payment methods which can be used for transaction
361
-     * (according to the relations between payment methods and events, and
362
-     * the currencies used for the transaction and their relation to payment methods)
363
-     * @param EE_Transaction $transaction
364
-     * @param string    $scope @see EEM_Payment_Method::get_all_for_events
365
-     * @return EE_Payment_Method[]
366
-     */
367
-    public function get_all_for_transaction($transaction, $scope)
368
-    {
369
-        // give addons a chance to override what payment methods are chosen based on the transaction
370
-        return apply_filters(
371
-            'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
372
-            $this->get_all_active($scope, array( 'group_by' => 'PMD_type' )),
373
-            $transaction,
374
-            $scope
375
-        );
376
-    }
377
-
378
-
379
-    /**
380
-     * Returns the payment method used for the last payment made for a registration.
381
-     *
382
-     * Note: if an offline payment method was selected on the related transaction then this will have no payment methods returned.
383
-     * It will ONLY return a payment method for a PAYMENT recorded against the registration.
384
-     *
385
-     * @param EE_Registration|int $registration_or_reg_id  Either the EE_Registration object or the id for the registration.
386
-     * @return EE_Payment|null
387
-     */
388
-    public function get_last_used_for_registration($registration_or_reg_id)
389
-    {
390
-        $registration_id = EEM_Registration::instance()->ensure_is_ID($registration_or_reg_id);
391
-
392
-        $query_params = array(
393
-            0 => array(
394
-                'Payment.Registration.REG_ID' => $registration_id,
395
-            ),
396
-            'order_by' => array( 'Payment.PAY_ID' => 'DESC' )
397
-        );
398
-        return $this->get_one($query_params);
399
-    }
65
+			'Payment' => new EE_Has_Many_Relation(),
66
+			'Currency' => new EE_HABTM_Relation('Currency_Payment_Method'),
67
+			'Transaction' => new EE_Has_Many_Relation(),
68
+			'WP_User' => new EE_Belongs_To_Relation(),
69
+		);
70
+		parent::__construct($timezone);
71
+	}
72
+
73
+
74
+
75
+	/**
76
+	 * Gets one by the slug provided
77
+	 * @param string $slug
78
+	 * @return EE_Payment_Method
79
+	 */
80
+	public function get_one_by_slug($slug)
81
+	{
82
+		return $this->get_one(array( array( 'PMD_slug' => $slug ) ));
83
+	}
84
+
85
+
86
+
87
+	/**
88
+	 * Gets all the acceptable scopes for payment methods.
89
+	 * Keys are their names as store din the DB, and values are nice names for displaying them
90
+	 * @return array
91
+	 */
92
+	public function scopes()
93
+	{
94
+		return apply_filters(
95
+			'FHEE__EEM_Payment_Method__scopes',
96
+			array(
97
+				self::scope_cart        => __("Front-end Registration Page", 'event_espresso'),
98
+				self::scope_admin   => __("Admin Registration Page (no online processing)", 'event_espresso')
99
+			)
100
+		);
101
+	}
102
+
103
+
104
+
105
+	/**
106
+	 * Determines if this is an valid scope
107
+	 * @param string $scope like one of EEM_Payment_Method::instance()->scopes()
108
+	 * @return boolean
109
+	 */
110
+	public function is_valid_scope($scope)
111
+	{
112
+		$scopes = $this->scopes();
113
+		if (isset($scopes[ $scope ])) {
114
+			return true;
115
+		} else {
116
+			return false;
117
+		}
118
+	}
119
+
120
+
121
+
122
+	/**
123
+	 * Gets all active payment methods
124
+	 * @param string $scope one of
125
+	 * @param array  $query_params
126
+	 * @throws EE_Error
127
+	 * @return EE_Payment_Method[]
128
+	 */
129
+	public function get_all_active($scope = null, $query_params = array())
130
+	{
131
+		if (! isset($query_params['order_by']) && ! isset($query_params['order'])) {
132
+			$query_params['order_by'] = array( 'PMD_order' => 'ASC', 'PMD_ID' => 'ASC' );
133
+		}
134
+		return $this->get_all($this->_get_query_params_for_all_active($scope, $query_params));
135
+	}
136
+
137
+	/**
138
+	 * Counts all active gateways in the specified scope
139
+	 * @param string $scope one of EEM_Payment_Method::scope_*
140
+	 * @param array $query_params
141
+	 * @return int
142
+	 */
143
+	public function count_active($scope = null, $query_params = array())
144
+	{
145
+		return $this->count($this->_get_query_params_for_all_active($scope, $query_params));
146
+	}
147
+
148
+	/**
149
+	 * Creates the $query_params that can be passed into any EEM_Payment_Method as their $query_params
150
+	 * argument to get all active for a given scope
151
+	 * @param string $scope one of the constants EEM_Payment_Method::scope_*
152
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
153
+	 * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
154
+	 * @throws EE_Error
155
+	 */
156
+	protected function _get_query_params_for_all_active($scope = null, $query_params = array())
157
+	{
158
+		if ($scope) {
159
+			if ($this->is_valid_scope($scope)) {
160
+				return array_replace_recursive(array( array( 'PMD_scope' => array( 'LIKE', "%$scope%" ) ) ), $query_params);
161
+			} else {
162
+				throw new EE_Error(sprintf(__("'%s' is not a valid scope for a payment method", "event_espresso"), $scope));
163
+			}
164
+		} else {
165
+			$acceptable_scopes = array();
166
+			$count = 0;
167
+			foreach ($this->scopes() as $scope_name => $desc) {
168
+				$count++;
169
+				$acceptable_scopes[ 'PMD_scope*' . $count ] = array( 'LIKE', '%' . $scope_name . '%' );
170
+			}
171
+			return array_replace_recursive(array( array( 'OR*active_scope' => $acceptable_scopes ) ), $query_params);
172
+		}
173
+	}
174
+
175
+	/**
176
+	 * Creates the $query_params that can be passed into any EEM_Payment_Method as their $query_params
177
+	 * argument to get all active for a given scope
178
+	 * @param string $scope one of the constants EEM_Payment_Method::scope_*
179
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
180
+	 * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
181
+	 * @throws EE_Error
182
+	 */
183
+	public function get_query_params_for_all_active($scope = null, $query_params = array())
184
+	{
185
+		return $this->_get_query_params_for_all_active($scope, $query_params);
186
+	}
187
+
188
+
189
+	/**
190
+	 * Gets one active payment method. see @get_all_active for documentation
191
+	 * @param string $scope
192
+	 * @param array  $query_params
193
+	 * @return EE_Payment_Method
194
+	 */
195
+	public function get_one_active($scope = null, $query_params = array())
196
+	{
197
+		return $this->get_one($this->_get_query_params_for_all_active($scope, $query_params));
198
+	}
199
+
200
+
201
+
202
+	/**
203
+	 * Gets one payment method of that type, regardless of whether its active or not
204
+	 * @param string $type
205
+	 * @return EE_Payment_Method
206
+	 */
207
+	public function get_one_of_type($type)
208
+	{
209
+		return $this->get_one(array( array( 'PMD_type' => $type ) ));
210
+	}
211
+
212
+
213
+
214
+	/**
215
+	 * Overrides parent ot also check by the slug
216
+	 * @see EEM_Base::ensure_is_obj()
217
+	 * @param string|int|EE_Payment_Method $base_class_obj_or_id
218
+	 * @param boolean                      $ensure_is_in_db
219
+	 * @return EE_Payment_Method
220
+	 * @throws EE_Error
221
+	 */
222
+	public function ensure_is_obj($base_class_obj_or_id, $ensure_is_in_db = false)
223
+	{
224
+		// first: check if it's a slug
225
+		if (is_string($base_class_obj_or_id)) {
226
+			$obj = $this->get_one_by_slug($base_class_obj_or_id);
227
+			if ($obj) {
228
+				return $obj;
229
+			}
230
+		}
231
+		// ok so it wasn't a slug we were passed. try the usual then (ie, it's an object or an ID)
232
+		try {
233
+			return parent::ensure_is_obj($base_class_obj_or_id, $ensure_is_in_db);
234
+		} catch (EE_Error $e) {
235
+			// handle it outside the catch
236
+		}
237
+		throw new EE_Error(sprintf(__("'%s' is neither a Payment Method ID, slug, nor object.", "event_espresso"), $base_class_obj_or_id));
238
+	}
239
+
240
+
241
+
242
+	/**
243
+	 * Gets the ID of this object, or if its a string finds the object's id
244
+	 * associated with that slug
245
+	 * @param mixed $base_obj_or_id_or_slug
246
+	 * @return int
247
+	 */
248
+	public function ensure_is_ID($base_obj_or_id_or_slug)
249
+	{
250
+		if (is_string($base_obj_or_id_or_slug)) {
251
+			// assume it's a slug
252
+			$base_obj_or_id_or_slug = $this->get_one_by_slug($base_obj_or_id_or_slug);
253
+		}
254
+		return parent::ensure_is_ID($base_obj_or_id_or_slug);
255
+	}
256
+
257
+
258
+
259
+	/**
260
+	 * Verifies the button urls on all the passed payment methods have a valid button url. If not, resets them to their default.
261
+	 * @param EE_Payment_Method[] $payment_methods. If NULL is provided defaults to all payment methods active in the cart
262
+	 */
263
+	public function verify_button_urls($payment_methods = null)
264
+	{
265
+		$payment_methods = is_array($payment_methods) ? $payment_methods : $this->get_all_active(EEM_Payment_Method::scope_cart);
266
+		foreach ($payment_methods as $payment_method) {
267
+			try {
268
+				$current_button_url = $payment_method->button_url();
269
+				$buttons_urls_to_try = apply_filters('FHEE__EEM_Payment_Method__verify_button_urls__button_urls_to_try', array(
270
+					'current_ssl' => str_replace("http://", "https://", $current_button_url),
271
+					'current' => str_replace("https://", "http://", $current_button_url),
272
+					'default_ssl' => str_replace("http://", "https://", $payment_method->type_obj()->default_button_url()),
273
+					'default' => str_replace("https://", "http://", $payment_method->type_obj()->default_button_url()),
274
+				));
275
+				foreach ($buttons_urls_to_try as $button_url_to_try) {
276
+					if ((// this is the current url and it exists, regardless of SSL issues
277
+								$button_url_to_try == $current_button_url &&
278
+								EEH_URL::remote_file_exists(
279
+									$button_url_to_try,
280
+									array(
281
+											'sslverify' => false,
282
+											'limit_response_size' => 4095,// we don't really care for a full response, but we do want headers at least. Lets just ask for a one block
283
+											)
284
+								)
285
+							)
286
+							||
287
+							(// this is NOT the current url and it exists with a working SSL cert
288
+								$button_url_to_try != $current_button_url &&
289
+								EEH_URL::remote_file_exists($button_url_to_try)
290
+							) ) {
291
+						if ($current_button_url != $button_url_to_try) {
292
+							$payment_method->save(array( 'PMD_button_url' => $button_url_to_try ));
293
+							EE_Error::add_attention(sprintf(__("Payment Method %s's button url was set to %s, because the old image either didnt exist or SSL was recently enabled.", "event_espresso"), $payment_method->name(), $button_url_to_try));
294
+						}
295
+						// this image exists. So if wasn't set before, now it is;
296
+						// or if it was already set, we have nothing to do
297
+						break;
298
+					}
299
+				}
300
+			} catch (EE_Error $e) {
301
+				$payment_method->set_active(false);
302
+			}
303
+		}
304
+	}
305
+
306
+
307
+
308
+	/**
309
+	 * Overrides parent to not only turn wpdb results into EE_Payment_Method objects,
310
+	 * but also verifies the payment method type of each is a usable object. If not,
311
+	 * deactivate it, sets a notification, and deactivates it
312
+	 *
313
+	 * @param array $rows
314
+	 * @return EE_Payment_Method[]
315
+	 * @throws InvalidDataTypeException
316
+	 */
317
+	protected function _create_objects($rows = array())
318
+	{
319
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
320
+		$payment_methods = parent::_create_objects($rows);
321
+		/* @var $payment_methods EE_Payment_Method[] */
322
+		$usable_payment_methods = array();
323
+		foreach ($payment_methods as $key => $payment_method) {
324
+			if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($payment_method->type())) {
325
+				$usable_payment_methods[ $key ] = $payment_method;
326
+				// some payment methods enqueue their scripts in EE_PMT_*::__construct
327
+				// which is kinda a no-no (just because it's being constructed doesn't mean we need to enqueue
328
+				// its scripts). but for backwards-compat we should continue to do that
329
+				$payment_method->type_obj();
330
+			} elseif ($payment_method->active()) {
331
+				// only deactivate and notify the admin if the payment is active somewhere
332
+				$payment_method->deactivate();
333
+				$payment_method->save();
334
+				do_action(
335
+					'AHEE__EEM_Payment_Method___create_objects_auto_deactivated_payment_method',
336
+					$payment_method
337
+				);
338
+				new PersistentAdminNotice(
339
+					'auto-deactivated-' . $payment_method->type(),
340
+					sprintf(
341
+						__(
342
+							'The payment method %1$s was automatically deactivated because it appears its associated Event Espresso Addon was recently deactivated.%2$sIt can be reactivated on the %3$sPlugins admin page%4$s, then you can reactivate the payment method.',
343
+							'event_espresso'
344
+						),
345
+						$payment_method->admin_name(),
346
+						'<br />',
347
+						'<a href="' . admin_url('plugins.php') . '">',
348
+						'</a>'
349
+					),
350
+					true
351
+				);
352
+			}
353
+		}
354
+		return $usable_payment_methods;
355
+	}
356
+
357
+
358
+
359
+	/**
360
+	 * Gets all the payment methods which can be used for transaction
361
+	 * (according to the relations between payment methods and events, and
362
+	 * the currencies used for the transaction and their relation to payment methods)
363
+	 * @param EE_Transaction $transaction
364
+	 * @param string    $scope @see EEM_Payment_Method::get_all_for_events
365
+	 * @return EE_Payment_Method[]
366
+	 */
367
+	public function get_all_for_transaction($transaction, $scope)
368
+	{
369
+		// give addons a chance to override what payment methods are chosen based on the transaction
370
+		return apply_filters(
371
+			'FHEE__EEM_Payment_Method__get_all_for_transaction__payment_methods',
372
+			$this->get_all_active($scope, array( 'group_by' => 'PMD_type' )),
373
+			$transaction,
374
+			$scope
375
+		);
376
+	}
377
+
378
+
379
+	/**
380
+	 * Returns the payment method used for the last payment made for a registration.
381
+	 *
382
+	 * Note: if an offline payment method was selected on the related transaction then this will have no payment methods returned.
383
+	 * It will ONLY return a payment method for a PAYMENT recorded against the registration.
384
+	 *
385
+	 * @param EE_Registration|int $registration_or_reg_id  Either the EE_Registration object or the id for the registration.
386
+	 * @return EE_Payment|null
387
+	 */
388
+	public function get_last_used_for_registration($registration_or_reg_id)
389
+	{
390
+		$registration_id = EEM_Registration::instance()->ensure_is_ID($registration_or_reg_id);
391
+
392
+		$query_params = array(
393
+			0 => array(
394
+				'Payment.Registration.REG_ID' => $registration_id,
395
+			),
396
+			'order_by' => array( 'Payment.PAY_ID' => 'DESC' )
397
+		);
398
+		return $this->get_one($query_params);
399
+	}
400 400
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Line_Item.model.php 1 patch
Indentation   +436 added lines, -436 removed lines patch added patch discarded remove patch
@@ -32,443 +32,443 @@
 block discarded – undo
32 32
 class EEM_Line_Item extends EEM_Base
33 33
 {
34 34
 
35
-    /**
36
-     * Tax sub-total is just the total of all the taxes, which should be children
37
-     * of this line item. There should only ever be one tax sub-total, and it should
38
-     * be a direct child of. Its quantity and LIN_unit_price = 1.
39
-     */
40
-    const type_tax_sub_total = 'tax-sub-total';
41
-
42
-    /**
43
-     * Tax line items indicate a tax applied to all the taxable line items.
44
-     * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
45
-     * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
46
-     */
47
-    const type_tax = 'tax';
48
-
49
-    /**
50
-     * Indicating individual items purchased, or discounts or surcharges.
51
-     * The sum of all the regular line items  plus the tax items should equal
52
-     * the grand total.
53
-     * Possible children are sub-line-items and cancellations.
54
-     * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
55
-     * LIN_totals. Its LIN_percent = 0.
56
-     * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
57
-     * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
58
-     */
59
-    const type_line_item = 'line-item';
60
-
61
-    /**
62
-     * Line item indicating all the factors that make a single line item.
63
-     * Sub-line items should have NO children line items.
64
-     * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
65
-     * contribution towards the price of ONE of their parent items, and its LIN_total should be
66
-     *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
67
-     * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
68
-     * = LIN_percent / 100 * sum of lower-priority sibling line items..
69
-     */
70
-    const type_sub_line_item = 'sub-item';
71
-
72
-    /**
73
-     * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
74
-     * Direct children should be event subtotals.
75
-     * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
76
-     *
77
-     */
78
-    const type_sub_total = 'sub-total';
79
-
80
-    /**
81
-     * Line item for the grand total of an order. Its direct children
82
-     * should be tax subtotals and (pre-tax) subtotals, and possibly a regular line item
83
-     * indicating a transaction-wide discount/surcharge. Should have a quantity of 1, a LIN_total and LIN_unit_price of
84
-     * the entire order's mount.
85
-     */
86
-    const type_total = 'total';
87
-
88
-    /**
89
-     * When a line item is cancelled, a sub-line-item of type 'cancellation'
90
-     * should be created, indicating the quantity that were cancelled
91
-     * (because a line item could have a quantity of 1, and its cancellation item
92
-     * could be for 3, indicating that originally 4 were purchased, but 3 have been
93
-     * cancelled, and only one remains).
94
-     * When items are refunded, a cancellation line item should be made, which points
95
-     * to teh payment model object which actually refunded the payment.
96
-     * Cancellations should NOT have any children line items; the should NOT affect
97
-     * any calculations, and are only meant as a record that cancellations have occurred.
98
-     * Their LIN_percent should be 0.
99
-     */
100
-    const type_cancellation = 'cancellation';
101
-
102
-    // private instance of the EEM_Line_Item object
103
-    protected static $_instance = null;
104
-
105
-
106
-    /**
107
-     *        private constructor to prevent direct creation
108
-     * @Constructor
109
-     * @access protected
110
-     * @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)
111
-     * @return \EEM_Line_Item
112
-     */
113
-    protected function __construct($timezone)
114
-    {
115
-        $this->singular_item = __('Line Item', 'event_espresso');
116
-        $this->plural_item = __('Line Items', 'event_espresso');
117
-
118
-        $this->_tables = array(
119
-            'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID')
120
-        );
121
-        $line_items_can_be_for = apply_filters('FHEE__EEM_Line_Item__line_items_can_be_for', array('Ticket', 'Price', 'Event'));
122
-        $this->_fields = array(
123
-            'Line_Item' => array(
124
-                'LIN_ID' => new EE_Primary_Key_Int_Field('LIN_ID', __("ID", "event_espresso")),
125
-                'LIN_code' => new EE_Slug_Field('LIN_code', __("Code for index into Cart", "event_espresso"), true),
126
-                'TXN_ID' => new EE_Foreign_Key_Int_Field('TXN_ID', __("Transaction ID", "event_espresso"), true, null, 'Transaction'),
127
-                'LIN_name' => new EE_Full_HTML_Field('LIN_name', __("Line Item Name", "event_espresso"), false, ''),
128
-                'LIN_desc' => new EE_Full_HTML_Field('LIN_desc', __("Line Item Description", "event_espresso"), true),
129
-                'LIN_unit_price' => new EE_Money_Field('LIN_unit_price', __("Unit Price", "event_espresso"), false, 0),
130
-                'LIN_percent' => new EE_Float_Field('LIN_percent', __("Percent", "event_espresso"), false, 0),
131
-                'LIN_is_taxable' => new EE_Boolean_Field('LIN_is_taxable', __("Taxable", "event_espresso"), false, false),
132
-                'LIN_order' => new EE_Integer_Field('LIN_order', __("Order of Application towards total of parent", "event_espresso"), false, 1),
133
-                'LIN_total' => new EE_Money_Field('LIN_total', __("Total (unit price x quantity)", "event_espresso"), false, 0),
134
-                'LIN_quantity' => new EE_Integer_Field('LIN_quantity', __("Quantity", "event_espresso"), true, 1),
135
-                'LIN_parent' => new EE_Integer_Field('LIN_parent', __("Parent ID (this item goes towards that Line Item's total)", "event_espresso"), true, null),
136
-                'LIN_type' => new EE_Enum_Text_Field('LIN_type', __("Type", "event_espresso"), false, 'line-item', array(
137
-                        self::type_line_item => __("Line Item", "event_espresso"),
138
-                        self::type_sub_line_item => __("Sub-Item", "event_espresso"),
139
-                        self::type_sub_total => __("Subtotal", "event_espresso"),
140
-                        self::type_tax_sub_total => __("Tax Subtotal", "event_espresso"),
141
-                        self::type_tax => __("Tax", "event_espresso"),
142
-                        self::type_total => __("Total", "event_espresso"),
143
-                        self::type_cancellation => __('Cancellation', 'event_espresso')
144
-                    )),
145
-                'OBJ_ID' => new EE_Foreign_Key_Int_Field('OBJ_ID', __('ID of Item purchased.', 'event_espresso'), true, null, $line_items_can_be_for),
146
-                '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),
147
-                'LIN_timestamp' => new EE_Datetime_Field('LIN_timestamp', __('When the line item was created', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
148
-            )
149
-        );
150
-        $this->_model_relations = array(
151
-            'Transaction' => new EE_Belongs_To_Relation(),
152
-            'Ticket' => new EE_Belongs_To_Any_Relation(),
153
-            'Price' => new EE_Belongs_To_Any_Relation(),
154
-            'Event' => new EE_Belongs_To_Any_Relation()
155
-        );
156
-        $this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
157
-        $this->_caps_slug = 'transactions';
158
-        parent::__construct($timezone);
159
-    }
160
-
161
-
162
-    /**
163
-     * Gets all the line items for this transaction of the given type
164
-     * @param string $line_item_type like one of EEM_Line_Item::type_*
165
-     * @param EE_Transaction|int $transaction
166
-     * @return EE_Line_Item[]
167
-     */
168
-    public function get_all_of_type_for_transaction($line_item_type, $transaction)
169
-    {
170
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
171
-        return $this->get_all(array(array(
172
-            'LIN_type' => $line_item_type,
173
-            'TXN_ID' => $transaction
174
-        )));
175
-    }
176
-
177
-
178
-    /**
179
-     * Gets all line items unrelated to tickets that are normal line items
180
-     * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
181
-     * @param EE_Transaction|int $transaction
182
-     * @return EE_Line_Item[]
183
-     */
184
-    public function get_all_non_ticket_line_items_for_transaction($transaction)
185
-    {
186
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
187
-        return $this->get_all(array(array(
188
-            'LIN_type' => self::type_line_item,
189
-            'TXN_ID' => $transaction,
190
-            'OR' => array(
191
-                'OBJ_type*notticket' => array('!=', 'Ticket'),
192
-                'OBJ_type*null' => array('IS_NULL'))
193
-        )));
194
-    }
195
-
196
-    /**
197
-     * Deletes line items with no transaction who have passed the transaction cutoff time.
198
-     * This needs to be very efficient
199
-     * because if there are spam bots afoot there will be LOTS of line items
200
-     * @return int count of how many deleted
201
-     */
202
-    public function delete_line_items_with_no_transaction()
203
-    {
204
-        /** @type WPDB $wpdb */
205
-        global $wpdb;
206
-        $time_to_leave_alone = apply_filters(
207
-            'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone',
208
-            WEEK_IN_SECONDS
209
-        );
210
-        $query = $wpdb->prepare(
211
-            'DELETE li
35
+	/**
36
+	 * Tax sub-total is just the total of all the taxes, which should be children
37
+	 * of this line item. There should only ever be one tax sub-total, and it should
38
+	 * be a direct child of. Its quantity and LIN_unit_price = 1.
39
+	 */
40
+	const type_tax_sub_total = 'tax-sub-total';
41
+
42
+	/**
43
+	 * Tax line items indicate a tax applied to all the taxable line items.
44
+	 * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
45
+	 * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
46
+	 */
47
+	const type_tax = 'tax';
48
+
49
+	/**
50
+	 * Indicating individual items purchased, or discounts or surcharges.
51
+	 * The sum of all the regular line items  plus the tax items should equal
52
+	 * the grand total.
53
+	 * Possible children are sub-line-items and cancellations.
54
+	 * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
55
+	 * LIN_totals. Its LIN_percent = 0.
56
+	 * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
57
+	 * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
58
+	 */
59
+	const type_line_item = 'line-item';
60
+
61
+	/**
62
+	 * Line item indicating all the factors that make a single line item.
63
+	 * Sub-line items should have NO children line items.
64
+	 * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
65
+	 * contribution towards the price of ONE of their parent items, and its LIN_total should be
66
+	 *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
67
+	 * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
68
+	 * = LIN_percent / 100 * sum of lower-priority sibling line items..
69
+	 */
70
+	const type_sub_line_item = 'sub-item';
71
+
72
+	/**
73
+	 * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
74
+	 * Direct children should be event subtotals.
75
+	 * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
76
+	 *
77
+	 */
78
+	const type_sub_total = 'sub-total';
79
+
80
+	/**
81
+	 * Line item for the grand total of an order. Its direct children
82
+	 * should be tax subtotals and (pre-tax) subtotals, and possibly a regular line item
83
+	 * indicating a transaction-wide discount/surcharge. Should have a quantity of 1, a LIN_total and LIN_unit_price of
84
+	 * the entire order's mount.
85
+	 */
86
+	const type_total = 'total';
87
+
88
+	/**
89
+	 * When a line item is cancelled, a sub-line-item of type 'cancellation'
90
+	 * should be created, indicating the quantity that were cancelled
91
+	 * (because a line item could have a quantity of 1, and its cancellation item
92
+	 * could be for 3, indicating that originally 4 were purchased, but 3 have been
93
+	 * cancelled, and only one remains).
94
+	 * When items are refunded, a cancellation line item should be made, which points
95
+	 * to teh payment model object which actually refunded the payment.
96
+	 * Cancellations should NOT have any children line items; the should NOT affect
97
+	 * any calculations, and are only meant as a record that cancellations have occurred.
98
+	 * Their LIN_percent should be 0.
99
+	 */
100
+	const type_cancellation = 'cancellation';
101
+
102
+	// private instance of the EEM_Line_Item object
103
+	protected static $_instance = null;
104
+
105
+
106
+	/**
107
+	 *        private constructor to prevent direct creation
108
+	 * @Constructor
109
+	 * @access protected
110
+	 * @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)
111
+	 * @return \EEM_Line_Item
112
+	 */
113
+	protected function __construct($timezone)
114
+	{
115
+		$this->singular_item = __('Line Item', 'event_espresso');
116
+		$this->plural_item = __('Line Items', 'event_espresso');
117
+
118
+		$this->_tables = array(
119
+			'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID')
120
+		);
121
+		$line_items_can_be_for = apply_filters('FHEE__EEM_Line_Item__line_items_can_be_for', array('Ticket', 'Price', 'Event'));
122
+		$this->_fields = array(
123
+			'Line_Item' => array(
124
+				'LIN_ID' => new EE_Primary_Key_Int_Field('LIN_ID', __("ID", "event_espresso")),
125
+				'LIN_code' => new EE_Slug_Field('LIN_code', __("Code for index into Cart", "event_espresso"), true),
126
+				'TXN_ID' => new EE_Foreign_Key_Int_Field('TXN_ID', __("Transaction ID", "event_espresso"), true, null, 'Transaction'),
127
+				'LIN_name' => new EE_Full_HTML_Field('LIN_name', __("Line Item Name", "event_espresso"), false, ''),
128
+				'LIN_desc' => new EE_Full_HTML_Field('LIN_desc', __("Line Item Description", "event_espresso"), true),
129
+				'LIN_unit_price' => new EE_Money_Field('LIN_unit_price', __("Unit Price", "event_espresso"), false, 0),
130
+				'LIN_percent' => new EE_Float_Field('LIN_percent', __("Percent", "event_espresso"), false, 0),
131
+				'LIN_is_taxable' => new EE_Boolean_Field('LIN_is_taxable', __("Taxable", "event_espresso"), false, false),
132
+				'LIN_order' => new EE_Integer_Field('LIN_order', __("Order of Application towards total of parent", "event_espresso"), false, 1),
133
+				'LIN_total' => new EE_Money_Field('LIN_total', __("Total (unit price x quantity)", "event_espresso"), false, 0),
134
+				'LIN_quantity' => new EE_Integer_Field('LIN_quantity', __("Quantity", "event_espresso"), true, 1),
135
+				'LIN_parent' => new EE_Integer_Field('LIN_parent', __("Parent ID (this item goes towards that Line Item's total)", "event_espresso"), true, null),
136
+				'LIN_type' => new EE_Enum_Text_Field('LIN_type', __("Type", "event_espresso"), false, 'line-item', array(
137
+						self::type_line_item => __("Line Item", "event_espresso"),
138
+						self::type_sub_line_item => __("Sub-Item", "event_espresso"),
139
+						self::type_sub_total => __("Subtotal", "event_espresso"),
140
+						self::type_tax_sub_total => __("Tax Subtotal", "event_espresso"),
141
+						self::type_tax => __("Tax", "event_espresso"),
142
+						self::type_total => __("Total", "event_espresso"),
143
+						self::type_cancellation => __('Cancellation', 'event_espresso')
144
+					)),
145
+				'OBJ_ID' => new EE_Foreign_Key_Int_Field('OBJ_ID', __('ID of Item purchased.', 'event_espresso'), true, null, $line_items_can_be_for),
146
+				'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),
147
+				'LIN_timestamp' => new EE_Datetime_Field('LIN_timestamp', __('When the line item was created', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
148
+			)
149
+		);
150
+		$this->_model_relations = array(
151
+			'Transaction' => new EE_Belongs_To_Relation(),
152
+			'Ticket' => new EE_Belongs_To_Any_Relation(),
153
+			'Price' => new EE_Belongs_To_Any_Relation(),
154
+			'Event' => new EE_Belongs_To_Any_Relation()
155
+		);
156
+		$this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
157
+		$this->_caps_slug = 'transactions';
158
+		parent::__construct($timezone);
159
+	}
160
+
161
+
162
+	/**
163
+	 * Gets all the line items for this transaction of the given type
164
+	 * @param string $line_item_type like one of EEM_Line_Item::type_*
165
+	 * @param EE_Transaction|int $transaction
166
+	 * @return EE_Line_Item[]
167
+	 */
168
+	public function get_all_of_type_for_transaction($line_item_type, $transaction)
169
+	{
170
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
171
+		return $this->get_all(array(array(
172
+			'LIN_type' => $line_item_type,
173
+			'TXN_ID' => $transaction
174
+		)));
175
+	}
176
+
177
+
178
+	/**
179
+	 * Gets all line items unrelated to tickets that are normal line items
180
+	 * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
181
+	 * @param EE_Transaction|int $transaction
182
+	 * @return EE_Line_Item[]
183
+	 */
184
+	public function get_all_non_ticket_line_items_for_transaction($transaction)
185
+	{
186
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
187
+		return $this->get_all(array(array(
188
+			'LIN_type' => self::type_line_item,
189
+			'TXN_ID' => $transaction,
190
+			'OR' => array(
191
+				'OBJ_type*notticket' => array('!=', 'Ticket'),
192
+				'OBJ_type*null' => array('IS_NULL'))
193
+		)));
194
+	}
195
+
196
+	/**
197
+	 * Deletes line items with no transaction who have passed the transaction cutoff time.
198
+	 * This needs to be very efficient
199
+	 * because if there are spam bots afoot there will be LOTS of line items
200
+	 * @return int count of how many deleted
201
+	 */
202
+	public function delete_line_items_with_no_transaction()
203
+	{
204
+		/** @type WPDB $wpdb */
205
+		global $wpdb;
206
+		$time_to_leave_alone = apply_filters(
207
+			'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone',
208
+			WEEK_IN_SECONDS
209
+		);
210
+		$query = $wpdb->prepare(
211
+			'DELETE li
212 212
 				FROM ' . $this->table() . ' li
213 213
 				LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID
214 214
 				WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s',
215
-            // use GMT time because that's what TXN_timestamps are in
216
-            date('Y-m-d H:i:s', time() - $time_to_leave_alone)
217
-        );
218
-        return $wpdb->query($query);
219
-    }
220
-
221
-
222
-    /**
223
-     * get_line_item_for_transaction_object
224
-     * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
225
-     *
226
-     * @param int $TXN_ID
227
-     * @param \EE_Base_Class $object
228
-     * @return EE_Line_Item[]
229
-     */
230
-    public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object)
231
-    {
232
-        return $this->get_all(array(array(
233
-            'TXN_ID' => $TXN_ID,
234
-            'OBJ_type' => str_replace('EE_', '', get_class($object)),
235
-            'OBJ_ID' => $object->ID()
236
-        )));
237
-    }
238
-
239
-
240
-    /**
241
-     * get_object_line_items_for_transaction
242
-     * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
243
-     *
244
-     * @param int $TXN_ID
245
-     * @param string $OBJ_type
246
-     * @param array $OBJ_IDs
247
-     * @return EE_Line_Item[]
248
-     */
249
-    public function get_object_line_items_for_transaction($TXN_ID, $OBJ_type = 'Event', $OBJ_IDs = array())
250
-    {
251
-        $query_params = array(
252
-            'OBJ_type' => $OBJ_type,
253
-            // if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
254
-            'OBJ_ID' => is_array($OBJ_IDs) && !isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
255
-        );
256
-        if ($TXN_ID) {
257
-            $query_params['TXN_ID'] = $TXN_ID;
258
-        }
259
-        return $this->get_all(array($query_params));
260
-    }
261
-
262
-
263
-    /**
264
-     * get_all_ticket_line_items_for_transaction
265
-     *
266
-     * @param EE_Transaction $transaction
267
-     * @return EE_Line_Item[]
268
-     */
269
-    public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction)
270
-    {
271
-        return $this->get_all(array(
272
-            array(
273
-                'TXN_ID' => $transaction->ID(),
274
-                'OBJ_type' => 'Ticket',
275
-            )
276
-        ));
277
-    }
278
-
279
-
280
-    /**
281
-     * get_ticket_line_item_for_transaction
282
-     *
283
-     * @param int $TXN_ID
284
-     * @param int $TKT_ID
285
-     * @return \EE_Line_Item
286
-     */
287
-    public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID)
288
-    {
289
-        return $this->get_one(array(
290
-            array(
291
-                'TXN_ID' => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
292
-                'OBJ_ID' => $TKT_ID,
293
-                'OBJ_type' => 'Ticket',
294
-            )
295
-        ));
296
-    }
297
-
298
-
299
-    /**
300
-     * get_existing_promotion_line_item
301
-     * searches the cart for existing line items for the specified promotion
302
-     *
303
-     * @since   1.0.0
304
-     *
305
-     * @param EE_Line_Item $parent_line_item
306
-     * @param EE_Promotion $promotion
307
-     * @return EE_Line_Item
308
-     */
309
-    public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion)
310
-    {
311
-        return $this->get_one(array(
312
-            array(
313
-                'TXN_ID' => $parent_line_item->TXN_ID(),
314
-                'LIN_parent' => $parent_line_item->ID(),
315
-                'OBJ_type' => 'Promotion',
316
-                'OBJ_ID' => $promotion->ID()
317
-            )
318
-        ));
319
-    }
320
-
321
-
322
-    /**
323
-     * get_all_promotion_line_items
324
-     * searches the cart for any and all existing promotion line items
325
-     *
326
-     * @since   1.0.0
327
-     *
328
-     * @param EE_Line_Item $parent_line_item
329
-     * @return EE_Line_Item[]
330
-     */
331
-    public function get_all_promotion_line_items(EE_Line_Item $parent_line_item)
332
-    {
333
-        return $this->get_all(array(
334
-            array(
335
-                'TXN_ID' => $parent_line_item->TXN_ID(),
336
-                'LIN_parent' => $parent_line_item->ID(),
337
-                'OBJ_type' => 'Promotion'
338
-            )
339
-        ));
340
-    }
341
-
342
-    /**
343
-     * Gets the registration's corresponding line item.
344
-     * Note: basically does NOT support having multiple line items for a single ticket,
345
-     * which would happen if some of the registrations had a price modifier while others didn't.
346
-     * In order to support that, we'd probably need a LIN_ID on registrations or something.
347
-     * @param EE_Registration $registration
348
-     * @return EE_Line_ITem
349
-     */
350
-    public function get_line_item_for_registration(EE_Registration $registration)
351
-    {
352
-        return $this->get_one($this->line_item_for_registration_query_params($registration));
353
-    }
354
-
355
-    /**
356
-     * Gets the query params used to retrieve a specific line item for the given registration
357
-     * @param EE_Registration $registration
358
-     * @param array $original_query_params any extra query params you'd like to be merged with
359
-     * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
360
-     */
361
-    public function line_item_for_registration_query_params(EE_Registration $registration, $original_query_params = array())
362
-    {
363
-        return array_replace_recursive($original_query_params, array(
364
-            array(
365
-                'OBJ_ID' => $registration->ticket_ID(),
366
-                'OBJ_type' => 'Ticket',
367
-                'TXN_ID' => $registration->transaction_ID()
368
-            )
369
-        ));
370
-    }
371
-
372
-
373
-    /**
374
-     * @return EE_Base_Class[]|EE_Line_Item[]
375
-     * @throws InvalidInterfaceException
376
-     * @throws InvalidDataTypeException
377
-     * @throws EE_Error
378
-     * @throws InvalidArgumentException
379
-     */
380
-    public function get_total_line_items_with_no_transaction()
381
-    {
382
-        return $this->get_total_line_items_for_carts();
383
-    }
384
-
385
-
386
-    /**
387
-     * @return EE_Base_Class[]|EE_Line_Item[]
388
-     * @throws InvalidInterfaceException
389
-     * @throws InvalidDataTypeException
390
-     * @throws EE_Error
391
-     * @throws InvalidArgumentException
392
-     */
393
-    public function get_total_line_items_for_active_carts()
394
-    {
395
-        return $this->get_total_line_items_for_carts(false);
396
-    }
397
-
398
-
399
-    /**
400
-     * @return EE_Base_Class[]|EE_Line_Item[]
401
-     * @throws InvalidInterfaceException
402
-     * @throws InvalidDataTypeException
403
-     * @throws EE_Error
404
-     * @throws InvalidArgumentException
405
-     */
406
-    public function get_total_line_items_for_expired_carts()
407
-    {
408
-        return $this->get_total_line_items_for_carts(true);
409
-    }
410
-
411
-
412
-    /**
413
-     * Returns an array of grand total line items where the TXN_ID is 0.
414
-     * If $expired is set to true, then only line items for expired sessions will be returned.
415
-     * If $expired is set to false, then only line items for active sessions will be returned.
416
-     *
417
-     * @param null $expired
418
-     * @return EE_Base_Class[]|EE_Line_Item[]
419
-     * @throws EE_Error
420
-     * @throws InvalidArgumentException
421
-     * @throws InvalidDataTypeException
422
-     * @throws InvalidInterfaceException
423
-     */
424
-    private function get_total_line_items_for_carts($expired = null)
425
-    {
426
-        $where_params = array(
427
-            'TXN_ID' => 0,
428
-            'LIN_type' => 'total',
429
-        );
430
-        if ($expired !== null) {
431
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
432
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
433
-                'EventEspresso\core\domain\values\session\SessionLifespan'
434
-            );
435
-            $where_params['LIN_timestamp'] = array(
436
-                $expired ? '<=' : '>',
437
-                $session_lifespan->expiration(),
438
-            );
439
-        }
440
-        return $this->get_all(array($where_params));
441
-    }
442
-
443
-
444
-    /**
445
-     * Returns an array of ticket total line items where the TXN_ID is 0
446
-     * AND the timestamp is older than the session lifespan.
447
-     *
448
-     * @param int $timestamp
449
-     * @return EE_Base_Class[]|EE_Line_Item[]
450
-     * @throws EE_Error
451
-     * @throws InvalidArgumentException
452
-     * @throws InvalidDataTypeException
453
-     * @throws InvalidInterfaceException
454
-     */
455
-    public function getTicketLineItemsForExpiredCarts($timestamp = 0)
456
-    {
457
-        if (! absint($timestamp)) {
458
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
459
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
460
-                'EventEspresso\core\domain\values\session\SessionLifespan'
461
-            );
462
-            $timestamp = $session_lifespan->expiration();
463
-        }
464
-        return $this->get_all(
465
-            array(
466
-                array(
467
-                    'TXN_ID'        => 0,
468
-                    'OBJ_type'      => 'Ticket',
469
-                    'LIN_timestamp' => array('<=', $timestamp),
470
-                )
471
-            )
472
-        );
473
-    }
215
+			// use GMT time because that's what TXN_timestamps are in
216
+			date('Y-m-d H:i:s', time() - $time_to_leave_alone)
217
+		);
218
+		return $wpdb->query($query);
219
+	}
220
+
221
+
222
+	/**
223
+	 * get_line_item_for_transaction_object
224
+	 * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
225
+	 *
226
+	 * @param int $TXN_ID
227
+	 * @param \EE_Base_Class $object
228
+	 * @return EE_Line_Item[]
229
+	 */
230
+	public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object)
231
+	{
232
+		return $this->get_all(array(array(
233
+			'TXN_ID' => $TXN_ID,
234
+			'OBJ_type' => str_replace('EE_', '', get_class($object)),
235
+			'OBJ_ID' => $object->ID()
236
+		)));
237
+	}
238
+
239
+
240
+	/**
241
+	 * get_object_line_items_for_transaction
242
+	 * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
243
+	 *
244
+	 * @param int $TXN_ID
245
+	 * @param string $OBJ_type
246
+	 * @param array $OBJ_IDs
247
+	 * @return EE_Line_Item[]
248
+	 */
249
+	public function get_object_line_items_for_transaction($TXN_ID, $OBJ_type = 'Event', $OBJ_IDs = array())
250
+	{
251
+		$query_params = array(
252
+			'OBJ_type' => $OBJ_type,
253
+			// if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
254
+			'OBJ_ID' => is_array($OBJ_IDs) && !isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
255
+		);
256
+		if ($TXN_ID) {
257
+			$query_params['TXN_ID'] = $TXN_ID;
258
+		}
259
+		return $this->get_all(array($query_params));
260
+	}
261
+
262
+
263
+	/**
264
+	 * get_all_ticket_line_items_for_transaction
265
+	 *
266
+	 * @param EE_Transaction $transaction
267
+	 * @return EE_Line_Item[]
268
+	 */
269
+	public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction)
270
+	{
271
+		return $this->get_all(array(
272
+			array(
273
+				'TXN_ID' => $transaction->ID(),
274
+				'OBJ_type' => 'Ticket',
275
+			)
276
+		));
277
+	}
278
+
279
+
280
+	/**
281
+	 * get_ticket_line_item_for_transaction
282
+	 *
283
+	 * @param int $TXN_ID
284
+	 * @param int $TKT_ID
285
+	 * @return \EE_Line_Item
286
+	 */
287
+	public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID)
288
+	{
289
+		return $this->get_one(array(
290
+			array(
291
+				'TXN_ID' => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
292
+				'OBJ_ID' => $TKT_ID,
293
+				'OBJ_type' => 'Ticket',
294
+			)
295
+		));
296
+	}
297
+
298
+
299
+	/**
300
+	 * get_existing_promotion_line_item
301
+	 * searches the cart for existing line items for the specified promotion
302
+	 *
303
+	 * @since   1.0.0
304
+	 *
305
+	 * @param EE_Line_Item $parent_line_item
306
+	 * @param EE_Promotion $promotion
307
+	 * @return EE_Line_Item
308
+	 */
309
+	public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion)
310
+	{
311
+		return $this->get_one(array(
312
+			array(
313
+				'TXN_ID' => $parent_line_item->TXN_ID(),
314
+				'LIN_parent' => $parent_line_item->ID(),
315
+				'OBJ_type' => 'Promotion',
316
+				'OBJ_ID' => $promotion->ID()
317
+			)
318
+		));
319
+	}
320
+
321
+
322
+	/**
323
+	 * get_all_promotion_line_items
324
+	 * searches the cart for any and all existing promotion line items
325
+	 *
326
+	 * @since   1.0.0
327
+	 *
328
+	 * @param EE_Line_Item $parent_line_item
329
+	 * @return EE_Line_Item[]
330
+	 */
331
+	public function get_all_promotion_line_items(EE_Line_Item $parent_line_item)
332
+	{
333
+		return $this->get_all(array(
334
+			array(
335
+				'TXN_ID' => $parent_line_item->TXN_ID(),
336
+				'LIN_parent' => $parent_line_item->ID(),
337
+				'OBJ_type' => 'Promotion'
338
+			)
339
+		));
340
+	}
341
+
342
+	/**
343
+	 * Gets the registration's corresponding line item.
344
+	 * Note: basically does NOT support having multiple line items for a single ticket,
345
+	 * which would happen if some of the registrations had a price modifier while others didn't.
346
+	 * In order to support that, we'd probably need a LIN_ID on registrations or something.
347
+	 * @param EE_Registration $registration
348
+	 * @return EE_Line_ITem
349
+	 */
350
+	public function get_line_item_for_registration(EE_Registration $registration)
351
+	{
352
+		return $this->get_one($this->line_item_for_registration_query_params($registration));
353
+	}
354
+
355
+	/**
356
+	 * Gets the query params used to retrieve a specific line item for the given registration
357
+	 * @param EE_Registration $registration
358
+	 * @param array $original_query_params any extra query params you'd like to be merged with
359
+	 * @return array @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
360
+	 */
361
+	public function line_item_for_registration_query_params(EE_Registration $registration, $original_query_params = array())
362
+	{
363
+		return array_replace_recursive($original_query_params, array(
364
+			array(
365
+				'OBJ_ID' => $registration->ticket_ID(),
366
+				'OBJ_type' => 'Ticket',
367
+				'TXN_ID' => $registration->transaction_ID()
368
+			)
369
+		));
370
+	}
371
+
372
+
373
+	/**
374
+	 * @return EE_Base_Class[]|EE_Line_Item[]
375
+	 * @throws InvalidInterfaceException
376
+	 * @throws InvalidDataTypeException
377
+	 * @throws EE_Error
378
+	 * @throws InvalidArgumentException
379
+	 */
380
+	public function get_total_line_items_with_no_transaction()
381
+	{
382
+		return $this->get_total_line_items_for_carts();
383
+	}
384
+
385
+
386
+	/**
387
+	 * @return EE_Base_Class[]|EE_Line_Item[]
388
+	 * @throws InvalidInterfaceException
389
+	 * @throws InvalidDataTypeException
390
+	 * @throws EE_Error
391
+	 * @throws InvalidArgumentException
392
+	 */
393
+	public function get_total_line_items_for_active_carts()
394
+	{
395
+		return $this->get_total_line_items_for_carts(false);
396
+	}
397
+
398
+
399
+	/**
400
+	 * @return EE_Base_Class[]|EE_Line_Item[]
401
+	 * @throws InvalidInterfaceException
402
+	 * @throws InvalidDataTypeException
403
+	 * @throws EE_Error
404
+	 * @throws InvalidArgumentException
405
+	 */
406
+	public function get_total_line_items_for_expired_carts()
407
+	{
408
+		return $this->get_total_line_items_for_carts(true);
409
+	}
410
+
411
+
412
+	/**
413
+	 * Returns an array of grand total line items where the TXN_ID is 0.
414
+	 * If $expired is set to true, then only line items for expired sessions will be returned.
415
+	 * If $expired is set to false, then only line items for active sessions will be returned.
416
+	 *
417
+	 * @param null $expired
418
+	 * @return EE_Base_Class[]|EE_Line_Item[]
419
+	 * @throws EE_Error
420
+	 * @throws InvalidArgumentException
421
+	 * @throws InvalidDataTypeException
422
+	 * @throws InvalidInterfaceException
423
+	 */
424
+	private function get_total_line_items_for_carts($expired = null)
425
+	{
426
+		$where_params = array(
427
+			'TXN_ID' => 0,
428
+			'LIN_type' => 'total',
429
+		);
430
+		if ($expired !== null) {
431
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
432
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
433
+				'EventEspresso\core\domain\values\session\SessionLifespan'
434
+			);
435
+			$where_params['LIN_timestamp'] = array(
436
+				$expired ? '<=' : '>',
437
+				$session_lifespan->expiration(),
438
+			);
439
+		}
440
+		return $this->get_all(array($where_params));
441
+	}
442
+
443
+
444
+	/**
445
+	 * Returns an array of ticket total line items where the TXN_ID is 0
446
+	 * AND the timestamp is older than the session lifespan.
447
+	 *
448
+	 * @param int $timestamp
449
+	 * @return EE_Base_Class[]|EE_Line_Item[]
450
+	 * @throws EE_Error
451
+	 * @throws InvalidArgumentException
452
+	 * @throws InvalidDataTypeException
453
+	 * @throws InvalidInterfaceException
454
+	 */
455
+	public function getTicketLineItemsForExpiredCarts($timestamp = 0)
456
+	{
457
+		if (! absint($timestamp)) {
458
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
459
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
460
+				'EventEspresso\core\domain\values\session\SessionLifespan'
461
+			);
462
+			$timestamp = $session_lifespan->expiration();
463
+		}
464
+		return $this->get_all(
465
+			array(
466
+				array(
467
+					'TXN_ID'        => 0,
468
+					'OBJ_type'      => 'Ticket',
469
+					'LIN_timestamp' => array('<=', $timestamp),
470
+				)
471
+			)
472
+		);
473
+	}
474 474
 }
Please login to merge, or discard this patch.
core/db_models/relations/EE_Belongs_To_Relation.php 1 patch
Indentation   +123 added lines, -123 removed lines patch added patch discarded remove patch
@@ -12,137 +12,137 @@
 block discarded – undo
12 12
 class EE_Belongs_To_Relation extends EE_Model_Relation_Base
13 13
 {
14 14
 
15
-    /**
16
-     * Object representing the relationship between two models. Belongs_To means that THIS model has the foreign key
17
-     * to the other model. This knows how to join the models,
18
-     * get related models across the relation, and add-and-remove the relationships.
19
-     *
20
-     * @param boolean $block_deletes                                For Belongs_To relations, this is set to FALSE by
21
-     *                                                              default. if there are related models across this
22
-     *                                                              relation, block (prevent and add an error) the
23
-     *                                                              deletion of this model
24
-     * @param string  $related_model_objects_deletion_error_message a customized error message on blocking deletes
25
-     *                                                              instead of the default
26
-     */
27
-    public function __construct($block_deletes = false, $related_model_objects_deletion_error_message = null)
28
-    {
29
-        parent::__construct($block_deletes, $related_model_objects_deletion_error_message);
30
-    }
15
+	/**
16
+	 * Object representing the relationship between two models. Belongs_To means that THIS model has the foreign key
17
+	 * to the other model. This knows how to join the models,
18
+	 * get related models across the relation, and add-and-remove the relationships.
19
+	 *
20
+	 * @param boolean $block_deletes                                For Belongs_To relations, this is set to FALSE by
21
+	 *                                                              default. if there are related models across this
22
+	 *                                                              relation, block (prevent and add an error) the
23
+	 *                                                              deletion of this model
24
+	 * @param string  $related_model_objects_deletion_error_message a customized error message on blocking deletes
25
+	 *                                                              instead of the default
26
+	 */
27
+	public function __construct($block_deletes = false, $related_model_objects_deletion_error_message = null)
28
+	{
29
+		parent::__construct($block_deletes, $related_model_objects_deletion_error_message);
30
+	}
31 31
 
32 32
 
33
-    /**
34
-     * get_join_statement
35
-     *
36
-     * @param string $model_relation_chain
37
-     * @return string
38
-     * @throws \EE_Error
39
-     */
40
-    public function get_join_statement($model_relation_chain)
41
-    {
42
-        // create the sql string like
43
-        $this_table_fk_field  = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
44
-        $other_table_pk_field = $this->get_other_model()->get_primary_key_field();
45
-        $this_table_alias     = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
46
-            $model_relation_chain,
47
-            $this->get_this_model()->get_this_model_name()
48
-        ) . $this_table_fk_field->get_table_alias();
49
-        $other_table_alias    = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
50
-            $model_relation_chain,
51
-            $this->get_other_model()->get_this_model_name()
52
-        ) . $other_table_pk_field->get_table_alias();
53
-        $other_table          = $this->get_other_model()->get_table_for_alias($other_table_alias);
54
-        return $this->_left_join(
55
-            $other_table,
56
-            $other_table_alias,
57
-            $other_table_pk_field->get_table_column(),
58
-            $this_table_alias,
59
-            $this_table_fk_field->get_table_column()
60
-        ) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
61
-    }
33
+	/**
34
+	 * get_join_statement
35
+	 *
36
+	 * @param string $model_relation_chain
37
+	 * @return string
38
+	 * @throws \EE_Error
39
+	 */
40
+	public function get_join_statement($model_relation_chain)
41
+	{
42
+		// create the sql string like
43
+		$this_table_fk_field  = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
44
+		$other_table_pk_field = $this->get_other_model()->get_primary_key_field();
45
+		$this_table_alias     = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
46
+			$model_relation_chain,
47
+			$this->get_this_model()->get_this_model_name()
48
+		) . $this_table_fk_field->get_table_alias();
49
+		$other_table_alias    = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
50
+			$model_relation_chain,
51
+			$this->get_other_model()->get_this_model_name()
52
+		) . $other_table_pk_field->get_table_alias();
53
+		$other_table          = $this->get_other_model()->get_table_for_alias($other_table_alias);
54
+		return $this->_left_join(
55
+			$other_table,
56
+			$other_table_alias,
57
+			$other_table_pk_field->get_table_column(),
58
+			$this_table_alias,
59
+			$this_table_fk_field->get_table_column()
60
+		) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
61
+	}
62 62
 
63 63
 
64
-    /**
65
-     * Sets this model object's foreign key to the other model object's primary key. Feel free to do this manually if
66
-     * you like.
67
-     *
68
-     * @param EE_Base_Class|int $this_obj_or_id
69
-     * @param EE_Base_Class|int $other_obj_or_id
70
-     * @param array             $extra_join_model_fields_n_values
71
-     * @return \EE_Base_Class
72
-     * @throws \EE_Error
73
-     */
74
-    public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
75
-    {
76
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
77
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
78
-        // find the field on the other model which is a foreign key to this model
79
-        $fk_on_this_model = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
80
-        if ($this_model_obj->get($fk_on_this_model->get_name()) != $other_model_obj->ID()) {
81
-            // set that field on the other model to this model's ID
82
-            $this_model_obj->set($fk_on_this_model->get_name(), $other_model_obj->ID());
83
-            $this_model_obj->save();
84
-        }
85
-        return $other_model_obj;
86
-    }
64
+	/**
65
+	 * Sets this model object's foreign key to the other model object's primary key. Feel free to do this manually if
66
+	 * you like.
67
+	 *
68
+	 * @param EE_Base_Class|int $this_obj_or_id
69
+	 * @param EE_Base_Class|int $other_obj_or_id
70
+	 * @param array             $extra_join_model_fields_n_values
71
+	 * @return \EE_Base_Class
72
+	 * @throws \EE_Error
73
+	 */
74
+	public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
75
+	{
76
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
77
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
78
+		// find the field on the other model which is a foreign key to this model
79
+		$fk_on_this_model = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
80
+		if ($this_model_obj->get($fk_on_this_model->get_name()) != $other_model_obj->ID()) {
81
+			// set that field on the other model to this model's ID
82
+			$this_model_obj->set($fk_on_this_model->get_name(), $other_model_obj->ID());
83
+			$this_model_obj->save();
84
+		}
85
+		return $other_model_obj;
86
+	}
87 87
 
88 88
 
89
-    /**
90
-     * Sets the this model object's foreign key to its default, instead of pointing to the other model object
91
-     *
92
-     * @param EE_Base_Class|int $this_obj_or_id
93
-     * @param EE_Base_Class|int $other_obj_or_id
94
-     * @param array             $where_query
95
-     * @return \EE_Base_Class
96
-     * @throws \EE_Error
97
-     */
98
-    public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
99
-    {
100
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
101
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
102
-        // find the field on the other model which is a foreign key to this model
103
-        $fk_on_this_model = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
104
-        // set that field on the other model to this model's ID
105
-        $this_model_obj->set($fk_on_this_model->get_name(), null, true);
106
-        $this_model_obj->save();
107
-        return $other_model_obj;
108
-    }
89
+	/**
90
+	 * Sets the this model object's foreign key to its default, instead of pointing to the other model object
91
+	 *
92
+	 * @param EE_Base_Class|int $this_obj_or_id
93
+	 * @param EE_Base_Class|int $other_obj_or_id
94
+	 * @param array             $where_query
95
+	 * @return \EE_Base_Class
96
+	 * @throws \EE_Error
97
+	 */
98
+	public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
99
+	{
100
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
101
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
102
+		// find the field on the other model which is a foreign key to this model
103
+		$fk_on_this_model = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
104
+		// set that field on the other model to this model's ID
105
+		$this_model_obj->set($fk_on_this_model->get_name(), null, true);
106
+		$this_model_obj->save();
107
+		return $other_model_obj;
108
+	}
109 109
 
110 110
 
111
-    /**
112
-     * Overrides parent so that we don't NEED to save the $model_object before getting the related objects.
113
-     *
114
-     * @param EE_Base_Class $model_obj_or_id
115
-     * @param array         $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
116
-     * @param boolean       $values_already_prepared_by_model_object @deprecated since 4.8.1
117
-     * @return EE_Base_Class[]
118
-     * @throws \EE_Error
119
-     */
120
-    public function get_all_related(
121
-        $model_obj_or_id,
122
-        $query_params = array(),
123
-        $values_already_prepared_by_model_object = false
124
-    ) {
125
-        if ($values_already_prepared_by_model_object !== false) {
126
-            EE_Error::doing_it_wrong(
127
-                'EE_Model_Relation_Base::get_all_related',
128
-                __('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
129
-                '4.8.1'
130
-            );
131
-        }
132
-        // get column on this model object which is a foreign key to the other model
133
-        $fk_field_obj = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
134
-        // get its value
135
-        if ($model_obj_or_id instanceof EE_Base_Class) {
136
-            $model_obj = $model_obj_or_id;
137
-        } else {
138
-            $model_obj = $this->get_this_model()->ensure_is_obj($model_obj_or_id);
139
-        }
140
-        $ID_value_on_other_model = $model_obj->get($fk_field_obj->get_name());
141
-        // get all where their PK matches that value
142
-        $query_params[0][ $this->get_other_model()->get_primary_key_field()->get_name() ] = $ID_value_on_other_model;
143
-        $query_params                                                                   = $this->_disable_default_where_conditions_on_query_param($query_params);
111
+	/**
112
+	 * Overrides parent so that we don't NEED to save the $model_object before getting the related objects.
113
+	 *
114
+	 * @param EE_Base_Class $model_obj_or_id
115
+	 * @param array         $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
116
+	 * @param boolean       $values_already_prepared_by_model_object @deprecated since 4.8.1
117
+	 * @return EE_Base_Class[]
118
+	 * @throws \EE_Error
119
+	 */
120
+	public function get_all_related(
121
+		$model_obj_or_id,
122
+		$query_params = array(),
123
+		$values_already_prepared_by_model_object = false
124
+	) {
125
+		if ($values_already_prepared_by_model_object !== false) {
126
+			EE_Error::doing_it_wrong(
127
+				'EE_Model_Relation_Base::get_all_related',
128
+				__('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
129
+				'4.8.1'
130
+			);
131
+		}
132
+		// get column on this model object which is a foreign key to the other model
133
+		$fk_field_obj = $this->get_this_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
134
+		// get its value
135
+		if ($model_obj_or_id instanceof EE_Base_Class) {
136
+			$model_obj = $model_obj_or_id;
137
+		} else {
138
+			$model_obj = $this->get_this_model()->ensure_is_obj($model_obj_or_id);
139
+		}
140
+		$ID_value_on_other_model = $model_obj->get($fk_field_obj->get_name());
141
+		// get all where their PK matches that value
142
+		$query_params[0][ $this->get_other_model()->get_primary_key_field()->get_name() ] = $ID_value_on_other_model;
143
+		$query_params                                                                   = $this->_disable_default_where_conditions_on_query_param($query_params);
144 144
 //      echo '$query_params';
145 145
 //      var_dump($query_params);
146
-        return $this->get_other_model()->get_all($query_params);
147
-    }
146
+		return $this->get_other_model()->get_all($query_params);
147
+	}
148 148
 }
Please login to merge, or discard this patch.
core/db_models/relations/EE_Has_Many_Revision_Relation.php 1 patch
Indentation   +296 added lines, -296 removed lines patch added patch discarded remove patch
@@ -12,303 +12,303 @@
 block discarded – undo
12 12
 {
13 13
 
14 14
 
15
-    /**
16
-     * The Foreign key on the model that acts as the PRIMARY KEY used in special autosave handling where we query for
17
-     * autosaves (or the Foreign key on other models in relations pointing to this models primary key which is this
18
-     * value).  The _primary_cpt_field is what is equivalent to the post_id field on a cpt join.
19
-     *
20
-     * @var string
21
-     */
22
-    private $_primary_cpt_field;
23
-
24
-
25
-    /**
26
-     * This is what field serves as the "parent" column that is linked with whatever the main model's calling this
27
-     * relation has as a primary key.  In other words EEM_Event has 'Datetime' => new
28
-     * EE_Has_Many_Revision_Relation('EVT_ID', 'DTT_parent').  That means that in the EEM_Datetime model the
29
-     * 'DTT_Parent' field is related to the 'DTT_ID' primary key field (in the same model) because 'DTT_ID' is the
30
-     * primary key in the other model (EEM_Datetime).
31
-     *
32
-     * @var string
33
-     */
34
-    private $_parent_pk_relation_field;
35
-
36
-
37
-    /**
38
-     * Object representing the relationship between two models. Has_Many_Relations are where the OTHER model has the
39
-     * foreign key this model. IE, there can be many other model objects related to one of this model's objects (but
40
-     * NOT through a JOIN table, which is the case for EE_HABTM_Relations). This knows how to join the models, get
41
-     * related models across the relation, and add-and-remove the relationships.
42
-     *
43
-     * @param string  $primary_cpt_field             See property description for details
44
-     * @param string  $parent_pk_relation_field      This is the field that is "connected" to the $primary_cpt_field.
45
-     *                                               See property desc for details.
46
-     * @param boolean $block_deletes                 For this type of relation, we block by default. If there are
47
-     *                                               related models across this relation, block (prevent and add an
48
-     *                                               error) the deletion of this model
49
-     * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
50
-     *                                               default
51
-     */
52
-    public function __construct(
53
-        $primary_cpt_field,
54
-        $parent_pk_relation_field,
55
-        $block_deletes = true,
56
-        $blocking_delete_error_message = null
57
-    ) {
58
-        $this->_primary_cpt_field        = $primary_cpt_field;
59
-        $this->_parent_pk_relation_field = $parent_pk_relation_field;
60
-        parent::__construct($block_deletes, $blocking_delete_error_message);
61
-    }
62
-
63
-
64
-    /**
65
-     * Sets the other model object's foreign key to this model object's primary key. Feel free to do this manually if
66
-     * you like.
67
-     *
68
-     * @param EE_Base_Class|int $this_obj_or_id
69
-     * @param EE_Base_Class|int $other_obj_or_id
70
-     * @param array             $extra_join_model_fields_n_values
71
-     * @return \EE_Base_Class
72
-     * @throws \EE_Error
73
-     */
74
-    public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
75
-    {
76
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
77
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
78
-
79
-        // handle possible revisions
80
-        $other_model_obj = $this->_check_for_revision($this_model_obj, $other_model_obj);
81
-
82
-        // if is array, then we've already done the add_relation so let's get out
83
-        if (is_array($other_model_obj)) {
84
-            return $other_model_obj[0];
85
-        }
86
-        // find the field on the other model which is a foreign key to this model
87
-        $fk_field_on_other_model = $this->get_other_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
88
-        // set that field on the other model to this model's ID
89
-        $other_model_obj->set($fk_field_on_other_model->get_name(), $this_model_obj->ID());
90
-        $other_model_obj->save();
91
-        return $other_model_obj;
92
-    }
93
-
94
-
95
-    /**
96
-     * Sets the other model object's foreign key to its default, instead of pointing to this model object
97
-     *
98
-     * @param EE_Base_Class|int $this_obj_or_id
99
-     * @param EE_Base_Class|int $other_obj_or_id
100
-     * @param array             $where_query
101
-     * @return \EE_Base_Class
102
-     * @throws \EE_Error
103
-     */
104
-    public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
105
-    {
106
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id);
107
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
108
-        // handle possible revisions
109
-        $other_model_obj = $this->_check_for_revision($this_model_obj, $other_model_obj, true);
110
-
111
-
112
-        // if is array, then we've already done the add_relation so let's get out
113
-        if (is_array($other_model_obj)) {
114
-            return $other_model_obj[0];
115
-        }
116
-
117
-        // find the field on the other model which is a foreign key to this model
118
-        $fk_field_on_other_model = $this->get_other_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
119
-
120
-
121
-        // set that field on the other model to this model's ID
122
-        if ($this->_blocking_delete) {
123
-            $other_model_obj->set($fk_field_on_other_model->get_name(), null, true);
124
-            $other_model_obj->save();
125
-        } else {
126
-            $other_model_obj->delete();
127
-            $other_model_obj->set($fk_field_on_other_model->get_name(), null, true);
128
-            return $other_model_obj;
129
-        }
130
-        return $other_model_obj;
131
-    }
132
-
133
-
134
-    /**
135
-     * This is identical to EE_Model_Relation->get_all_related() except we're going handle special autosave conditions
136
-     * in here.
137
-     *
138
-     * @param  EE_Base_Class|int $model_object_or_id
139
-     * @param  array             $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
140
-     * @param  boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
141
-     * @return EE_Base_Class[]
142
-     * @throws \EE_Error
143
-     */
144
-    public function get_all_related(
145
-        $model_object_or_id,
146
-        $query_params = array(),
147
-        $values_already_prepared_by_model_object = false
148
-    ) {
149
-        if ($values_already_prepared_by_model_object !== false) {
150
-            EE_Error::doing_it_wrong(
151
-                'EE_Model_Relation_Base::get_all_related',
152
-                __('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
153
-                '4.8.1'
154
-            );
155
-        }
156
-
157
-        // if this is an autosave then we're going to get things differently
158
-        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
159
-            return $this->_do_autosave_get_all($model_object_or_id, $query_params);
160
-        }
161
-
162
-        return parent::get_all_related($model_object_or_id, $query_params);
163
-    }
164
-
165
-
166
-    /**
167
-     * If we're in the midst of an autosave then we're going to do things a bit differently than the usual
168
-     * get_all_related (commenting within).  For description of params see the get_all_related() comments
169
-     *
170
-     * @access protected
171
-     * @param      $model_object_or_id
172
-     * @param      $query_params
173
-     * @param bool $deprecated
174
-     * @return \EE_Base_Class[]
175
-     * @throws \EE_Error
176
-     */
177
-    protected function _do_autosave_get_all($model_object_or_id, $query_params, $deprecated = false)
178
-    {
179
-
180
-        // first we check if the post_id for the incoming query is for an autosave.  If it isn't that's what we want!
181
-        $model_object_id = $this->_get_model_object_id($model_object_or_id);
182
-
183
-        $autosave  = wp_get_post_autosave($model_object_id);
184
-        $id_to_use = $autosave ? $autosave->ID : $model_object_id;
185
-
186
-        $autosave_relations = parent::get_all_related($id_to_use, $query_params);
187
-        $parent_ids         = $parents = array();
188
-        $return_objs        = array();
189
-
190
-        // k this is where things differ because NOW what we're going to do is get the PARENTS for the get all related (and we'll also start setting up the return_objs array containing related that DON'T have parent ids, for those that DON'T have parents to merge with our returned objects);
191
-        foreach ($autosave_relations as $a_r) {
192
-            $pid = $a_r->parent();
193
-            if (! empty($pid)) {
194
-                $parent_ids[] = $pid;
195
-            } else {
196
-                $return_objs[] = $a_r;
197
-            }
198
-        }
199
-
200
-        // we have to make sure we also include the ORIGINAL values
201
-        $originals = parent::get_all_related($model_object_or_id, $query_params);
202
-
203
-        // merge $originals with $return_objs
204
-        if ($originals) {
205
-            $return_objs = array_merge($originals, $return_objs);
206
-        }
207
-
208
-        // now we setup the query to get all the parents
209
-        if (! empty($parent_ids)) {
210
-            $query_param_where_this_model_pk                  = $this->get_this_model()->get_this_model_name() . "." . $this->get_this_model()->get_primary_key_field()->get_name();
211
-            $query_param[0][ $query_param_where_this_model_pk ] = array('IN', $parent_ids);
212
-            $parents                                          = $this->get_other_model()->get_all($query_params);
213
-        }
214
-
215
-        // var_dump($parents);
216
-
217
-
218
-        // now merge parents with our current $return_objs and send back
219
-        return array_merge($parents, $return_objs);
220
-    }
221
-
222
-
223
-    /**
224
-     * Basically this method gets called to verify if the incoming object needs to be manipulated somewhat because it
225
-     * is a revision save.  If so, then we change things before sending back.  We also do verifications when this IS
226
-     * NOT an revision because we always need to make sure that the autosave/revision has parent recorded (which is
227
-     * sometime delayed if the object is created/saved first by the autosave)
228
-     *
229
-     * @param  EE_Base_Class $this_obj
230
-     * @param  EE_Base_Class $other_obj
231
-     * @param  boolean       $remove_relation Indicates whether we're doing a remove_relation or add_relation.
232
-     * @return EE_Base_Class. ($other_obj);
233
-     * @throws \EE_Error
234
-     */
235
-    protected function _check_for_revision($this_obj, $other_obj, $remove_relation = false)
236
-    {
237
-        $pk_on_related_model = $this->get_other_model()->get_primary_key_field()->get_name();
238
-        // now we need to determine if we're in a WP revision save cause if we are we need to do some special handling
239
-        if ($this_obj->post_type() === 'revision') {
240
-            // first if $other_obj fk = this_obj pk then we know that this is a pk object, let's make sure there is a matching set for the autosave if there is then we save over it, if there isn't then we need to create a new one.
241
-            $parent_evt_id = $this_obj->parent();
242
-            /*var_dump($parent_evt_id);
15
+	/**
16
+	 * The Foreign key on the model that acts as the PRIMARY KEY used in special autosave handling where we query for
17
+	 * autosaves (or the Foreign key on other models in relations pointing to this models primary key which is this
18
+	 * value).  The _primary_cpt_field is what is equivalent to the post_id field on a cpt join.
19
+	 *
20
+	 * @var string
21
+	 */
22
+	private $_primary_cpt_field;
23
+
24
+
25
+	/**
26
+	 * This is what field serves as the "parent" column that is linked with whatever the main model's calling this
27
+	 * relation has as a primary key.  In other words EEM_Event has 'Datetime' => new
28
+	 * EE_Has_Many_Revision_Relation('EVT_ID', 'DTT_parent').  That means that in the EEM_Datetime model the
29
+	 * 'DTT_Parent' field is related to the 'DTT_ID' primary key field (in the same model) because 'DTT_ID' is the
30
+	 * primary key in the other model (EEM_Datetime).
31
+	 *
32
+	 * @var string
33
+	 */
34
+	private $_parent_pk_relation_field;
35
+
36
+
37
+	/**
38
+	 * Object representing the relationship between two models. Has_Many_Relations are where the OTHER model has the
39
+	 * foreign key this model. IE, there can be many other model objects related to one of this model's objects (but
40
+	 * NOT through a JOIN table, which is the case for EE_HABTM_Relations). This knows how to join the models, get
41
+	 * related models across the relation, and add-and-remove the relationships.
42
+	 *
43
+	 * @param string  $primary_cpt_field             See property description for details
44
+	 * @param string  $parent_pk_relation_field      This is the field that is "connected" to the $primary_cpt_field.
45
+	 *                                               See property desc for details.
46
+	 * @param boolean $block_deletes                 For this type of relation, we block by default. If there are
47
+	 *                                               related models across this relation, block (prevent and add an
48
+	 *                                               error) the deletion of this model
49
+	 * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
50
+	 *                                               default
51
+	 */
52
+	public function __construct(
53
+		$primary_cpt_field,
54
+		$parent_pk_relation_field,
55
+		$block_deletes = true,
56
+		$blocking_delete_error_message = null
57
+	) {
58
+		$this->_primary_cpt_field        = $primary_cpt_field;
59
+		$this->_parent_pk_relation_field = $parent_pk_relation_field;
60
+		parent::__construct($block_deletes, $blocking_delete_error_message);
61
+	}
62
+
63
+
64
+	/**
65
+	 * Sets the other model object's foreign key to this model object's primary key. Feel free to do this manually if
66
+	 * you like.
67
+	 *
68
+	 * @param EE_Base_Class|int $this_obj_or_id
69
+	 * @param EE_Base_Class|int $other_obj_or_id
70
+	 * @param array             $extra_join_model_fields_n_values
71
+	 * @return \EE_Base_Class
72
+	 * @throws \EE_Error
73
+	 */
74
+	public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
75
+	{
76
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
77
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
78
+
79
+		// handle possible revisions
80
+		$other_model_obj = $this->_check_for_revision($this_model_obj, $other_model_obj);
81
+
82
+		// if is array, then we've already done the add_relation so let's get out
83
+		if (is_array($other_model_obj)) {
84
+			return $other_model_obj[0];
85
+		}
86
+		// find the field on the other model which is a foreign key to this model
87
+		$fk_field_on_other_model = $this->get_other_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
88
+		// set that field on the other model to this model's ID
89
+		$other_model_obj->set($fk_field_on_other_model->get_name(), $this_model_obj->ID());
90
+		$other_model_obj->save();
91
+		return $other_model_obj;
92
+	}
93
+
94
+
95
+	/**
96
+	 * Sets the other model object's foreign key to its default, instead of pointing to this model object
97
+	 *
98
+	 * @param EE_Base_Class|int $this_obj_or_id
99
+	 * @param EE_Base_Class|int $other_obj_or_id
100
+	 * @param array             $where_query
101
+	 * @return \EE_Base_Class
102
+	 * @throws \EE_Error
103
+	 */
104
+	public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
105
+	{
106
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id);
107
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id);
108
+		// handle possible revisions
109
+		$other_model_obj = $this->_check_for_revision($this_model_obj, $other_model_obj, true);
110
+
111
+
112
+		// if is array, then we've already done the add_relation so let's get out
113
+		if (is_array($other_model_obj)) {
114
+			return $other_model_obj[0];
115
+		}
116
+
117
+		// find the field on the other model which is a foreign key to this model
118
+		$fk_field_on_other_model = $this->get_other_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
119
+
120
+
121
+		// set that field on the other model to this model's ID
122
+		if ($this->_blocking_delete) {
123
+			$other_model_obj->set($fk_field_on_other_model->get_name(), null, true);
124
+			$other_model_obj->save();
125
+		} else {
126
+			$other_model_obj->delete();
127
+			$other_model_obj->set($fk_field_on_other_model->get_name(), null, true);
128
+			return $other_model_obj;
129
+		}
130
+		return $other_model_obj;
131
+	}
132
+
133
+
134
+	/**
135
+	 * This is identical to EE_Model_Relation->get_all_related() except we're going handle special autosave conditions
136
+	 * in here.
137
+	 *
138
+	 * @param  EE_Base_Class|int $model_object_or_id
139
+	 * @param  array             $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
140
+	 * @param  boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
141
+	 * @return EE_Base_Class[]
142
+	 * @throws \EE_Error
143
+	 */
144
+	public function get_all_related(
145
+		$model_object_or_id,
146
+		$query_params = array(),
147
+		$values_already_prepared_by_model_object = false
148
+	) {
149
+		if ($values_already_prepared_by_model_object !== false) {
150
+			EE_Error::doing_it_wrong(
151
+				'EE_Model_Relation_Base::get_all_related',
152
+				__('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
153
+				'4.8.1'
154
+			);
155
+		}
156
+
157
+		// if this is an autosave then we're going to get things differently
158
+		if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
159
+			return $this->_do_autosave_get_all($model_object_or_id, $query_params);
160
+		}
161
+
162
+		return parent::get_all_related($model_object_or_id, $query_params);
163
+	}
164
+
165
+
166
+	/**
167
+	 * If we're in the midst of an autosave then we're going to do things a bit differently than the usual
168
+	 * get_all_related (commenting within).  For description of params see the get_all_related() comments
169
+	 *
170
+	 * @access protected
171
+	 * @param      $model_object_or_id
172
+	 * @param      $query_params
173
+	 * @param bool $deprecated
174
+	 * @return \EE_Base_Class[]
175
+	 * @throws \EE_Error
176
+	 */
177
+	protected function _do_autosave_get_all($model_object_or_id, $query_params, $deprecated = false)
178
+	{
179
+
180
+		// first we check if the post_id for the incoming query is for an autosave.  If it isn't that's what we want!
181
+		$model_object_id = $this->_get_model_object_id($model_object_or_id);
182
+
183
+		$autosave  = wp_get_post_autosave($model_object_id);
184
+		$id_to_use = $autosave ? $autosave->ID : $model_object_id;
185
+
186
+		$autosave_relations = parent::get_all_related($id_to_use, $query_params);
187
+		$parent_ids         = $parents = array();
188
+		$return_objs        = array();
189
+
190
+		// k this is where things differ because NOW what we're going to do is get the PARENTS for the get all related (and we'll also start setting up the return_objs array containing related that DON'T have parent ids, for those that DON'T have parents to merge with our returned objects);
191
+		foreach ($autosave_relations as $a_r) {
192
+			$pid = $a_r->parent();
193
+			if (! empty($pid)) {
194
+				$parent_ids[] = $pid;
195
+			} else {
196
+				$return_objs[] = $a_r;
197
+			}
198
+		}
199
+
200
+		// we have to make sure we also include the ORIGINAL values
201
+		$originals = parent::get_all_related($model_object_or_id, $query_params);
202
+
203
+		// merge $originals with $return_objs
204
+		if ($originals) {
205
+			$return_objs = array_merge($originals, $return_objs);
206
+		}
207
+
208
+		// now we setup the query to get all the parents
209
+		if (! empty($parent_ids)) {
210
+			$query_param_where_this_model_pk                  = $this->get_this_model()->get_this_model_name() . "." . $this->get_this_model()->get_primary_key_field()->get_name();
211
+			$query_param[0][ $query_param_where_this_model_pk ] = array('IN', $parent_ids);
212
+			$parents                                          = $this->get_other_model()->get_all($query_params);
213
+		}
214
+
215
+		// var_dump($parents);
216
+
217
+
218
+		// now merge parents with our current $return_objs and send back
219
+		return array_merge($parents, $return_objs);
220
+	}
221
+
222
+
223
+	/**
224
+	 * Basically this method gets called to verify if the incoming object needs to be manipulated somewhat because it
225
+	 * is a revision save.  If so, then we change things before sending back.  We also do verifications when this IS
226
+	 * NOT an revision because we always need to make sure that the autosave/revision has parent recorded (which is
227
+	 * sometime delayed if the object is created/saved first by the autosave)
228
+	 *
229
+	 * @param  EE_Base_Class $this_obj
230
+	 * @param  EE_Base_Class $other_obj
231
+	 * @param  boolean       $remove_relation Indicates whether we're doing a remove_relation or add_relation.
232
+	 * @return EE_Base_Class. ($other_obj);
233
+	 * @throws \EE_Error
234
+	 */
235
+	protected function _check_for_revision($this_obj, $other_obj, $remove_relation = false)
236
+	{
237
+		$pk_on_related_model = $this->get_other_model()->get_primary_key_field()->get_name();
238
+		// now we need to determine if we're in a WP revision save cause if we are we need to do some special handling
239
+		if ($this_obj->post_type() === 'revision') {
240
+			// first if $other_obj fk = this_obj pk then we know that this is a pk object, let's make sure there is a matching set for the autosave if there is then we save over it, if there isn't then we need to create a new one.
241
+			$parent_evt_id = $this_obj->parent();
242
+			/*var_dump($parent_evt_id);
243 243
             var_dump($this_obj);
244 244
             var_dump($other_obj);/**/
245 245
 
246
-            if (! empty($parent_evt_id) && $parent_evt_id == $other_obj->get($this->_primary_cpt_field)) {
247
-                // let's do query on this objects model to see if the incoming pk value on the obj matches any parents in this objects table.
248
-                $has_parent_obj = $this->get_other_model()->get_one(array(
249
-                    array(
250
-                        $this->_parent_pk_relation_field => $other_obj->ID(),
251
-                        $this->_primary_cpt_field        => $this_obj->ID(),
252
-                    ),
253
-                ));
254
-
255
-                if ($has_parent_obj) {
256
-                    // this makes sure the update on the current obj happens to the revision's row NOT the parent row.
257
-
258
-                    $other_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
259
-                    $other_obj->set($pk_on_related_model, $has_parent_obj->ID());
260
-                    $other_obj->set($this->_primary_cpt_field, $this_obj->ID());
261
-
262
-                    if (! $remove_relation) {
263
-                        $other_obj->save();
264
-                        return array($other_obj);
265
-                    } elseif ($remove_relation && ! $this->_blocking_delete) {
266
-                        $other_obj->delete();
267
-                        $other_obj->set($this->_parent_pk_relation_field, null, true);
268
-                        return array($other_obj);
269
-                    }
270
-                } else {
271
-                    $other_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
272
-                    $other_obj->set($this->_primary_cpt_field, $this_obj->ID());
273
-                    $other_obj->set(
274
-                        $pk_on_related_model,
275
-                        null,
276
-                        true
277
-                    ); // ensure we create a new row for the autosave with parent id the same as the incoming ID.
278
-                    $other_obj->save(); // make sure we insert.
279
-                    return array($other_obj);
280
-                }
281
-            }
282
-
283
-            // var_dump('what makes it here');
284
-            // var_dump($other_obj);
285
-            // the next possible condition is that the incoming other_model obj has a NULL pk which means it just gets saved (which in turn creates it)
286
-
287
-            // the last possible condition on a revision is that the incoming other_model object has a fk that == $this_obj pk which means we just return the $other obj and let it save as normal so we see the return at the bottom of this method.
288
-        } else {
289
-            // we only need to do the below IF this is not a remove relation
290
-            if (! $remove_relation) {
291
-                // okay this is is a normal update/save/remove so, let's make sure the other object is not a revision of the current object.
292
-                // the other object will likely NOT have the correct fk on it (which is the primary_cpt_field_mame) so we must retrieve from the db to get that first.
293
-                $existing_other_obj    = $this->get_other_model()->get_one_by_ID($other_obj->ID());
294
-                $potential_revision_id = is_object($existing_other_obj) ? $existing_other_obj->get($this->_primary_cpt_field) : null;
295
-
296
-                if ($parent_this_obj_id = wp_is_post_revision($potential_revision_id)) {
297
-                    // yes the OTHER object is linked to the revision of the parent, not the parent itself. That means we need to make the other_object an attachment of this_obj and then duplicate other_obj for the revision.
298
-                    $other_obj->set($this->_primary_cpt_field, $this_obj->ID());
299
-                    $other_obj->save();
300
-
301
-                    // now create a new other_obj and fill with details from existing object
302
-                    $new_obj = $other_obj;
303
-                    $new_obj->set($this->_primary_cpt_field, $potential_revision_id);
304
-                    $new_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
305
-                    $new_obj->set($pk_on_related_model, null);
306
-                    $new_obj->save();
307
-                    return array($new_obj);
308
-                }
309
-            }
310
-        }
311
-
312
-        return $other_obj;
313
-    }
246
+			if (! empty($parent_evt_id) && $parent_evt_id == $other_obj->get($this->_primary_cpt_field)) {
247
+				// let's do query on this objects model to see if the incoming pk value on the obj matches any parents in this objects table.
248
+				$has_parent_obj = $this->get_other_model()->get_one(array(
249
+					array(
250
+						$this->_parent_pk_relation_field => $other_obj->ID(),
251
+						$this->_primary_cpt_field        => $this_obj->ID(),
252
+					),
253
+				));
254
+
255
+				if ($has_parent_obj) {
256
+					// this makes sure the update on the current obj happens to the revision's row NOT the parent row.
257
+
258
+					$other_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
259
+					$other_obj->set($pk_on_related_model, $has_parent_obj->ID());
260
+					$other_obj->set($this->_primary_cpt_field, $this_obj->ID());
261
+
262
+					if (! $remove_relation) {
263
+						$other_obj->save();
264
+						return array($other_obj);
265
+					} elseif ($remove_relation && ! $this->_blocking_delete) {
266
+						$other_obj->delete();
267
+						$other_obj->set($this->_parent_pk_relation_field, null, true);
268
+						return array($other_obj);
269
+					}
270
+				} else {
271
+					$other_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
272
+					$other_obj->set($this->_primary_cpt_field, $this_obj->ID());
273
+					$other_obj->set(
274
+						$pk_on_related_model,
275
+						null,
276
+						true
277
+					); // ensure we create a new row for the autosave with parent id the same as the incoming ID.
278
+					$other_obj->save(); // make sure we insert.
279
+					return array($other_obj);
280
+				}
281
+			}
282
+
283
+			// var_dump('what makes it here');
284
+			// var_dump($other_obj);
285
+			// the next possible condition is that the incoming other_model obj has a NULL pk which means it just gets saved (which in turn creates it)
286
+
287
+			// the last possible condition on a revision is that the incoming other_model object has a fk that == $this_obj pk which means we just return the $other obj and let it save as normal so we see the return at the bottom of this method.
288
+		} else {
289
+			// we only need to do the below IF this is not a remove relation
290
+			if (! $remove_relation) {
291
+				// okay this is is a normal update/save/remove so, let's make sure the other object is not a revision of the current object.
292
+				// the other object will likely NOT have the correct fk on it (which is the primary_cpt_field_mame) so we must retrieve from the db to get that first.
293
+				$existing_other_obj    = $this->get_other_model()->get_one_by_ID($other_obj->ID());
294
+				$potential_revision_id = is_object($existing_other_obj) ? $existing_other_obj->get($this->_primary_cpt_field) : null;
295
+
296
+				if ($parent_this_obj_id = wp_is_post_revision($potential_revision_id)) {
297
+					// yes the OTHER object is linked to the revision of the parent, not the parent itself. That means we need to make the other_object an attachment of this_obj and then duplicate other_obj for the revision.
298
+					$other_obj->set($this->_primary_cpt_field, $this_obj->ID());
299
+					$other_obj->save();
300
+
301
+					// now create a new other_obj and fill with details from existing object
302
+					$new_obj = $other_obj;
303
+					$new_obj->set($this->_primary_cpt_field, $potential_revision_id);
304
+					$new_obj->set($this->_parent_pk_relation_field, $other_obj->ID());
305
+					$new_obj->set($pk_on_related_model, null);
306
+					$new_obj->save();
307
+					return array($new_obj);
308
+				}
309
+			}
310
+		}
311
+
312
+		return $other_obj;
313
+	}
314 314
 }
Please login to merge, or discard this patch.
core/db_models/relations/EE_Model_Relation_Base.php 1 patch
Indentation   +497 added lines, -497 removed lines patch added patch discarded remove patch
@@ -15,502 +15,502 @@
 block discarded – undo
15 15
  */
16 16
 abstract class EE_Model_Relation_Base implements HasSchemaInterface
17 17
 {
18
-    /**
19
-     * The model name of which this relation is a component (ie, the model that called new EE_Model_Relation_Base)
20
-     *
21
-     * @var string eg Event, Question_Group, Registration
22
-     */
23
-    private $_this_model_name;
24
-    /**
25
-     * The model name pointed to by this relation (ie, the model we want to establish a relationship to)
26
-     *
27
-     * @var string eg Event, Question_Group, Registration
28
-     */
29
-    private $_other_model_name;
30
-
31
-    /**
32
-     * this is typically used when calling the relation models to make sure they inherit any set timezone from the
33
-     * initiating model.
34
-     *
35
-     * @var string
36
-     */
37
-    protected $_timezone;
38
-
39
-    /**
40
-     * If you try to delete "this_model", and there are related "other_models",
41
-     * and this isn't null, then abandon the deletion and add this warning.
42
-     * This effectively makes it impossible to delete "this_model" while there are
43
-     * related "other_models" along this relation.
44
-     *
45
-     * @var string (internationalized)
46
-     */
47
-    protected $_blocking_delete_error_message;
48
-
49
-    protected $_blocking_delete = false;
50
-
51
-    /**
52
-     * Object representing the relationship between two models. This knows how to join the models,
53
-     * get related models across the relation, and add-and-remove the relationships.
54
-     *
55
-     * @param boolean $block_deletes                 if there are related models across this relation, block (prevent
56
-     *                                               and add an error) the deletion of this model
57
-     * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
58
-     *                                               default
59
-     */
60
-    public function __construct($block_deletes, $blocking_delete_error_message)
61
-    {
62
-        $this->_blocking_delete               = $block_deletes;
63
-        $this->_blocking_delete_error_message = $blocking_delete_error_message;
64
-    }
65
-
66
-
67
-    /**
68
-     * @param $this_model_name
69
-     * @param $other_model_name
70
-     * @throws EE_Error
71
-     */
72
-    public function _construct_finalize_set_models($this_model_name, $other_model_name)
73
-    {
74
-        $this->_this_model_name  = $this_model_name;
75
-        $this->_other_model_name = $other_model_name;
76
-        if (is_string($this->_blocking_delete)) {
77
-            throw new EE_Error(sprintf(
78
-                __(
79
-                    "When instantiating the relation of type %s from %s to %s, the \$block_deletes argument should be a boolean, not a string (%s)",
80
-                    "event_espresso"
81
-                ),
82
-                get_class($this),
83
-                $this_model_name,
84
-                $other_model_name,
85
-                $this->_blocking_delete
86
-            ));
87
-        }
88
-    }
89
-
90
-
91
-    /**
92
-     * Gets the model where this relation is defined.
93
-     *
94
-     * @return EEM_Base
95
-     */
96
-    public function get_this_model()
97
-    {
98
-        return $this->_get_model($this->_this_model_name);
99
-    }
100
-
101
-
102
-    /**
103
-     * Gets the model which this relation establishes the relation TO (ie,
104
-     * this relation object was defined on get_this_model(), get_other_model() is the other one)
105
-     *
106
-     * @return EEM_Base
107
-     */
108
-    public function get_other_model()
109
-    {
110
-        return $this->_get_model($this->_other_model_name);
111
-    }
112
-
113
-
114
-    /**
115
-     * Internally used by get_this_model() and get_other_model()
116
-     *
117
-     * @param string $model_name like Event, Question_Group, etc. omit the EEM_
118
-     * @return EEM_Base
119
-     */
120
-    protected function _get_model($model_name)
121
-    {
122
-        $modelInstance = EE_Registry::instance()->load_model($model_name);
123
-        $modelInstance->set_timezone($this->_timezone);
124
-        return $modelInstance;
125
-    }
126
-
127
-
128
-    /**
129
-     * entirely possible that relations may be called from a model and we need to make sure those relations have their
130
-     * timezone set correctly.
131
-     *
132
-     * @param string $timezone timezone to set.
133
-     */
134
-    public function set_timezone($timezone)
135
-    {
136
-        if ($timezone !== null) {
137
-            $this->_timezone = $timezone;
138
-        }
139
-    }
140
-
141
-
142
-    /**
143
-     * @param        $other_table
144
-     * @param        $other_table_alias
145
-     * @param        $other_table_column
146
-     * @param        $this_table_alias
147
-     * @param        $this_table_join_column
148
-     * @param string $extra_join_sql
149
-     * @return string
150
-     */
151
-    protected function _left_join(
152
-        $other_table,
153
-        $other_table_alias,
154
-        $other_table_column,
155
-        $this_table_alias,
156
-        $this_table_join_column,
157
-        $extra_join_sql = ''
158
-    ) {
159
-        return " LEFT JOIN " . $other_table . " AS " . $other_table_alias . " ON " . $other_table_alias . "." . $other_table_column . "=" . $this_table_alias . "." . $this_table_join_column . ($extra_join_sql ? " AND $extra_join_sql" : '');
160
-    }
161
-
162
-
163
-    /**
164
-     * Gets all the model objects of type of other model related to $model_object,
165
-     * according to this relation. This is the same code for EE_HABTM_Relation and EE_Has_Many_Relation.
166
-     * For both of those child classes, $model_object must be saved so that it has an ID before querying,
167
-     * otherwise an error will be thrown. Note: by default we disable default_where_conditions
168
-     * EE_Belongs_To_Relation doesn't need to be saved before querying.
169
-     *
170
-     * @param EE_Base_Class|int $model_object_or_id                      or the primary key of this model
171
-     * @param array             $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
172
-     * @param boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
173
-     * @return EE_Base_Class[]
174
-     * @throws \EE_Error
175
-     */
176
-    public function get_all_related(
177
-        $model_object_or_id,
178
-        $query_params = array(),
179
-        $values_already_prepared_by_model_object = false
180
-    ) {
181
-        if ($values_already_prepared_by_model_object !== false) {
182
-            EE_Error::doing_it_wrong(
183
-                'EE_Model_Relation_Base::get_all_related',
184
-                __('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
185
-                '4.8.1'
186
-            );
187
-        }
188
-        $query_params                                      = $this->_disable_default_where_conditions_on_query_param($query_params);
189
-        $query_param_where_this_model_pk                   = $this->get_this_model()->get_this_model_name()
190
-                                                             . "."
191
-                                                             . $this->get_this_model()->get_primary_key_field()->get_name();
192
-        $model_object_id                                   = $this->_get_model_object_id($model_object_or_id);
193
-        $query_params[0][ $query_param_where_this_model_pk ] = $model_object_id;
194
-        return $this->get_other_model()->get_all($query_params);
195
-    }
196
-
197
-
198
-    /**
199
-     * Alters the $query_params to disable default where conditions, unless otherwise specified
200
-     *
201
-     * @param string $query_params
202
-     * @return array
203
-     */
204
-    protected function _disable_default_where_conditions_on_query_param($query_params)
205
-    {
206
-        if (! isset($query_params['default_where_conditions'])) {
207
-            $query_params['default_where_conditions'] = 'none';
208
-        }
209
-        return $query_params;
210
-    }
211
-
212
-
213
-    /**
214
-     * Deletes the related model objects which meet the query parameters. If no
215
-     * parameters are specified, then all related model objects will be deleted.
216
-     * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
217
-     * model objects will only be soft-deleted.
218
-     *
219
-     * @param EE_Base_Class|int|string $model_object_or_id
220
-     * @param array                    $query_params
221
-     * @return int of how many related models got deleted
222
-     * @throws \EE_Error
223
-     */
224
-    public function delete_all_related($model_object_or_id, $query_params = array())
225
-    {
226
-        // for each thing we would delete,
227
-        $related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
228
-        // determine if it's blocked by anything else before it can be deleted
229
-        $deleted_count = 0;
230
-        foreach ($related_model_objects as $related_model_object) {
231
-            $delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
232
-                $related_model_object,
233
-                $model_object_or_id
234
-            );
235
-            /* @var $model_object_or_id EE_Base_Class */
236
-            if (! $delete_is_blocked) {
237
-                $this->remove_relation_to($model_object_or_id, $related_model_object);
238
-                $related_model_object->delete();
239
-                $deleted_count++;
240
-            }
241
-        }
242
-        return $deleted_count;
243
-    }
244
-
245
-
246
-    /**
247
-     * Deletes the related model objects which meet the query parameters. If no
248
-     * parameters are specified, then all related model objects will be deleted.
249
-     * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
250
-     * model objects will only be soft-deleted.
251
-     *
252
-     * @param EE_Base_Class|int|string $model_object_or_id
253
-     * @param array                    $query_params
254
-     * @return int of how many related models got deleted
255
-     * @throws \EE_Error
256
-     */
257
-    public function delete_related_permanently($model_object_or_id, $query_params = array())
258
-    {
259
-        // for each thing we would delete,
260
-        $related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
261
-        // determine if it's blocked by anything else before it can be deleted
262
-        $deleted_count = 0;
263
-        foreach ($related_model_objects as $related_model_object) {
264
-            $delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
265
-                $related_model_object,
266
-                $model_object_or_id
267
-            );
268
-            /* @var $model_object_or_id EE_Base_Class */
269
-            if ($related_model_object instanceof EE_Soft_Delete_Base_Class) {
270
-                $this->remove_relation_to($model_object_or_id, $related_model_object);
271
-                $deleted_count++;
272
-                if (! $delete_is_blocked) {
273
-                    $related_model_object->delete_permanently();
274
-                } else {
275
-                    // delete is blocked
276
-                    // brent and darren, in this case, wanted to just soft delete it then
277
-                    $related_model_object->delete();
278
-                }
279
-            } else {
280
-                // its not a soft-deletable thing anyways. do the normal logic.
281
-                if (! $delete_is_blocked) {
282
-                    $this->remove_relation_to($model_object_or_id, $related_model_object);
283
-                    $related_model_object->delete();
284
-                    $deleted_count++;
285
-                }
286
-            }
287
-        }
288
-        return $deleted_count;
289
-    }
290
-
291
-
292
-    /**
293
-     * this just returns a model_object_id for incoming item that could be an object or id.
294
-     *
295
-     * @param  EE_Base_Class|int $model_object_or_id model object or the primary key of this model
296
-     * @throws EE_Error
297
-     * @return int
298
-     */
299
-    protected function _get_model_object_id($model_object_or_id)
300
-    {
301
-        $model_object_id = $model_object_or_id;
302
-        if ($model_object_or_id instanceof EE_Base_Class) {
303
-            $model_object_id = $model_object_or_id->ID();
304
-        }
305
-        if (! $model_object_id) {
306
-            throw new EE_Error(sprintf(
307
-                __(
308
-                    "Sorry, we cant get the related %s model objects to %s model object before it has an ID. You can solve that by just saving it before trying to get its related model objects",
309
-                    "event_espresso"
310
-                ),
311
-                $this->get_other_model()->get_this_model_name(),
312
-                $this->get_this_model()->get_this_model_name()
313
-            ));
314
-        }
315
-        return $model_object_id;
316
-    }
317
-
318
-
319
-    /**
320
-     * Gets the SQL string for performing the join between this model and the other model.
321
-     *
322
-     * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
323
-     * @return string of SQL, eg "LEFT JOIN table_name AS table_alias ON this_model_primary_table.pk =
324
-     *                other_model_primary_table.fk" etc
325
-     */
326
-    abstract public function get_join_statement($model_relation_chain);
327
-
328
-
329
-    /**
330
-     * Adds a relationships between the two model objects provided. Each type of relationship handles this differently
331
-     * (EE_Belongs_To is a slight exception, it should more accurately be called set_relation_to(...), as this
332
-     * relationship only allows this model to be related to a single other model of this type)
333
-     *
334
-     * @param       $this_obj_or_id
335
-     * @param       $other_obj_or_id
336
-     * @param array $extra_join_model_fields_n_values
337
-     * @return \EE_Base_Class the EE_Base_Class which was added as a relation. (Convenient if you only pass an ID for
338
-     *                        $other_obj_or_id)
339
-     */
340
-    abstract public function add_relation_to(
341
-        $this_obj_or_id,
342
-        $other_obj_or_id,
343
-        $extra_join_model_fields_n_values = array()
344
-    );
345
-
346
-
347
-    /**
348
-     * Similar to 'add_relation_to(...)', performs the opposite action of removing the relationship between the two
349
-     * model objects
350
-     *
351
-     * @param       $this_obj_or_id
352
-     * @param       $other_obj_or_id
353
-     * @param array $where_query
354
-     * @return bool
355
-     */
356
-    abstract public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array());
357
-
358
-
359
-    /**
360
-     * Removes ALL relation instances for this relation obj
361
-     *
362
-     * @param EE_Base_Class|int $this_obj_or_id
363
-     * @param array             $where_query_param @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
364
-     * @return EE_Base_Class[]
365
-     * @throws \EE_Error
366
-     */
367
-    public function remove_relations($this_obj_or_id, $where_query_param = array())
368
-    {
369
-        $related_things = $this->get_all_related($this_obj_or_id, array($where_query_param));
370
-        $objs_removed   = array();
371
-        foreach ($related_things as $related_thing) {
372
-            $objs_removed[] = $this->remove_relation_to($this_obj_or_id, $related_thing);
373
-        }
374
-        return $objs_removed;
375
-    }
376
-
377
-
378
-    /**
379
-     * If you aren't allowed to delete this model when there are related models across this
380
-     * relation object, return true. Otherwise, if you can delete this model even though
381
-     * related objects exist, returns false.
382
-     *
383
-     * @return boolean
384
-     */
385
-    public function block_delete_if_related_models_exist()
386
-    {
387
-        return $this->_blocking_delete;
388
-    }
389
-
390
-
391
-    /**
392
-     * Gets the error message to show
393
-     *
394
-     * @return string
395
-     */
396
-    public function get_deletion_error_message()
397
-    {
398
-        if ($this->_blocking_delete_error_message) {
399
-            return $this->_blocking_delete_error_message;
400
-        } else {
18
+	/**
19
+	 * The model name of which this relation is a component (ie, the model that called new EE_Model_Relation_Base)
20
+	 *
21
+	 * @var string eg Event, Question_Group, Registration
22
+	 */
23
+	private $_this_model_name;
24
+	/**
25
+	 * The model name pointed to by this relation (ie, the model we want to establish a relationship to)
26
+	 *
27
+	 * @var string eg Event, Question_Group, Registration
28
+	 */
29
+	private $_other_model_name;
30
+
31
+	/**
32
+	 * this is typically used when calling the relation models to make sure they inherit any set timezone from the
33
+	 * initiating model.
34
+	 *
35
+	 * @var string
36
+	 */
37
+	protected $_timezone;
38
+
39
+	/**
40
+	 * If you try to delete "this_model", and there are related "other_models",
41
+	 * and this isn't null, then abandon the deletion and add this warning.
42
+	 * This effectively makes it impossible to delete "this_model" while there are
43
+	 * related "other_models" along this relation.
44
+	 *
45
+	 * @var string (internationalized)
46
+	 */
47
+	protected $_blocking_delete_error_message;
48
+
49
+	protected $_blocking_delete = false;
50
+
51
+	/**
52
+	 * Object representing the relationship between two models. This knows how to join the models,
53
+	 * get related models across the relation, and add-and-remove the relationships.
54
+	 *
55
+	 * @param boolean $block_deletes                 if there are related models across this relation, block (prevent
56
+	 *                                               and add an error) the deletion of this model
57
+	 * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
58
+	 *                                               default
59
+	 */
60
+	public function __construct($block_deletes, $blocking_delete_error_message)
61
+	{
62
+		$this->_blocking_delete               = $block_deletes;
63
+		$this->_blocking_delete_error_message = $blocking_delete_error_message;
64
+	}
65
+
66
+
67
+	/**
68
+	 * @param $this_model_name
69
+	 * @param $other_model_name
70
+	 * @throws EE_Error
71
+	 */
72
+	public function _construct_finalize_set_models($this_model_name, $other_model_name)
73
+	{
74
+		$this->_this_model_name  = $this_model_name;
75
+		$this->_other_model_name = $other_model_name;
76
+		if (is_string($this->_blocking_delete)) {
77
+			throw new EE_Error(sprintf(
78
+				__(
79
+					"When instantiating the relation of type %s from %s to %s, the \$block_deletes argument should be a boolean, not a string (%s)",
80
+					"event_espresso"
81
+				),
82
+				get_class($this),
83
+				$this_model_name,
84
+				$other_model_name,
85
+				$this->_blocking_delete
86
+			));
87
+		}
88
+	}
89
+
90
+
91
+	/**
92
+	 * Gets the model where this relation is defined.
93
+	 *
94
+	 * @return EEM_Base
95
+	 */
96
+	public function get_this_model()
97
+	{
98
+		return $this->_get_model($this->_this_model_name);
99
+	}
100
+
101
+
102
+	/**
103
+	 * Gets the model which this relation establishes the relation TO (ie,
104
+	 * this relation object was defined on get_this_model(), get_other_model() is the other one)
105
+	 *
106
+	 * @return EEM_Base
107
+	 */
108
+	public function get_other_model()
109
+	{
110
+		return $this->_get_model($this->_other_model_name);
111
+	}
112
+
113
+
114
+	/**
115
+	 * Internally used by get_this_model() and get_other_model()
116
+	 *
117
+	 * @param string $model_name like Event, Question_Group, etc. omit the EEM_
118
+	 * @return EEM_Base
119
+	 */
120
+	protected function _get_model($model_name)
121
+	{
122
+		$modelInstance = EE_Registry::instance()->load_model($model_name);
123
+		$modelInstance->set_timezone($this->_timezone);
124
+		return $modelInstance;
125
+	}
126
+
127
+
128
+	/**
129
+	 * entirely possible that relations may be called from a model and we need to make sure those relations have their
130
+	 * timezone set correctly.
131
+	 *
132
+	 * @param string $timezone timezone to set.
133
+	 */
134
+	public function set_timezone($timezone)
135
+	{
136
+		if ($timezone !== null) {
137
+			$this->_timezone = $timezone;
138
+		}
139
+	}
140
+
141
+
142
+	/**
143
+	 * @param        $other_table
144
+	 * @param        $other_table_alias
145
+	 * @param        $other_table_column
146
+	 * @param        $this_table_alias
147
+	 * @param        $this_table_join_column
148
+	 * @param string $extra_join_sql
149
+	 * @return string
150
+	 */
151
+	protected function _left_join(
152
+		$other_table,
153
+		$other_table_alias,
154
+		$other_table_column,
155
+		$this_table_alias,
156
+		$this_table_join_column,
157
+		$extra_join_sql = ''
158
+	) {
159
+		return " LEFT JOIN " . $other_table . " AS " . $other_table_alias . " ON " . $other_table_alias . "." . $other_table_column . "=" . $this_table_alias . "." . $this_table_join_column . ($extra_join_sql ? " AND $extra_join_sql" : '');
160
+	}
161
+
162
+
163
+	/**
164
+	 * Gets all the model objects of type of other model related to $model_object,
165
+	 * according to this relation. This is the same code for EE_HABTM_Relation and EE_Has_Many_Relation.
166
+	 * For both of those child classes, $model_object must be saved so that it has an ID before querying,
167
+	 * otherwise an error will be thrown. Note: by default we disable default_where_conditions
168
+	 * EE_Belongs_To_Relation doesn't need to be saved before querying.
169
+	 *
170
+	 * @param EE_Base_Class|int $model_object_or_id                      or the primary key of this model
171
+	 * @param array             $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
172
+	 * @param boolean           $values_already_prepared_by_model_object @deprecated since 4.8.1
173
+	 * @return EE_Base_Class[]
174
+	 * @throws \EE_Error
175
+	 */
176
+	public function get_all_related(
177
+		$model_object_or_id,
178
+		$query_params = array(),
179
+		$values_already_prepared_by_model_object = false
180
+	) {
181
+		if ($values_already_prepared_by_model_object !== false) {
182
+			EE_Error::doing_it_wrong(
183
+				'EE_Model_Relation_Base::get_all_related',
184
+				__('The argument $values_already_prepared_by_model_object is no longer used.', 'event_espresso'),
185
+				'4.8.1'
186
+			);
187
+		}
188
+		$query_params                                      = $this->_disable_default_where_conditions_on_query_param($query_params);
189
+		$query_param_where_this_model_pk                   = $this->get_this_model()->get_this_model_name()
190
+															 . "."
191
+															 . $this->get_this_model()->get_primary_key_field()->get_name();
192
+		$model_object_id                                   = $this->_get_model_object_id($model_object_or_id);
193
+		$query_params[0][ $query_param_where_this_model_pk ] = $model_object_id;
194
+		return $this->get_other_model()->get_all($query_params);
195
+	}
196
+
197
+
198
+	/**
199
+	 * Alters the $query_params to disable default where conditions, unless otherwise specified
200
+	 *
201
+	 * @param string $query_params
202
+	 * @return array
203
+	 */
204
+	protected function _disable_default_where_conditions_on_query_param($query_params)
205
+	{
206
+		if (! isset($query_params['default_where_conditions'])) {
207
+			$query_params['default_where_conditions'] = 'none';
208
+		}
209
+		return $query_params;
210
+	}
211
+
212
+
213
+	/**
214
+	 * Deletes the related model objects which meet the query parameters. If no
215
+	 * parameters are specified, then all related model objects will be deleted.
216
+	 * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
217
+	 * model objects will only be soft-deleted.
218
+	 *
219
+	 * @param EE_Base_Class|int|string $model_object_or_id
220
+	 * @param array                    $query_params
221
+	 * @return int of how many related models got deleted
222
+	 * @throws \EE_Error
223
+	 */
224
+	public function delete_all_related($model_object_or_id, $query_params = array())
225
+	{
226
+		// for each thing we would delete,
227
+		$related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
228
+		// determine if it's blocked by anything else before it can be deleted
229
+		$deleted_count = 0;
230
+		foreach ($related_model_objects as $related_model_object) {
231
+			$delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
232
+				$related_model_object,
233
+				$model_object_or_id
234
+			);
235
+			/* @var $model_object_or_id EE_Base_Class */
236
+			if (! $delete_is_blocked) {
237
+				$this->remove_relation_to($model_object_or_id, $related_model_object);
238
+				$related_model_object->delete();
239
+				$deleted_count++;
240
+			}
241
+		}
242
+		return $deleted_count;
243
+	}
244
+
245
+
246
+	/**
247
+	 * Deletes the related model objects which meet the query parameters. If no
248
+	 * parameters are specified, then all related model objects will be deleted.
249
+	 * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
250
+	 * model objects will only be soft-deleted.
251
+	 *
252
+	 * @param EE_Base_Class|int|string $model_object_or_id
253
+	 * @param array                    $query_params
254
+	 * @return int of how many related models got deleted
255
+	 * @throws \EE_Error
256
+	 */
257
+	public function delete_related_permanently($model_object_or_id, $query_params = array())
258
+	{
259
+		// for each thing we would delete,
260
+		$related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
261
+		// determine if it's blocked by anything else before it can be deleted
262
+		$deleted_count = 0;
263
+		foreach ($related_model_objects as $related_model_object) {
264
+			$delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
265
+				$related_model_object,
266
+				$model_object_or_id
267
+			);
268
+			/* @var $model_object_or_id EE_Base_Class */
269
+			if ($related_model_object instanceof EE_Soft_Delete_Base_Class) {
270
+				$this->remove_relation_to($model_object_or_id, $related_model_object);
271
+				$deleted_count++;
272
+				if (! $delete_is_blocked) {
273
+					$related_model_object->delete_permanently();
274
+				} else {
275
+					// delete is blocked
276
+					// brent and darren, in this case, wanted to just soft delete it then
277
+					$related_model_object->delete();
278
+				}
279
+			} else {
280
+				// its not a soft-deletable thing anyways. do the normal logic.
281
+				if (! $delete_is_blocked) {
282
+					$this->remove_relation_to($model_object_or_id, $related_model_object);
283
+					$related_model_object->delete();
284
+					$deleted_count++;
285
+				}
286
+			}
287
+		}
288
+		return $deleted_count;
289
+	}
290
+
291
+
292
+	/**
293
+	 * this just returns a model_object_id for incoming item that could be an object or id.
294
+	 *
295
+	 * @param  EE_Base_Class|int $model_object_or_id model object or the primary key of this model
296
+	 * @throws EE_Error
297
+	 * @return int
298
+	 */
299
+	protected function _get_model_object_id($model_object_or_id)
300
+	{
301
+		$model_object_id = $model_object_or_id;
302
+		if ($model_object_or_id instanceof EE_Base_Class) {
303
+			$model_object_id = $model_object_or_id->ID();
304
+		}
305
+		if (! $model_object_id) {
306
+			throw new EE_Error(sprintf(
307
+				__(
308
+					"Sorry, we cant get the related %s model objects to %s model object before it has an ID. You can solve that by just saving it before trying to get its related model objects",
309
+					"event_espresso"
310
+				),
311
+				$this->get_other_model()->get_this_model_name(),
312
+				$this->get_this_model()->get_this_model_name()
313
+			));
314
+		}
315
+		return $model_object_id;
316
+	}
317
+
318
+
319
+	/**
320
+	 * Gets the SQL string for performing the join between this model and the other model.
321
+	 *
322
+	 * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
323
+	 * @return string of SQL, eg "LEFT JOIN table_name AS table_alias ON this_model_primary_table.pk =
324
+	 *                other_model_primary_table.fk" etc
325
+	 */
326
+	abstract public function get_join_statement($model_relation_chain);
327
+
328
+
329
+	/**
330
+	 * Adds a relationships between the two model objects provided. Each type of relationship handles this differently
331
+	 * (EE_Belongs_To is a slight exception, it should more accurately be called set_relation_to(...), as this
332
+	 * relationship only allows this model to be related to a single other model of this type)
333
+	 *
334
+	 * @param       $this_obj_or_id
335
+	 * @param       $other_obj_or_id
336
+	 * @param array $extra_join_model_fields_n_values
337
+	 * @return \EE_Base_Class the EE_Base_Class which was added as a relation. (Convenient if you only pass an ID for
338
+	 *                        $other_obj_or_id)
339
+	 */
340
+	abstract public function add_relation_to(
341
+		$this_obj_or_id,
342
+		$other_obj_or_id,
343
+		$extra_join_model_fields_n_values = array()
344
+	);
345
+
346
+
347
+	/**
348
+	 * Similar to 'add_relation_to(...)', performs the opposite action of removing the relationship between the two
349
+	 * model objects
350
+	 *
351
+	 * @param       $this_obj_or_id
352
+	 * @param       $other_obj_or_id
353
+	 * @param array $where_query
354
+	 * @return bool
355
+	 */
356
+	abstract public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array());
357
+
358
+
359
+	/**
360
+	 * Removes ALL relation instances for this relation obj
361
+	 *
362
+	 * @param EE_Base_Class|int $this_obj_or_id
363
+	 * @param array             $where_query_param @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
364
+	 * @return EE_Base_Class[]
365
+	 * @throws \EE_Error
366
+	 */
367
+	public function remove_relations($this_obj_or_id, $where_query_param = array())
368
+	{
369
+		$related_things = $this->get_all_related($this_obj_or_id, array($where_query_param));
370
+		$objs_removed   = array();
371
+		foreach ($related_things as $related_thing) {
372
+			$objs_removed[] = $this->remove_relation_to($this_obj_or_id, $related_thing);
373
+		}
374
+		return $objs_removed;
375
+	}
376
+
377
+
378
+	/**
379
+	 * If you aren't allowed to delete this model when there are related models across this
380
+	 * relation object, return true. Otherwise, if you can delete this model even though
381
+	 * related objects exist, returns false.
382
+	 *
383
+	 * @return boolean
384
+	 */
385
+	public function block_delete_if_related_models_exist()
386
+	{
387
+		return $this->_blocking_delete;
388
+	}
389
+
390
+
391
+	/**
392
+	 * Gets the error message to show
393
+	 *
394
+	 * @return string
395
+	 */
396
+	public function get_deletion_error_message()
397
+	{
398
+		if ($this->_blocking_delete_error_message) {
399
+			return $this->_blocking_delete_error_message;
400
+		} else {
401 401
 //          return sprintf(__('Cannot delete %1$s when there are related %2$s', "event_espresso"),$this->get_this_model()->item_name(2),$this->get_other_model()->item_name(2));
402
-            return sprintf(
403
-                __(
404
-                    'This %1$s is currently linked to one or more %2$s records. If this %1$s is incorrect, then please remove it from all %3$s before attempting to delete it.',
405
-                    "event_espresso"
406
-                ),
407
-                $this->get_this_model()->item_name(1),
408
-                $this->get_other_model()->item_name(1),
409
-                $this->get_other_model()->item_name(2)
410
-            );
411
-        }
412
-    }
413
-
414
-    /**
415
-     * Returns whatever is set as the nicename for the object.
416
-     *
417
-     * @return string
418
-     */
419
-    public function getSchemaDescription()
420
-    {
421
-        $description = $this instanceof EE_Belongs_To_Relation
422
-            ? esc_html__('The related %1$s entity to the %2$s.', 'event_espresso')
423
-            : esc_html__('The related %1$s entities to the %2$s.', 'event_espresso');
424
-        return sprintf(
425
-            $description,
426
-            $this->get_other_model()->get_this_model_name(),
427
-            $this->get_this_model()->get_this_model_name()
428
-        );
429
-    }
430
-
431
-    /**
432
-     * Returns whatever is set as the $_schema_type property for the object.
433
-     * Note: this will automatically add 'null' to the schema if the object is_nullable()
434
-     *
435
-     * @return string|array
436
-     */
437
-    public function getSchemaType()
438
-    {
439
-        return $this instanceof EE_Belongs_To_Relation ? 'object' : 'array';
440
-    }
441
-
442
-    /**
443
-     * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
444
-     * this method and return the properties for the schema.
445
-     * The reason this is not a property on the class is because there may be filters set on the values for the property
446
-     * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
447
-     *
448
-     * @return array
449
-     */
450
-    public function getSchemaProperties()
451
-    {
452
-        return array();
453
-    }
454
-
455
-    /**
456
-     * If a child class has enum values, they should override this method and provide a simple array
457
-     * of the enum values.
458
-     * The reason this is not a property on the class is because there may be filterable enum values that
459
-     * are set on the instantiated object that could be filtered after construct.
460
-     *
461
-     * @return array
462
-     */
463
-    public function getSchemaEnum()
464
-    {
465
-        return array();
466
-    }
467
-
468
-    /**
469
-     * This returns the value of the $_schema_format property on the object.
470
-     *
471
-     * @return string
472
-     */
473
-    public function getSchemaFormat()
474
-    {
475
-        return array();
476
-    }
477
-
478
-    /**
479
-     * This returns the value of the $_schema_readonly property on the object.
480
-     *
481
-     * @return bool
482
-     */
483
-    public function getSchemaReadonly()
484
-    {
485
-        return true;
486
-    }
487
-
488
-    /**
489
-     * This returns elements used to represent this field in the json schema.
490
-     *
491
-     * @link http://json-schema.org/
492
-     * @return array
493
-     */
494
-    public function getSchema()
495
-    {
496
-        $schema = array(
497
-            'description' => $this->getSchemaDescription(),
498
-            'type' => $this->getSchemaType(),
499
-            'relation' => true,
500
-            'relation_type' => get_class($this),
501
-            'readonly' => $this->getSchemaReadonly()
502
-        );
503
-
504
-        if ($this instanceof EE_HABTM_Relation) {
505
-            $schema['joining_model_name'] = $this->get_join_model()->get_this_model_name();
506
-        }
507
-
508
-        if ($this->getSchemaType() === 'array') {
509
-            $schema['items'] = array(
510
-                'type' => 'object'
511
-            );
512
-        }
513
-
514
-        return $schema;
515
-    }
402
+			return sprintf(
403
+				__(
404
+					'This %1$s is currently linked to one or more %2$s records. If this %1$s is incorrect, then please remove it from all %3$s before attempting to delete it.',
405
+					"event_espresso"
406
+				),
407
+				$this->get_this_model()->item_name(1),
408
+				$this->get_other_model()->item_name(1),
409
+				$this->get_other_model()->item_name(2)
410
+			);
411
+		}
412
+	}
413
+
414
+	/**
415
+	 * Returns whatever is set as the nicename for the object.
416
+	 *
417
+	 * @return string
418
+	 */
419
+	public function getSchemaDescription()
420
+	{
421
+		$description = $this instanceof EE_Belongs_To_Relation
422
+			? esc_html__('The related %1$s entity to the %2$s.', 'event_espresso')
423
+			: esc_html__('The related %1$s entities to the %2$s.', 'event_espresso');
424
+		return sprintf(
425
+			$description,
426
+			$this->get_other_model()->get_this_model_name(),
427
+			$this->get_this_model()->get_this_model_name()
428
+		);
429
+	}
430
+
431
+	/**
432
+	 * Returns whatever is set as the $_schema_type property for the object.
433
+	 * Note: this will automatically add 'null' to the schema if the object is_nullable()
434
+	 *
435
+	 * @return string|array
436
+	 */
437
+	public function getSchemaType()
438
+	{
439
+		return $this instanceof EE_Belongs_To_Relation ? 'object' : 'array';
440
+	}
441
+
442
+	/**
443
+	 * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
444
+	 * this method and return the properties for the schema.
445
+	 * The reason this is not a property on the class is because there may be filters set on the values for the property
446
+	 * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
447
+	 *
448
+	 * @return array
449
+	 */
450
+	public function getSchemaProperties()
451
+	{
452
+		return array();
453
+	}
454
+
455
+	/**
456
+	 * If a child class has enum values, they should override this method and provide a simple array
457
+	 * of the enum values.
458
+	 * The reason this is not a property on the class is because there may be filterable enum values that
459
+	 * are set on the instantiated object that could be filtered after construct.
460
+	 *
461
+	 * @return array
462
+	 */
463
+	public function getSchemaEnum()
464
+	{
465
+		return array();
466
+	}
467
+
468
+	/**
469
+	 * This returns the value of the $_schema_format property on the object.
470
+	 *
471
+	 * @return string
472
+	 */
473
+	public function getSchemaFormat()
474
+	{
475
+		return array();
476
+	}
477
+
478
+	/**
479
+	 * This returns the value of the $_schema_readonly property on the object.
480
+	 *
481
+	 * @return bool
482
+	 */
483
+	public function getSchemaReadonly()
484
+	{
485
+		return true;
486
+	}
487
+
488
+	/**
489
+	 * This returns elements used to represent this field in the json schema.
490
+	 *
491
+	 * @link http://json-schema.org/
492
+	 * @return array
493
+	 */
494
+	public function getSchema()
495
+	{
496
+		$schema = array(
497
+			'description' => $this->getSchemaDescription(),
498
+			'type' => $this->getSchemaType(),
499
+			'relation' => true,
500
+			'relation_type' => get_class($this),
501
+			'readonly' => $this->getSchemaReadonly()
502
+		);
503
+
504
+		if ($this instanceof EE_HABTM_Relation) {
505
+			$schema['joining_model_name'] = $this->get_join_model()->get_this_model_name();
506
+		}
507
+
508
+		if ($this->getSchemaType() === 'array') {
509
+			$schema['items'] = array(
510
+				'type' => 'object'
511
+			);
512
+		}
513
+
514
+		return $schema;
515
+	}
516 516
 }
Please login to merge, or discard this patch.