Completed
Branch dependabot/npm_and_yarn/eslint... (38e449)
by
unknown
74:57 queued 67:07
created
core/db_models/relations/EE_HABTM_Relation.php 2 patches
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -65,18 +65,18 @@  discard block
 block discarded – undo
65 65
         // remember the model relation chain to the JOIN model, because we'll
66 66
         // need it for get_join_statement()
67 67
         $this->_model_relation_chain_to_join_model = $model_relation_chain;
68
-        $this_table_pk_field                       = $this->get_this_model()->get_primary_key_field();// get_foreign_key_to($this->get_other_model()->get_this_model_name());
68
+        $this_table_pk_field                       = $this->get_this_model()->get_primary_key_field(); // get_foreign_key_to($this->get_other_model()->get_this_model_name());
69 69
         $join_table_fk_field_to_this_table         = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
70 70
         $this_table_alias                          = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
71 71
             $model_relation_chain,
72 72
             $this->get_this_model()->get_this_model_name()
73
-        ) . $this_table_pk_field->get_table_alias();
73
+        ).$this_table_pk_field->get_table_alias();
74 74
 
75 75
         $join_table_alias = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
76 76
             $model_relation_chain,
77 77
             $this->get_join_model()->get_this_model_name()
78
-        ) . $join_table_fk_field_to_this_table->get_table_alias();
79
-        $join_table       = $this->get_join_model()->get_table_for_alias($join_table_alias);
78
+        ).$join_table_fk_field_to_this_table->get_table_alias();
79
+        $join_table = $this->get_join_model()->get_table_for_alias($join_table_alias);
80 80
         // phew! ok, we have all the info we need, now we can create the SQL join string
81 81
         $SQL = $this->_left_join(
82 82
             $join_table,
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
             $join_table_fk_field_to_this_table->get_table_column(),
85 85
             $this_table_alias,
86 86
             $this_table_pk_field->get_table_column()
87
-        ) . $this->get_join_model()->_construct_internal_join_to_table_with_alias($join_table_alias);
87
+        ).$this->get_join_model()->_construct_internal_join_to_table_with_alias($join_table_alias);
88 88
 
89 89
         return $SQL;
90 90
     }
@@ -113,14 +113,14 @@  discard block
 block discarded – undo
113 113
         $join_table_alias                   = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
114 114
             $this->_model_relation_chain_to_join_model,
115 115
             $this->get_join_model()->get_this_model_name()
116
-        ) . $join_table_fk_field_to_this_table->get_table_alias();
116
+        ).$join_table_fk_field_to_this_table->get_table_alias();
117 117
         $other_table_pk_field               = $this->get_other_model()->get_primary_key_field();
118 118
         $join_table_fk_field_to_other_table = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
119 119
         $other_table_alias                  = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
120 120
             $model_relation_chain,
121 121
             $this->get_other_model()->get_this_model_name()
122
-        ) . $other_table_pk_field->get_table_alias();
123
-        $other_table                        = $this->get_other_model()->get_table_for_alias($other_table_alias);
122
+        ).$other_table_pk_field->get_table_alias();
123
+        $other_table = $this->get_other_model()->get_table_for_alias($other_table_alias);
124 124
 
125 125
         $SQL = $this->_left_join(
126 126
             $other_table,
@@ -128,7 +128,7 @@  discard block
 block discarded – undo
128 128
             $other_table_pk_field->get_table_column(),
129 129
             $join_table_alias,
130 130
             $join_table_fk_field_to_other_table->get_table_column()
131
-        ) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
131
+        ).$this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
132 132
         return $SQL;
133 133
     }
134 134
 
@@ -161,17 +161,17 @@  discard block
 block discarded – undo
161 161
         );
162 162
 
163 163
         // if $where_query exists lets add them to the query_params.
164
-        if (! empty($extra_join_model_fields_n_values)) {
164
+        if ( ! empty($extra_join_model_fields_n_values)) {
165 165
             // make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
166 166
             // make sure we strip THIS models name from the query param
167 167
             $parsed_query = array();
168 168
             foreach ($extra_join_model_fields_n_values as $query_param => $val) {
169
-                $query_param                = str_replace(
170
-                    $this->get_join_model()->get_this_model_name() . ".",
169
+                $query_param = str_replace(
170
+                    $this->get_join_model()->get_this_model_name().".",
171 171
                     "",
172 172
                     $query_param
173 173
                 );
174
-                $parsed_query[ $query_param ] = $val;
174
+                $parsed_query[$query_param] = $val;
175 175
             }
176 176
             $all_fields = array_merge($foreign_keys, $parsed_query);
177 177
         }
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
         // new row.
182 182
         // Again, if you want more sophisticated logic or insertions (handling more columns than just 2 foreign keys to
183 183
         // the other tables) use the joining model directly!
184
-        if (! $existing_entry_in_join_table) {
184
+        if ( ! $existing_entry_in_join_table) {
185 185
             $this->get_join_model()->insert($all_fields);
186 186
         } else {
187 187
             $this->get_join_model()->update(
@@ -217,17 +217,17 @@  discard block
 block discarded – undo
217 217
         );
218 218
 
219 219
         // if $where_query exists lets add them to the query_params.
220
-        if (! empty($where_query)) {
220
+        if ( ! empty($where_query)) {
221 221
             // make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
222 222
             // make sure we strip THIS models name from the query param
223 223
             $parsed_query = array();
224 224
             foreach ($where_query as $query_param => $val) {
225
-                $query_param                = str_replace(
226
-                    $this->get_join_model()->get_this_model_name() . ".",
225
+                $query_param = str_replace(
226
+                    $this->get_join_model()->get_this_model_name().".",
227 227
                     "",
228 228
                     $query_param
229 229
                 );
230
-                $parsed_query[ $query_param ] = $val;
230
+                $parsed_query[$query_param] = $val;
231 231
             }
232 232
             $cols_n_values = array_merge($cols_n_values, $parsed_query);
233 233
         }
Please login to merge, or discard this patch.
Indentation   +239 added lines, -239 removed lines patch added patch discarded remove patch
@@ -9,266 +9,266 @@
 block discarded – undo
9 9
  */
10 10
 class EE_HABTM_Relation extends EE_Model_Relation_Base
11 11
 {
12
-    /**
13
-     * Model which defines the relation between two other models. Eg, the EE_Event_Question_Group model,
14
-     * which joins EE_Event and EE_Question_Group
15
-     *
16
-     * @var EEM_Base
17
-     */
18
-    protected $_joining_model_name;
12
+	/**
13
+	 * Model which defines the relation between two other models. Eg, the EE_Event_Question_Group model,
14
+	 * which joins EE_Event and EE_Question_Group
15
+	 *
16
+	 * @var EEM_Base
17
+	 */
18
+	protected $_joining_model_name;
19 19
 
20
-    protected $_model_relation_chain_to_join_model;
20
+	protected $_model_relation_chain_to_join_model;
21 21
 
22 22
 
23
-    /**
24
-     * Object representing the relationship between two models. HasAndBelongsToMany relations always use a join-table
25
-     * (and an ee joining-model.) This knows how to join the models,
26
-     * get related models across the relation, and add-and-remove the relationships.
27
-     *
28
-     * @param bool    $joining_model_name
29
-     * @param boolean $block_deletes                 for this type of relation, we block by default for now. if there
30
-     *                                               are related models across this relation, block (prevent and add an
31
-     *                                               error) the deletion of this model
32
-     * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
33
-     *                                               default
34
-     */
35
-    public function __construct($joining_model_name, $block_deletes = true, $blocking_delete_error_message = '')
36
-    {
37
-        $this->_joining_model_name = $joining_model_name;
38
-        parent::__construct($block_deletes, $blocking_delete_error_message);
39
-    }
23
+	/**
24
+	 * Object representing the relationship between two models. HasAndBelongsToMany relations always use a join-table
25
+	 * (and an ee joining-model.) This knows how to join the models,
26
+	 * get related models across the relation, and add-and-remove the relationships.
27
+	 *
28
+	 * @param bool    $joining_model_name
29
+	 * @param boolean $block_deletes                 for this type of relation, we block by default for now. if there
30
+	 *                                               are related models across this relation, block (prevent and add an
31
+	 *                                               error) the deletion of this model
32
+	 * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
33
+	 *                                               default
34
+	 */
35
+	public function __construct($joining_model_name, $block_deletes = true, $blocking_delete_error_message = '')
36
+	{
37
+		$this->_joining_model_name = $joining_model_name;
38
+		parent::__construct($block_deletes, $blocking_delete_error_message);
39
+	}
40 40
 
41
-    /**
42
-     * Gets the joining model's object
43
-     *
44
-     * @return EEM_Base
45
-     */
46
-    public function get_join_model()
47
-    {
48
-        return $this->_get_model($this->_joining_model_name);
49
-    }
41
+	/**
42
+	 * Gets the joining model's object
43
+	 *
44
+	 * @return EEM_Base
45
+	 */
46
+	public function get_join_model()
47
+	{
48
+		return $this->_get_model($this->_joining_model_name);
49
+	}
50 50
 
51 51
 
52
-    /**
53
-     * Gets the SQL string for joining the main model's table containing the pk to the join table. Eg "LEFT JOIN
54
-     * real_join_table AS join_table_alias ON this_table_alias.pk = join_table_alias.fk_to_this_table"
55
-     *
56
-     * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
57
-     * @return string of SQL
58
-     * @throws \EE_Error
59
-     */
60
-    public function get_join_to_intermediate_model_statement($model_relation_chain)
61
-    {
62
-        // create sql like
63
-        // LEFT JOIN join_table AS join_table_alias ON this_table_alias.this_table_pk = join_table_alias.join_table_fk_to_this
64
-        // LEFT JOIN other_table AS other_table_alias ON join_table_alias.join_table_fk_to_other = other_table_alias.other_table_pk
65
-        // remember the model relation chain to the JOIN model, because we'll
66
-        // need it for get_join_statement()
67
-        $this->_model_relation_chain_to_join_model = $model_relation_chain;
68
-        $this_table_pk_field                       = $this->get_this_model()->get_primary_key_field();// get_foreign_key_to($this->get_other_model()->get_this_model_name());
69
-        $join_table_fk_field_to_this_table         = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
70
-        $this_table_alias                          = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
71
-            $model_relation_chain,
72
-            $this->get_this_model()->get_this_model_name()
73
-        ) . $this_table_pk_field->get_table_alias();
52
+	/**
53
+	 * Gets the SQL string for joining the main model's table containing the pk to the join table. Eg "LEFT JOIN
54
+	 * real_join_table AS join_table_alias ON this_table_alias.pk = join_table_alias.fk_to_this_table"
55
+	 *
56
+	 * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
57
+	 * @return string of SQL
58
+	 * @throws \EE_Error
59
+	 */
60
+	public function get_join_to_intermediate_model_statement($model_relation_chain)
61
+	{
62
+		// create sql like
63
+		// LEFT JOIN join_table AS join_table_alias ON this_table_alias.this_table_pk = join_table_alias.join_table_fk_to_this
64
+		// LEFT JOIN other_table AS other_table_alias ON join_table_alias.join_table_fk_to_other = other_table_alias.other_table_pk
65
+		// remember the model relation chain to the JOIN model, because we'll
66
+		// need it for get_join_statement()
67
+		$this->_model_relation_chain_to_join_model = $model_relation_chain;
68
+		$this_table_pk_field                       = $this->get_this_model()->get_primary_key_field();// get_foreign_key_to($this->get_other_model()->get_this_model_name());
69
+		$join_table_fk_field_to_this_table         = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
70
+		$this_table_alias                          = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
71
+			$model_relation_chain,
72
+			$this->get_this_model()->get_this_model_name()
73
+		) . $this_table_pk_field->get_table_alias();
74 74
 
75
-        $join_table_alias = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
76
-            $model_relation_chain,
77
-            $this->get_join_model()->get_this_model_name()
78
-        ) . $join_table_fk_field_to_this_table->get_table_alias();
79
-        $join_table       = $this->get_join_model()->get_table_for_alias($join_table_alias);
80
-        // phew! ok, we have all the info we need, now we can create the SQL join string
81
-        $SQL = $this->_left_join(
82
-            $join_table,
83
-            $join_table_alias,
84
-            $join_table_fk_field_to_this_table->get_table_column(),
85
-            $this_table_alias,
86
-            $this_table_pk_field->get_table_column()
87
-        ) . $this->get_join_model()->_construct_internal_join_to_table_with_alias($join_table_alias);
75
+		$join_table_alias = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
76
+			$model_relation_chain,
77
+			$this->get_join_model()->get_this_model_name()
78
+		) . $join_table_fk_field_to_this_table->get_table_alias();
79
+		$join_table       = $this->get_join_model()->get_table_for_alias($join_table_alias);
80
+		// phew! ok, we have all the info we need, now we can create the SQL join string
81
+		$SQL = $this->_left_join(
82
+			$join_table,
83
+			$join_table_alias,
84
+			$join_table_fk_field_to_this_table->get_table_column(),
85
+			$this_table_alias,
86
+			$this_table_pk_field->get_table_column()
87
+		) . $this->get_join_model()->_construct_internal_join_to_table_with_alias($join_table_alias);
88 88
 
89
-        return $SQL;
90
-    }
89
+		return $SQL;
90
+	}
91 91
 
92 92
 
93
-    /**
94
-     * Gets the SQL string for joining the join table to the other model's pk's table. Eg "LEFT JOIN real_other_table
95
-     * AS other_table_alias ON join_table_alias.fk_to_other_table = other_table_alias.pk" If you want to join between
96
-     * modelA -> joinModelAB -> modelB (eg, Event -> Event_Question_Group -> Question_Group), you should prepend the
97
-     * result of this function with results from get_join_to_intermediate_model_statement(), so that you join first to
98
-     * the intermediate join table, and then to the other model's pk's table
99
-     *
100
-     * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
101
-     * @return string of SQL
102
-     * @throws \EE_Error
103
-     */
104
-    public function get_join_statement($model_relation_chain)
105
-    {
106
-        if ($this->_model_relation_chain_to_join_model === null) {
107
-            throw new EE_Error(sprintf(__(
108
-                'When using EE_HABTM_Relation to create a join, you must call get_join_to_intermediate_model_statement BEFORE get_join_statement',
109
-                'event_espresso'
110
-            )));
111
-        }
112
-        $join_table_fk_field_to_this_table  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
113
-        $join_table_alias                   = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
114
-            $this->_model_relation_chain_to_join_model,
115
-            $this->get_join_model()->get_this_model_name()
116
-        ) . $join_table_fk_field_to_this_table->get_table_alias();
117
-        $other_table_pk_field               = $this->get_other_model()->get_primary_key_field();
118
-        $join_table_fk_field_to_other_table = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
119
-        $other_table_alias                  = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
120
-            $model_relation_chain,
121
-            $this->get_other_model()->get_this_model_name()
122
-        ) . $other_table_pk_field->get_table_alias();
123
-        $other_table                        = $this->get_other_model()->get_table_for_alias($other_table_alias);
93
+	/**
94
+	 * Gets the SQL string for joining the join table to the other model's pk's table. Eg "LEFT JOIN real_other_table
95
+	 * AS other_table_alias ON join_table_alias.fk_to_other_table = other_table_alias.pk" If you want to join between
96
+	 * modelA -> joinModelAB -> modelB (eg, Event -> Event_Question_Group -> Question_Group), you should prepend the
97
+	 * result of this function with results from get_join_to_intermediate_model_statement(), so that you join first to
98
+	 * the intermediate join table, and then to the other model's pk's table
99
+	 *
100
+	 * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
101
+	 * @return string of SQL
102
+	 * @throws \EE_Error
103
+	 */
104
+	public function get_join_statement($model_relation_chain)
105
+	{
106
+		if ($this->_model_relation_chain_to_join_model === null) {
107
+			throw new EE_Error(sprintf(__(
108
+				'When using EE_HABTM_Relation to create a join, you must call get_join_to_intermediate_model_statement BEFORE get_join_statement',
109
+				'event_espresso'
110
+			)));
111
+		}
112
+		$join_table_fk_field_to_this_table  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
113
+		$join_table_alias                   = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
114
+			$this->_model_relation_chain_to_join_model,
115
+			$this->get_join_model()->get_this_model_name()
116
+		) . $join_table_fk_field_to_this_table->get_table_alias();
117
+		$other_table_pk_field               = $this->get_other_model()->get_primary_key_field();
118
+		$join_table_fk_field_to_other_table = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
119
+		$other_table_alias                  = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
120
+			$model_relation_chain,
121
+			$this->get_other_model()->get_this_model_name()
122
+		) . $other_table_pk_field->get_table_alias();
123
+		$other_table                        = $this->get_other_model()->get_table_for_alias($other_table_alias);
124 124
 
125
-        $SQL = $this->_left_join(
126
-            $other_table,
127
-            $other_table_alias,
128
-            $other_table_pk_field->get_table_column(),
129
-            $join_table_alias,
130
-            $join_table_fk_field_to_other_table->get_table_column()
131
-        ) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
132
-        return $SQL;
133
-    }
125
+		$SQL = $this->_left_join(
126
+			$other_table,
127
+			$other_table_alias,
128
+			$other_table_pk_field->get_table_column(),
129
+			$join_table_alias,
130
+			$join_table_fk_field_to_other_table->get_table_column()
131
+		) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
132
+		return $SQL;
133
+	}
134 134
 
135 135
 
136
-    /**
137
-     * Ensures there is an entry in the join table between these two models. Feel free to do this manually if you like.
138
-     * If the join table has additional columns (eg, the Event_Question_Group table has a is_primary column), then
139
-     * you'll want to directly use the EEM_Event_Question_Group model to add the entry to the table and set those extra
140
-     * columns' values
141
-     *
142
-     * @param EE_Base_Class|int $this_obj_or_id
143
-     * @param EE_Base_Class|int $other_obj_or_id
144
-     * @param array             $extra_join_model_fields_n_values col=>val pairs that are used as extra conditions for
145
-     *                                                            checking existing values and for setting new rows if
146
-     *                                                            no exact matches.
147
-     * @return EE_Base_Class
148
-     * @throws \EE_Error
149
-     */
150
-    public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
151
-    {
152
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
153
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
154
-        // check if such a relationship already exists
155
-        $join_model_fk_to_this_model  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
156
-        $join_model_fk_to_other_model = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
136
+	/**
137
+	 * Ensures there is an entry in the join table between these two models. Feel free to do this manually if you like.
138
+	 * If the join table has additional columns (eg, the Event_Question_Group table has a is_primary column), then
139
+	 * you'll want to directly use the EEM_Event_Question_Group model to add the entry to the table and set those extra
140
+	 * columns' values
141
+	 *
142
+	 * @param EE_Base_Class|int $this_obj_or_id
143
+	 * @param EE_Base_Class|int $other_obj_or_id
144
+	 * @param array             $extra_join_model_fields_n_values col=>val pairs that are used as extra conditions for
145
+	 *                                                            checking existing values and for setting new rows if
146
+	 *                                                            no exact matches.
147
+	 * @return EE_Base_Class
148
+	 * @throws \EE_Error
149
+	 */
150
+	public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
151
+	{
152
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
153
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
154
+		// check if such a relationship already exists
155
+		$join_model_fk_to_this_model  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
156
+		$join_model_fk_to_other_model = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
157 157
 
158
-        $foreign_keys = $all_fields = array(
159
-            $join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
160
-            $join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
161
-        );
158
+		$foreign_keys = $all_fields = array(
159
+			$join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
160
+			$join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
161
+		);
162 162
 
163
-        // if $where_query exists lets add them to the query_params.
164
-        if (! empty($extra_join_model_fields_n_values)) {
165
-            // make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
166
-            // make sure we strip THIS models name from the query param
167
-            $parsed_query = array();
168
-            foreach ($extra_join_model_fields_n_values as $query_param => $val) {
169
-                $query_param                = str_replace(
170
-                    $this->get_join_model()->get_this_model_name() . ".",
171
-                    "",
172
-                    $query_param
173
-                );
174
-                $parsed_query[ $query_param ] = $val;
175
-            }
176
-            $all_fields = array_merge($foreign_keys, $parsed_query);
177
-        }
163
+		// if $where_query exists lets add them to the query_params.
164
+		if (! empty($extra_join_model_fields_n_values)) {
165
+			// make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
166
+			// make sure we strip THIS models name from the query param
167
+			$parsed_query = array();
168
+			foreach ($extra_join_model_fields_n_values as $query_param => $val) {
169
+				$query_param                = str_replace(
170
+					$this->get_join_model()->get_this_model_name() . ".",
171
+					"",
172
+					$query_param
173
+				);
174
+				$parsed_query[ $query_param ] = $val;
175
+			}
176
+			$all_fields = array_merge($foreign_keys, $parsed_query);
177
+		}
178 178
 
179
-        $existing_entry_in_join_table = $this->get_join_model()->get_one(array($foreign_keys));
180
-        // If there is already an entry in the join table, indicating a relationship, update it instead of adding a
181
-        // new row.
182
-        // Again, if you want more sophisticated logic or insertions (handling more columns than just 2 foreign keys to
183
-        // the other tables) use the joining model directly!
184
-        if (! $existing_entry_in_join_table) {
185
-            $this->get_join_model()->insert($all_fields);
186
-        } else {
187
-            $this->get_join_model()->update(
188
-                $all_fields,
189
-                [$foreign_keys]
190
-            );
191
-        }
192
-        return $other_model_obj;
193
-    }
179
+		$existing_entry_in_join_table = $this->get_join_model()->get_one(array($foreign_keys));
180
+		// If there is already an entry in the join table, indicating a relationship, update it instead of adding a
181
+		// new row.
182
+		// Again, if you want more sophisticated logic or insertions (handling more columns than just 2 foreign keys to
183
+		// the other tables) use the joining model directly!
184
+		if (! $existing_entry_in_join_table) {
185
+			$this->get_join_model()->insert($all_fields);
186
+		} else {
187
+			$this->get_join_model()->update(
188
+				$all_fields,
189
+				[$foreign_keys]
190
+			);
191
+		}
192
+		return $other_model_obj;
193
+	}
194 194
 
195 195
 
196
-    /**
197
-     * Deletes any rows in the join table that have foreign keys matching the other model objects specified
198
-     *
199
-     * @param EE_Base_Class|int $this_obj_or_id
200
-     * @param EE_Base_Class|int $other_obj_or_id
201
-     * @param array             $where_query col=>val pairs that are used as extra conditions for checking existing
202
-     *                                       values and for removing existing rows if exact matches exist.
203
-     * @return EE_Base_Class
204
-     * @throws \EE_Error
205
-     */
206
-    public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
207
-    {
208
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
209
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
210
-        // check if such a relationship already exists
211
-        $join_model_fk_to_this_model  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
212
-        $join_model_fk_to_other_model = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
196
+	/**
197
+	 * Deletes any rows in the join table that have foreign keys matching the other model objects specified
198
+	 *
199
+	 * @param EE_Base_Class|int $this_obj_or_id
200
+	 * @param EE_Base_Class|int $other_obj_or_id
201
+	 * @param array             $where_query col=>val pairs that are used as extra conditions for checking existing
202
+	 *                                       values and for removing existing rows if exact matches exist.
203
+	 * @return EE_Base_Class
204
+	 * @throws \EE_Error
205
+	 */
206
+	public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
207
+	{
208
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
209
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
210
+		// check if such a relationship already exists
211
+		$join_model_fk_to_this_model  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
212
+		$join_model_fk_to_other_model = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
213 213
 
214
-        $cols_n_values = array(
215
-            $join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
216
-            $join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
217
-        );
214
+		$cols_n_values = array(
215
+			$join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
216
+			$join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
217
+		);
218 218
 
219
-        // if $where_query exists lets add them to the query_params.
220
-        if (! empty($where_query)) {
221
-            // make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
222
-            // make sure we strip THIS models name from the query param
223
-            $parsed_query = array();
224
-            foreach ($where_query as $query_param => $val) {
225
-                $query_param                = str_replace(
226
-                    $this->get_join_model()->get_this_model_name() . ".",
227
-                    "",
228
-                    $query_param
229
-                );
230
-                $parsed_query[ $query_param ] = $val;
231
-            }
232
-            $cols_n_values = array_merge($cols_n_values, $parsed_query);
233
-        }
219
+		// if $where_query exists lets add them to the query_params.
220
+		if (! empty($where_query)) {
221
+			// make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
222
+			// make sure we strip THIS models name from the query param
223
+			$parsed_query = array();
224
+			foreach ($where_query as $query_param => $val) {
225
+				$query_param                = str_replace(
226
+					$this->get_join_model()->get_this_model_name() . ".",
227
+					"",
228
+					$query_param
229
+				);
230
+				$parsed_query[ $query_param ] = $val;
231
+			}
232
+			$cols_n_values = array_merge($cols_n_values, $parsed_query);
233
+		}
234 234
 
235
-        $this->get_join_model()->delete(array($cols_n_values));
236
-        return $other_model_obj;
237
-    }
235
+		$this->get_join_model()->delete(array($cols_n_values));
236
+		return $other_model_obj;
237
+	}
238 238
 
239
-    /**
240
-     * Gets all the non-key fields (ie, not the primary key and not foreign keys) on the join model.
241
-     * @since 4.9.76.p
242
-     * @return EE_Model_Field_Base[]
243
-     * @throws EE_Error
244
-     */
245
-    public function getNonKeyFields()
246
-    {
247
-        // all fields besides the primary key and two foreign keys should be parameters
248
-        $join_model = $this->get_join_model();
249
-        $standard_fields = array();
250
-        if ($join_model->has_primary_key_field()) {
251
-            $standard_fields[] = $join_model->primary_key_name();
252
-        }
253
-        if ($this->get_this_model()->has_primary_key_field()) {
254
-            $standard_fields[] = $this->get_this_model()->primary_key_name();
255
-        }
256
-        if ($this->get_other_model()->has_primary_key_field()) {
257
-            $standard_fields[] = $this->get_other_model()->primary_key_name();
258
-        }
259
-        return array_diff_key(
260
-            $join_model->field_settings(),
261
-            array_flip($standard_fields)
262
-        );
263
-    }
239
+	/**
240
+	 * Gets all the non-key fields (ie, not the primary key and not foreign keys) on the join model.
241
+	 * @since 4.9.76.p
242
+	 * @return EE_Model_Field_Base[]
243
+	 * @throws EE_Error
244
+	 */
245
+	public function getNonKeyFields()
246
+	{
247
+		// all fields besides the primary key and two foreign keys should be parameters
248
+		$join_model = $this->get_join_model();
249
+		$standard_fields = array();
250
+		if ($join_model->has_primary_key_field()) {
251
+			$standard_fields[] = $join_model->primary_key_name();
252
+		}
253
+		if ($this->get_this_model()->has_primary_key_field()) {
254
+			$standard_fields[] = $this->get_this_model()->primary_key_name();
255
+		}
256
+		if ($this->get_other_model()->has_primary_key_field()) {
257
+			$standard_fields[] = $this->get_other_model()->primary_key_name();
258
+		}
259
+		return array_diff_key(
260
+			$join_model->field_settings(),
261
+			array_flip($standard_fields)
262
+		);
263
+	}
264 264
 
265
-    /**
266
-     * Returns true if the join model has non-key fields (ie, fields that aren't the primary key or foreign keys.)
267
-     * @since 4.9.76.p
268
-     * @return boolean
269
-     */
270
-    public function hasNonKeyFields()
271
-    {
272
-        return count($this->get_join_model()->field_settings()) > 3;
273
-    }
265
+	/**
266
+	 * Returns true if the join model has non-key fields (ie, fields that aren't the primary key or foreign keys.)
267
+	 * @since 4.9.76.p
268
+	 * @return boolean
269
+	 */
270
+	public function hasNonKeyFields()
271
+	{
272
+		return count($this->get_join_model()->field_settings()) > 3;
273
+	}
274 274
 }
Please login to merge, or discard this patch.
core/EE_Data_Migration_Manager.core.php 3 patches
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -3,7 +3,6 @@
 block discarded – undo
3 3
 use EventEspresso\core\exceptions\InvalidDataTypeException;
4 4
 use EventEspresso\core\exceptions\InvalidInterfaceException;
5 5
 use EventEspresso\core\interfaces\ResettableInterface;
6
-
7 6
 use EventEspresso\core\services\database\TableManager;
8 7
 use EventEspresso\core\services\database\TableAnalysis;
9 8
 use EventEspresso\core\services\loaders\LoaderFactory;
Please login to merge, or discard this patch.
Indentation   +1234 added lines, -1234 removed lines patch added patch discarded remove patch
@@ -33,1238 +33,1238 @@
 block discarded – undo
33 33
 class EE_Data_Migration_Manager implements ResettableInterface
34 34
 {
35 35
 
36
-    /**
37
-     *
38
-     * @var EE_Registry
39
-     */
40
-    // protected $EE;
41
-    /**
42
-     * name of the wordpress option which stores an array of data about
43
-     */
44
-    const data_migrations_option_name = 'ee_data_migration';
45
-
46
-
47
-    const data_migration_script_option_prefix = 'ee_data_migration_script_';
48
-
49
-    const data_migration_script_mapping_option_prefix = 'ee_dms_map_';
50
-
51
-    /**
52
-     * name of the wordpress option which stores the database' current version. IE, the code may be at version 4.2.0,
53
-     * but as migrations are performed the database will progress from 3.1.35 to 4.1.0 etc.
54
-     */
55
-    const current_database_state = 'ee_data_migration_current_db_state';
56
-
57
-    /**
58
-     * Special status string returned when we're positive there are no more data migration
59
-     * scripts that can be run.
60
-     */
61
-    const status_no_more_migration_scripts = 'no_more_migration_scripts';
62
-    /**
63
-     * string indicating the migration should continue
64
-     */
65
-    const status_continue = 'status_continue';
66
-    /**
67
-     * string indicating the migration has completed and should be ended
68
-     */
69
-    const status_completed = 'status_completed';
70
-    /**
71
-     * string indicating a fatal error occurred and the data migration should be completely aborted
72
-     */
73
-    const status_fatal_error = 'status_fatal_error';
74
-
75
-    /**
76
-     * the number of 'items' (usually DB rows) to migrate on each 'step' (ajax request sent
77
-     * during migration)
78
-     */
79
-    const step_size = 50;
80
-
81
-    /**
82
-     * option name that stores the queue of ee plugins needing to have
83
-     * their data initialized (or re-initialized) once we are done migrations
84
-     */
85
-    const db_init_queue_option_name = 'ee_db_init_queue';
86
-    /**
87
-     * Array of information concerning data migrations that have ran in the history
88
-     * of this EE installation. Keys should be the name of the version the script upgraded to
89
-     *
90
-     * @var EE_Data_Migration_Script_Base[]
91
-     */
92
-    private $_data_migrations_ran = null;
93
-    /**
94
-     * The last ran script. It's nice to store this somewhere accessible, as its easiest
95
-     * to know which was the last run by which is the newest wp option; but in most of the code
96
-     * we just use the local $_data_migration_ran array, which organized the scripts differently
97
-     *
98
-     * @var EE_Data_Migration_Script_Base
99
-     */
100
-    private $_last_ran_script = null;
101
-
102
-    /**
103
-     * Similarly to _last_ran_script, but this is the last INCOMPLETE migration script.
104
-     *
105
-     * @var EE_Data_Migration_Script_Base
106
-     */
107
-    private $_last_ran_incomplete_script = null;
108
-    /**
109
-     * array where keys are classnames, and values are filepaths of all the known migration scripts
110
-     *
111
-     * @var array
112
-     */
113
-    private $_data_migration_class_to_filepath_map;
114
-
115
-    /**
116
-     * the following 4 properties are fully set on construction.
117
-     * Note: the first two apply to whether to continue running ALL migration scripts (ie, even though we're finished
118
-     * one, we may want to start the next one); whereas the last two indicate whether to continue running a single
119
-     * data migration script
120
-     *
121
-     * @var array
122
-     */
123
-    public $stati_that_indicate_to_continue_migrations = array();
124
-
125
-    public $stati_that_indicate_to_stop_migrations = array();
126
-
127
-    public $stati_that_indicate_to_continue_single_migration_script = array();
128
-
129
-    public $stati_that_indicate_to_stop_single_migration_script = array();
130
-
131
-    /**
132
-     * @var \EventEspresso\core\services\database\TableManager $table_manager
133
-     */
134
-    protected $_table_manager;
135
-
136
-    /**
137
-     * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
138
-     */
139
-    protected $_table_analysis;
140
-
141
-    /**
142
-     * @var array $script_migration_versions
143
-     */
144
-    protected $script_migration_versions;
145
-
146
-    /**
147
-     * @var EE_Data_Migration_Manager $_instance
148
-     * @access    private
149
-     */
150
-    private static $_instance = null;
151
-
152
-
153
-    /**
154
-     * @singleton method used to instantiate class object
155
-     * @access    public
156
-     * @return EE_Data_Migration_Manager instance
157
-     */
158
-    public static function instance()
159
-    {
160
-        // check if class object is instantiated
161
-        if (! self::$_instance instanceof EE_Data_Migration_Manager) {
162
-            self::$_instance = new self();
163
-        }
164
-        return self::$_instance;
165
-    }
166
-
167
-    /**
168
-     * resets the singleton to its brand-new state (but does NOT delete old references to the old singleton. Meaning,
169
-     * all new usages of the singleton should be made with Classname::instance()) and returns it
170
-     *
171
-     * @return EE_Data_Migration_Manager
172
-     */
173
-    public static function reset()
174
-    {
175
-        self::$_instance = null;
176
-        return self::instance();
177
-    }
178
-
179
-
180
-    /**
181
-     * constructor
182
-     */
183
-    private function __construct()
184
-    {
185
-        $this->stati_that_indicate_to_continue_migrations = array(
186
-            self::status_continue,
187
-            self::status_completed,
188
-        );
189
-        $this->stati_that_indicate_to_stop_migrations = array(
190
-            self::status_fatal_error,
191
-            self::status_no_more_migration_scripts,
192
-        );
193
-        $this->stati_that_indicate_to_continue_single_migration_script = array(
194
-            self::status_continue,
195
-        );
196
-        $this->stati_that_indicate_to_stop_single_migration_script = array(
197
-            self::status_completed,
198
-            self::status_fatal_error
199
-            // note: status_no_more_migration_scripts doesn't apply
200
-        );
201
-        // make sure we've included the base migration script, because we may need the EE_DMS_Unknown_1_0_0 class
202
-        // to be defined, because right now it doesn't get autoloaded on its own
203
-        EE_Registry::instance()->load_core('Data_Migration_Class_Base', array(), true);
204
-        EE_Registry::instance()->load_core('Data_Migration_Script_Base', array(), true);
205
-        EE_Registry::instance()->load_core('DMS_Unknown_1_0_0', array(), true);
206
-        EE_Registry::instance()->load_core('Data_Migration_Script_Stage', array(), true);
207
-        EE_Registry::instance()->load_core('Data_Migration_Script_Stage_Table', array(), true);
208
-        $this->_table_manager = EE_Registry::instance()->create('TableManager', array(), true);
209
-        $this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
210
-    }
211
-
212
-
213
-    /**
214
-     * Deciphers, from an option's name, what plugin and version it relates to (see _save_migrations_ran to see what
215
-     * the option names are like, but generally they're like
216
-     * 'ee_data_migration_script_Core.4.1.0' in 4.2 or 'ee_data_migration_script_4.1.0' before that).
217
-     * The option name shouldn't ever be like 'ee_data_migration_script_Core.4.1.0.reg' because it's derived,
218
-     * indirectly, from the data migration's classname, which should always be like EE_DMS_%s_%d_%d_%d.dms.php (eg
219
-     * EE_DMS_Core_4_1_0.dms.php)
220
-     *
221
-     * @param string $option_name (see EE_Data_Migration_Manage::_save_migrations_ran() where the option name is set)
222
-     * @return array where the first item is the plugin slug (eg 'Core','Calendar',etc) and the 2nd is the version of
223
-     *               that plugin (eg '4.1.0')
224
-     */
225
-    private function _get_plugin_slug_and_version_string_from_dms_option_name($option_name)
226
-    {
227
-        $plugin_slug_and_version_string = str_replace(
228
-            EE_Data_Migration_Manager::data_migration_script_option_prefix,
229
-            "",
230
-            $option_name
231
-        );
232
-        // check if $plugin_slug_and_version_string is like '4.1.0' (4.1-style) or 'Core.4.1.0' (4.2-style)
233
-        $parts = explode(".", $plugin_slug_and_version_string);
234
-
235
-        if (count($parts) == 4) {
236
-            // it's 4.2-style.eg Core.4.1.0
237
-            $plugin_slug = $parts[0];// eg Core
238
-            $version_string = $parts[1] . "." . $parts[2] . "." . $parts[3]; // eg 4.1.0
239
-        } else {
240
-            // it's 4.1-style: eg 4.1.0
241
-            $plugin_slug = 'Core';
242
-            $version_string = $plugin_slug_and_version_string;// eg 4.1.0
243
-        }
244
-        return array($plugin_slug, $version_string);
245
-    }
246
-
247
-    /**
248
-     * Gets the DMS class from the wordpress option, otherwise throws an EE_Error if it's not
249
-     * for a known DMS class.
250
-     *
251
-     * @param string $dms_option_name
252
-     * @param string $dms_option_value (serialized)
253
-     * @return EE_Data_Migration_Script_Base
254
-     * @throws EE_Error
255
-     */
256
-    private function _get_dms_class_from_wp_option($dms_option_name, $dms_option_value)
257
-    {
258
-        $data_migration_data = maybe_unserialize($dms_option_value);
259
-        if (isset($data_migration_data['class']) && class_exists($data_migration_data['class'])) {
260
-            $class = LoaderFactory::getLoader()->getShared($data_migration_data['class']);
261
-            if ($class instanceof EE_Data_Migration_Script_Base) {
262
-                $class->instantiate_from_array_of_properties($data_migration_data);
263
-                return $class;
264
-            } else {
265
-                // huh, so its an object but not a data migration script?? that shouldn't happen
266
-                // just leave it as an array (which will probably just get ignored)
267
-                throw new EE_Error(
268
-                    sprintf(
269
-                        __(
270
-                            "Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists",
271
-                            'event_espresso'
272
-                        ),
273
-                        $data_migration_data['class']
274
-                    )
275
-                );
276
-            }
277
-        } else {
278
-            // so the data doesn't specify a class. So it must either be a legacy array of info or some array (which we'll probably just ignore), or a class that no longer exists
279
-            throw new EE_Error(
280
-                sprintf(__("The wp option  with key '%s' does not represent a DMS", 'event_espresso'), $dms_option_name)
281
-            );
282
-        }
283
-    }
284
-
285
-    /**
286
-     * Gets the array describing what data migrations have run. Also has a side-effect of recording which was the last
287
-     * ran, and which was the last ran which hasn't finished yet
288
-     *
289
-     * @return array where each element should be an array of EE_Data_Migration_Script_Base (but also has a few legacy
290
-     *               arrays in there - which should probably be ignored)
291
-     */
292
-    public function get_data_migrations_ran()
293
-    {
294
-        if (! $this->_data_migrations_ran) {
295
-            // setup autoloaders for each of the scripts in there
296
-            $this->get_all_data_migration_scripts_available();
297
-            $data_migrations_options = $this->get_all_migration_script_options(
298
-            );// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
299
-
300
-            $data_migrations_ran = array();
301
-            // convert into data migration script classes where possible
302
-            foreach ($data_migrations_options as $data_migration_option) {
303
-                list($plugin_slug, $version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name(
304
-                    $data_migration_option['option_name']
305
-                );
306
-
307
-                try {
308
-                    $class = $this->_get_dms_class_from_wp_option(
309
-                        $data_migration_option['option_name'],
310
-                        $data_migration_option['option_value']
311
-                    );
312
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
313
-                    // ok so far THIS is the 'last-ran-script'... unless we find another on next iteration
314
-                    $this->_last_ran_script = $class;
315
-                    if (! $class->is_completed()) {
316
-                        // sometimes we also like to know which was the last incomplete script (or if there are any at all)
317
-                        $this->_last_ran_incomplete_script = $class;
318
-                    }
319
-                } catch (EE_Error $e) {
320
-                    // ok so its not a DMS. We'll just keep it, although other code will need to expect non-DMSs
321
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
322
-                        $data_migration_option['option_value']
323
-                    );
324
-                }
325
-            }
326
-            // so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
327
-            $this->_data_migrations_ran = $data_migrations_ran;
328
-            if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
329
-                $this->_data_migrations_ran = array();
330
-            }
331
-        }
332
-        return $this->_data_migrations_ran;
333
-    }
334
-
335
-
336
-    /**
337
-     *
338
-     * @param string $script_name eg 'DMS_Core_4_1_0'
339
-     * @param string $old_table   eg 'wp_events_detail'
340
-     * @param string $old_pk      eg 'wp_esp_posts'
341
-     * @param        $new_table
342
-     * @return mixed string or int
343
-     */
344
-    public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table)
345
-    {
346
-        $script = EE_Registry::instance()->load_dms($script_name);
347
-        $mapping = $script->get_mapping_new_pk($old_table, $old_pk, $new_table);
348
-        return $mapping;
349
-    }
350
-
351
-    /**
352
-     * Gets all the options containing migration scripts that have been run. Ordering is important: it's assumed that
353
-     * the last option returned in this array is the most-recently ran DMS option
354
-     *
355
-     * @return array
356
-     */
357
-    public function get_all_migration_script_options()
358
-    {
359
-        global $wpdb;
360
-        return $wpdb->get_results(
361
-            "SELECT * FROM {$wpdb->options} WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id ASC",
362
-            ARRAY_A
363
-        );
364
-    }
365
-
366
-    /**
367
-     * Gets the array of folders which contain data migration scripts. Also adds them to be auto-loaded
368
-     *
369
-     * @return array where each value is the full folder path of a folder containing data migration scripts, WITH
370
-     *               slashes at the end of the folder name.
371
-     */
372
-    public function get_data_migration_script_folders()
373
-    {
374
-        return apply_filters(
375
-            'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
376
-            array('Core' => EE_CORE . 'data_migration_scripts')
377
-        );
378
-    }
379
-
380
-    /**
381
-     * Gets the version the migration script upgrades to
382
-     *
383
-     * @param string $migration_script_name eg 'EE_DMS_Core_4_1_0'
384
-     * @return array {
385
-     * @type string  $slug                  like 'Core','Calendar',etc
386
-     * @type string  $version               like 4.3.0
387
-     *                                      }
388
-     * @throws EE_Error
389
-     */
390
-    public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
391
-    {
392
-        if (isset($this->script_migration_versions[ $migration_script_name ])) {
393
-            return $this->script_migration_versions[ $migration_script_name ];
394
-        }
395
-        $dms_info = $this->parse_dms_classname($migration_script_name);
396
-        $this->script_migration_versions[ $migration_script_name ] = array(
397
-            'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
398
-            'version' => $dms_info['major_version'] . "." . $dms_info['minor_version'] . "." . $dms_info['micro_version'],
399
-        );
400
-        return $this->script_migration_versions[ $migration_script_name ];
401
-    }
402
-
403
-    /**
404
-     * Gets the juicy details out of a dms filename like 'EE_DMS_Core_4_1_0'
405
-     *
406
-     * @param string $classname
407
-     * @return array with keys 'slug','major_version','minor_version', and 'micro_version' (the last 3 are ints)
408
-     * @throws EE_Error
409
-     */
410
-    public function parse_dms_classname($classname)
411
-    {
412
-        $matches = array();
413
-        preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
414
-        if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
415
-            throw new EE_Error(
416
-                sprintf(
417
-                    __(
418
-                        "%s is not a valid Data Migration Script. The classname should be like EE_DMS_w_x_y_z, where w is either 'Core' or the slug of an addon and x, y and z are numbers, ",
419
-                        "event_espresso"
420
-                    ),
421
-                    $classname
422
-                )
423
-            );
424
-        }
425
-        return array(
426
-            'slug'          => $matches[1],
427
-            'major_version' => intval($matches[2]),
428
-            'minor_version' => intval($matches[3]),
429
-            'micro_version' => intval($matches[4]),
430
-        );
431
-    }
432
-
433
-    /**
434
-     * Ensures that the option indicating the current DB version is set. This should only be
435
-     * a concern when activating EE for the first time, THEORETICALLY.
436
-     * If we detect that we're activating EE4 over top of EE3.1, then we set the current db state to 3.1.x, otherwise
437
-     * to 4.1.x.
438
-     *
439
-     * @return string of current db state
440
-     */
441
-    public function ensure_current_database_state_is_set()
442
-    {
443
-        $espresso_db_core_updates = get_option('espresso_db_update', array());
444
-        $db_state = get_option(EE_Data_Migration_Manager::current_database_state);
445
-        if (! $db_state) {
446
-            // mark the DB as being in the state as the last version in there.
447
-            // this is done to trigger maintenance mode and do data migration scripts
448
-            // if the admin installed this version of EE over 3.1.x or 4.0.x
449
-            // otherwise, the normal maintenance mode code is fine
450
-            $previous_versions_installed = array_keys($espresso_db_core_updates);
451
-            $previous_version_installed = end($previous_versions_installed);
452
-            if (version_compare('4.1.0', $previous_version_installed)) {
453
-                // last installed version was less than 4.1
454
-                // so we want the data migrations to happen. SO, we're going to say the DB is at that state
455
-                $db_state = array('Core' => $previous_version_installed);
456
-            } else {
457
-                $db_state = array('Core' => EVENT_ESPRESSO_VERSION);
458
-            }
459
-            update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
460
-        }
461
-        // in 4.1, $db_state would have only been a simple string like '4.1.0',
462
-        // but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
463
-        // db, and possibly other keys for other addons like 'Calendar','Permissions',etc
464
-        if (! is_array($db_state)) {
465
-            $db_state = array('Core' => $db_state);
466
-            update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
467
-        }
468
-        return $db_state;
469
-    }
470
-
471
-    /**
472
-     * Checks if there are any data migration scripts that ought to be run. If found,
473
-     * returns the instantiated classes. If none are found (ie, they've all already been run
474
-     * or they don't apply), returns an empty array
475
-     *
476
-     * @return EE_Data_Migration_Script_Base[]
477
-     */
478
-    public function check_for_applicable_data_migration_scripts()
479
-    {
480
-        // get the option describing what options have already run
481
-        $scripts_ran = $this->get_data_migrations_ran();
482
-        // $scripts_ran = array('4.1.0.core'=>array('monkey'=>null));
483
-        $script_class_and_filepaths_available = $this->get_all_data_migration_scripts_available();
484
-
485
-
486
-        $current_database_state = $this->ensure_current_database_state_is_set();
487
-        // determine which have already been run
488
-        $script_classes_that_should_run_per_iteration = array();
489
-        $iteration = 0;
490
-        $next_database_state_to_consider = $current_database_state;
491
-        $theoretical_database_state = null;
492
-        do {
493
-            // the next state after the currently-considered one will start off looking the same as the current, but we may make additions...
494
-            $theoretical_database_state = $next_database_state_to_consider;
495
-            // the next db state to consider is "what would the DB be like had we run all the scripts we found that applied last time?)
496
-            foreach ($script_class_and_filepaths_available as $classname => $filepath) {
497
-                $migrates_to_version = $this->script_migrates_to_version($classname);
498
-                $script_converts_plugin_slug = $migrates_to_version['slug'];
499
-                $script_converts_to_version = $migrates_to_version['version'];
500
-                // check if this version script is DONE or not; or if it's never been ran
501
-                if (! $scripts_ran ||
502
-                    ! isset($scripts_ran[ $script_converts_plugin_slug ]) ||
503
-                    ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])) {
504
-                    // we haven't ran this conversion script before
505
-                    // now check if it applies... note that we've added an autoloader for it on get_all_data_migration_scripts_available
506
-                    $script = LoaderFactory::getLoader()->load($classname);
507
-                    /* @var $script EE_Data_Migration_Script_Base */
508
-                    $can_migrate = $script->can_migrate_from_version($theoretical_database_state);
509
-                    if ($can_migrate) {
510
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
511
-                        $migrates_to_version = $script->migrates_to_version();
512
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
513
-                        unset($script_class_and_filepaths_available[ $classname ]);
514
-                    }
515
-                } elseif ($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ] instanceof EE_Data_Migration_Script_Base) {
516
-                    // this script has been ran, or at least started
517
-                    $script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
518
-                    if ($script->get_status() != self::status_completed) {
519
-                        // this script is already underway... keep going with it
520
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
521
-                        $migrates_to_version = $script->migrates_to_version();
522
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
523
-                        unset($script_class_and_filepaths_available[ $classname ]);
524
-                    } else {
525
-                        // it must have a status that indicates it has finished, so we don't want to try and run it again
526
-                    }
527
-                } else {
528
-                    // it exists but it's not  a proper data migration script
529
-                    // maybe the script got renamed? or was simply removed from EE?
530
-                    // either way, its certainly not runnable!
531
-                }
532
-            }
533
-            $iteration++;
534
-        } while ($next_database_state_to_consider != $theoretical_database_state && $iteration < 6);
535
-        // ok we have all the scripts that should run, now let's make them into flat array
536
-        $scripts_that_should_run = array();
537
-        foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
538
-            ksort($scripts_at_priority);
539
-            foreach ($scripts_at_priority as $scripts) {
540
-                foreach ($scripts as $script) {
541
-                    $scripts_that_should_run[ get_class($script) ] = $script;
542
-                }
543
-            }
544
-        }
545
-
546
-        do_action(
547
-            'AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run',
548
-            $scripts_that_should_run
549
-        );
550
-        return $scripts_that_should_run;
551
-    }
552
-
553
-
554
-    /**
555
-     * Gets the script which is currently being ran, if there is one. If $include_completed_scripts is set to TRUE
556
-     * it will return the last ran script even if its complete.
557
-     * This means: if you want to find the currently-executing script, leave it as FALSE.
558
-     * If you really just want to find the script which ran most recently, regardless of status, leave it as TRUE.
559
-     *
560
-     * @param bool $include_completed_scripts
561
-     * @return EE_Data_Migration_Script_Base
562
-     */
563
-    public function get_last_ran_script($include_completed_scripts = false)
564
-    {
565
-        // make sure we've setup the class properties _last_ran_script and _last_ran_incomplete_script
566
-        if (! $this->_data_migrations_ran) {
567
-            $this->get_data_migrations_ran();
568
-        }
569
-        if ($include_completed_scripts) {
570
-            return $this->_last_ran_script;
571
-        } else {
572
-            return $this->_last_ran_incomplete_script;
573
-        }
574
-    }
575
-
576
-
577
-    /**
578
-     * Runs the data migration scripts (well, each request to this method calls one of the
579
-     * data migration scripts' migration_step() functions).
580
-     *
581
-     * @param int   $step_size
582
-     * @throws EE_Error
583
-     * @return array {
584
-     *                                  // where the first item is one EE_Data_Migration_Script_Base's stati,
585
-     *                                  //and the second item is a string describing what was done
586
-     * @type int    $records_to_migrate from the current migration script
587
-     * @type int    $records_migrated
588
-     * @type string $status             one of EE_Data_Migration_Manager::status_*
589
-     * @type string $script             verbose name of the current DMS
590
-     * @type string $message            string describing what was done during this step
591
-     *                                  }
592
-     */
593
-    public function migration_step($step_size = 0)
594
-    {
595
-
596
-        // bandaid fix for issue https://events.codebasehq.com/projects/event-espresso/tickets/7535
597
-        if (class_exists('EE_CPT_Strategy')) {
598
-            remove_action('pre_get_posts', array(EE_CPT_Strategy::instance(), 'pre_get_posts'), 5);
599
-        }
600
-
601
-        try {
602
-            $currently_executing_script = $this->get_last_ran_script();
603
-            if (! $currently_executing_script) {
604
-                // Find the next script that needs to execute
605
-                $scripts = $this->check_for_applicable_data_migration_scripts();
606
-                if (! $scripts) {
607
-                    // huh, no more scripts to run... apparently we're done!
608
-                    // but dont forget to make sure initial data is there
609
-                    // we should be good to allow them to exit maintenance mode now
610
-                    EE_Maintenance_Mode::instance()->set_maintenance_level(
611
-                        intval(EE_Maintenance_Mode::level_0_not_in_maintenance)
612
-                    );
613
-                    // saving migrations ran should actually be unnecessary, but leaving in place just in case
614
-                    // remember this migration was finished (even if we timeout initing db for core and plugins)
615
-                    $this->_save_migrations_ran();
616
-                    // make sure DB was updated AFTER we've recorded the migration was done
617
-                    $this->initialize_db_for_enqueued_ee_plugins();
618
-                    return array(
619
-                        'records_to_migrate' => 1,
620
-                        'records_migrated'   => 1,
621
-                        'status'             => self::status_no_more_migration_scripts,
622
-                        'script'             => __("Data Migration Completed Successfully", "event_espresso"),
623
-                        'message'            => __("All done!", "event_espresso"),
624
-                    );
625
-                }
626
-                $currently_executing_script = array_shift($scripts);
627
-                // and add to the array/wp option showing the scripts ran
628
-
629
-                $migrates_to = $this->script_migrates_to_version(get_class($currently_executing_script));
630
-                $plugin_slug = $migrates_to['slug'];
631
-                $version = $migrates_to['version'];
632
-                $this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
633
-            }
634
-            $current_script_name = get_class($currently_executing_script);
635
-        } catch (Exception $e) {
636
-            // an exception occurred while trying to get migration scripts
637
-
638
-            $message = sprintf(
639
-                __("Error Message: %sStack Trace:%s", "event_espresso"),
640
-                $e->getMessage() . '<br>',
641
-                $e->getTraceAsString()
642
-            );
643
-            // record it on the array of data migration scripts ran. This will be overwritten next time we try and try to run data migrations
644
-            // but that's ok-- it's just an FYI to support that we couldn't even run any data migrations
645
-            $this->add_error_to_migrations_ran(
646
-                sprintf(__("Could not run data migrations because: %s", "event_espresso"), $message)
647
-            );
648
-            return array(
649
-                'records_to_migrate' => 1,
650
-                'records_migrated'   => 0,
651
-                'status'             => self::status_fatal_error,
652
-                'script'             => __("Error loading data migration scripts", "event_espresso"),
653
-                'message'            => $message,
654
-            );
655
-        }
656
-        // ok so we definitely have a data migration script
657
-        try {
658
-            // how big of a bite do we want to take? Allow users to easily override via their wp-config
659
-            if (absint($step_size) < 1) {
660
-                $step_size = defined('EE_MIGRATION_STEP_SIZE') && absint(EE_MIGRATION_STEP_SIZE)
661
-                    ? EE_MIGRATION_STEP_SIZE : EE_Data_Migration_Manager::step_size;
662
-            }
663
-            // do what we came to do!
664
-            $currently_executing_script->migration_step($step_size);
665
-            // can we wrap it up and verify default data?
666
-            $init_dbs = false;
667
-            switch ($currently_executing_script->get_status()) {
668
-                case EE_Data_Migration_Manager::status_continue:
669
-                    $response_array = array(
670
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
671
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
672
-                        'status'             => EE_Data_Migration_Manager::status_continue,
673
-                        'message'            => $currently_executing_script->get_feedback_message(),
674
-                        'script'             => $currently_executing_script->pretty_name(),
675
-                    );
676
-                    break;
677
-                case EE_Data_Migration_Manager::status_completed:
678
-                    // ok so THAT script has completed
679
-                    $this->update_current_database_state_to($this->script_migrates_to_version($current_script_name));
680
-                    $response_array = array(
681
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
682
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
683
-                        'status'             => EE_Data_Migration_Manager::status_completed,
684
-                        'message'            => $currently_executing_script->get_feedback_message(),
685
-                        'script'             => sprintf(
686
-                            __("%s Completed", 'event_espresso'),
687
-                            $currently_executing_script->pretty_name()
688
-                        ),
689
-                    );
690
-                    // check if there are any more after this one.
691
-                    $scripts_remaining = $this->check_for_applicable_data_migration_scripts();
692
-                    if (! $scripts_remaining) {
693
-                        // we should be good to allow them to exit maintenance mode now
694
-                        EE_Maintenance_Mode::instance()->set_maintenance_level(
695
-                            intval(EE_Maintenance_Mode::level_0_not_in_maintenance)
696
-                        );
697
-                        // huh, no more scripts to run... apparently we're done!
698
-                        // but dont forget to make sure initial data is there
699
-                        $init_dbs = true;
700
-                        $response_array['status'] = self::status_no_more_migration_scripts;
701
-                    }
702
-                    break;
703
-                default:
704
-                    $response_array = array(
705
-                        'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
706
-                        'records_migrated'   => $currently_executing_script->count_records_migrated(),
707
-                        'status'             => $currently_executing_script->get_status(),
708
-                        'message'            => sprintf(
709
-                            __("Minor errors occurred during %s: %s", "event_espresso"),
710
-                            $currently_executing_script->pretty_name(),
711
-                            implode(", ", $currently_executing_script->get_errors())
712
-                        ),
713
-                        'script'             => $currently_executing_script->pretty_name(),
714
-                    );
715
-                    break;
716
-            }
717
-        } catch (Exception $e) {
718
-            // ok so some exception was thrown which killed the data migration script
719
-            // double-check we have a real script
720
-            if ($currently_executing_script instanceof EE_Data_Migration_Script_Base) {
721
-                $script_name = $currently_executing_script->pretty_name();
722
-                $currently_executing_script->set_broken();
723
-                $currently_executing_script->add_error($e->getMessage());
724
-            } else {
725
-                $script_name = __("Error getting Migration Script", "event_espresso");
726
-            }
727
-            $response_array = array(
728
-                'records_to_migrate' => 1,
729
-                'records_migrated'   => 0,
730
-                'status'             => self::status_fatal_error,
731
-                'message'            => sprintf(
732
-                    __("A fatal error occurred during the migration: %s", "event_espresso"),
733
-                    $e->getMessage()
734
-                ),
735
-                'script'             => $script_name,
736
-            );
737
-        }
738
-        $successful_save = $this->_save_migrations_ran();
739
-        if ($successful_save !== true) {
740
-            // ok so the current wp option didn't save. that's tricky, because we'd like to update it
741
-            // and mark it as having a fatal error, but remember- WE CAN'T SAVE THIS WP OPTION!
742
-            // however, if we throw an exception, and return that, then the next request
743
-            // won't have as much info in it, and it may be able to save
744
-            throw new EE_Error(
745
-                sprintf(
746
-                    __(
747
-                        "The error '%s' occurred updating the status of the migration. This is a FATAL ERROR, but the error is preventing the system from remembering that. Please contact event espresso support.",
748
-                        "event_espresso"
749
-                    ),
750
-                    $successful_save
751
-                )
752
-            );
753
-        }
754
-        // if we're all done, initialize EE plugins' default data etc.
755
-        if ($init_dbs) {
756
-            $this->initialize_db_for_enqueued_ee_plugins();
757
-        }
758
-        return $response_array;
759
-    }
760
-
761
-
762
-    /**
763
-     * Echo out JSON response to migration script AJAX requests. Takes precautions
764
-     * to buffer output so that we don't throw junk into our json.
765
-     *
766
-     * @return array with keys:
767
-     * 'records_to_migrate' which counts ALL the records for the current migration, and should remain constant. (ie,
768
-     * it's NOT the count of hwo many remain)
769
-     * 'records_migrated' which also counts ALL the records which have been migrated (ie, percent_complete =
770
-     * records_migrated/records_to_migrate)
771
-     * 'status'=>a string, one of EE_Data_migration_Manager::status_*
772
-     * 'message'=>a string, containing any message you want to show to the user. We may decide to split this up into
773
-     * errors, notifications, and successes
774
-     * 'script'=>a pretty name of the script currently running
775
-     */
776
-    public function response_to_migration_ajax_request()
777
-    {
778
-        ob_start();
779
-        try {
780
-            $response = $this->migration_step();
781
-        } catch (Exception $e) {
782
-            $response = array(
783
-                'records_to_migrate' => 0,
784
-                'records_migrated'   => 0,
785
-                'status'             => EE_Data_Migration_Manager::status_fatal_error,
786
-                'message'            => sprintf(
787
-                    __("Unknown fatal error occurred: %s", "event_espresso"),
788
-                    $e->getMessage()
789
-                ),
790
-                'script'             => 'Unknown',
791
-            );
792
-            $this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
793
-        }
794
-        $warnings_etc = @ob_get_contents();
795
-        ob_end_clean();
796
-        $response['message'] .= $warnings_etc;
797
-        return $response;
798
-    }
799
-
800
-    /**
801
-     * Updates the wordpress option that keeps track of which which EE version the database
802
-     * is at (ie, the code may be at 4.1.0, but the database is still at 3.1.35)
803
-     *
804
-     * @param array $slug_and_version {
805
-     * @type string $slug             like 'Core' or 'Calendar',
806
-     * @type string $version          like '4.1.0'
807
-     *                                }
808
-     * @return void
809
-     */
810
-    public function update_current_database_state_to($slug_and_version = null)
811
-    {
812
-        if (! $slug_and_version) {
813
-            // no version was provided, assume it should be at the current code version
814
-            $slug_and_version = array('slug' => 'Core', 'version' => espresso_version());
815
-        }
816
-        $current_database_state = get_option(self::current_database_state);
817
-        $current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
818
-        update_option(self::current_database_state, $current_database_state);
819
-    }
820
-
821
-    /**
822
-     * Determines if the database is currently at a state matching what's indicated in $slug and $version.
823
-     *
824
-     * @param array $slug_and_version {
825
-     * @type string $slug             like 'Core' or 'Calendar',
826
-     * @type string $version          like '4.1.0'
827
-     *                                }
828
-     * @return boolean
829
-     */
830
-    public function database_needs_updating_to($slug_and_version)
831
-    {
832
-
833
-        $slug = $slug_and_version['slug'];
834
-        $version = $slug_and_version['version'];
835
-        $current_database_state = get_option(self::current_database_state);
836
-        if (! isset($current_database_state[ $slug ])) {
837
-            return true;
838
-        } else {
839
-            // just compare the first 3 parts of version string, eg "4.7.1", not "4.7.1.dev.032" because DBs shouldn't change on nano version changes
840
-            $version_parts_current_db_state = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
841
-            $version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
842
-            $needs_updating = false;
843
-            foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
844
-                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
845
-                    $needs_updating = true;
846
-                    break;
847
-                }
848
-            }
849
-            return $needs_updating;
850
-        }
851
-    }
852
-
853
-
854
-    /**
855
-     * Gets all the data migration scripts available in the core folder and folders
856
-     * in addons. Has the side effect of adding them for autoloading
857
-     *
858
-     * @return array keys are expected classnames, values are their filepaths
859
-     * @throws InvalidInterfaceException
860
-     * @throws InvalidDataTypeException
861
-     * @throws EE_Error
862
-     * @throws InvalidArgumentException
863
-     */
864
-    public function get_all_data_migration_scripts_available()
865
-    {
866
-        if (! $this->_data_migration_class_to_filepath_map) {
867
-            $this->_data_migration_class_to_filepath_map = array();
868
-            foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
869
-                // strip any placeholders added to classname to make it a unique array key
870
-                $eeAddonClass = trim($eeAddonClass, '*');
871
-                $eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass)
872
-                    ? $eeAddonClass
873
-                    : '';
874
-                $folder_path = EEH_File::end_with_directory_separator($folder_path);
875
-                $files = glob($folder_path . '*.dms.php');
876
-                if (empty($files)) {
877
-                    continue;
878
-                }
879
-                foreach ($files as $file) {
880
-                    $pos_of_last_slash = strrpos($file, DS);
881
-                    $classname = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1));
882
-                    $migrates_to = $this->script_migrates_to_version($classname, $eeAddonClass);
883
-                    $slug = $migrates_to['slug'];
884
-                    // check that the slug as contained in the DMS is associated with
885
-                    // the slug of an addon or core
886
-                    if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) {
887
-                        EE_Error::doing_it_wrong(
888
-                            __FUNCTION__,
889
-                            sprintf(
890
-                                esc_html__(
891
-                                    'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ',
892
-                                    'event_espresso'
893
-                                ),
894
-                                $classname,
895
-                                $slug,
896
-                                implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name()))
897
-                            ),
898
-                            '4.3.0.alpha.019'
899
-                        );
900
-                    }
901
-                    $this->_data_migration_class_to_filepath_map[ $classname ] = $file;
902
-                }
903
-            }
904
-            EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
905
-        }
906
-        return $this->_data_migration_class_to_filepath_map;
907
-    }
908
-
909
-
910
-    /**
911
-     * Once we have an addon that works with EE4.1, we will actually want to fetch the PUE slugs
912
-     * from each addon, and check if they need updating,
913
-     *
914
-     * @return boolean
915
-     */
916
-    public function addons_need_updating()
917
-    {
918
-        return false;
919
-    }
920
-
921
-    /**
922
-     * Adds this error string to the data_migrations_ran array, but we dont necessarily know
923
-     * where to put it, so we just throw it in there... better than nothing...
924
-     *
925
-     * @param string $error_message
926
-     * @throws EE_Error
927
-     */
928
-    public function add_error_to_migrations_ran($error_message)
929
-    {
930
-        // get last-ran migration script
931
-        global $wpdb;
932
-        $last_migration_script_option = $wpdb->get_row(
933
-            "SELECT * FROM $wpdb->options WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id DESC LIMIT 1",
934
-            ARRAY_A
935
-        );
936
-
937
-        $last_ran_migration_script_properties = isset($last_migration_script_option['option_value'])
938
-            ? maybe_unserialize($last_migration_script_option['option_value']) : null;
939
-        // now, tread lightly because we're here because a FATAL non-catchable error
940
-        // was thrown last time when we were trying to run a data migration script
941
-        // so the fatal error could have happened while getting the migration script
942
-        // or doing running it...
943
-        $versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace(
944
-            EE_Data_Migration_Manager::data_migration_script_option_prefix,
945
-            "",
946
-            $last_migration_script_option['option_name']
947
-        ) : null;
948
-
949
-        // check if it THINKS its a data migration script and especially if it's one that HASN'T finished yet
950
-        // because if it has finished, then it obviously couldn't be the cause of this error, right? (because its all done)
951
-        if (isset($last_ran_migration_script_properties['class']) && isset($last_ran_migration_script_properties['_status']) && $last_ran_migration_script_properties['_status'] != self::status_completed) {
952
-            // ok then just add this error to its list of errors
953
-            $last_ran_migration_script_properties['_errors'][] = $error_message;
954
-            $last_ran_migration_script_properties['_status'] = self::status_fatal_error;
955
-        } else {
956
-            // so we don't even know which script was last running
957
-            // use the data migration error stub, which is designed specifically for this type of thing
958
-            $general_migration_error = new EE_DMS_Unknown_1_0_0();
959
-            $general_migration_error->add_error($error_message);
960
-            $general_migration_error->set_broken();
961
-            $last_ran_migration_script_properties = $general_migration_error->properties_as_array();
962
-            $versions_migrated_to = 'Unknown.1.0.0';
963
-            // now just to make sure appears as last (in case the were previously a fatal error like this)
964
-            // delete the old one
965
-            delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
966
-        }
967
-        update_option(
968
-            self::data_migration_script_option_prefix . $versions_migrated_to,
969
-            $last_ran_migration_script_properties
970
-        );
971
-    }
972
-
973
-    /**
974
-     * saves what data migrations have ran to the database
975
-     *
976
-     * @return mixed TRUE if successfully saved migrations ran, string if an error occurred
977
-     */
978
-    protected function _save_migrations_ran()
979
-    {
980
-        if ($this->_data_migrations_ran == null) {
981
-            $this->get_data_migrations_ran();
982
-        }
983
-        // now, we don't want to save actual classes to the DB because that's messy
984
-        $successful_updates = true;
985
-        foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
986
-            foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
987
-                $plugin_slug_for_use_in_option_name = $plugin_slug . ".";
988
-                $option_name = self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
989
-                $old_option_value = get_option($option_name);
990
-                if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
991
-                    $script_array_for_saving = $array_or_migration_obj->properties_as_array();
992
-                    if ($old_option_value != $script_array_for_saving) {
993
-                        $successful_updates = update_option($option_name, $script_array_for_saving);
994
-                    }
995
-                } else {// we don't know what this array-thing is. So just save it as-is
996
-                    if ($old_option_value != $array_or_migration_obj) {
997
-                        $successful_updates = update_option($option_name, $array_or_migration_obj);
998
-                    }
999
-                }
1000
-                if (! $successful_updates) {
1001
-                    global $wpdb;
1002
-                    return $wpdb->last_error;
1003
-                }
1004
-            }
1005
-        }
1006
-        return true;
1007
-        // $updated = update_option(self::data_migrations_option_name, $array_of_migrations);
1008
-        // if ($updated !== true) {
1009
-        //     global $wpdb;
1010
-        //     return $wpdb->last_error;
1011
-        // } else {
1012
-        //     return true;
1013
-        // }
1014
-        // wp_mail(
1015
-        //     "[email protected]",
1016
-        //     time() . " price debug info",
1017
-        //     "updated: $updated, last error: $last_error, byte length of option: " . strlen(
1018
-        //         serialize($array_of_migrations)
1019
-        //     )
1020
-        // );
1021
-    }
1022
-
1023
-    /**
1024
-     * Takes an array of data migration script properties and re-creates the class from
1025
-     * them. The argument $properties_array is assumed to have been made by
1026
-     * EE_Data_Migration_Script_Base::properties_as_array()
1027
-     *
1028
-     * @param array $properties_array
1029
-     * @return EE_Data_Migration_Script_Base
1030
-     * @throws EE_Error
1031
-     */
1032
-    public function _instantiate_script_from_properties_array($properties_array)
1033
-    {
1034
-        if (! isset($properties_array['class'])) {
1035
-            throw new EE_Error(
1036
-                sprintf(
1037
-                    __("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
1038
-                    implode(",", $properties_array)
1039
-                )
1040
-            );
1041
-        }
1042
-        $class_name = $properties_array['class'];
1043
-        if (! class_exists($class_name)) {
1044
-            throw new EE_Error(sprintf(__("There is no migration script named %s", "event_espresso"), $class_name));
1045
-        }
1046
-        $class = new $class_name;
1047
-        if (! $class instanceof EE_Data_Migration_Script_Base) {
1048
-            throw new EE_Error(
1049
-                sprintf(
1050
-                    __("Class '%s' is supposed to be a migration script. Its not, its a '%s'", "event_espresso"),
1051
-                    $class_name,
1052
-                    get_class($class)
1053
-                )
1054
-            );
1055
-        }
1056
-        $class->instantiate_from_array_of_properties($properties_array);
1057
-        return $class;
1058
-    }
1059
-
1060
-    /**
1061
-     * Gets the classname for the most up-to-date DMS (ie, the one that will finally
1062
-     * leave the DB in a state usable by the current plugin code).
1063
-     *
1064
-     * @param string $plugin_slug the slug for the ee plugin we are searching for. Default is 'Core'
1065
-     * @return string
1066
-     */
1067
-    public function get_most_up_to_date_dms($plugin_slug = 'Core')
1068
-    {
1069
-        $class_to_filepath_map = $this->get_all_data_migration_scripts_available();
1070
-        $most_up_to_date_dms_classname = null;
1071
-        foreach ($class_to_filepath_map as $classname => $filepath) {
1072
-            if ($most_up_to_date_dms_classname === null) {
1073
-                $migrates_to = $this->script_migrates_to_version($classname);
1074
-                $this_plugin_slug = $migrates_to['slug'];
1075
-                if ($this_plugin_slug == $plugin_slug) {
1076
-                    // if it's for core, it wins
1077
-                    $most_up_to_date_dms_classname = $classname;
1078
-                }
1079
-                // if it wasn't for core, we must keep searching for one that is!
1080
-                continue;
1081
-            } else {
1082
-                $champion_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms_classname);
1083
-                $contender_migrates_to = $this->script_migrates_to_version($classname);
1084
-                if ($contender_migrates_to['slug'] == $plugin_slug
1085
-                    && version_compare(
1086
-                        $champion_migrates_to['version'],
1087
-                        $contender_migrates_to['version'],
1088
-                        '<'
1089
-                    )) {
1090
-                    // so the contenders version is higher and its for Core
1091
-                    $most_up_to_date_dms_classname = $classname;
1092
-                }
1093
-            }
1094
-        }
1095
-        return $most_up_to_date_dms_classname;
1096
-    }
1097
-
1098
-    /**
1099
-     * Gets the migration script specified but ONLY if it has already ran.
1100
-     *
1101
-     * Eg, if you wanted to see if 'EE_DMS_Core_4_1_0' has ran, you would run the following code:
1102
-     * <code> $core_4_1_0_dms_ran = EE_Data_Migration_Manager::instance()->get_migration_ran( '4.1.0', 'Core' ) !==
1103
-     * NULL;</code> This is especially useful in addons' data migration scripts, this way they can tell if a core (or
1104
-     * other addon) DMS has ran, in case the current DMS depends on it.
1105
-     *
1106
-     * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1107
-     *                            period. Eg '4.1.0'
1108
-     * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1109
-     * @return EE_Data_Migration_Script_Base
1110
-     */
1111
-    public function get_migration_ran($version, $plugin_slug = 'Core')
1112
-    {
1113
-        $migrations_ran = $this->get_data_migrations_ran();
1114
-        if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1115
-            return $migrations_ran[ $plugin_slug ][ $version ];
1116
-        } else {
1117
-            return null;
1118
-        }
1119
-    }
1120
-
1121
-    /**
1122
-     * Resets the borked data migration scripts so they're no longer borked
1123
-     * so we can again attempt to migrate
1124
-     *
1125
-     * @return bool
1126
-     * @throws EE_Error
1127
-     */
1128
-    public function reattempt()
1129
-    {
1130
-        // find if the last-ran script was borked
1131
-        // set it as being non-borked (we shouldn't ever get DMSs that we don't recognize)
1132
-        // add an 'error' saying that we attempted to reset
1133
-        // does it have a stage that was borked too? if so make it no longer borked
1134
-        // add an 'error' saying we attempted to reset
1135
-        $last_ran_script = $this->get_last_ran_script();
1136
-        if ($last_ran_script instanceof EE_DMS_Unknown_1_0_0) {
1137
-            // if it was an error DMS, just mark it as complete (if another error occurs it will overwrite it)
1138
-            $last_ran_script->set_completed();
1139
-        } elseif ($last_ran_script instanceof EE_Data_Migration_Script_Base) {
1140
-            $last_ran_script->reattempt();
1141
-        } else {
1142
-            throw new EE_Error(
1143
-                sprintf(
1144
-                    __(
1145
-                        'Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s',
1146
-                        'event_espresso'
1147
-                    ),
1148
-                    print_r($last_ran_script, true)
1149
-                )
1150
-            );
1151
-        }
1152
-        return $this->_save_migrations_ran();
1153
-    }
1154
-
1155
-    /**
1156
-     * Gets whether or not this particular migration has run or not
1157
-     *
1158
-     * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1159
-     *                            period. Eg '4.1.0'
1160
-     * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1161
-     * @return boolean
1162
-     */
1163
-    public function migration_has_ran($version, $plugin_slug = 'Core')
1164
-    {
1165
-        return $this->get_migration_ran($version, $plugin_slug) !== null;
1166
-    }
1167
-
1168
-    /**
1169
-     * Enqueues this ee plugin to have its data initialized
1170
-     *
1171
-     * @param string $plugin_slug either 'Core' or EE_Addon::name()'s return value
1172
-     */
1173
-    public function enqueue_db_initialization_for($plugin_slug)
1174
-    {
1175
-        $queue = $this->get_db_initialization_queue();
1176
-        if (! in_array($plugin_slug, $queue)) {
1177
-            $queue[] = $plugin_slug;
1178
-        }
1179
-        update_option(self::db_init_queue_option_name, $queue);
1180
-    }
1181
-
1182
-    /**
1183
-     * Calls EE_Addon::initialize_db_if_no_migrations_required() on each addon
1184
-     * specified in EE_Data_Migration_Manager::get_db_init_queue(), and if 'Core' is
1185
-     * in the queue, calls EE_System::initialize_db_if_no_migrations_required().
1186
-     */
1187
-    public function initialize_db_for_enqueued_ee_plugins()
1188
-    {
1189
-        $queue = $this->get_db_initialization_queue();
1190
-        foreach ($queue as $plugin_slug) {
1191
-            $most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1192
-            if (! $most_up_to_date_dms) {
1193
-                // if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1194
-                $verify_db = false;
1195
-            } else {
1196
-                $most_up_to_date_dms_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms);
1197
-                $verify_db = $this->database_needs_updating_to($most_up_to_date_dms_migrates_to);
1198
-            }
1199
-            if ($plugin_slug == 'Core') {
1200
-                EE_System::instance()->initialize_db_if_no_migrations_required(
1201
-                    false,
1202
-                    $verify_db
1203
-                );
1204
-            } else {
1205
-                // just loop through the addons to make sure their database is setup
1206
-                foreach (EE_Registry::instance()->addons as $addon) {
1207
-                    if ($addon->name() == $plugin_slug) {
1208
-                        $addon->initialize_db_if_no_migrations_required($verify_db);
1209
-                        break;
1210
-                    }
1211
-                }
1212
-            }
1213
-        }
1214
-        // because we just initialized the DBs for the enqueued ee plugins
1215
-        // we don't need to keep remembering which ones needed to be initialized
1216
-        delete_option(self::db_init_queue_option_name);
1217
-    }
1218
-
1219
-    /**
1220
-     * Gets a numerically-indexed array of plugin slugs that need to have their databases
1221
-     * (re-)initialized after migrations are complete. ie, each element should be either
1222
-     * 'Core', or the return value of EE_Addon::name() for an addon
1223
-     *
1224
-     * @return array
1225
-     */
1226
-    public function get_db_initialization_queue()
1227
-    {
1228
-        return get_option(self::db_init_queue_option_name, array());
1229
-    }
1230
-
1231
-    /**
1232
-     * Gets the injected table analyzer, or throws an exception
1233
-     *
1234
-     * @return TableAnalysis
1235
-     * @throws EE_Error
1236
-     */
1237
-    protected function _get_table_analysis()
1238
-    {
1239
-        if ($this->_table_analysis instanceof TableAnalysis) {
1240
-            return $this->_table_analysis;
1241
-        } else {
1242
-            throw new EE_Error(
1243
-                sprintf(
1244
-                    __('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
1245
-                    get_class($this)
1246
-                )
1247
-            );
1248
-        }
1249
-    }
1250
-
1251
-    /**
1252
-     * Gets the injected table manager, or throws an exception
1253
-     *
1254
-     * @return TableManager
1255
-     * @throws EE_Error
1256
-     */
1257
-    protected function _get_table_manager()
1258
-    {
1259
-        if ($this->_table_manager instanceof TableManager) {
1260
-            return $this->_table_manager;
1261
-        } else {
1262
-            throw new EE_Error(
1263
-                sprintf(
1264
-                    __('Table manager class on class %1$s is not set properly.', 'event_espresso'),
1265
-                    get_class($this)
1266
-                )
1267
-            );
1268
-        }
1269
-    }
36
+	/**
37
+	 *
38
+	 * @var EE_Registry
39
+	 */
40
+	// protected $EE;
41
+	/**
42
+	 * name of the wordpress option which stores an array of data about
43
+	 */
44
+	const data_migrations_option_name = 'ee_data_migration';
45
+
46
+
47
+	const data_migration_script_option_prefix = 'ee_data_migration_script_';
48
+
49
+	const data_migration_script_mapping_option_prefix = 'ee_dms_map_';
50
+
51
+	/**
52
+	 * name of the wordpress option which stores the database' current version. IE, the code may be at version 4.2.0,
53
+	 * but as migrations are performed the database will progress from 3.1.35 to 4.1.0 etc.
54
+	 */
55
+	const current_database_state = 'ee_data_migration_current_db_state';
56
+
57
+	/**
58
+	 * Special status string returned when we're positive there are no more data migration
59
+	 * scripts that can be run.
60
+	 */
61
+	const status_no_more_migration_scripts = 'no_more_migration_scripts';
62
+	/**
63
+	 * string indicating the migration should continue
64
+	 */
65
+	const status_continue = 'status_continue';
66
+	/**
67
+	 * string indicating the migration has completed and should be ended
68
+	 */
69
+	const status_completed = 'status_completed';
70
+	/**
71
+	 * string indicating a fatal error occurred and the data migration should be completely aborted
72
+	 */
73
+	const status_fatal_error = 'status_fatal_error';
74
+
75
+	/**
76
+	 * the number of 'items' (usually DB rows) to migrate on each 'step' (ajax request sent
77
+	 * during migration)
78
+	 */
79
+	const step_size = 50;
80
+
81
+	/**
82
+	 * option name that stores the queue of ee plugins needing to have
83
+	 * their data initialized (or re-initialized) once we are done migrations
84
+	 */
85
+	const db_init_queue_option_name = 'ee_db_init_queue';
86
+	/**
87
+	 * Array of information concerning data migrations that have ran in the history
88
+	 * of this EE installation. Keys should be the name of the version the script upgraded to
89
+	 *
90
+	 * @var EE_Data_Migration_Script_Base[]
91
+	 */
92
+	private $_data_migrations_ran = null;
93
+	/**
94
+	 * The last ran script. It's nice to store this somewhere accessible, as its easiest
95
+	 * to know which was the last run by which is the newest wp option; but in most of the code
96
+	 * we just use the local $_data_migration_ran array, which organized the scripts differently
97
+	 *
98
+	 * @var EE_Data_Migration_Script_Base
99
+	 */
100
+	private $_last_ran_script = null;
101
+
102
+	/**
103
+	 * Similarly to _last_ran_script, but this is the last INCOMPLETE migration script.
104
+	 *
105
+	 * @var EE_Data_Migration_Script_Base
106
+	 */
107
+	private $_last_ran_incomplete_script = null;
108
+	/**
109
+	 * array where keys are classnames, and values are filepaths of all the known migration scripts
110
+	 *
111
+	 * @var array
112
+	 */
113
+	private $_data_migration_class_to_filepath_map;
114
+
115
+	/**
116
+	 * the following 4 properties are fully set on construction.
117
+	 * Note: the first two apply to whether to continue running ALL migration scripts (ie, even though we're finished
118
+	 * one, we may want to start the next one); whereas the last two indicate whether to continue running a single
119
+	 * data migration script
120
+	 *
121
+	 * @var array
122
+	 */
123
+	public $stati_that_indicate_to_continue_migrations = array();
124
+
125
+	public $stati_that_indicate_to_stop_migrations = array();
126
+
127
+	public $stati_that_indicate_to_continue_single_migration_script = array();
128
+
129
+	public $stati_that_indicate_to_stop_single_migration_script = array();
130
+
131
+	/**
132
+	 * @var \EventEspresso\core\services\database\TableManager $table_manager
133
+	 */
134
+	protected $_table_manager;
135
+
136
+	/**
137
+	 * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
138
+	 */
139
+	protected $_table_analysis;
140
+
141
+	/**
142
+	 * @var array $script_migration_versions
143
+	 */
144
+	protected $script_migration_versions;
145
+
146
+	/**
147
+	 * @var EE_Data_Migration_Manager $_instance
148
+	 * @access    private
149
+	 */
150
+	private static $_instance = null;
151
+
152
+
153
+	/**
154
+	 * @singleton method used to instantiate class object
155
+	 * @access    public
156
+	 * @return EE_Data_Migration_Manager instance
157
+	 */
158
+	public static function instance()
159
+	{
160
+		// check if class object is instantiated
161
+		if (! self::$_instance instanceof EE_Data_Migration_Manager) {
162
+			self::$_instance = new self();
163
+		}
164
+		return self::$_instance;
165
+	}
166
+
167
+	/**
168
+	 * resets the singleton to its brand-new state (but does NOT delete old references to the old singleton. Meaning,
169
+	 * all new usages of the singleton should be made with Classname::instance()) and returns it
170
+	 *
171
+	 * @return EE_Data_Migration_Manager
172
+	 */
173
+	public static function reset()
174
+	{
175
+		self::$_instance = null;
176
+		return self::instance();
177
+	}
178
+
179
+
180
+	/**
181
+	 * constructor
182
+	 */
183
+	private function __construct()
184
+	{
185
+		$this->stati_that_indicate_to_continue_migrations = array(
186
+			self::status_continue,
187
+			self::status_completed,
188
+		);
189
+		$this->stati_that_indicate_to_stop_migrations = array(
190
+			self::status_fatal_error,
191
+			self::status_no_more_migration_scripts,
192
+		);
193
+		$this->stati_that_indicate_to_continue_single_migration_script = array(
194
+			self::status_continue,
195
+		);
196
+		$this->stati_that_indicate_to_stop_single_migration_script = array(
197
+			self::status_completed,
198
+			self::status_fatal_error
199
+			// note: status_no_more_migration_scripts doesn't apply
200
+		);
201
+		// make sure we've included the base migration script, because we may need the EE_DMS_Unknown_1_0_0 class
202
+		// to be defined, because right now it doesn't get autoloaded on its own
203
+		EE_Registry::instance()->load_core('Data_Migration_Class_Base', array(), true);
204
+		EE_Registry::instance()->load_core('Data_Migration_Script_Base', array(), true);
205
+		EE_Registry::instance()->load_core('DMS_Unknown_1_0_0', array(), true);
206
+		EE_Registry::instance()->load_core('Data_Migration_Script_Stage', array(), true);
207
+		EE_Registry::instance()->load_core('Data_Migration_Script_Stage_Table', array(), true);
208
+		$this->_table_manager = EE_Registry::instance()->create('TableManager', array(), true);
209
+		$this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
210
+	}
211
+
212
+
213
+	/**
214
+	 * Deciphers, from an option's name, what plugin and version it relates to (see _save_migrations_ran to see what
215
+	 * the option names are like, but generally they're like
216
+	 * 'ee_data_migration_script_Core.4.1.0' in 4.2 or 'ee_data_migration_script_4.1.0' before that).
217
+	 * The option name shouldn't ever be like 'ee_data_migration_script_Core.4.1.0.reg' because it's derived,
218
+	 * indirectly, from the data migration's classname, which should always be like EE_DMS_%s_%d_%d_%d.dms.php (eg
219
+	 * EE_DMS_Core_4_1_0.dms.php)
220
+	 *
221
+	 * @param string $option_name (see EE_Data_Migration_Manage::_save_migrations_ran() where the option name is set)
222
+	 * @return array where the first item is the plugin slug (eg 'Core','Calendar',etc) and the 2nd is the version of
223
+	 *               that plugin (eg '4.1.0')
224
+	 */
225
+	private function _get_plugin_slug_and_version_string_from_dms_option_name($option_name)
226
+	{
227
+		$plugin_slug_and_version_string = str_replace(
228
+			EE_Data_Migration_Manager::data_migration_script_option_prefix,
229
+			"",
230
+			$option_name
231
+		);
232
+		// check if $plugin_slug_and_version_string is like '4.1.0' (4.1-style) or 'Core.4.1.0' (4.2-style)
233
+		$parts = explode(".", $plugin_slug_and_version_string);
234
+
235
+		if (count($parts) == 4) {
236
+			// it's 4.2-style.eg Core.4.1.0
237
+			$plugin_slug = $parts[0];// eg Core
238
+			$version_string = $parts[1] . "." . $parts[2] . "." . $parts[3]; // eg 4.1.0
239
+		} else {
240
+			// it's 4.1-style: eg 4.1.0
241
+			$plugin_slug = 'Core';
242
+			$version_string = $plugin_slug_and_version_string;// eg 4.1.0
243
+		}
244
+		return array($plugin_slug, $version_string);
245
+	}
246
+
247
+	/**
248
+	 * Gets the DMS class from the wordpress option, otherwise throws an EE_Error if it's not
249
+	 * for a known DMS class.
250
+	 *
251
+	 * @param string $dms_option_name
252
+	 * @param string $dms_option_value (serialized)
253
+	 * @return EE_Data_Migration_Script_Base
254
+	 * @throws EE_Error
255
+	 */
256
+	private function _get_dms_class_from_wp_option($dms_option_name, $dms_option_value)
257
+	{
258
+		$data_migration_data = maybe_unserialize($dms_option_value);
259
+		if (isset($data_migration_data['class']) && class_exists($data_migration_data['class'])) {
260
+			$class = LoaderFactory::getLoader()->getShared($data_migration_data['class']);
261
+			if ($class instanceof EE_Data_Migration_Script_Base) {
262
+				$class->instantiate_from_array_of_properties($data_migration_data);
263
+				return $class;
264
+			} else {
265
+				// huh, so its an object but not a data migration script?? that shouldn't happen
266
+				// just leave it as an array (which will probably just get ignored)
267
+				throw new EE_Error(
268
+					sprintf(
269
+						__(
270
+							"Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists",
271
+							'event_espresso'
272
+						),
273
+						$data_migration_data['class']
274
+					)
275
+				);
276
+			}
277
+		} else {
278
+			// so the data doesn't specify a class. So it must either be a legacy array of info or some array (which we'll probably just ignore), or a class that no longer exists
279
+			throw new EE_Error(
280
+				sprintf(__("The wp option  with key '%s' does not represent a DMS", 'event_espresso'), $dms_option_name)
281
+			);
282
+		}
283
+	}
284
+
285
+	/**
286
+	 * Gets the array describing what data migrations have run. Also has a side-effect of recording which was the last
287
+	 * ran, and which was the last ran which hasn't finished yet
288
+	 *
289
+	 * @return array where each element should be an array of EE_Data_Migration_Script_Base (but also has a few legacy
290
+	 *               arrays in there - which should probably be ignored)
291
+	 */
292
+	public function get_data_migrations_ran()
293
+	{
294
+		if (! $this->_data_migrations_ran) {
295
+			// setup autoloaders for each of the scripts in there
296
+			$this->get_all_data_migration_scripts_available();
297
+			$data_migrations_options = $this->get_all_migration_script_options(
298
+			);// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
299
+
300
+			$data_migrations_ran = array();
301
+			// convert into data migration script classes where possible
302
+			foreach ($data_migrations_options as $data_migration_option) {
303
+				list($plugin_slug, $version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name(
304
+					$data_migration_option['option_name']
305
+				);
306
+
307
+				try {
308
+					$class = $this->_get_dms_class_from_wp_option(
309
+						$data_migration_option['option_name'],
310
+						$data_migration_option['option_value']
311
+					);
312
+					$data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
313
+					// ok so far THIS is the 'last-ran-script'... unless we find another on next iteration
314
+					$this->_last_ran_script = $class;
315
+					if (! $class->is_completed()) {
316
+						// sometimes we also like to know which was the last incomplete script (or if there are any at all)
317
+						$this->_last_ran_incomplete_script = $class;
318
+					}
319
+				} catch (EE_Error $e) {
320
+					// ok so its not a DMS. We'll just keep it, although other code will need to expect non-DMSs
321
+					$data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
322
+						$data_migration_option['option_value']
323
+					);
324
+				}
325
+			}
326
+			// so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
327
+			$this->_data_migrations_ran = $data_migrations_ran;
328
+			if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
329
+				$this->_data_migrations_ran = array();
330
+			}
331
+		}
332
+		return $this->_data_migrations_ran;
333
+	}
334
+
335
+
336
+	/**
337
+	 *
338
+	 * @param string $script_name eg 'DMS_Core_4_1_0'
339
+	 * @param string $old_table   eg 'wp_events_detail'
340
+	 * @param string $old_pk      eg 'wp_esp_posts'
341
+	 * @param        $new_table
342
+	 * @return mixed string or int
343
+	 */
344
+	public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table)
345
+	{
346
+		$script = EE_Registry::instance()->load_dms($script_name);
347
+		$mapping = $script->get_mapping_new_pk($old_table, $old_pk, $new_table);
348
+		return $mapping;
349
+	}
350
+
351
+	/**
352
+	 * Gets all the options containing migration scripts that have been run. Ordering is important: it's assumed that
353
+	 * the last option returned in this array is the most-recently ran DMS option
354
+	 *
355
+	 * @return array
356
+	 */
357
+	public function get_all_migration_script_options()
358
+	{
359
+		global $wpdb;
360
+		return $wpdb->get_results(
361
+			"SELECT * FROM {$wpdb->options} WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id ASC",
362
+			ARRAY_A
363
+		);
364
+	}
365
+
366
+	/**
367
+	 * Gets the array of folders which contain data migration scripts. Also adds them to be auto-loaded
368
+	 *
369
+	 * @return array where each value is the full folder path of a folder containing data migration scripts, WITH
370
+	 *               slashes at the end of the folder name.
371
+	 */
372
+	public function get_data_migration_script_folders()
373
+	{
374
+		return apply_filters(
375
+			'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
376
+			array('Core' => EE_CORE . 'data_migration_scripts')
377
+		);
378
+	}
379
+
380
+	/**
381
+	 * Gets the version the migration script upgrades to
382
+	 *
383
+	 * @param string $migration_script_name eg 'EE_DMS_Core_4_1_0'
384
+	 * @return array {
385
+	 * @type string  $slug                  like 'Core','Calendar',etc
386
+	 * @type string  $version               like 4.3.0
387
+	 *                                      }
388
+	 * @throws EE_Error
389
+	 */
390
+	public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
391
+	{
392
+		if (isset($this->script_migration_versions[ $migration_script_name ])) {
393
+			return $this->script_migration_versions[ $migration_script_name ];
394
+		}
395
+		$dms_info = $this->parse_dms_classname($migration_script_name);
396
+		$this->script_migration_versions[ $migration_script_name ] = array(
397
+			'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
398
+			'version' => $dms_info['major_version'] . "." . $dms_info['minor_version'] . "." . $dms_info['micro_version'],
399
+		);
400
+		return $this->script_migration_versions[ $migration_script_name ];
401
+	}
402
+
403
+	/**
404
+	 * Gets the juicy details out of a dms filename like 'EE_DMS_Core_4_1_0'
405
+	 *
406
+	 * @param string $classname
407
+	 * @return array with keys 'slug','major_version','minor_version', and 'micro_version' (the last 3 are ints)
408
+	 * @throws EE_Error
409
+	 */
410
+	public function parse_dms_classname($classname)
411
+	{
412
+		$matches = array();
413
+		preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
414
+		if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
415
+			throw new EE_Error(
416
+				sprintf(
417
+					__(
418
+						"%s is not a valid Data Migration Script. The classname should be like EE_DMS_w_x_y_z, where w is either 'Core' or the slug of an addon and x, y and z are numbers, ",
419
+						"event_espresso"
420
+					),
421
+					$classname
422
+				)
423
+			);
424
+		}
425
+		return array(
426
+			'slug'          => $matches[1],
427
+			'major_version' => intval($matches[2]),
428
+			'minor_version' => intval($matches[3]),
429
+			'micro_version' => intval($matches[4]),
430
+		);
431
+	}
432
+
433
+	/**
434
+	 * Ensures that the option indicating the current DB version is set. This should only be
435
+	 * a concern when activating EE for the first time, THEORETICALLY.
436
+	 * If we detect that we're activating EE4 over top of EE3.1, then we set the current db state to 3.1.x, otherwise
437
+	 * to 4.1.x.
438
+	 *
439
+	 * @return string of current db state
440
+	 */
441
+	public function ensure_current_database_state_is_set()
442
+	{
443
+		$espresso_db_core_updates = get_option('espresso_db_update', array());
444
+		$db_state = get_option(EE_Data_Migration_Manager::current_database_state);
445
+		if (! $db_state) {
446
+			// mark the DB as being in the state as the last version in there.
447
+			// this is done to trigger maintenance mode and do data migration scripts
448
+			// if the admin installed this version of EE over 3.1.x or 4.0.x
449
+			// otherwise, the normal maintenance mode code is fine
450
+			$previous_versions_installed = array_keys($espresso_db_core_updates);
451
+			$previous_version_installed = end($previous_versions_installed);
452
+			if (version_compare('4.1.0', $previous_version_installed)) {
453
+				// last installed version was less than 4.1
454
+				// so we want the data migrations to happen. SO, we're going to say the DB is at that state
455
+				$db_state = array('Core' => $previous_version_installed);
456
+			} else {
457
+				$db_state = array('Core' => EVENT_ESPRESSO_VERSION);
458
+			}
459
+			update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
460
+		}
461
+		// in 4.1, $db_state would have only been a simple string like '4.1.0',
462
+		// but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
463
+		// db, and possibly other keys for other addons like 'Calendar','Permissions',etc
464
+		if (! is_array($db_state)) {
465
+			$db_state = array('Core' => $db_state);
466
+			update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
467
+		}
468
+		return $db_state;
469
+	}
470
+
471
+	/**
472
+	 * Checks if there are any data migration scripts that ought to be run. If found,
473
+	 * returns the instantiated classes. If none are found (ie, they've all already been run
474
+	 * or they don't apply), returns an empty array
475
+	 *
476
+	 * @return EE_Data_Migration_Script_Base[]
477
+	 */
478
+	public function check_for_applicable_data_migration_scripts()
479
+	{
480
+		// get the option describing what options have already run
481
+		$scripts_ran = $this->get_data_migrations_ran();
482
+		// $scripts_ran = array('4.1.0.core'=>array('monkey'=>null));
483
+		$script_class_and_filepaths_available = $this->get_all_data_migration_scripts_available();
484
+
485
+
486
+		$current_database_state = $this->ensure_current_database_state_is_set();
487
+		// determine which have already been run
488
+		$script_classes_that_should_run_per_iteration = array();
489
+		$iteration = 0;
490
+		$next_database_state_to_consider = $current_database_state;
491
+		$theoretical_database_state = null;
492
+		do {
493
+			// the next state after the currently-considered one will start off looking the same as the current, but we may make additions...
494
+			$theoretical_database_state = $next_database_state_to_consider;
495
+			// the next db state to consider is "what would the DB be like had we run all the scripts we found that applied last time?)
496
+			foreach ($script_class_and_filepaths_available as $classname => $filepath) {
497
+				$migrates_to_version = $this->script_migrates_to_version($classname);
498
+				$script_converts_plugin_slug = $migrates_to_version['slug'];
499
+				$script_converts_to_version = $migrates_to_version['version'];
500
+				// check if this version script is DONE or not; or if it's never been ran
501
+				if (! $scripts_ran ||
502
+					! isset($scripts_ran[ $script_converts_plugin_slug ]) ||
503
+					! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])) {
504
+					// we haven't ran this conversion script before
505
+					// now check if it applies... note that we've added an autoloader for it on get_all_data_migration_scripts_available
506
+					$script = LoaderFactory::getLoader()->load($classname);
507
+					/* @var $script EE_Data_Migration_Script_Base */
508
+					$can_migrate = $script->can_migrate_from_version($theoretical_database_state);
509
+					if ($can_migrate) {
510
+						$script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
511
+						$migrates_to_version = $script->migrates_to_version();
512
+						$next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
513
+						unset($script_class_and_filepaths_available[ $classname ]);
514
+					}
515
+				} elseif ($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ] instanceof EE_Data_Migration_Script_Base) {
516
+					// this script has been ran, or at least started
517
+					$script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
518
+					if ($script->get_status() != self::status_completed) {
519
+						// this script is already underway... keep going with it
520
+						$script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
521
+						$migrates_to_version = $script->migrates_to_version();
522
+						$next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
523
+						unset($script_class_and_filepaths_available[ $classname ]);
524
+					} else {
525
+						// it must have a status that indicates it has finished, so we don't want to try and run it again
526
+					}
527
+				} else {
528
+					// it exists but it's not  a proper data migration script
529
+					// maybe the script got renamed? or was simply removed from EE?
530
+					// either way, its certainly not runnable!
531
+				}
532
+			}
533
+			$iteration++;
534
+		} while ($next_database_state_to_consider != $theoretical_database_state && $iteration < 6);
535
+		// ok we have all the scripts that should run, now let's make them into flat array
536
+		$scripts_that_should_run = array();
537
+		foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
538
+			ksort($scripts_at_priority);
539
+			foreach ($scripts_at_priority as $scripts) {
540
+				foreach ($scripts as $script) {
541
+					$scripts_that_should_run[ get_class($script) ] = $script;
542
+				}
543
+			}
544
+		}
545
+
546
+		do_action(
547
+			'AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run',
548
+			$scripts_that_should_run
549
+		);
550
+		return $scripts_that_should_run;
551
+	}
552
+
553
+
554
+	/**
555
+	 * Gets the script which is currently being ran, if there is one. If $include_completed_scripts is set to TRUE
556
+	 * it will return the last ran script even if its complete.
557
+	 * This means: if you want to find the currently-executing script, leave it as FALSE.
558
+	 * If you really just want to find the script which ran most recently, regardless of status, leave it as TRUE.
559
+	 *
560
+	 * @param bool $include_completed_scripts
561
+	 * @return EE_Data_Migration_Script_Base
562
+	 */
563
+	public function get_last_ran_script($include_completed_scripts = false)
564
+	{
565
+		// make sure we've setup the class properties _last_ran_script and _last_ran_incomplete_script
566
+		if (! $this->_data_migrations_ran) {
567
+			$this->get_data_migrations_ran();
568
+		}
569
+		if ($include_completed_scripts) {
570
+			return $this->_last_ran_script;
571
+		} else {
572
+			return $this->_last_ran_incomplete_script;
573
+		}
574
+	}
575
+
576
+
577
+	/**
578
+	 * Runs the data migration scripts (well, each request to this method calls one of the
579
+	 * data migration scripts' migration_step() functions).
580
+	 *
581
+	 * @param int   $step_size
582
+	 * @throws EE_Error
583
+	 * @return array {
584
+	 *                                  // where the first item is one EE_Data_Migration_Script_Base's stati,
585
+	 *                                  //and the second item is a string describing what was done
586
+	 * @type int    $records_to_migrate from the current migration script
587
+	 * @type int    $records_migrated
588
+	 * @type string $status             one of EE_Data_Migration_Manager::status_*
589
+	 * @type string $script             verbose name of the current DMS
590
+	 * @type string $message            string describing what was done during this step
591
+	 *                                  }
592
+	 */
593
+	public function migration_step($step_size = 0)
594
+	{
595
+
596
+		// bandaid fix for issue https://events.codebasehq.com/projects/event-espresso/tickets/7535
597
+		if (class_exists('EE_CPT_Strategy')) {
598
+			remove_action('pre_get_posts', array(EE_CPT_Strategy::instance(), 'pre_get_posts'), 5);
599
+		}
600
+
601
+		try {
602
+			$currently_executing_script = $this->get_last_ran_script();
603
+			if (! $currently_executing_script) {
604
+				// Find the next script that needs to execute
605
+				$scripts = $this->check_for_applicable_data_migration_scripts();
606
+				if (! $scripts) {
607
+					// huh, no more scripts to run... apparently we're done!
608
+					// but dont forget to make sure initial data is there
609
+					// we should be good to allow them to exit maintenance mode now
610
+					EE_Maintenance_Mode::instance()->set_maintenance_level(
611
+						intval(EE_Maintenance_Mode::level_0_not_in_maintenance)
612
+					);
613
+					// saving migrations ran should actually be unnecessary, but leaving in place just in case
614
+					// remember this migration was finished (even if we timeout initing db for core and plugins)
615
+					$this->_save_migrations_ran();
616
+					// make sure DB was updated AFTER we've recorded the migration was done
617
+					$this->initialize_db_for_enqueued_ee_plugins();
618
+					return array(
619
+						'records_to_migrate' => 1,
620
+						'records_migrated'   => 1,
621
+						'status'             => self::status_no_more_migration_scripts,
622
+						'script'             => __("Data Migration Completed Successfully", "event_espresso"),
623
+						'message'            => __("All done!", "event_espresso"),
624
+					);
625
+				}
626
+				$currently_executing_script = array_shift($scripts);
627
+				// and add to the array/wp option showing the scripts ran
628
+
629
+				$migrates_to = $this->script_migrates_to_version(get_class($currently_executing_script));
630
+				$plugin_slug = $migrates_to['slug'];
631
+				$version = $migrates_to['version'];
632
+				$this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
633
+			}
634
+			$current_script_name = get_class($currently_executing_script);
635
+		} catch (Exception $e) {
636
+			// an exception occurred while trying to get migration scripts
637
+
638
+			$message = sprintf(
639
+				__("Error Message: %sStack Trace:%s", "event_espresso"),
640
+				$e->getMessage() . '<br>',
641
+				$e->getTraceAsString()
642
+			);
643
+			// record it on the array of data migration scripts ran. This will be overwritten next time we try and try to run data migrations
644
+			// but that's ok-- it's just an FYI to support that we couldn't even run any data migrations
645
+			$this->add_error_to_migrations_ran(
646
+				sprintf(__("Could not run data migrations because: %s", "event_espresso"), $message)
647
+			);
648
+			return array(
649
+				'records_to_migrate' => 1,
650
+				'records_migrated'   => 0,
651
+				'status'             => self::status_fatal_error,
652
+				'script'             => __("Error loading data migration scripts", "event_espresso"),
653
+				'message'            => $message,
654
+			);
655
+		}
656
+		// ok so we definitely have a data migration script
657
+		try {
658
+			// how big of a bite do we want to take? Allow users to easily override via their wp-config
659
+			if (absint($step_size) < 1) {
660
+				$step_size = defined('EE_MIGRATION_STEP_SIZE') && absint(EE_MIGRATION_STEP_SIZE)
661
+					? EE_MIGRATION_STEP_SIZE : EE_Data_Migration_Manager::step_size;
662
+			}
663
+			// do what we came to do!
664
+			$currently_executing_script->migration_step($step_size);
665
+			// can we wrap it up and verify default data?
666
+			$init_dbs = false;
667
+			switch ($currently_executing_script->get_status()) {
668
+				case EE_Data_Migration_Manager::status_continue:
669
+					$response_array = array(
670
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
671
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
672
+						'status'             => EE_Data_Migration_Manager::status_continue,
673
+						'message'            => $currently_executing_script->get_feedback_message(),
674
+						'script'             => $currently_executing_script->pretty_name(),
675
+					);
676
+					break;
677
+				case EE_Data_Migration_Manager::status_completed:
678
+					// ok so THAT script has completed
679
+					$this->update_current_database_state_to($this->script_migrates_to_version($current_script_name));
680
+					$response_array = array(
681
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
682
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
683
+						'status'             => EE_Data_Migration_Manager::status_completed,
684
+						'message'            => $currently_executing_script->get_feedback_message(),
685
+						'script'             => sprintf(
686
+							__("%s Completed", 'event_espresso'),
687
+							$currently_executing_script->pretty_name()
688
+						),
689
+					);
690
+					// check if there are any more after this one.
691
+					$scripts_remaining = $this->check_for_applicable_data_migration_scripts();
692
+					if (! $scripts_remaining) {
693
+						// we should be good to allow them to exit maintenance mode now
694
+						EE_Maintenance_Mode::instance()->set_maintenance_level(
695
+							intval(EE_Maintenance_Mode::level_0_not_in_maintenance)
696
+						);
697
+						// huh, no more scripts to run... apparently we're done!
698
+						// but dont forget to make sure initial data is there
699
+						$init_dbs = true;
700
+						$response_array['status'] = self::status_no_more_migration_scripts;
701
+					}
702
+					break;
703
+				default:
704
+					$response_array = array(
705
+						'records_to_migrate' => $currently_executing_script->count_records_to_migrate(),
706
+						'records_migrated'   => $currently_executing_script->count_records_migrated(),
707
+						'status'             => $currently_executing_script->get_status(),
708
+						'message'            => sprintf(
709
+							__("Minor errors occurred during %s: %s", "event_espresso"),
710
+							$currently_executing_script->pretty_name(),
711
+							implode(", ", $currently_executing_script->get_errors())
712
+						),
713
+						'script'             => $currently_executing_script->pretty_name(),
714
+					);
715
+					break;
716
+			}
717
+		} catch (Exception $e) {
718
+			// ok so some exception was thrown which killed the data migration script
719
+			// double-check we have a real script
720
+			if ($currently_executing_script instanceof EE_Data_Migration_Script_Base) {
721
+				$script_name = $currently_executing_script->pretty_name();
722
+				$currently_executing_script->set_broken();
723
+				$currently_executing_script->add_error($e->getMessage());
724
+			} else {
725
+				$script_name = __("Error getting Migration Script", "event_espresso");
726
+			}
727
+			$response_array = array(
728
+				'records_to_migrate' => 1,
729
+				'records_migrated'   => 0,
730
+				'status'             => self::status_fatal_error,
731
+				'message'            => sprintf(
732
+					__("A fatal error occurred during the migration: %s", "event_espresso"),
733
+					$e->getMessage()
734
+				),
735
+				'script'             => $script_name,
736
+			);
737
+		}
738
+		$successful_save = $this->_save_migrations_ran();
739
+		if ($successful_save !== true) {
740
+			// ok so the current wp option didn't save. that's tricky, because we'd like to update it
741
+			// and mark it as having a fatal error, but remember- WE CAN'T SAVE THIS WP OPTION!
742
+			// however, if we throw an exception, and return that, then the next request
743
+			// won't have as much info in it, and it may be able to save
744
+			throw new EE_Error(
745
+				sprintf(
746
+					__(
747
+						"The error '%s' occurred updating the status of the migration. This is a FATAL ERROR, but the error is preventing the system from remembering that. Please contact event espresso support.",
748
+						"event_espresso"
749
+					),
750
+					$successful_save
751
+				)
752
+			);
753
+		}
754
+		// if we're all done, initialize EE plugins' default data etc.
755
+		if ($init_dbs) {
756
+			$this->initialize_db_for_enqueued_ee_plugins();
757
+		}
758
+		return $response_array;
759
+	}
760
+
761
+
762
+	/**
763
+	 * Echo out JSON response to migration script AJAX requests. Takes precautions
764
+	 * to buffer output so that we don't throw junk into our json.
765
+	 *
766
+	 * @return array with keys:
767
+	 * 'records_to_migrate' which counts ALL the records for the current migration, and should remain constant. (ie,
768
+	 * it's NOT the count of hwo many remain)
769
+	 * 'records_migrated' which also counts ALL the records which have been migrated (ie, percent_complete =
770
+	 * records_migrated/records_to_migrate)
771
+	 * 'status'=>a string, one of EE_Data_migration_Manager::status_*
772
+	 * 'message'=>a string, containing any message you want to show to the user. We may decide to split this up into
773
+	 * errors, notifications, and successes
774
+	 * 'script'=>a pretty name of the script currently running
775
+	 */
776
+	public function response_to_migration_ajax_request()
777
+	{
778
+		ob_start();
779
+		try {
780
+			$response = $this->migration_step();
781
+		} catch (Exception $e) {
782
+			$response = array(
783
+				'records_to_migrate' => 0,
784
+				'records_migrated'   => 0,
785
+				'status'             => EE_Data_Migration_Manager::status_fatal_error,
786
+				'message'            => sprintf(
787
+					__("Unknown fatal error occurred: %s", "event_espresso"),
788
+					$e->getMessage()
789
+				),
790
+				'script'             => 'Unknown',
791
+			);
792
+			$this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
793
+		}
794
+		$warnings_etc = @ob_get_contents();
795
+		ob_end_clean();
796
+		$response['message'] .= $warnings_etc;
797
+		return $response;
798
+	}
799
+
800
+	/**
801
+	 * Updates the wordpress option that keeps track of which which EE version the database
802
+	 * is at (ie, the code may be at 4.1.0, but the database is still at 3.1.35)
803
+	 *
804
+	 * @param array $slug_and_version {
805
+	 * @type string $slug             like 'Core' or 'Calendar',
806
+	 * @type string $version          like '4.1.0'
807
+	 *                                }
808
+	 * @return void
809
+	 */
810
+	public function update_current_database_state_to($slug_and_version = null)
811
+	{
812
+		if (! $slug_and_version) {
813
+			// no version was provided, assume it should be at the current code version
814
+			$slug_and_version = array('slug' => 'Core', 'version' => espresso_version());
815
+		}
816
+		$current_database_state = get_option(self::current_database_state);
817
+		$current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
818
+		update_option(self::current_database_state, $current_database_state);
819
+	}
820
+
821
+	/**
822
+	 * Determines if the database is currently at a state matching what's indicated in $slug and $version.
823
+	 *
824
+	 * @param array $slug_and_version {
825
+	 * @type string $slug             like 'Core' or 'Calendar',
826
+	 * @type string $version          like '4.1.0'
827
+	 *                                }
828
+	 * @return boolean
829
+	 */
830
+	public function database_needs_updating_to($slug_and_version)
831
+	{
832
+
833
+		$slug = $slug_and_version['slug'];
834
+		$version = $slug_and_version['version'];
835
+		$current_database_state = get_option(self::current_database_state);
836
+		if (! isset($current_database_state[ $slug ])) {
837
+			return true;
838
+		} else {
839
+			// just compare the first 3 parts of version string, eg "4.7.1", not "4.7.1.dev.032" because DBs shouldn't change on nano version changes
840
+			$version_parts_current_db_state = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
841
+			$version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
842
+			$needs_updating = false;
843
+			foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
844
+				if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
845
+					$needs_updating = true;
846
+					break;
847
+				}
848
+			}
849
+			return $needs_updating;
850
+		}
851
+	}
852
+
853
+
854
+	/**
855
+	 * Gets all the data migration scripts available in the core folder and folders
856
+	 * in addons. Has the side effect of adding them for autoloading
857
+	 *
858
+	 * @return array keys are expected classnames, values are their filepaths
859
+	 * @throws InvalidInterfaceException
860
+	 * @throws InvalidDataTypeException
861
+	 * @throws EE_Error
862
+	 * @throws InvalidArgumentException
863
+	 */
864
+	public function get_all_data_migration_scripts_available()
865
+	{
866
+		if (! $this->_data_migration_class_to_filepath_map) {
867
+			$this->_data_migration_class_to_filepath_map = array();
868
+			foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
869
+				// strip any placeholders added to classname to make it a unique array key
870
+				$eeAddonClass = trim($eeAddonClass, '*');
871
+				$eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass)
872
+					? $eeAddonClass
873
+					: '';
874
+				$folder_path = EEH_File::end_with_directory_separator($folder_path);
875
+				$files = glob($folder_path . '*.dms.php');
876
+				if (empty($files)) {
877
+					continue;
878
+				}
879
+				foreach ($files as $file) {
880
+					$pos_of_last_slash = strrpos($file, DS);
881
+					$classname = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1));
882
+					$migrates_to = $this->script_migrates_to_version($classname, $eeAddonClass);
883
+					$slug = $migrates_to['slug'];
884
+					// check that the slug as contained in the DMS is associated with
885
+					// the slug of an addon or core
886
+					if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) {
887
+						EE_Error::doing_it_wrong(
888
+							__FUNCTION__,
889
+							sprintf(
890
+								esc_html__(
891
+									'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ',
892
+									'event_espresso'
893
+								),
894
+								$classname,
895
+								$slug,
896
+								implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name()))
897
+							),
898
+							'4.3.0.alpha.019'
899
+						);
900
+					}
901
+					$this->_data_migration_class_to_filepath_map[ $classname ] = $file;
902
+				}
903
+			}
904
+			EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
905
+		}
906
+		return $this->_data_migration_class_to_filepath_map;
907
+	}
908
+
909
+
910
+	/**
911
+	 * Once we have an addon that works with EE4.1, we will actually want to fetch the PUE slugs
912
+	 * from each addon, and check if they need updating,
913
+	 *
914
+	 * @return boolean
915
+	 */
916
+	public function addons_need_updating()
917
+	{
918
+		return false;
919
+	}
920
+
921
+	/**
922
+	 * Adds this error string to the data_migrations_ran array, but we dont necessarily know
923
+	 * where to put it, so we just throw it in there... better than nothing...
924
+	 *
925
+	 * @param string $error_message
926
+	 * @throws EE_Error
927
+	 */
928
+	public function add_error_to_migrations_ran($error_message)
929
+	{
930
+		// get last-ran migration script
931
+		global $wpdb;
932
+		$last_migration_script_option = $wpdb->get_row(
933
+			"SELECT * FROM $wpdb->options WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id DESC LIMIT 1",
934
+			ARRAY_A
935
+		);
936
+
937
+		$last_ran_migration_script_properties = isset($last_migration_script_option['option_value'])
938
+			? maybe_unserialize($last_migration_script_option['option_value']) : null;
939
+		// now, tread lightly because we're here because a FATAL non-catchable error
940
+		// was thrown last time when we were trying to run a data migration script
941
+		// so the fatal error could have happened while getting the migration script
942
+		// or doing running it...
943
+		$versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace(
944
+			EE_Data_Migration_Manager::data_migration_script_option_prefix,
945
+			"",
946
+			$last_migration_script_option['option_name']
947
+		) : null;
948
+
949
+		// check if it THINKS its a data migration script and especially if it's one that HASN'T finished yet
950
+		// because if it has finished, then it obviously couldn't be the cause of this error, right? (because its all done)
951
+		if (isset($last_ran_migration_script_properties['class']) && isset($last_ran_migration_script_properties['_status']) && $last_ran_migration_script_properties['_status'] != self::status_completed) {
952
+			// ok then just add this error to its list of errors
953
+			$last_ran_migration_script_properties['_errors'][] = $error_message;
954
+			$last_ran_migration_script_properties['_status'] = self::status_fatal_error;
955
+		} else {
956
+			// so we don't even know which script was last running
957
+			// use the data migration error stub, which is designed specifically for this type of thing
958
+			$general_migration_error = new EE_DMS_Unknown_1_0_0();
959
+			$general_migration_error->add_error($error_message);
960
+			$general_migration_error->set_broken();
961
+			$last_ran_migration_script_properties = $general_migration_error->properties_as_array();
962
+			$versions_migrated_to = 'Unknown.1.0.0';
963
+			// now just to make sure appears as last (in case the were previously a fatal error like this)
964
+			// delete the old one
965
+			delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
966
+		}
967
+		update_option(
968
+			self::data_migration_script_option_prefix . $versions_migrated_to,
969
+			$last_ran_migration_script_properties
970
+		);
971
+	}
972
+
973
+	/**
974
+	 * saves what data migrations have ran to the database
975
+	 *
976
+	 * @return mixed TRUE if successfully saved migrations ran, string if an error occurred
977
+	 */
978
+	protected function _save_migrations_ran()
979
+	{
980
+		if ($this->_data_migrations_ran == null) {
981
+			$this->get_data_migrations_ran();
982
+		}
983
+		// now, we don't want to save actual classes to the DB because that's messy
984
+		$successful_updates = true;
985
+		foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
986
+			foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
987
+				$plugin_slug_for_use_in_option_name = $plugin_slug . ".";
988
+				$option_name = self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
989
+				$old_option_value = get_option($option_name);
990
+				if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
991
+					$script_array_for_saving = $array_or_migration_obj->properties_as_array();
992
+					if ($old_option_value != $script_array_for_saving) {
993
+						$successful_updates = update_option($option_name, $script_array_for_saving);
994
+					}
995
+				} else {// we don't know what this array-thing is. So just save it as-is
996
+					if ($old_option_value != $array_or_migration_obj) {
997
+						$successful_updates = update_option($option_name, $array_or_migration_obj);
998
+					}
999
+				}
1000
+				if (! $successful_updates) {
1001
+					global $wpdb;
1002
+					return $wpdb->last_error;
1003
+				}
1004
+			}
1005
+		}
1006
+		return true;
1007
+		// $updated = update_option(self::data_migrations_option_name, $array_of_migrations);
1008
+		// if ($updated !== true) {
1009
+		//     global $wpdb;
1010
+		//     return $wpdb->last_error;
1011
+		// } else {
1012
+		//     return true;
1013
+		// }
1014
+		// wp_mail(
1015
+		//     "[email protected]",
1016
+		//     time() . " price debug info",
1017
+		//     "updated: $updated, last error: $last_error, byte length of option: " . strlen(
1018
+		//         serialize($array_of_migrations)
1019
+		//     )
1020
+		// );
1021
+	}
1022
+
1023
+	/**
1024
+	 * Takes an array of data migration script properties and re-creates the class from
1025
+	 * them. The argument $properties_array is assumed to have been made by
1026
+	 * EE_Data_Migration_Script_Base::properties_as_array()
1027
+	 *
1028
+	 * @param array $properties_array
1029
+	 * @return EE_Data_Migration_Script_Base
1030
+	 * @throws EE_Error
1031
+	 */
1032
+	public function _instantiate_script_from_properties_array($properties_array)
1033
+	{
1034
+		if (! isset($properties_array['class'])) {
1035
+			throw new EE_Error(
1036
+				sprintf(
1037
+					__("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
1038
+					implode(",", $properties_array)
1039
+				)
1040
+			);
1041
+		}
1042
+		$class_name = $properties_array['class'];
1043
+		if (! class_exists($class_name)) {
1044
+			throw new EE_Error(sprintf(__("There is no migration script named %s", "event_espresso"), $class_name));
1045
+		}
1046
+		$class = new $class_name;
1047
+		if (! $class instanceof EE_Data_Migration_Script_Base) {
1048
+			throw new EE_Error(
1049
+				sprintf(
1050
+					__("Class '%s' is supposed to be a migration script. Its not, its a '%s'", "event_espresso"),
1051
+					$class_name,
1052
+					get_class($class)
1053
+				)
1054
+			);
1055
+		}
1056
+		$class->instantiate_from_array_of_properties($properties_array);
1057
+		return $class;
1058
+	}
1059
+
1060
+	/**
1061
+	 * Gets the classname for the most up-to-date DMS (ie, the one that will finally
1062
+	 * leave the DB in a state usable by the current plugin code).
1063
+	 *
1064
+	 * @param string $plugin_slug the slug for the ee plugin we are searching for. Default is 'Core'
1065
+	 * @return string
1066
+	 */
1067
+	public function get_most_up_to_date_dms($plugin_slug = 'Core')
1068
+	{
1069
+		$class_to_filepath_map = $this->get_all_data_migration_scripts_available();
1070
+		$most_up_to_date_dms_classname = null;
1071
+		foreach ($class_to_filepath_map as $classname => $filepath) {
1072
+			if ($most_up_to_date_dms_classname === null) {
1073
+				$migrates_to = $this->script_migrates_to_version($classname);
1074
+				$this_plugin_slug = $migrates_to['slug'];
1075
+				if ($this_plugin_slug == $plugin_slug) {
1076
+					// if it's for core, it wins
1077
+					$most_up_to_date_dms_classname = $classname;
1078
+				}
1079
+				// if it wasn't for core, we must keep searching for one that is!
1080
+				continue;
1081
+			} else {
1082
+				$champion_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms_classname);
1083
+				$contender_migrates_to = $this->script_migrates_to_version($classname);
1084
+				if ($contender_migrates_to['slug'] == $plugin_slug
1085
+					&& version_compare(
1086
+						$champion_migrates_to['version'],
1087
+						$contender_migrates_to['version'],
1088
+						'<'
1089
+					)) {
1090
+					// so the contenders version is higher and its for Core
1091
+					$most_up_to_date_dms_classname = $classname;
1092
+				}
1093
+			}
1094
+		}
1095
+		return $most_up_to_date_dms_classname;
1096
+	}
1097
+
1098
+	/**
1099
+	 * Gets the migration script specified but ONLY if it has already ran.
1100
+	 *
1101
+	 * Eg, if you wanted to see if 'EE_DMS_Core_4_1_0' has ran, you would run the following code:
1102
+	 * <code> $core_4_1_0_dms_ran = EE_Data_Migration_Manager::instance()->get_migration_ran( '4.1.0', 'Core' ) !==
1103
+	 * NULL;</code> This is especially useful in addons' data migration scripts, this way they can tell if a core (or
1104
+	 * other addon) DMS has ran, in case the current DMS depends on it.
1105
+	 *
1106
+	 * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1107
+	 *                            period. Eg '4.1.0'
1108
+	 * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1109
+	 * @return EE_Data_Migration_Script_Base
1110
+	 */
1111
+	public function get_migration_ran($version, $plugin_slug = 'Core')
1112
+	{
1113
+		$migrations_ran = $this->get_data_migrations_ran();
1114
+		if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1115
+			return $migrations_ran[ $plugin_slug ][ $version ];
1116
+		} else {
1117
+			return null;
1118
+		}
1119
+	}
1120
+
1121
+	/**
1122
+	 * Resets the borked data migration scripts so they're no longer borked
1123
+	 * so we can again attempt to migrate
1124
+	 *
1125
+	 * @return bool
1126
+	 * @throws EE_Error
1127
+	 */
1128
+	public function reattempt()
1129
+	{
1130
+		// find if the last-ran script was borked
1131
+		// set it as being non-borked (we shouldn't ever get DMSs that we don't recognize)
1132
+		// add an 'error' saying that we attempted to reset
1133
+		// does it have a stage that was borked too? if so make it no longer borked
1134
+		// add an 'error' saying we attempted to reset
1135
+		$last_ran_script = $this->get_last_ran_script();
1136
+		if ($last_ran_script instanceof EE_DMS_Unknown_1_0_0) {
1137
+			// if it was an error DMS, just mark it as complete (if another error occurs it will overwrite it)
1138
+			$last_ran_script->set_completed();
1139
+		} elseif ($last_ran_script instanceof EE_Data_Migration_Script_Base) {
1140
+			$last_ran_script->reattempt();
1141
+		} else {
1142
+			throw new EE_Error(
1143
+				sprintf(
1144
+					__(
1145
+						'Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s',
1146
+						'event_espresso'
1147
+					),
1148
+					print_r($last_ran_script, true)
1149
+				)
1150
+			);
1151
+		}
1152
+		return $this->_save_migrations_ran();
1153
+	}
1154
+
1155
+	/**
1156
+	 * Gets whether or not this particular migration has run or not
1157
+	 *
1158
+	 * @param string $version     the version the DMS searched for migrates to. Usually just the content before the 3rd
1159
+	 *                            period. Eg '4.1.0'
1160
+	 * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
1161
+	 * @return boolean
1162
+	 */
1163
+	public function migration_has_ran($version, $plugin_slug = 'Core')
1164
+	{
1165
+		return $this->get_migration_ran($version, $plugin_slug) !== null;
1166
+	}
1167
+
1168
+	/**
1169
+	 * Enqueues this ee plugin to have its data initialized
1170
+	 *
1171
+	 * @param string $plugin_slug either 'Core' or EE_Addon::name()'s return value
1172
+	 */
1173
+	public function enqueue_db_initialization_for($plugin_slug)
1174
+	{
1175
+		$queue = $this->get_db_initialization_queue();
1176
+		if (! in_array($plugin_slug, $queue)) {
1177
+			$queue[] = $plugin_slug;
1178
+		}
1179
+		update_option(self::db_init_queue_option_name, $queue);
1180
+	}
1181
+
1182
+	/**
1183
+	 * Calls EE_Addon::initialize_db_if_no_migrations_required() on each addon
1184
+	 * specified in EE_Data_Migration_Manager::get_db_init_queue(), and if 'Core' is
1185
+	 * in the queue, calls EE_System::initialize_db_if_no_migrations_required().
1186
+	 */
1187
+	public function initialize_db_for_enqueued_ee_plugins()
1188
+	{
1189
+		$queue = $this->get_db_initialization_queue();
1190
+		foreach ($queue as $plugin_slug) {
1191
+			$most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1192
+			if (! $most_up_to_date_dms) {
1193
+				// if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1194
+				$verify_db = false;
1195
+			} else {
1196
+				$most_up_to_date_dms_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms);
1197
+				$verify_db = $this->database_needs_updating_to($most_up_to_date_dms_migrates_to);
1198
+			}
1199
+			if ($plugin_slug == 'Core') {
1200
+				EE_System::instance()->initialize_db_if_no_migrations_required(
1201
+					false,
1202
+					$verify_db
1203
+				);
1204
+			} else {
1205
+				// just loop through the addons to make sure their database is setup
1206
+				foreach (EE_Registry::instance()->addons as $addon) {
1207
+					if ($addon->name() == $plugin_slug) {
1208
+						$addon->initialize_db_if_no_migrations_required($verify_db);
1209
+						break;
1210
+					}
1211
+				}
1212
+			}
1213
+		}
1214
+		// because we just initialized the DBs for the enqueued ee plugins
1215
+		// we don't need to keep remembering which ones needed to be initialized
1216
+		delete_option(self::db_init_queue_option_name);
1217
+	}
1218
+
1219
+	/**
1220
+	 * Gets a numerically-indexed array of plugin slugs that need to have their databases
1221
+	 * (re-)initialized after migrations are complete. ie, each element should be either
1222
+	 * 'Core', or the return value of EE_Addon::name() for an addon
1223
+	 *
1224
+	 * @return array
1225
+	 */
1226
+	public function get_db_initialization_queue()
1227
+	{
1228
+		return get_option(self::db_init_queue_option_name, array());
1229
+	}
1230
+
1231
+	/**
1232
+	 * Gets the injected table analyzer, or throws an exception
1233
+	 *
1234
+	 * @return TableAnalysis
1235
+	 * @throws EE_Error
1236
+	 */
1237
+	protected function _get_table_analysis()
1238
+	{
1239
+		if ($this->_table_analysis instanceof TableAnalysis) {
1240
+			return $this->_table_analysis;
1241
+		} else {
1242
+			throw new EE_Error(
1243
+				sprintf(
1244
+					__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
1245
+					get_class($this)
1246
+				)
1247
+			);
1248
+		}
1249
+	}
1250
+
1251
+	/**
1252
+	 * Gets the injected table manager, or throws an exception
1253
+	 *
1254
+	 * @return TableManager
1255
+	 * @throws EE_Error
1256
+	 */
1257
+	protected function _get_table_manager()
1258
+	{
1259
+		if ($this->_table_manager instanceof TableManager) {
1260
+			return $this->_table_manager;
1261
+		} else {
1262
+			throw new EE_Error(
1263
+				sprintf(
1264
+					__('Table manager class on class %1$s is not set properly.', 'event_espresso'),
1265
+					get_class($this)
1266
+				)
1267
+			);
1268
+		}
1269
+	}
1270 1270
 }
Please login to merge, or discard this patch.
Spacing   +61 added lines, -61 removed lines patch added patch discarded remove patch
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
     public static function instance()
159 159
     {
160 160
         // check if class object is instantiated
161
-        if (! self::$_instance instanceof EE_Data_Migration_Manager) {
161
+        if ( ! self::$_instance instanceof EE_Data_Migration_Manager) {
162 162
             self::$_instance = new self();
163 163
         }
164 164
         return self::$_instance;
@@ -234,12 +234,12 @@  discard block
 block discarded – undo
234 234
 
235 235
         if (count($parts) == 4) {
236 236
             // it's 4.2-style.eg Core.4.1.0
237
-            $plugin_slug = $parts[0];// eg Core
238
-            $version_string = $parts[1] . "." . $parts[2] . "." . $parts[3]; // eg 4.1.0
237
+            $plugin_slug = $parts[0]; // eg Core
238
+            $version_string = $parts[1].".".$parts[2].".".$parts[3]; // eg 4.1.0
239 239
         } else {
240 240
             // it's 4.1-style: eg 4.1.0
241 241
             $plugin_slug = 'Core';
242
-            $version_string = $plugin_slug_and_version_string;// eg 4.1.0
242
+            $version_string = $plugin_slug_and_version_string; // eg 4.1.0
243 243
         }
244 244
         return array($plugin_slug, $version_string);
245 245
     }
@@ -291,11 +291,11 @@  discard block
 block discarded – undo
291 291
      */
292 292
     public function get_data_migrations_ran()
293 293
     {
294
-        if (! $this->_data_migrations_ran) {
294
+        if ( ! $this->_data_migrations_ran) {
295 295
             // setup autoloaders for each of the scripts in there
296 296
             $this->get_all_data_migration_scripts_available();
297 297
             $data_migrations_options = $this->get_all_migration_script_options(
298
-            );// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
298
+            ); // get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
299 299
 
300 300
             $data_migrations_ran = array();
301 301
             // convert into data migration script classes where possible
@@ -309,23 +309,23 @@  discard block
 block discarded – undo
309 309
                         $data_migration_option['option_name'],
310 310
                         $data_migration_option['option_value']
311 311
                     );
312
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = $class;
312
+                    $data_migrations_ran[$plugin_slug][$version_string] = $class;
313 313
                     // ok so far THIS is the 'last-ran-script'... unless we find another on next iteration
314 314
                     $this->_last_ran_script = $class;
315
-                    if (! $class->is_completed()) {
315
+                    if ( ! $class->is_completed()) {
316 316
                         // sometimes we also like to know which was the last incomplete script (or if there are any at all)
317 317
                         $this->_last_ran_incomplete_script = $class;
318 318
                     }
319 319
                 } catch (EE_Error $e) {
320 320
                     // ok so its not a DMS. We'll just keep it, although other code will need to expect non-DMSs
321
-                    $data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize(
321
+                    $data_migrations_ran[$plugin_slug][$version_string] = maybe_unserialize(
322 322
                         $data_migration_option['option_value']
323 323
                     );
324 324
                 }
325 325
             }
326 326
             // so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
327 327
             $this->_data_migrations_ran = $data_migrations_ran;
328
-            if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
328
+            if ( ! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
329 329
                 $this->_data_migrations_ran = array();
330 330
             }
331 331
         }
@@ -358,7 +358,7 @@  discard block
 block discarded – undo
358 358
     {
359 359
         global $wpdb;
360 360
         return $wpdb->get_results(
361
-            "SELECT * FROM {$wpdb->options} WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id ASC",
361
+            "SELECT * FROM {$wpdb->options} WHERE option_name like '".EE_Data_Migration_Manager::data_migration_script_option_prefix."%' ORDER BY option_id ASC",
362 362
             ARRAY_A
363 363
         );
364 364
     }
@@ -373,7 +373,7 @@  discard block
 block discarded – undo
373 373
     {
374 374
         return apply_filters(
375 375
             'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
376
-            array('Core' => EE_CORE . 'data_migration_scripts')
376
+            array('Core' => EE_CORE.'data_migration_scripts')
377 377
         );
378 378
     }
379 379
 
@@ -389,15 +389,15 @@  discard block
 block discarded – undo
389 389
      */
390 390
     public function script_migrates_to_version($migration_script_name, $eeAddonClass = '')
391 391
     {
392
-        if (isset($this->script_migration_versions[ $migration_script_name ])) {
393
-            return $this->script_migration_versions[ $migration_script_name ];
392
+        if (isset($this->script_migration_versions[$migration_script_name])) {
393
+            return $this->script_migration_versions[$migration_script_name];
394 394
         }
395 395
         $dms_info = $this->parse_dms_classname($migration_script_name);
396
-        $this->script_migration_versions[ $migration_script_name ] = array(
396
+        $this->script_migration_versions[$migration_script_name] = array(
397 397
             'slug'    => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
398
-            'version' => $dms_info['major_version'] . "." . $dms_info['minor_version'] . "." . $dms_info['micro_version'],
398
+            'version' => $dms_info['major_version'].".".$dms_info['minor_version'].".".$dms_info['micro_version'],
399 399
         );
400
-        return $this->script_migration_versions[ $migration_script_name ];
400
+        return $this->script_migration_versions[$migration_script_name];
401 401
     }
402 402
 
403 403
     /**
@@ -411,7 +411,7 @@  discard block
 block discarded – undo
411 411
     {
412 412
         $matches = array();
413 413
         preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
414
-        if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
414
+        if ( ! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
415 415
             throw new EE_Error(
416 416
                 sprintf(
417 417
                     __(
@@ -442,7 +442,7 @@  discard block
 block discarded – undo
442 442
     {
443 443
         $espresso_db_core_updates = get_option('espresso_db_update', array());
444 444
         $db_state = get_option(EE_Data_Migration_Manager::current_database_state);
445
-        if (! $db_state) {
445
+        if ( ! $db_state) {
446 446
             // mark the DB as being in the state as the last version in there.
447 447
             // this is done to trigger maintenance mode and do data migration scripts
448 448
             // if the admin installed this version of EE over 3.1.x or 4.0.x
@@ -461,7 +461,7 @@  discard block
 block discarded – undo
461 461
         // in 4.1, $db_state would have only been a simple string like '4.1.0',
462 462
         // but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
463 463
         // db, and possibly other keys for other addons like 'Calendar','Permissions',etc
464
-        if (! is_array($db_state)) {
464
+        if ( ! is_array($db_state)) {
465 465
             $db_state = array('Core' => $db_state);
466 466
             update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
467 467
         }
@@ -498,29 +498,29 @@  discard block
 block discarded – undo
498 498
                 $script_converts_plugin_slug = $migrates_to_version['slug'];
499 499
                 $script_converts_to_version = $migrates_to_version['version'];
500 500
                 // check if this version script is DONE or not; or if it's never been ran
501
-                if (! $scripts_ran ||
502
-                    ! isset($scripts_ran[ $script_converts_plugin_slug ]) ||
503
-                    ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ])) {
501
+                if ( ! $scripts_ran ||
502
+                    ! isset($scripts_ran[$script_converts_plugin_slug]) ||
503
+                    ! isset($scripts_ran[$script_converts_plugin_slug][$script_converts_to_version])) {
504 504
                     // we haven't ran this conversion script before
505 505
                     // now check if it applies... note that we've added an autoloader for it on get_all_data_migration_scripts_available
506 506
                     $script = LoaderFactory::getLoader()->load($classname);
507 507
                     /* @var $script EE_Data_Migration_Script_Base */
508 508
                     $can_migrate = $script->can_migrate_from_version($theoretical_database_state);
509 509
                     if ($can_migrate) {
510
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
510
+                        $script_classes_that_should_run_per_iteration[$iteration][$script->priority()][] = $script;
511 511
                         $migrates_to_version = $script->migrates_to_version();
512
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
513
-                        unset($script_class_and_filepaths_available[ $classname ]);
512
+                        $next_database_state_to_consider[$migrates_to_version['slug']] = $migrates_to_version['version'];
513
+                        unset($script_class_and_filepaths_available[$classname]);
514 514
                     }
515
-                } elseif ($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ] instanceof EE_Data_Migration_Script_Base) {
515
+                } elseif ($scripts_ran[$script_converts_plugin_slug][$script_converts_to_version] instanceof EE_Data_Migration_Script_Base) {
516 516
                     // this script has been ran, or at least started
517
-                    $script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ];
517
+                    $script = $scripts_ran[$script_converts_plugin_slug][$script_converts_to_version];
518 518
                     if ($script->get_status() != self::status_completed) {
519 519
                         // this script is already underway... keep going with it
520
-                        $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script;
520
+                        $script_classes_that_should_run_per_iteration[$iteration][$script->priority()][] = $script;
521 521
                         $migrates_to_version = $script->migrates_to_version();
522
-                        $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version'];
523
-                        unset($script_class_and_filepaths_available[ $classname ]);
522
+                        $next_database_state_to_consider[$migrates_to_version['slug']] = $migrates_to_version['version'];
523
+                        unset($script_class_and_filepaths_available[$classname]);
524 524
                     } else {
525 525
                         // it must have a status that indicates it has finished, so we don't want to try and run it again
526 526
                     }
@@ -531,14 +531,14 @@  discard block
 block discarded – undo
531 531
                 }
532 532
             }
533 533
             $iteration++;
534
-        } while ($next_database_state_to_consider != $theoretical_database_state && $iteration < 6);
534
+        }while ($next_database_state_to_consider != $theoretical_database_state && $iteration < 6);
535 535
         // ok we have all the scripts that should run, now let's make them into flat array
536 536
         $scripts_that_should_run = array();
537 537
         foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
538 538
             ksort($scripts_at_priority);
539 539
             foreach ($scripts_at_priority as $scripts) {
540 540
                 foreach ($scripts as $script) {
541
-                    $scripts_that_should_run[ get_class($script) ] = $script;
541
+                    $scripts_that_should_run[get_class($script)] = $script;
542 542
                 }
543 543
             }
544 544
         }
@@ -563,7 +563,7 @@  discard block
 block discarded – undo
563 563
     public function get_last_ran_script($include_completed_scripts = false)
564 564
     {
565 565
         // make sure we've setup the class properties _last_ran_script and _last_ran_incomplete_script
566
-        if (! $this->_data_migrations_ran) {
566
+        if ( ! $this->_data_migrations_ran) {
567 567
             $this->get_data_migrations_ran();
568 568
         }
569 569
         if ($include_completed_scripts) {
@@ -600,10 +600,10 @@  discard block
 block discarded – undo
600 600
 
601 601
         try {
602 602
             $currently_executing_script = $this->get_last_ran_script();
603
-            if (! $currently_executing_script) {
603
+            if ( ! $currently_executing_script) {
604 604
                 // Find the next script that needs to execute
605 605
                 $scripts = $this->check_for_applicable_data_migration_scripts();
606
-                if (! $scripts) {
606
+                if ( ! $scripts) {
607 607
                     // huh, no more scripts to run... apparently we're done!
608 608
                     // but dont forget to make sure initial data is there
609 609
                     // we should be good to allow them to exit maintenance mode now
@@ -629,7 +629,7 @@  discard block
 block discarded – undo
629 629
                 $migrates_to = $this->script_migrates_to_version(get_class($currently_executing_script));
630 630
                 $plugin_slug = $migrates_to['slug'];
631 631
                 $version = $migrates_to['version'];
632
-                $this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script;
632
+                $this->_data_migrations_ran[$plugin_slug][$version] = $currently_executing_script;
633 633
             }
634 634
             $current_script_name = get_class($currently_executing_script);
635 635
         } catch (Exception $e) {
@@ -637,7 +637,7 @@  discard block
 block discarded – undo
637 637
 
638 638
             $message = sprintf(
639 639
                 __("Error Message: %sStack Trace:%s", "event_espresso"),
640
-                $e->getMessage() . '<br>',
640
+                $e->getMessage().'<br>',
641 641
                 $e->getTraceAsString()
642 642
             );
643 643
             // record it on the array of data migration scripts ran. This will be overwritten next time we try and try to run data migrations
@@ -689,7 +689,7 @@  discard block
 block discarded – undo
689 689
                     );
690 690
                     // check if there are any more after this one.
691 691
                     $scripts_remaining = $this->check_for_applicable_data_migration_scripts();
692
-                    if (! $scripts_remaining) {
692
+                    if ( ! $scripts_remaining) {
693 693
                         // we should be good to allow them to exit maintenance mode now
694 694
                         EE_Maintenance_Mode::instance()->set_maintenance_level(
695 695
                             intval(EE_Maintenance_Mode::level_0_not_in_maintenance)
@@ -789,7 +789,7 @@  discard block
 block discarded – undo
789 789
                 ),
790 790
                 'script'             => 'Unknown',
791 791
             );
792
-            $this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString());
792
+            $this->add_error_to_migrations_ran($e->getMessage()."; Stack trace:".$e->getTraceAsString());
793 793
         }
794 794
         $warnings_etc = @ob_get_contents();
795 795
         ob_end_clean();
@@ -809,12 +809,12 @@  discard block
 block discarded – undo
809 809
      */
810 810
     public function update_current_database_state_to($slug_and_version = null)
811 811
     {
812
-        if (! $slug_and_version) {
812
+        if ( ! $slug_and_version) {
813 813
             // no version was provided, assume it should be at the current code version
814 814
             $slug_and_version = array('slug' => 'Core', 'version' => espresso_version());
815 815
         }
816 816
         $current_database_state = get_option(self::current_database_state);
817
-        $current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version'];
817
+        $current_database_state[$slug_and_version['slug']] = $slug_and_version['version'];
818 818
         update_option(self::current_database_state, $current_database_state);
819 819
     }
820 820
 
@@ -833,15 +833,15 @@  discard block
 block discarded – undo
833 833
         $slug = $slug_and_version['slug'];
834 834
         $version = $slug_and_version['version'];
835 835
         $current_database_state = get_option(self::current_database_state);
836
-        if (! isset($current_database_state[ $slug ])) {
836
+        if ( ! isset($current_database_state[$slug])) {
837 837
             return true;
838 838
         } else {
839 839
             // just compare the first 3 parts of version string, eg "4.7.1", not "4.7.1.dev.032" because DBs shouldn't change on nano version changes
840
-            $version_parts_current_db_state = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3);
840
+            $version_parts_current_db_state = array_slice(explode('.', $current_database_state[$slug]), 0, 3);
841 841
             $version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
842 842
             $needs_updating = false;
843 843
             foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
844
-                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) {
844
+                if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[$offset]) {
845 845
                     $needs_updating = true;
846 846
                     break;
847 847
                 }
@@ -863,7 +863,7 @@  discard block
 block discarded – undo
863 863
      */
864 864
     public function get_all_data_migration_scripts_available()
865 865
     {
866
-        if (! $this->_data_migration_class_to_filepath_map) {
866
+        if ( ! $this->_data_migration_class_to_filepath_map) {
867 867
             $this->_data_migration_class_to_filepath_map = array();
868 868
             foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
869 869
                 // strip any placeholders added to classname to make it a unique array key
@@ -872,7 +872,7 @@  discard block
 block discarded – undo
872 872
                     ? $eeAddonClass
873 873
                     : '';
874 874
                 $folder_path = EEH_File::end_with_directory_separator($folder_path);
875
-                $files = glob($folder_path . '*.dms.php');
875
+                $files = glob($folder_path.'*.dms.php');
876 876
                 if (empty($files)) {
877 877
                     continue;
878 878
                 }
@@ -898,7 +898,7 @@  discard block
 block discarded – undo
898 898
                             '4.3.0.alpha.019'
899 899
                         );
900 900
                     }
901
-                    $this->_data_migration_class_to_filepath_map[ $classname ] = $file;
901
+                    $this->_data_migration_class_to_filepath_map[$classname] = $file;
902 902
                 }
903 903
             }
904 904
             EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
@@ -930,7 +930,7 @@  discard block
 block discarded – undo
930 930
         // get last-ran migration script
931 931
         global $wpdb;
932 932
         $last_migration_script_option = $wpdb->get_row(
933
-            "SELECT * FROM $wpdb->options WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id DESC LIMIT 1",
933
+            "SELECT * FROM $wpdb->options WHERE option_name like '".EE_Data_Migration_Manager::data_migration_script_option_prefix."%' ORDER BY option_id DESC LIMIT 1",
934 934
             ARRAY_A
935 935
         );
936 936
 
@@ -962,10 +962,10 @@  discard block
 block discarded – undo
962 962
             $versions_migrated_to = 'Unknown.1.0.0';
963 963
             // now just to make sure appears as last (in case the were previously a fatal error like this)
964 964
             // delete the old one
965
-            delete_option(self::data_migration_script_option_prefix . $versions_migrated_to);
965
+            delete_option(self::data_migration_script_option_prefix.$versions_migrated_to);
966 966
         }
967 967
         update_option(
968
-            self::data_migration_script_option_prefix . $versions_migrated_to,
968
+            self::data_migration_script_option_prefix.$versions_migrated_to,
969 969
             $last_ran_migration_script_properties
970 970
         );
971 971
     }
@@ -984,8 +984,8 @@  discard block
 block discarded – undo
984 984
         $successful_updates = true;
985 985
         foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
986 986
             foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
987
-                $plugin_slug_for_use_in_option_name = $plugin_slug . ".";
988
-                $option_name = self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string;
987
+                $plugin_slug_for_use_in_option_name = $plugin_slug.".";
988
+                $option_name = self::data_migration_script_option_prefix.$plugin_slug_for_use_in_option_name.$version_string;
989 989
                 $old_option_value = get_option($option_name);
990 990
                 if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
991 991
                     $script_array_for_saving = $array_or_migration_obj->properties_as_array();
@@ -997,7 +997,7 @@  discard block
 block discarded – undo
997 997
                         $successful_updates = update_option($option_name, $array_or_migration_obj);
998 998
                     }
999 999
                 }
1000
-                if (! $successful_updates) {
1000
+                if ( ! $successful_updates) {
1001 1001
                     global $wpdb;
1002 1002
                     return $wpdb->last_error;
1003 1003
                 }
@@ -1031,7 +1031,7 @@  discard block
 block discarded – undo
1031 1031
      */
1032 1032
     public function _instantiate_script_from_properties_array($properties_array)
1033 1033
     {
1034
-        if (! isset($properties_array['class'])) {
1034
+        if ( ! isset($properties_array['class'])) {
1035 1035
             throw new EE_Error(
1036 1036
                 sprintf(
1037 1037
                     __("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),
@@ -1040,11 +1040,11 @@  discard block
 block discarded – undo
1040 1040
             );
1041 1041
         }
1042 1042
         $class_name = $properties_array['class'];
1043
-        if (! class_exists($class_name)) {
1043
+        if ( ! class_exists($class_name)) {
1044 1044
             throw new EE_Error(sprintf(__("There is no migration script named %s", "event_espresso"), $class_name));
1045 1045
         }
1046 1046
         $class = new $class_name;
1047
-        if (! $class instanceof EE_Data_Migration_Script_Base) {
1047
+        if ( ! $class instanceof EE_Data_Migration_Script_Base) {
1048 1048
             throw new EE_Error(
1049 1049
                 sprintf(
1050 1050
                     __("Class '%s' is supposed to be a migration script. Its not, its a '%s'", "event_espresso"),
@@ -1111,8 +1111,8 @@  discard block
 block discarded – undo
1111 1111
     public function get_migration_ran($version, $plugin_slug = 'Core')
1112 1112
     {
1113 1113
         $migrations_ran = $this->get_data_migrations_ran();
1114
-        if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) {
1115
-            return $migrations_ran[ $plugin_slug ][ $version ];
1114
+        if (isset($migrations_ran[$plugin_slug]) && isset($migrations_ran[$plugin_slug][$version])) {
1115
+            return $migrations_ran[$plugin_slug][$version];
1116 1116
         } else {
1117 1117
             return null;
1118 1118
         }
@@ -1173,7 +1173,7 @@  discard block
 block discarded – undo
1173 1173
     public function enqueue_db_initialization_for($plugin_slug)
1174 1174
     {
1175 1175
         $queue = $this->get_db_initialization_queue();
1176
-        if (! in_array($plugin_slug, $queue)) {
1176
+        if ( ! in_array($plugin_slug, $queue)) {
1177 1177
             $queue[] = $plugin_slug;
1178 1178
         }
1179 1179
         update_option(self::db_init_queue_option_name, $queue);
@@ -1189,7 +1189,7 @@  discard block
 block discarded – undo
1189 1189
         $queue = $this->get_db_initialization_queue();
1190 1190
         foreach ($queue as $plugin_slug) {
1191 1191
             $most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1192
-            if (! $most_up_to_date_dms) {
1192
+            if ( ! $most_up_to_date_dms) {
1193 1193
                 // if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1194 1194
                 $verify_db = false;
1195 1195
             } else {
Please login to merge, or discard this patch.
core/EE_Dependency_Map.core.php 2 patches
Spacing   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -122,7 +122,7 @@  discard block
 block discarded – undo
122 122
     public static function instance(ClassInterfaceCache $class_cache = null)
123 123
     {
124 124
         // check if class object is instantiated, and instantiated properly
125
-        if (! self::$_instance instanceof EE_Dependency_Map
125
+        if ( ! self::$_instance instanceof EE_Dependency_Map
126 126
             && $class_cache instanceof ClassInterfaceCache
127 127
         ) {
128 128
             self::$_instance = new EE_Dependency_Map($class_cache);
@@ -203,18 +203,18 @@  discard block
 block discarded – undo
203 203
     ) {
204 204
         $class = trim($class, '\\');
205 205
         $registered = false;
206
-        if (empty(self::$_instance->_dependency_map[ $class ])) {
207
-            self::$_instance->_dependency_map[ $class ] = array();
206
+        if (empty(self::$_instance->_dependency_map[$class])) {
207
+            self::$_instance->_dependency_map[$class] = array();
208 208
         }
209 209
         // we need to make sure that any aliases used when registering a dependency
210 210
         // get resolved to the correct class name
211 211
         foreach ($dependencies as $dependency => $load_source) {
212 212
             $alias = self::$_instance->getFqnForAlias($dependency);
213 213
             if ($overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
214
-                || ! isset(self::$_instance->_dependency_map[ $class ][ $alias ])
214
+                || ! isset(self::$_instance->_dependency_map[$class][$alias])
215 215
             ) {
216
-                unset($dependencies[ $dependency ]);
217
-                $dependencies[ $alias ] = $load_source;
216
+                unset($dependencies[$dependency]);
217
+                $dependencies[$alias] = $load_source;
218 218
                 $registered = true;
219 219
             }
220 220
         }
@@ -224,13 +224,13 @@  discard block
 block discarded – undo
224 224
         // ie: with A = B + C, entries in B take precedence over duplicate entries in C
225 225
         // Union is way faster than array_merge() but should be used with caution...
226 226
         // especially with numerically indexed arrays
227
-        $dependencies += self::$_instance->_dependency_map[ $class ];
227
+        $dependencies += self::$_instance->_dependency_map[$class];
228 228
         // now we need to ensure that the resulting dependencies
229 229
         // array only has the entries that are required for the class
230 230
         // so first count how many dependencies were originally registered for the class
231
-        $dependency_count = count(self::$_instance->_dependency_map[ $class ]);
231
+        $dependency_count = count(self::$_instance->_dependency_map[$class]);
232 232
         // if that count is non-zero (meaning dependencies were already registered)
233
-        self::$_instance->_dependency_map[ $class ] = $dependency_count
233
+        self::$_instance->_dependency_map[$class] = $dependency_count
234 234
             // then truncate the  final array to match that count
235 235
             ? array_slice($dependencies, 0, $dependency_count)
236 236
             // otherwise just take the incoming array because nothing previously existed
@@ -247,13 +247,13 @@  discard block
 block discarded – undo
247 247
      */
248 248
     public static function register_class_loader($class_name, $loader = 'load_core')
249 249
     {
250
-        if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
250
+        if ( ! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
251 251
             throw new DomainException(
252 252
                 esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
253 253
             );
254 254
         }
255 255
         // check that loader is callable or method starts with "load_" and exists in EE_Registry
256
-        if (! is_callable($loader)
256
+        if ( ! is_callable($loader)
257 257
             && (
258 258
                 strpos($loader, 'load_') !== 0
259 259
                 || ! method_exists('EE_Registry', $loader)
@@ -270,8 +270,8 @@  discard block
 block discarded – undo
270 270
             );
271 271
         }
272 272
         $class_name = self::$_instance->getFqnForAlias($class_name);
273
-        if (! isset(self::$_instance->_class_loaders[ $class_name ])) {
274
-            self::$_instance->_class_loaders[ $class_name ] = $loader;
273
+        if ( ! isset(self::$_instance->_class_loaders[$class_name])) {
274
+            self::$_instance->_class_loaders[$class_name] = $loader;
275 275
             return true;
276 276
         }
277 277
         return false;
@@ -299,7 +299,7 @@  discard block
 block discarded – undo
299 299
         if (strpos($class_name, 'EEM_') === 0) {
300 300
             $class_name = 'LEGACY_MODELS';
301 301
         }
302
-        return isset($this->_dependency_map[ $class_name ]) ? true : false;
302
+        return isset($this->_dependency_map[$class_name]) ? true : false;
303 303
     }
304 304
 
305 305
 
@@ -317,7 +317,7 @@  discard block
 block discarded – undo
317 317
             $class_name = 'LEGACY_MODELS';
318 318
         }
319 319
         $dependency = $this->getFqnForAlias($dependency, $class_name);
320
-        return isset($this->_dependency_map[ $class_name ][ $dependency ])
320
+        return isset($this->_dependency_map[$class_name][$dependency])
321 321
             ? true
322 322
             : false;
323 323
     }
@@ -338,7 +338,7 @@  discard block
 block discarded – undo
338 338
         }
339 339
         $dependency = $this->getFqnForAlias($dependency);
340 340
         return $this->has_dependency_for_class($class_name, $dependency)
341
-            ? $this->_dependency_map[ $class_name ][ $dependency ]
341
+            ? $this->_dependency_map[$class_name][$dependency]
342 342
             : EE_Dependency_Map::not_registered;
343 343
     }
344 344
 
@@ -361,7 +361,7 @@  discard block
 block discarded – undo
361 361
             return 'load_core';
362 362
         }
363 363
         $class_name = $this->getFqnForAlias($class_name);
364
-        return isset($this->_class_loaders[ $class_name ]) ? $this->_class_loaders[ $class_name ] : '';
364
+        return isset($this->_class_loaders[$class_name]) ? $this->_class_loaders[$class_name] : '';
365 365
     }
366 366
 
367 367
 
@@ -882,7 +882,7 @@  discard block
 block discarded – undo
882 882
     {
883 883
         $this->_class_loaders = array(
884 884
             // load_core
885
-            'EE_Dependency_Map'                            => function () {
885
+            'EE_Dependency_Map'                            => function() {
886 886
                 return $this;
887 887
             },
888 888
             'EE_Capabilities'                              => 'load_core',
@@ -890,13 +890,13 @@  discard block
 block discarded – undo
890 890
             'EE_Front_Controller'                          => 'load_core',
891 891
             'EE_Module_Request_Router'                     => 'load_core',
892 892
             'EE_Registry'                                  => 'load_core',
893
-            'EE_Request'                                   => function () {
893
+            'EE_Request'                                   => function() {
894 894
                 return $this->legacy_request;
895 895
             },
896
-            'EventEspresso\core\services\request\Request'  => function () {
896
+            'EventEspresso\core\services\request\Request'  => function() {
897 897
                 return $this->request;
898 898
             },
899
-            'EventEspresso\core\services\request\Response' => function () {
899
+            'EventEspresso\core\services\request\Response' => function() {
900 900
                 return $this->response;
901 901
             },
902 902
             'EE_Base'                                      => 'load_core',
@@ -929,7 +929,7 @@  discard block
 block discarded – undo
929 929
             'EE_DMS_Core_4_8_0'                            => 'load_dms',
930 930
             'EE_DMS_Core_4_9_0'                            => 'load_dms',
931 931
             'EE_DMS_Core_4_10_0'                            => 'load_dms',
932
-            'EE_Messages_Generator'                        => function () {
932
+            'EE_Messages_Generator'                        => function() {
933 933
                 return EE_Registry::instance()->load_lib(
934 934
                     'Messages_Generator',
935 935
                     array(),
@@ -937,7 +937,7 @@  discard block
 block discarded – undo
937 937
                     false
938 938
                 );
939 939
             },
940
-            'EE_Messages_Template_Defaults'                => function ($arguments = array()) {
940
+            'EE_Messages_Template_Defaults'                => function($arguments = array()) {
941 941
                 return EE_Registry::instance()->load_lib(
942 942
                     'Messages_Template_Defaults',
943 943
                     $arguments,
@@ -946,46 +946,46 @@  discard block
 block discarded – undo
946 946
                 );
947 947
             },
948 948
             // load_helper
949
-            'EEH_Parse_Shortcodes'                         => function () {
949
+            'EEH_Parse_Shortcodes'                         => function() {
950 950
                 if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
951 951
                     return new EEH_Parse_Shortcodes();
952 952
                 }
953 953
                 return null;
954 954
             },
955
-            'EE_Template_Config'                           => function () {
955
+            'EE_Template_Config'                           => function() {
956 956
                 return EE_Config::instance()->template_settings;
957 957
             },
958
-            'EE_Currency_Config'                           => function () {
958
+            'EE_Currency_Config'                           => function() {
959 959
                 return EE_Config::instance()->currency;
960 960
             },
961
-            'EE_Registration_Config'                       => function () {
961
+            'EE_Registration_Config'                       => function() {
962 962
                 return EE_Config::instance()->registration;
963 963
             },
964
-            'EE_Core_Config'                               => function () {
964
+            'EE_Core_Config'                               => function() {
965 965
                 return EE_Config::instance()->core;
966 966
             },
967
-            'EventEspresso\core\services\loaders\Loader'   => function () {
967
+            'EventEspresso\core\services\loaders\Loader'   => function() {
968 968
                 return LoaderFactory::getLoader();
969 969
             },
970
-            'EE_Network_Config'                            => function () {
970
+            'EE_Network_Config'                            => function() {
971 971
                 return EE_Network_Config::instance();
972 972
             },
973
-            'EE_Config'                                    => function () {
973
+            'EE_Config'                                    => function() {
974 974
                 return EE_Config::instance();
975 975
             },
976
-            'EventEspresso\core\domain\Domain'             => function () {
976
+            'EventEspresso\core\domain\Domain'             => function() {
977 977
                 return DomainFactory::getEventEspressoCoreDomain();
978 978
             },
979
-            'EE_Admin_Config'                              => function () {
979
+            'EE_Admin_Config'                              => function() {
980 980
                 return EE_Config::instance()->admin;
981 981
             },
982
-            'EE_Organization_Config'                       => function () {
982
+            'EE_Organization_Config'                       => function() {
983 983
                 return EE_Config::instance()->organization;
984 984
             },
985
-            'EE_Network_Core_Config'                       => function () {
985
+            'EE_Network_Core_Config'                       => function() {
986 986
                 return EE_Network_Config::instance()->core;
987 987
             },
988
-            'EE_Environment_Config'                        => function () {
988
+            'EE_Environment_Config'                        => function() {
989 989
                 return EE_Config::instance()->environment;
990 990
             },
991 991
         );
@@ -1046,7 +1046,7 @@  discard block
 block discarded – undo
1046 1046
             }
1047 1047
             $this->class_cache->addAlias($fqn, $alias);
1048 1048
         }
1049
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1049
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1050 1050
             $this->class_cache->addAlias(
1051 1051
                 'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1052 1052
                 'EventEspresso\core\services\notices\NoticeConverterInterface'
Please login to merge, or discard this patch.
Indentation   +1103 added lines, -1103 removed lines patch added patch discarded remove patch
@@ -20,1107 +20,1107 @@
 block discarded – undo
20 20
 class EE_Dependency_Map
21 21
 {
22 22
 
23
-    /**
24
-     * This means that the requested class dependency is not present in the dependency map
25
-     */
26
-    const not_registered = 0;
27
-
28
-    /**
29
-     * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
30
-     */
31
-    const load_new_object = 1;
32
-
33
-    /**
34
-     * This instructs class loaders to return a previously instantiated and cached object for the requested class.
35
-     * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
36
-     */
37
-    const load_from_cache = 2;
38
-
39
-    /**
40
-     * When registering a dependency,
41
-     * this indicates to keep any existing dependencies that already exist,
42
-     * and simply discard any new dependencies declared in the incoming data
43
-     */
44
-    const KEEP_EXISTING_DEPENDENCIES = 0;
45
-
46
-    /**
47
-     * When registering a dependency,
48
-     * this indicates to overwrite any existing dependencies that already exist using the incoming data
49
-     */
50
-    const OVERWRITE_DEPENDENCIES = 1;
51
-
52
-
53
-    /**
54
-     * @type EE_Dependency_Map $_instance
55
-     */
56
-    protected static $_instance;
57
-
58
-    /**
59
-     * @var ClassInterfaceCache $class_cache
60
-     */
61
-    private $class_cache;
62
-
63
-    /**
64
-     * @type RequestInterface $request
65
-     */
66
-    protected $request;
67
-
68
-    /**
69
-     * @type LegacyRequestInterface $legacy_request
70
-     */
71
-    protected $legacy_request;
72
-
73
-    /**
74
-     * @type ResponseInterface $response
75
-     */
76
-    protected $response;
77
-
78
-    /**
79
-     * @type LoaderInterface $loader
80
-     */
81
-    protected $loader;
82
-
83
-    /**
84
-     * @type array $_dependency_map
85
-     */
86
-    protected $_dependency_map = array();
87
-
88
-    /**
89
-     * @type array $_class_loaders
90
-     */
91
-    protected $_class_loaders = array();
92
-
93
-
94
-    /**
95
-     * EE_Dependency_Map constructor.
96
-     *
97
-     * @param ClassInterfaceCache $class_cache
98
-     */
99
-    protected function __construct(ClassInterfaceCache $class_cache)
100
-    {
101
-        $this->class_cache = $class_cache;
102
-        do_action('EE_Dependency_Map____construct', $this);
103
-    }
104
-
105
-
106
-    /**
107
-     * @return void
108
-     */
109
-    public function initialize()
110
-    {
111
-        $this->_register_core_dependencies();
112
-        $this->_register_core_class_loaders();
113
-        $this->_register_core_aliases();
114
-    }
115
-
116
-
117
-    /**
118
-     * @singleton method used to instantiate class object
119
-     * @param ClassInterfaceCache|null $class_cache
120
-     * @return EE_Dependency_Map
121
-     */
122
-    public static function instance(ClassInterfaceCache $class_cache = null)
123
-    {
124
-        // check if class object is instantiated, and instantiated properly
125
-        if (! self::$_instance instanceof EE_Dependency_Map
126
-            && $class_cache instanceof ClassInterfaceCache
127
-        ) {
128
-            self::$_instance = new EE_Dependency_Map($class_cache);
129
-        }
130
-        return self::$_instance;
131
-    }
132
-
133
-
134
-    /**
135
-     * @param RequestInterface $request
136
-     */
137
-    public function setRequest(RequestInterface $request)
138
-    {
139
-        $this->request = $request;
140
-    }
141
-
142
-
143
-    /**
144
-     * @param LegacyRequestInterface $legacy_request
145
-     */
146
-    public function setLegacyRequest(LegacyRequestInterface $legacy_request)
147
-    {
148
-        $this->legacy_request = $legacy_request;
149
-    }
150
-
151
-
152
-    /**
153
-     * @param ResponseInterface $response
154
-     */
155
-    public function setResponse(ResponseInterface $response)
156
-    {
157
-        $this->response = $response;
158
-    }
159
-
160
-
161
-    /**
162
-     * @param LoaderInterface $loader
163
-     */
164
-    public function setLoader(LoaderInterface $loader)
165
-    {
166
-        $this->loader = $loader;
167
-    }
168
-
169
-
170
-    /**
171
-     * @param string $class
172
-     * @param array  $dependencies
173
-     * @param int    $overwrite
174
-     * @return bool
175
-     */
176
-    public static function register_dependencies(
177
-        $class,
178
-        array $dependencies,
179
-        $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
180
-    ) {
181
-        return self::$_instance->registerDependencies($class, $dependencies, $overwrite);
182
-    }
183
-
184
-
185
-    /**
186
-     * Assigns an array of class names and corresponding load sources (new or cached)
187
-     * to the class specified by the first parameter.
188
-     * IMPORTANT !!!
189
-     * The order of elements in the incoming $dependencies array MUST match
190
-     * the order of the constructor parameters for the class in question.
191
-     * This is especially important when overriding any existing dependencies that are registered.
192
-     * the third parameter controls whether any duplicate dependencies are overwritten or not.
193
-     *
194
-     * @param string $class
195
-     * @param array  $dependencies
196
-     * @param int    $overwrite
197
-     * @return bool
198
-     */
199
-    public function registerDependencies(
200
-        $class,
201
-        array $dependencies,
202
-        $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
203
-    ) {
204
-        $class = trim($class, '\\');
205
-        $registered = false;
206
-        if (empty(self::$_instance->_dependency_map[ $class ])) {
207
-            self::$_instance->_dependency_map[ $class ] = array();
208
-        }
209
-        // we need to make sure that any aliases used when registering a dependency
210
-        // get resolved to the correct class name
211
-        foreach ($dependencies as $dependency => $load_source) {
212
-            $alias = self::$_instance->getFqnForAlias($dependency);
213
-            if ($overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
214
-                || ! isset(self::$_instance->_dependency_map[ $class ][ $alias ])
215
-            ) {
216
-                unset($dependencies[ $dependency ]);
217
-                $dependencies[ $alias ] = $load_source;
218
-                $registered = true;
219
-            }
220
-        }
221
-        // now add our two lists of dependencies together.
222
-        // using Union (+=) favours the arrays in precedence from left to right,
223
-        // so $dependencies is NOT overwritten because it is listed first
224
-        // ie: with A = B + C, entries in B take precedence over duplicate entries in C
225
-        // Union is way faster than array_merge() but should be used with caution...
226
-        // especially with numerically indexed arrays
227
-        $dependencies += self::$_instance->_dependency_map[ $class ];
228
-        // now we need to ensure that the resulting dependencies
229
-        // array only has the entries that are required for the class
230
-        // so first count how many dependencies were originally registered for the class
231
-        $dependency_count = count(self::$_instance->_dependency_map[ $class ]);
232
-        // if that count is non-zero (meaning dependencies were already registered)
233
-        self::$_instance->_dependency_map[ $class ] = $dependency_count
234
-            // then truncate the  final array to match that count
235
-            ? array_slice($dependencies, 0, $dependency_count)
236
-            // otherwise just take the incoming array because nothing previously existed
237
-            : $dependencies;
238
-        return $registered;
239
-    }
240
-
241
-
242
-    /**
243
-     * @param string $class_name
244
-     * @param string $loader
245
-     * @return bool
246
-     * @throws DomainException
247
-     */
248
-    public static function register_class_loader($class_name, $loader = 'load_core')
249
-    {
250
-        if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
251
-            throw new DomainException(
252
-                esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
253
-            );
254
-        }
255
-        // check that loader is callable or method starts with "load_" and exists in EE_Registry
256
-        if (! is_callable($loader)
257
-            && (
258
-                strpos($loader, 'load_') !== 0
259
-                || ! method_exists('EE_Registry', $loader)
260
-            )
261
-        ) {
262
-            throw new DomainException(
263
-                sprintf(
264
-                    esc_html__(
265
-                        '"%1$s" is not a valid loader method on EE_Registry.',
266
-                        'event_espresso'
267
-                    ),
268
-                    $loader
269
-                )
270
-            );
271
-        }
272
-        $class_name = self::$_instance->getFqnForAlias($class_name);
273
-        if (! isset(self::$_instance->_class_loaders[ $class_name ])) {
274
-            self::$_instance->_class_loaders[ $class_name ] = $loader;
275
-            return true;
276
-        }
277
-        return false;
278
-    }
279
-
280
-
281
-    /**
282
-     * @return array
283
-     */
284
-    public function dependency_map()
285
-    {
286
-        return $this->_dependency_map;
287
-    }
288
-
289
-
290
-    /**
291
-     * returns TRUE if dependency map contains a listing for the provided class name
292
-     *
293
-     * @param string $class_name
294
-     * @return boolean
295
-     */
296
-    public function has($class_name = '')
297
-    {
298
-        // all legacy models have the same dependencies
299
-        if (strpos($class_name, 'EEM_') === 0) {
300
-            $class_name = 'LEGACY_MODELS';
301
-        }
302
-        return isset($this->_dependency_map[ $class_name ]) ? true : false;
303
-    }
304
-
305
-
306
-    /**
307
-     * returns TRUE if dependency map contains a listing for the provided class name AND dependency
308
-     *
309
-     * @param string $class_name
310
-     * @param string $dependency
311
-     * @return bool
312
-     */
313
-    public function has_dependency_for_class($class_name = '', $dependency = '')
314
-    {
315
-        // all legacy models have the same dependencies
316
-        if (strpos($class_name, 'EEM_') === 0) {
317
-            $class_name = 'LEGACY_MODELS';
318
-        }
319
-        $dependency = $this->getFqnForAlias($dependency, $class_name);
320
-        return isset($this->_dependency_map[ $class_name ][ $dependency ])
321
-            ? true
322
-            : false;
323
-    }
324
-
325
-
326
-    /**
327
-     * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
328
-     *
329
-     * @param string $class_name
330
-     * @param string $dependency
331
-     * @return int
332
-     */
333
-    public function loading_strategy_for_class_dependency($class_name = '', $dependency = '')
334
-    {
335
-        // all legacy models have the same dependencies
336
-        if (strpos($class_name, 'EEM_') === 0) {
337
-            $class_name = 'LEGACY_MODELS';
338
-        }
339
-        $dependency = $this->getFqnForAlias($dependency);
340
-        return $this->has_dependency_for_class($class_name, $dependency)
341
-            ? $this->_dependency_map[ $class_name ][ $dependency ]
342
-            : EE_Dependency_Map::not_registered;
343
-    }
344
-
345
-
346
-    /**
347
-     * @param string $class_name
348
-     * @return string | Closure
349
-     */
350
-    public function class_loader($class_name)
351
-    {
352
-        // all legacy models use load_model()
353
-        if (strpos($class_name, 'EEM_') === 0) {
354
-            return 'load_model';
355
-        }
356
-        // EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
357
-        // perform strpos() first to avoid loading regex every time we load a class
358
-        if (strpos($class_name, 'EE_CPT_') === 0
359
-            && preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
360
-        ) {
361
-            return 'load_core';
362
-        }
363
-        $class_name = $this->getFqnForAlias($class_name);
364
-        return isset($this->_class_loaders[ $class_name ]) ? $this->_class_loaders[ $class_name ] : '';
365
-    }
366
-
367
-
368
-    /**
369
-     * @return array
370
-     */
371
-    public function class_loaders()
372
-    {
373
-        return $this->_class_loaders;
374
-    }
375
-
376
-
377
-    /**
378
-     * adds an alias for a classname
379
-     *
380
-     * @param string $fqcn      the class name that should be used (concrete class to replace interface)
381
-     * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
382
-     * @param string $for_class the class that has the dependency (is type hinting for the interface)
383
-     */
384
-    public function add_alias($fqcn, $alias, $for_class = '')
385
-    {
386
-        $this->class_cache->addAlias($fqcn, $alias, $for_class);
387
-    }
388
-
389
-
390
-    /**
391
-     * Returns TRUE if the provided fully qualified name IS an alias
392
-     * WHY?
393
-     * Because if a class is type hinting for a concretion,
394
-     * then why would we need to find another class to supply it?
395
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
396
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
397
-     * Don't go looking for some substitute.
398
-     * Whereas if a class is type hinting for an interface...
399
-     * then we need to find an actual class to use.
400
-     * So the interface IS the alias for some other FQN,
401
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
402
-     * represents some other class.
403
-     *
404
-     * @param string $fqn
405
-     * @param string $for_class
406
-     * @return bool
407
-     */
408
-    public function isAlias($fqn = '', $for_class = '')
409
-    {
410
-        return $this->class_cache->isAlias($fqn, $for_class);
411
-    }
412
-
413
-
414
-    /**
415
-     * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
416
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
417
-     *  for example:
418
-     *      if the following two entries were added to the _aliases array:
419
-     *          array(
420
-     *              'interface_alias'           => 'some\namespace\interface'
421
-     *              'some\namespace\interface'  => 'some\namespace\classname'
422
-     *          )
423
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
424
-     *      to load an instance of 'some\namespace\classname'
425
-     *
426
-     * @param string $alias
427
-     * @param string $for_class
428
-     * @return string
429
-     */
430
-    public function getFqnForAlias($alias = '', $for_class = '')
431
-    {
432
-        return (string) $this->class_cache->getFqnForAlias($alias, $for_class);
433
-    }
434
-
435
-
436
-    /**
437
-     * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
438
-     * if one exists, or whether a new object should be generated every time the requested class is loaded.
439
-     * This is done by using the following class constants:
440
-     *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
441
-     *        EE_Dependency_Map::load_new_object - generates a new object every time
442
-     */
443
-    protected function _register_core_dependencies()
444
-    {
445
-        $this->_dependency_map = array(
446
-            'EE_Request_Handler'                                                                                          => array(
447
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
448
-            ),
449
-            'EE_System'                                                                                                   => array(
450
-                'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
451
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
452
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
453
-                'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
454
-            ),
455
-            'EE_Session'                                                                                                  => array(
456
-                'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
457
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
458
-                'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
459
-                'EventEspresso\core\services\session\SessionStartHandler'  => EE_Dependency_Map::load_from_cache,
460
-                'EE_Encryption'                                            => EE_Dependency_Map::load_from_cache,
461
-            ),
462
-            'EE_Cart'                                                                                                     => array(
463
-                'EE_Session' => EE_Dependency_Map::load_from_cache,
464
-            ),
465
-            'EE_Front_Controller'                                                                                         => array(
466
-                'EE_Registry'              => EE_Dependency_Map::load_from_cache,
467
-                'EE_Request_Handler'       => EE_Dependency_Map::load_from_cache,
468
-                'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
469
-            ),
470
-            'EE_Messenger_Collection_Loader'                                                                              => array(
471
-                'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
472
-            ),
473
-            'EE_Message_Type_Collection_Loader'                                                                           => array(
474
-                'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
475
-            ),
476
-            'EE_Message_Resource_Manager'                                                                                 => array(
477
-                'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
478
-                'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
479
-                'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
480
-            ),
481
-            'EE_Message_Factory'                                                                                          => array(
482
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
483
-            ),
484
-            'EE_messages'                                                                                                 => array(
485
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
486
-            ),
487
-            'EE_Messages_Generator'                                                                                       => array(
488
-                'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
489
-                'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
490
-                'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
491
-                'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
492
-            ),
493
-            'EE_Messages_Processor'                                                                                       => array(
494
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
495
-            ),
496
-            'EE_Messages_Queue'                                                                                           => array(
497
-                'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
498
-            ),
499
-            'EE_Messages_Template_Defaults'                                                                               => array(
500
-                'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
501
-                'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
502
-            ),
503
-            'EE_Message_To_Generate_From_Request'                                                                         => array(
504
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
505
-                'EE_Request_Handler'          => EE_Dependency_Map::load_from_cache,
506
-            ),
507
-            'EventEspresso\core\services\commands\CommandBus'                                                             => array(
508
-                'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
509
-            ),
510
-            'EventEspresso\services\commands\CommandHandler'                                                              => array(
511
-                'EE_Registry'         => EE_Dependency_Map::load_from_cache,
512
-                'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
513
-            ),
514
-            'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => array(
515
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
516
-            ),
517
-            'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => array(
518
-                'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
519
-                'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
520
-            ),
521
-            'EventEspresso\core\services\commands\CommandFactory'                                                         => array(
522
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
523
-            ),
524
-            'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => array(
525
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
526
-            ),
527
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => array(
528
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
529
-            ),
530
-            'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => array(
531
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
532
-            ),
533
-            'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => array(
534
-                'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
535
-            ),
536
-            'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => array(
537
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
538
-            ),
539
-            'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => array(
540
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
541
-            ),
542
-            'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => array(
543
-                'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
544
-            ),
545
-            'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => array(
546
-                'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
547
-            ),
548
-            'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => array(
549
-                'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
550
-            ),
551
-            'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => array(
552
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
553
-            ),
554
-            'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => array(
555
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
556
-            ),
557
-            'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => array(
558
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
559
-            ),
560
-            'EventEspresso\core\services\database\TableManager'                                                           => array(
561
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
562
-            ),
563
-            'EE_Data_Migration_Class_Base'                                                                                => array(
564
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
565
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
566
-            ),
567
-            'EE_DMS_Core_4_1_0'                                                                                           => array(
568
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
569
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
570
-            ),
571
-            'EE_DMS_Core_4_2_0'                                                                                           => array(
572
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
573
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
574
-            ),
575
-            'EE_DMS_Core_4_3_0'                                                                                           => array(
576
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
577
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
578
-            ),
579
-            'EE_DMS_Core_4_4_0'                                                                                           => array(
580
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
581
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
582
-            ),
583
-            'EE_DMS_Core_4_5_0'                                                                                           => array(
584
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
585
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
586
-            ),
587
-            'EE_DMS_Core_4_6_0'                                                                                           => array(
588
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
589
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
590
-            ),
591
-            'EE_DMS_Core_4_7_0'                                                                                           => array(
592
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
593
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
594
-            ),
595
-            'EE_DMS_Core_4_8_0'                                                                                           => array(
596
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
597
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
598
-            ),
599
-            'EE_DMS_Core_4_9_0' => array(
600
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
601
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
602
-            ),
603
-            'EE_DMS_Core_4_10_0' => array(
604
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
605
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
606
-                'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
607
-            ),
608
-            'EventEspresso\core\services\assets\I18nRegistry'                                                             => array(
609
-                array(),
610
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
611
-            ),
612
-            'EventEspresso\core\services\assets\Registry'                                                                 => array(
613
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
614
-                'EventEspresso\core\services\assets\I18nRegistry'    => EE_Dependency_Map::load_from_cache,
615
-            ),
616
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => array(
617
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
618
-            ),
619
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => array(
620
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
621
-            ),
622
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => array(
623
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
624
-            ),
625
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => array(
626
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
627
-            ),
628
-            'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => array(
629
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
630
-            ),
631
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => array(
632
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
633
-            ),
634
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => array(
635
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
636
-            ),
637
-            'EventEspresso\core\services\cache\BasicCacheManager'                                                         => array(
638
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
639
-            ),
640
-            'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => array(
641
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
642
-            ),
643
-            'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => array(
644
-                'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
645
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
646
-            ),
647
-            'EventEspresso\core\domain\values\EmailAddress'                                                               => array(
648
-                null,
649
-                'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
650
-            ),
651
-            'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => array(
652
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
653
-            ),
654
-            'LEGACY_MODELS'                                                                                               => array(
655
-                null,
656
-                'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
657
-            ),
658
-            'EE_Module_Request_Router'                                                                                    => array(
659
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
660
-            ),
661
-            'EE_Registration_Processor'                                                                                   => array(
662
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
663
-            ),
664
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => array(
665
-                null,
666
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
667
-                'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
668
-            ),
669
-            'EventEspresso\core\services\licensing\LicenseService'                                                        => array(
670
-                'EventEspresso\core\domain\services\pue\Stats'  => EE_Dependency_Map::load_from_cache,
671
-                'EventEspresso\core\domain\services\pue\Config' => EE_Dependency_Map::load_from_cache,
672
-            ),
673
-            'EE_Admin_Transactions_List_Table'                                                                            => array(
674
-                null,
675
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
676
-            ),
677
-            'EventEspresso\core\domain\services\pue\Stats'                                                                => array(
678
-                'EventEspresso\core\domain\services\pue\Config'        => EE_Dependency_Map::load_from_cache,
679
-                'EE_Maintenance_Mode'                                  => EE_Dependency_Map::load_from_cache,
680
-                'EventEspresso\core\domain\services\pue\StatsGatherer' => EE_Dependency_Map::load_from_cache,
681
-            ),
682
-            'EventEspresso\core\domain\services\pue\Config'                                                               => array(
683
-                'EE_Network_Config' => EE_Dependency_Map::load_from_cache,
684
-                'EE_Config'         => EE_Dependency_Map::load_from_cache,
685
-            ),
686
-            'EventEspresso\core\domain\services\pue\StatsGatherer'                                                        => array(
687
-                'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
688
-                'EEM_Event'          => EE_Dependency_Map::load_from_cache,
689
-                'EEM_Datetime'       => EE_Dependency_Map::load_from_cache,
690
-                'EEM_Ticket'         => EE_Dependency_Map::load_from_cache,
691
-                'EEM_Registration'   => EE_Dependency_Map::load_from_cache,
692
-                'EEM_Transaction'    => EE_Dependency_Map::load_from_cache,
693
-                'EE_Config'          => EE_Dependency_Map::load_from_cache,
694
-            ),
695
-            'EventEspresso\core\domain\services\admin\ExitModal'                                                          => array(
696
-                'EventEspresso\core\services\assets\Registry' => EE_Dependency_Map::load_from_cache,
697
-            ),
698
-            'EventEspresso\core\domain\services\admin\PluginUpsells'                                                      => array(
699
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
700
-            ),
701
-            'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => array(
702
-                'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
703
-                'EE_Session'             => EE_Dependency_Map::load_from_cache,
704
-            ),
705
-            'EventEspresso\caffeinated\modules\recaptcha_invisible\RecaptchaAdminSettings'                                => array(
706
-                'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
707
-            ),
708
-            'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => array(
709
-                'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
710
-                'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
711
-                'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
712
-                'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
713
-                'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
714
-            ),
715
-            'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => array(
716
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
717
-            ),
718
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => array(
719
-                'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
720
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
721
-            ),
722
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => array(
723
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
724
-            ),
725
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => array(
726
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
727
-            ),
728
-            'EE_CPT_Strategy'                                                                                             => array(
729
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
730
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
731
-            ),
732
-            'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => array(
733
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
734
-            ),
735
-            'EventEspresso\core\domain\services\assets\CoreAssetManager'                                                  => array(
736
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
737
-                'EE_Currency_Config'                                 => EE_Dependency_Map::load_from_cache,
738
-                'EE_Template_Config'                                 => EE_Dependency_Map::load_from_cache,
739
-                'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
740
-                'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
741
-            ),
742
-            'EventEspresso\core\domain\services\admin\privacy\policy\PrivacyPolicy' => array(
743
-                'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
744
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache
745
-            ),
746
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendee' => array(
747
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
748
-            ),
749
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendeeBillingData' => array(
750
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
751
-                'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache
752
-            ),
753
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportCheckins' => array(
754
-                'EEM_Checkin' => EE_Dependency_Map::load_from_cache,
755
-            ),
756
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportRegistration' => array(
757
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache,
758
-            ),
759
-            'EventEspresso\core\domain\services\admin\privacy\export\ExportTransaction' => array(
760
-                'EEM_Transaction' => EE_Dependency_Map::load_from_cache,
761
-            ),
762
-            'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAttendeeData' => array(
763
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
764
-            ),
765
-            'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAnswers' => array(
766
-                'EEM_Answer' => EE_Dependency_Map::load_from_cache,
767
-                'EEM_Question' => EE_Dependency_Map::load_from_cache,
768
-            ),
769
-            'EventEspresso\core\CPTs\CptQueryModifier' => array(
770
-                null,
771
-                null,
772
-                null,
773
-                'EE_Request_Handler'                          => EE_Dependency_Map::load_from_cache,
774
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
775
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
776
-            ),
777
-            'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler' => array(
778
-                'EE_Registry' => EE_Dependency_Map::load_from_cache,
779
-                'EE_Config' => EE_Dependency_Map::load_from_cache
780
-            ),
781
-            'EventEspresso\core\services\editor\BlockRegistrationManager'                                                 => array(
782
-                'EventEspresso\core\services\assets\BlockAssetManagerCollection' => EE_Dependency_Map::load_from_cache,
783
-                'EventEspresso\core\domain\entities\editor\BlockCollection'      => EE_Dependency_Map::load_from_cache,
784
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => EE_Dependency_Map::load_from_cache,
785
-                'EventEspresso\core\services\request\Request'                    => EE_Dependency_Map::load_from_cache,
786
-            ),
787
-            'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => array(
788
-                'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
789
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
790
-                'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
791
-            ),
792
-            'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => array(
793
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
794
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
795
-            ),
796
-            'EventEspresso\core\domain\entities\editor\blocks\EventAttendees' => array(
797
-                'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => self::load_from_cache,
798
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
799
-                'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => self::load_from_cache,
800
-            ),
801
-            'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => array(
802
-                'EventEspresso\core\services\container\Mirror' => EE_Dependency_Map::load_from_cache,
803
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
804
-                'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
805
-            ),
806
-            'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => array(
807
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
808
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
809
-            ),
810
-            'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => array(
811
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
812
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => EE_Dependency_Map::load_from_cache,
813
-            ),
814
-            'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => array(
815
-                'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => EE_Dependency_Map::load_from_cache
816
-            ),
817
-            'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => array(
818
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
819
-            ),
820
-            'EventEspresso\core\libraries\rest_api\controllers\model\Read' => array(
821
-                'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => EE_Dependency_Map::load_from_cache
822
-            ),
823
-            'EventEspresso\core\libraries\rest_api\calculations\Datetime' => array(
824
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
825
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache
826
-            ),
827
-            'EventEspresso\core\libraries\rest_api\calculations\Event' => array(
828
-                'EEM_Event' => EE_Dependency_Map::load_from_cache,
829
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache
830
-            ),
831
-            'EventEspresso\core\libraries\rest_api\calculations\Registration' => array(
832
-                'EEM_Registration' => EE_Dependency_Map::load_from_cache
833
-            ),
834
-            'EventEspresso\core\services\session\SessionStartHandler' => array(
835
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
836
-            ),
837
-            'EE_URL_Validation_Strategy' => array(
838
-                null,
839
-                null,
840
-                'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache
841
-            ),
842
-            'EventEspresso\admin_pages\general_settings\OrganizationSettings' => array(
843
-                'EE_Registry'                                             => EE_Dependency_Map::load_from_cache,
844
-                'EE_Organization_Config'                                  => EE_Dependency_Map::load_from_cache,
845
-                'EE_Core_Config'                                          => EE_Dependency_Map::load_from_cache,
846
-                'EE_Network_Core_Config'                                  => EE_Dependency_Map::load_from_cache,
847
-                'EventEspresso\core\services\address\CountrySubRegionDao' => EE_Dependency_Map::load_from_cache,
848
-            ),
849
-            'EventEspresso\core\services\address\CountrySubRegionDao' => array(
850
-                'EEM_State'                                            => EE_Dependency_Map::load_from_cache,
851
-                'EventEspresso\core\services\validators\JsonValidator' => EE_Dependency_Map::load_from_cache
852
-            ),
853
-            'EventEspresso\core\domain\services\admin\ajax\WordpressHeartbeat' => array(
854
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
855
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
856
-            ),
857
-            'EventEspresso\core\domain\services\admin\ajax\EventEditorHeartbeat' => array(
858
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
859
-                'EE_Environment_Config'            => EE_Dependency_Map::load_from_cache,
860
-            ),
861
-            'EventEspresso\core\services\request\files\FilesDataHandler' => array(
862
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
863
-            ),
864
-            'EventEspressoBatchRequest\BatchRequestProcessor' => [
865
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
866
-            ]
867
-        );
868
-    }
869
-
870
-
871
-    /**
872
-     * Registers how core classes are loaded.
873
-     * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
874
-     *        'EE_Request_Handler' => 'load_core'
875
-     *        'EE_Messages_Queue'  => 'load_lib'
876
-     *        'EEH_Debug_Tools'    => 'load_helper'
877
-     * or, if greater control is required, by providing a custom closure. For example:
878
-     *        'Some_Class' => function () {
879
-     *            return new Some_Class();
880
-     *        },
881
-     * This is required for instantiating dependencies
882
-     * where an interface has been type hinted in a class constructor. For example:
883
-     *        'Required_Interface' => function () {
884
-     *            return new A_Class_That_Implements_Required_Interface();
885
-     *        },
886
-     */
887
-    protected function _register_core_class_loaders()
888
-    {
889
-        $this->_class_loaders = array(
890
-            // load_core
891
-            'EE_Dependency_Map'                            => function () {
892
-                return $this;
893
-            },
894
-            'EE_Capabilities'                              => 'load_core',
895
-            'EE_Encryption'                                => 'load_core',
896
-            'EE_Front_Controller'                          => 'load_core',
897
-            'EE_Module_Request_Router'                     => 'load_core',
898
-            'EE_Registry'                                  => 'load_core',
899
-            'EE_Request'                                   => function () {
900
-                return $this->legacy_request;
901
-            },
902
-            'EventEspresso\core\services\request\Request'  => function () {
903
-                return $this->request;
904
-            },
905
-            'EventEspresso\core\services\request\Response' => function () {
906
-                return $this->response;
907
-            },
908
-            'EE_Base'                                      => 'load_core',
909
-            'EE_Request_Handler'                           => 'load_core',
910
-            'EE_Session'                                   => 'load_core',
911
-            'EE_Cron_Tasks'                                => 'load_core',
912
-            'EE_System'                                    => 'load_core',
913
-            'EE_Maintenance_Mode'                          => 'load_core',
914
-            'EE_Register_CPTs'                             => 'load_core',
915
-            'EE_Admin'                                     => 'load_core',
916
-            'EE_CPT_Strategy'                              => 'load_core',
917
-            // load_class
918
-            'EE_Registration_Processor'                    => 'load_class',
919
-            // load_lib
920
-            'EE_Message_Resource_Manager'                  => 'load_lib',
921
-            'EE_Message_Type_Collection'                   => 'load_lib',
922
-            'EE_Message_Type_Collection_Loader'            => 'load_lib',
923
-            'EE_Messenger_Collection'                      => 'load_lib',
924
-            'EE_Messenger_Collection_Loader'               => 'load_lib',
925
-            'EE_Messages_Processor'                        => 'load_lib',
926
-            'EE_Message_Repository'                        => 'load_lib',
927
-            'EE_Messages_Queue'                            => 'load_lib',
928
-            'EE_Messages_Data_Handler_Collection'          => 'load_lib',
929
-            'EE_Message_Template_Group_Collection'         => 'load_lib',
930
-            'EE_Payment_Method_Manager'                    => 'load_lib',
931
-            'EE_DMS_Core_4_1_0'                            => 'load_dms',
932
-            'EE_DMS_Core_4_2_0'                            => 'load_dms',
933
-            'EE_DMS_Core_4_3_0'                            => 'load_dms',
934
-            'EE_DMS_Core_4_5_0'                            => 'load_dms',
935
-            'EE_DMS_Core_4_6_0'                            => 'load_dms',
936
-            'EE_DMS_Core_4_7_0'                            => 'load_dms',
937
-            'EE_DMS_Core_4_8_0'                            => 'load_dms',
938
-            'EE_DMS_Core_4_9_0'                            => 'load_dms',
939
-            'EE_DMS_Core_4_10_0'                            => 'load_dms',
940
-            'EE_Messages_Generator'                        => function () {
941
-                return EE_Registry::instance()->load_lib(
942
-                    'Messages_Generator',
943
-                    array(),
944
-                    false,
945
-                    false
946
-                );
947
-            },
948
-            'EE_Messages_Template_Defaults'                => function ($arguments = array()) {
949
-                return EE_Registry::instance()->load_lib(
950
-                    'Messages_Template_Defaults',
951
-                    $arguments,
952
-                    false,
953
-                    false
954
-                );
955
-            },
956
-            // load_helper
957
-            'EEH_Parse_Shortcodes'                         => function () {
958
-                if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
959
-                    return new EEH_Parse_Shortcodes();
960
-                }
961
-                return null;
962
-            },
963
-            'EE_Template_Config'                           => function () {
964
-                return EE_Config::instance()->template_settings;
965
-            },
966
-            'EE_Currency_Config'                           => function () {
967
-                return EE_Config::instance()->currency;
968
-            },
969
-            'EE_Registration_Config'                       => function () {
970
-                return EE_Config::instance()->registration;
971
-            },
972
-            'EE_Core_Config'                               => function () {
973
-                return EE_Config::instance()->core;
974
-            },
975
-            'EventEspresso\core\services\loaders\Loader'   => function () {
976
-                return LoaderFactory::getLoader();
977
-            },
978
-            'EE_Network_Config'                            => function () {
979
-                return EE_Network_Config::instance();
980
-            },
981
-            'EE_Config'                                    => function () {
982
-                return EE_Config::instance();
983
-            },
984
-            'EventEspresso\core\domain\Domain'             => function () {
985
-                return DomainFactory::getEventEspressoCoreDomain();
986
-            },
987
-            'EE_Admin_Config'                              => function () {
988
-                return EE_Config::instance()->admin;
989
-            },
990
-            'EE_Organization_Config'                       => function () {
991
-                return EE_Config::instance()->organization;
992
-            },
993
-            'EE_Network_Core_Config'                       => function () {
994
-                return EE_Network_Config::instance()->core;
995
-            },
996
-            'EE_Environment_Config'                        => function () {
997
-                return EE_Config::instance()->environment;
998
-            },
999
-        );
1000
-    }
1001
-
1002
-
1003
-    /**
1004
-     * can be used for supplying alternate names for classes,
1005
-     * or for connecting interface names to instantiable classes
1006
-     */
1007
-    protected function _register_core_aliases()
1008
-    {
1009
-        $aliases = array(
1010
-            'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
1011
-            'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
1012
-            'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
1013
-            'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1014
-            'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1015
-            'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1016
-            'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1017
-            'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1018
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1019
-            'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1020
-            'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1021
-            'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
1022
-            'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
1023
-            'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1024
-            'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1025
-            'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
1026
-            'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
1027
-            'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
1028
-            'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1029
-            'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1030
-            'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1031
-            'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1032
-            'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1033
-            'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1034
-            'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1035
-            'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1036
-            'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1037
-            'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1038
-            'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1039
-            'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1040
-            'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1041
-            'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1042
-            'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1043
-            'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1044
-            'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1045
-            'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1046
-            'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1047
-            'Registration_Processor'                                                       => 'EE_Registration_Processor',
1048
-        );
1049
-        foreach ($aliases as $alias => $fqn) {
1050
-            if (is_array($fqn)) {
1051
-                foreach ($fqn as $class => $for_class) {
1052
-                    $this->class_cache->addAlias($class, $alias, $for_class);
1053
-                }
1054
-                continue;
1055
-            }
1056
-            $this->class_cache->addAlias($fqn, $alias);
1057
-        }
1058
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1059
-            $this->class_cache->addAlias(
1060
-                'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1061
-                'EventEspresso\core\services\notices\NoticeConverterInterface'
1062
-            );
1063
-        }
1064
-    }
1065
-
1066
-
1067
-    /**
1068
-     * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1069
-     * request Primarily used by unit tests.
1070
-     */
1071
-    public function reset()
1072
-    {
1073
-        $this->_register_core_class_loaders();
1074
-        $this->_register_core_dependencies();
1075
-    }
1076
-
1077
-
1078
-    /**
1079
-     * PLZ NOTE: a better name for this method would be is_alias()
1080
-     * because it returns TRUE if the provided fully qualified name IS an alias
1081
-     * WHY?
1082
-     * Because if a class is type hinting for a concretion,
1083
-     * then why would we need to find another class to supply it?
1084
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1085
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1086
-     * Don't go looking for some substitute.
1087
-     * Whereas if a class is type hinting for an interface...
1088
-     * then we need to find an actual class to use.
1089
-     * So the interface IS the alias for some other FQN,
1090
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1091
-     * represents some other class.
1092
-     *
1093
-     * @deprecated 4.9.62.p
1094
-     * @param string $fqn
1095
-     * @param string $for_class
1096
-     * @return bool
1097
-     */
1098
-    public function has_alias($fqn = '', $for_class = '')
1099
-    {
1100
-        return $this->isAlias($fqn, $for_class);
1101
-    }
1102
-
1103
-
1104
-    /**
1105
-     * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1106
-     * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1107
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
1108
-     *  for example:
1109
-     *      if the following two entries were added to the _aliases array:
1110
-     *          array(
1111
-     *              'interface_alias'           => 'some\namespace\interface'
1112
-     *              'some\namespace\interface'  => 'some\namespace\classname'
1113
-     *          )
1114
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1115
-     *      to load an instance of 'some\namespace\classname'
1116
-     *
1117
-     * @deprecated 4.9.62.p
1118
-     * @param string $alias
1119
-     * @param string $for_class
1120
-     * @return string
1121
-     */
1122
-    public function get_alias($alias = '', $for_class = '')
1123
-    {
1124
-        return $this->getFqnForAlias($alias, $for_class);
1125
-    }
23
+	/**
24
+	 * This means that the requested class dependency is not present in the dependency map
25
+	 */
26
+	const not_registered = 0;
27
+
28
+	/**
29
+	 * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
30
+	 */
31
+	const load_new_object = 1;
32
+
33
+	/**
34
+	 * This instructs class loaders to return a previously instantiated and cached object for the requested class.
35
+	 * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
36
+	 */
37
+	const load_from_cache = 2;
38
+
39
+	/**
40
+	 * When registering a dependency,
41
+	 * this indicates to keep any existing dependencies that already exist,
42
+	 * and simply discard any new dependencies declared in the incoming data
43
+	 */
44
+	const KEEP_EXISTING_DEPENDENCIES = 0;
45
+
46
+	/**
47
+	 * When registering a dependency,
48
+	 * this indicates to overwrite any existing dependencies that already exist using the incoming data
49
+	 */
50
+	const OVERWRITE_DEPENDENCIES = 1;
51
+
52
+
53
+	/**
54
+	 * @type EE_Dependency_Map $_instance
55
+	 */
56
+	protected static $_instance;
57
+
58
+	/**
59
+	 * @var ClassInterfaceCache $class_cache
60
+	 */
61
+	private $class_cache;
62
+
63
+	/**
64
+	 * @type RequestInterface $request
65
+	 */
66
+	protected $request;
67
+
68
+	/**
69
+	 * @type LegacyRequestInterface $legacy_request
70
+	 */
71
+	protected $legacy_request;
72
+
73
+	/**
74
+	 * @type ResponseInterface $response
75
+	 */
76
+	protected $response;
77
+
78
+	/**
79
+	 * @type LoaderInterface $loader
80
+	 */
81
+	protected $loader;
82
+
83
+	/**
84
+	 * @type array $_dependency_map
85
+	 */
86
+	protected $_dependency_map = array();
87
+
88
+	/**
89
+	 * @type array $_class_loaders
90
+	 */
91
+	protected $_class_loaders = array();
92
+
93
+
94
+	/**
95
+	 * EE_Dependency_Map constructor.
96
+	 *
97
+	 * @param ClassInterfaceCache $class_cache
98
+	 */
99
+	protected function __construct(ClassInterfaceCache $class_cache)
100
+	{
101
+		$this->class_cache = $class_cache;
102
+		do_action('EE_Dependency_Map____construct', $this);
103
+	}
104
+
105
+
106
+	/**
107
+	 * @return void
108
+	 */
109
+	public function initialize()
110
+	{
111
+		$this->_register_core_dependencies();
112
+		$this->_register_core_class_loaders();
113
+		$this->_register_core_aliases();
114
+	}
115
+
116
+
117
+	/**
118
+	 * @singleton method used to instantiate class object
119
+	 * @param ClassInterfaceCache|null $class_cache
120
+	 * @return EE_Dependency_Map
121
+	 */
122
+	public static function instance(ClassInterfaceCache $class_cache = null)
123
+	{
124
+		// check if class object is instantiated, and instantiated properly
125
+		if (! self::$_instance instanceof EE_Dependency_Map
126
+			&& $class_cache instanceof ClassInterfaceCache
127
+		) {
128
+			self::$_instance = new EE_Dependency_Map($class_cache);
129
+		}
130
+		return self::$_instance;
131
+	}
132
+
133
+
134
+	/**
135
+	 * @param RequestInterface $request
136
+	 */
137
+	public function setRequest(RequestInterface $request)
138
+	{
139
+		$this->request = $request;
140
+	}
141
+
142
+
143
+	/**
144
+	 * @param LegacyRequestInterface $legacy_request
145
+	 */
146
+	public function setLegacyRequest(LegacyRequestInterface $legacy_request)
147
+	{
148
+		$this->legacy_request = $legacy_request;
149
+	}
150
+
151
+
152
+	/**
153
+	 * @param ResponseInterface $response
154
+	 */
155
+	public function setResponse(ResponseInterface $response)
156
+	{
157
+		$this->response = $response;
158
+	}
159
+
160
+
161
+	/**
162
+	 * @param LoaderInterface $loader
163
+	 */
164
+	public function setLoader(LoaderInterface $loader)
165
+	{
166
+		$this->loader = $loader;
167
+	}
168
+
169
+
170
+	/**
171
+	 * @param string $class
172
+	 * @param array  $dependencies
173
+	 * @param int    $overwrite
174
+	 * @return bool
175
+	 */
176
+	public static function register_dependencies(
177
+		$class,
178
+		array $dependencies,
179
+		$overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
180
+	) {
181
+		return self::$_instance->registerDependencies($class, $dependencies, $overwrite);
182
+	}
183
+
184
+
185
+	/**
186
+	 * Assigns an array of class names and corresponding load sources (new or cached)
187
+	 * to the class specified by the first parameter.
188
+	 * IMPORTANT !!!
189
+	 * The order of elements in the incoming $dependencies array MUST match
190
+	 * the order of the constructor parameters for the class in question.
191
+	 * This is especially important when overriding any existing dependencies that are registered.
192
+	 * the third parameter controls whether any duplicate dependencies are overwritten or not.
193
+	 *
194
+	 * @param string $class
195
+	 * @param array  $dependencies
196
+	 * @param int    $overwrite
197
+	 * @return bool
198
+	 */
199
+	public function registerDependencies(
200
+		$class,
201
+		array $dependencies,
202
+		$overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
203
+	) {
204
+		$class = trim($class, '\\');
205
+		$registered = false;
206
+		if (empty(self::$_instance->_dependency_map[ $class ])) {
207
+			self::$_instance->_dependency_map[ $class ] = array();
208
+		}
209
+		// we need to make sure that any aliases used when registering a dependency
210
+		// get resolved to the correct class name
211
+		foreach ($dependencies as $dependency => $load_source) {
212
+			$alias = self::$_instance->getFqnForAlias($dependency);
213
+			if ($overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
214
+				|| ! isset(self::$_instance->_dependency_map[ $class ][ $alias ])
215
+			) {
216
+				unset($dependencies[ $dependency ]);
217
+				$dependencies[ $alias ] = $load_source;
218
+				$registered = true;
219
+			}
220
+		}
221
+		// now add our two lists of dependencies together.
222
+		// using Union (+=) favours the arrays in precedence from left to right,
223
+		// so $dependencies is NOT overwritten because it is listed first
224
+		// ie: with A = B + C, entries in B take precedence over duplicate entries in C
225
+		// Union is way faster than array_merge() but should be used with caution...
226
+		// especially with numerically indexed arrays
227
+		$dependencies += self::$_instance->_dependency_map[ $class ];
228
+		// now we need to ensure that the resulting dependencies
229
+		// array only has the entries that are required for the class
230
+		// so first count how many dependencies were originally registered for the class
231
+		$dependency_count = count(self::$_instance->_dependency_map[ $class ]);
232
+		// if that count is non-zero (meaning dependencies were already registered)
233
+		self::$_instance->_dependency_map[ $class ] = $dependency_count
234
+			// then truncate the  final array to match that count
235
+			? array_slice($dependencies, 0, $dependency_count)
236
+			// otherwise just take the incoming array because nothing previously existed
237
+			: $dependencies;
238
+		return $registered;
239
+	}
240
+
241
+
242
+	/**
243
+	 * @param string $class_name
244
+	 * @param string $loader
245
+	 * @return bool
246
+	 * @throws DomainException
247
+	 */
248
+	public static function register_class_loader($class_name, $loader = 'load_core')
249
+	{
250
+		if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
251
+			throw new DomainException(
252
+				esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
253
+			);
254
+		}
255
+		// check that loader is callable or method starts with "load_" and exists in EE_Registry
256
+		if (! is_callable($loader)
257
+			&& (
258
+				strpos($loader, 'load_') !== 0
259
+				|| ! method_exists('EE_Registry', $loader)
260
+			)
261
+		) {
262
+			throw new DomainException(
263
+				sprintf(
264
+					esc_html__(
265
+						'"%1$s" is not a valid loader method on EE_Registry.',
266
+						'event_espresso'
267
+					),
268
+					$loader
269
+				)
270
+			);
271
+		}
272
+		$class_name = self::$_instance->getFqnForAlias($class_name);
273
+		if (! isset(self::$_instance->_class_loaders[ $class_name ])) {
274
+			self::$_instance->_class_loaders[ $class_name ] = $loader;
275
+			return true;
276
+		}
277
+		return false;
278
+	}
279
+
280
+
281
+	/**
282
+	 * @return array
283
+	 */
284
+	public function dependency_map()
285
+	{
286
+		return $this->_dependency_map;
287
+	}
288
+
289
+
290
+	/**
291
+	 * returns TRUE if dependency map contains a listing for the provided class name
292
+	 *
293
+	 * @param string $class_name
294
+	 * @return boolean
295
+	 */
296
+	public function has($class_name = '')
297
+	{
298
+		// all legacy models have the same dependencies
299
+		if (strpos($class_name, 'EEM_') === 0) {
300
+			$class_name = 'LEGACY_MODELS';
301
+		}
302
+		return isset($this->_dependency_map[ $class_name ]) ? true : false;
303
+	}
304
+
305
+
306
+	/**
307
+	 * returns TRUE if dependency map contains a listing for the provided class name AND dependency
308
+	 *
309
+	 * @param string $class_name
310
+	 * @param string $dependency
311
+	 * @return bool
312
+	 */
313
+	public function has_dependency_for_class($class_name = '', $dependency = '')
314
+	{
315
+		// all legacy models have the same dependencies
316
+		if (strpos($class_name, 'EEM_') === 0) {
317
+			$class_name = 'LEGACY_MODELS';
318
+		}
319
+		$dependency = $this->getFqnForAlias($dependency, $class_name);
320
+		return isset($this->_dependency_map[ $class_name ][ $dependency ])
321
+			? true
322
+			: false;
323
+	}
324
+
325
+
326
+	/**
327
+	 * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
328
+	 *
329
+	 * @param string $class_name
330
+	 * @param string $dependency
331
+	 * @return int
332
+	 */
333
+	public function loading_strategy_for_class_dependency($class_name = '', $dependency = '')
334
+	{
335
+		// all legacy models have the same dependencies
336
+		if (strpos($class_name, 'EEM_') === 0) {
337
+			$class_name = 'LEGACY_MODELS';
338
+		}
339
+		$dependency = $this->getFqnForAlias($dependency);
340
+		return $this->has_dependency_for_class($class_name, $dependency)
341
+			? $this->_dependency_map[ $class_name ][ $dependency ]
342
+			: EE_Dependency_Map::not_registered;
343
+	}
344
+
345
+
346
+	/**
347
+	 * @param string $class_name
348
+	 * @return string | Closure
349
+	 */
350
+	public function class_loader($class_name)
351
+	{
352
+		// all legacy models use load_model()
353
+		if (strpos($class_name, 'EEM_') === 0) {
354
+			return 'load_model';
355
+		}
356
+		// EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
357
+		// perform strpos() first to avoid loading regex every time we load a class
358
+		if (strpos($class_name, 'EE_CPT_') === 0
359
+			&& preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
360
+		) {
361
+			return 'load_core';
362
+		}
363
+		$class_name = $this->getFqnForAlias($class_name);
364
+		return isset($this->_class_loaders[ $class_name ]) ? $this->_class_loaders[ $class_name ] : '';
365
+	}
366
+
367
+
368
+	/**
369
+	 * @return array
370
+	 */
371
+	public function class_loaders()
372
+	{
373
+		return $this->_class_loaders;
374
+	}
375
+
376
+
377
+	/**
378
+	 * adds an alias for a classname
379
+	 *
380
+	 * @param string $fqcn      the class name that should be used (concrete class to replace interface)
381
+	 * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
382
+	 * @param string $for_class the class that has the dependency (is type hinting for the interface)
383
+	 */
384
+	public function add_alias($fqcn, $alias, $for_class = '')
385
+	{
386
+		$this->class_cache->addAlias($fqcn, $alias, $for_class);
387
+	}
388
+
389
+
390
+	/**
391
+	 * Returns TRUE if the provided fully qualified name IS an alias
392
+	 * WHY?
393
+	 * Because if a class is type hinting for a concretion,
394
+	 * then why would we need to find another class to supply it?
395
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
396
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
397
+	 * Don't go looking for some substitute.
398
+	 * Whereas if a class is type hinting for an interface...
399
+	 * then we need to find an actual class to use.
400
+	 * So the interface IS the alias for some other FQN,
401
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
402
+	 * represents some other class.
403
+	 *
404
+	 * @param string $fqn
405
+	 * @param string $for_class
406
+	 * @return bool
407
+	 */
408
+	public function isAlias($fqn = '', $for_class = '')
409
+	{
410
+		return $this->class_cache->isAlias($fqn, $for_class);
411
+	}
412
+
413
+
414
+	/**
415
+	 * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
416
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
417
+	 *  for example:
418
+	 *      if the following two entries were added to the _aliases array:
419
+	 *          array(
420
+	 *              'interface_alias'           => 'some\namespace\interface'
421
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
422
+	 *          )
423
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
424
+	 *      to load an instance of 'some\namespace\classname'
425
+	 *
426
+	 * @param string $alias
427
+	 * @param string $for_class
428
+	 * @return string
429
+	 */
430
+	public function getFqnForAlias($alias = '', $for_class = '')
431
+	{
432
+		return (string) $this->class_cache->getFqnForAlias($alias, $for_class);
433
+	}
434
+
435
+
436
+	/**
437
+	 * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
438
+	 * if one exists, or whether a new object should be generated every time the requested class is loaded.
439
+	 * This is done by using the following class constants:
440
+	 *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
441
+	 *        EE_Dependency_Map::load_new_object - generates a new object every time
442
+	 */
443
+	protected function _register_core_dependencies()
444
+	{
445
+		$this->_dependency_map = array(
446
+			'EE_Request_Handler'                                                                                          => array(
447
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
448
+			),
449
+			'EE_System'                                                                                                   => array(
450
+				'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
451
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
452
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
453
+				'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
454
+			),
455
+			'EE_Session'                                                                                                  => array(
456
+				'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
457
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
458
+				'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
459
+				'EventEspresso\core\services\session\SessionStartHandler'  => EE_Dependency_Map::load_from_cache,
460
+				'EE_Encryption'                                            => EE_Dependency_Map::load_from_cache,
461
+			),
462
+			'EE_Cart'                                                                                                     => array(
463
+				'EE_Session' => EE_Dependency_Map::load_from_cache,
464
+			),
465
+			'EE_Front_Controller'                                                                                         => array(
466
+				'EE_Registry'              => EE_Dependency_Map::load_from_cache,
467
+				'EE_Request_Handler'       => EE_Dependency_Map::load_from_cache,
468
+				'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
469
+			),
470
+			'EE_Messenger_Collection_Loader'                                                                              => array(
471
+				'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
472
+			),
473
+			'EE_Message_Type_Collection_Loader'                                                                           => array(
474
+				'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
475
+			),
476
+			'EE_Message_Resource_Manager'                                                                                 => array(
477
+				'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
478
+				'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
479
+				'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
480
+			),
481
+			'EE_Message_Factory'                                                                                          => array(
482
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
483
+			),
484
+			'EE_messages'                                                                                                 => array(
485
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
486
+			),
487
+			'EE_Messages_Generator'                                                                                       => array(
488
+				'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
489
+				'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
490
+				'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
491
+				'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
492
+			),
493
+			'EE_Messages_Processor'                                                                                       => array(
494
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
495
+			),
496
+			'EE_Messages_Queue'                                                                                           => array(
497
+				'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
498
+			),
499
+			'EE_Messages_Template_Defaults'                                                                               => array(
500
+				'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
501
+				'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
502
+			),
503
+			'EE_Message_To_Generate_From_Request'                                                                         => array(
504
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
505
+				'EE_Request_Handler'          => EE_Dependency_Map::load_from_cache,
506
+			),
507
+			'EventEspresso\core\services\commands\CommandBus'                                                             => array(
508
+				'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
509
+			),
510
+			'EventEspresso\services\commands\CommandHandler'                                                              => array(
511
+				'EE_Registry'         => EE_Dependency_Map::load_from_cache,
512
+				'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
513
+			),
514
+			'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => array(
515
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
516
+			),
517
+			'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => array(
518
+				'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
519
+				'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
520
+			),
521
+			'EventEspresso\core\services\commands\CommandFactory'                                                         => array(
522
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
523
+			),
524
+			'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => array(
525
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
526
+			),
527
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => array(
528
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
529
+			),
530
+			'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => array(
531
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
532
+			),
533
+			'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => array(
534
+				'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
535
+			),
536
+			'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => array(
537
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
538
+			),
539
+			'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => array(
540
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
541
+			),
542
+			'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => array(
543
+				'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
544
+			),
545
+			'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => array(
546
+				'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
547
+			),
548
+			'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => array(
549
+				'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
550
+			),
551
+			'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => array(
552
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
553
+			),
554
+			'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => array(
555
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
556
+			),
557
+			'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => array(
558
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
559
+			),
560
+			'EventEspresso\core\services\database\TableManager'                                                           => array(
561
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
562
+			),
563
+			'EE_Data_Migration_Class_Base'                                                                                => array(
564
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
565
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
566
+			),
567
+			'EE_DMS_Core_4_1_0'                                                                                           => array(
568
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
569
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
570
+			),
571
+			'EE_DMS_Core_4_2_0'                                                                                           => array(
572
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
573
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
574
+			),
575
+			'EE_DMS_Core_4_3_0'                                                                                           => array(
576
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
577
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
578
+			),
579
+			'EE_DMS_Core_4_4_0'                                                                                           => array(
580
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
581
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
582
+			),
583
+			'EE_DMS_Core_4_5_0'                                                                                           => array(
584
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
585
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
586
+			),
587
+			'EE_DMS_Core_4_6_0'                                                                                           => array(
588
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
589
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
590
+			),
591
+			'EE_DMS_Core_4_7_0'                                                                                           => array(
592
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
593
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
594
+			),
595
+			'EE_DMS_Core_4_8_0'                                                                                           => array(
596
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
597
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
598
+			),
599
+			'EE_DMS_Core_4_9_0' => array(
600
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
601
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
602
+			),
603
+			'EE_DMS_Core_4_10_0' => array(
604
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
605
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
606
+				'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
607
+			),
608
+			'EventEspresso\core\services\assets\I18nRegistry'                                                             => array(
609
+				array(),
610
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
611
+			),
612
+			'EventEspresso\core\services\assets\Registry'                                                                 => array(
613
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
614
+				'EventEspresso\core\services\assets\I18nRegistry'    => EE_Dependency_Map::load_from_cache,
615
+			),
616
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => array(
617
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
618
+			),
619
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => array(
620
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
621
+			),
622
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => array(
623
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
624
+			),
625
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => array(
626
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
627
+			),
628
+			'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => array(
629
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
630
+			),
631
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => array(
632
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
633
+			),
634
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => array(
635
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
636
+			),
637
+			'EventEspresso\core\services\cache\BasicCacheManager'                                                         => array(
638
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
639
+			),
640
+			'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => array(
641
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
642
+			),
643
+			'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => array(
644
+				'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
645
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
646
+			),
647
+			'EventEspresso\core\domain\values\EmailAddress'                                                               => array(
648
+				null,
649
+				'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
650
+			),
651
+			'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => array(
652
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
653
+			),
654
+			'LEGACY_MODELS'                                                                                               => array(
655
+				null,
656
+				'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
657
+			),
658
+			'EE_Module_Request_Router'                                                                                    => array(
659
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
660
+			),
661
+			'EE_Registration_Processor'                                                                                   => array(
662
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
663
+			),
664
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => array(
665
+				null,
666
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
667
+				'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
668
+			),
669
+			'EventEspresso\core\services\licensing\LicenseService'                                                        => array(
670
+				'EventEspresso\core\domain\services\pue\Stats'  => EE_Dependency_Map::load_from_cache,
671
+				'EventEspresso\core\domain\services\pue\Config' => EE_Dependency_Map::load_from_cache,
672
+			),
673
+			'EE_Admin_Transactions_List_Table'                                                                            => array(
674
+				null,
675
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
676
+			),
677
+			'EventEspresso\core\domain\services\pue\Stats'                                                                => array(
678
+				'EventEspresso\core\domain\services\pue\Config'        => EE_Dependency_Map::load_from_cache,
679
+				'EE_Maintenance_Mode'                                  => EE_Dependency_Map::load_from_cache,
680
+				'EventEspresso\core\domain\services\pue\StatsGatherer' => EE_Dependency_Map::load_from_cache,
681
+			),
682
+			'EventEspresso\core\domain\services\pue\Config'                                                               => array(
683
+				'EE_Network_Config' => EE_Dependency_Map::load_from_cache,
684
+				'EE_Config'         => EE_Dependency_Map::load_from_cache,
685
+			),
686
+			'EventEspresso\core\domain\services\pue\StatsGatherer'                                                        => array(
687
+				'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
688
+				'EEM_Event'          => EE_Dependency_Map::load_from_cache,
689
+				'EEM_Datetime'       => EE_Dependency_Map::load_from_cache,
690
+				'EEM_Ticket'         => EE_Dependency_Map::load_from_cache,
691
+				'EEM_Registration'   => EE_Dependency_Map::load_from_cache,
692
+				'EEM_Transaction'    => EE_Dependency_Map::load_from_cache,
693
+				'EE_Config'          => EE_Dependency_Map::load_from_cache,
694
+			),
695
+			'EventEspresso\core\domain\services\admin\ExitModal'                                                          => array(
696
+				'EventEspresso\core\services\assets\Registry' => EE_Dependency_Map::load_from_cache,
697
+			),
698
+			'EventEspresso\core\domain\services\admin\PluginUpsells'                                                      => array(
699
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
700
+			),
701
+			'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => array(
702
+				'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
703
+				'EE_Session'             => EE_Dependency_Map::load_from_cache,
704
+			),
705
+			'EventEspresso\caffeinated\modules\recaptcha_invisible\RecaptchaAdminSettings'                                => array(
706
+				'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
707
+			),
708
+			'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => array(
709
+				'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
710
+				'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
711
+				'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
712
+				'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
713
+				'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
714
+			),
715
+			'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => array(
716
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
717
+			),
718
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => array(
719
+				'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
720
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
721
+			),
722
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => array(
723
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
724
+			),
725
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => array(
726
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
727
+			),
728
+			'EE_CPT_Strategy'                                                                                             => array(
729
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
730
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
731
+			),
732
+			'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => array(
733
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
734
+			),
735
+			'EventEspresso\core\domain\services\assets\CoreAssetManager'                                                  => array(
736
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
737
+				'EE_Currency_Config'                                 => EE_Dependency_Map::load_from_cache,
738
+				'EE_Template_Config'                                 => EE_Dependency_Map::load_from_cache,
739
+				'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
740
+				'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
741
+			),
742
+			'EventEspresso\core\domain\services\admin\privacy\policy\PrivacyPolicy' => array(
743
+				'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache,
744
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache
745
+			),
746
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendee' => array(
747
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
748
+			),
749
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportAttendeeBillingData' => array(
750
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
751
+				'EEM_Payment_Method' => EE_Dependency_Map::load_from_cache
752
+			),
753
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportCheckins' => array(
754
+				'EEM_Checkin' => EE_Dependency_Map::load_from_cache,
755
+			),
756
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportRegistration' => array(
757
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache,
758
+			),
759
+			'EventEspresso\core\domain\services\admin\privacy\export\ExportTransaction' => array(
760
+				'EEM_Transaction' => EE_Dependency_Map::load_from_cache,
761
+			),
762
+			'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAttendeeData' => array(
763
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
764
+			),
765
+			'EventEspresso\core\domain\services\admin\privacy\erasure\EraseAnswers' => array(
766
+				'EEM_Answer' => EE_Dependency_Map::load_from_cache,
767
+				'EEM_Question' => EE_Dependency_Map::load_from_cache,
768
+			),
769
+			'EventEspresso\core\CPTs\CptQueryModifier' => array(
770
+				null,
771
+				null,
772
+				null,
773
+				'EE_Request_Handler'                          => EE_Dependency_Map::load_from_cache,
774
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
775
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
776
+			),
777
+			'EventEspresso\core\domain\services\admin\privacy\forms\PrivacySettingsFormHandler' => array(
778
+				'EE_Registry' => EE_Dependency_Map::load_from_cache,
779
+				'EE_Config' => EE_Dependency_Map::load_from_cache
780
+			),
781
+			'EventEspresso\core\services\editor\BlockRegistrationManager'                                                 => array(
782
+				'EventEspresso\core\services\assets\BlockAssetManagerCollection' => EE_Dependency_Map::load_from_cache,
783
+				'EventEspresso\core\domain\entities\editor\BlockCollection'      => EE_Dependency_Map::load_from_cache,
784
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => EE_Dependency_Map::load_from_cache,
785
+				'EventEspresso\core\services\request\Request'                    => EE_Dependency_Map::load_from_cache,
786
+			),
787
+			'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => array(
788
+				'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
789
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
790
+				'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
791
+			),
792
+			'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => array(
793
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
794
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
795
+			),
796
+			'EventEspresso\core\domain\entities\editor\blocks\EventAttendees' => array(
797
+				'EventEspresso\core\domain\entities\editor\CoreBlocksAssetManager' => self::load_from_cache,
798
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
799
+				'EventEspresso\core\domain\services\blocks\EventAttendeesBlockRenderer' => self::load_from_cache,
800
+			),
801
+			'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => array(
802
+				'EventEspresso\core\services\container\Mirror' => EE_Dependency_Map::load_from_cache,
803
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
804
+				'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
805
+			),
806
+			'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => array(
807
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
808
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
809
+			),
810
+			'EventEspresso\core\services\route_match\RouteMatchSpecificationManager' => array(
811
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
812
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationFactory' => EE_Dependency_Map::load_from_cache,
813
+			),
814
+			'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => array(
815
+				'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => EE_Dependency_Map::load_from_cache
816
+			),
817
+			'EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory' => array(
818
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
819
+			),
820
+			'EventEspresso\core\libraries\rest_api\controllers\model\Read' => array(
821
+				'EventEspresso\core\libraries\rest_api\CalculatedModelFields' => EE_Dependency_Map::load_from_cache
822
+			),
823
+			'EventEspresso\core\libraries\rest_api\calculations\Datetime' => array(
824
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
825
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache
826
+			),
827
+			'EventEspresso\core\libraries\rest_api\calculations\Event' => array(
828
+				'EEM_Event' => EE_Dependency_Map::load_from_cache,
829
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache
830
+			),
831
+			'EventEspresso\core\libraries\rest_api\calculations\Registration' => array(
832
+				'EEM_Registration' => EE_Dependency_Map::load_from_cache
833
+			),
834
+			'EventEspresso\core\services\session\SessionStartHandler' => array(
835
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
836
+			),
837
+			'EE_URL_Validation_Strategy' => array(
838
+				null,
839
+				null,
840
+				'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache
841
+			),
842
+			'EventEspresso\admin_pages\general_settings\OrganizationSettings' => array(
843
+				'EE_Registry'                                             => EE_Dependency_Map::load_from_cache,
844
+				'EE_Organization_Config'                                  => EE_Dependency_Map::load_from_cache,
845
+				'EE_Core_Config'                                          => EE_Dependency_Map::load_from_cache,
846
+				'EE_Network_Core_Config'                                  => EE_Dependency_Map::load_from_cache,
847
+				'EventEspresso\core\services\address\CountrySubRegionDao' => EE_Dependency_Map::load_from_cache,
848
+			),
849
+			'EventEspresso\core\services\address\CountrySubRegionDao' => array(
850
+				'EEM_State'                                            => EE_Dependency_Map::load_from_cache,
851
+				'EventEspresso\core\services\validators\JsonValidator' => EE_Dependency_Map::load_from_cache
852
+			),
853
+			'EventEspresso\core\domain\services\admin\ajax\WordpressHeartbeat' => array(
854
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
855
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
856
+			),
857
+			'EventEspresso\core\domain\services\admin\ajax\EventEditorHeartbeat' => array(
858
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
859
+				'EE_Environment_Config'            => EE_Dependency_Map::load_from_cache,
860
+			),
861
+			'EventEspresso\core\services\request\files\FilesDataHandler' => array(
862
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
863
+			),
864
+			'EventEspressoBatchRequest\BatchRequestProcessor' => [
865
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
866
+			]
867
+		);
868
+	}
869
+
870
+
871
+	/**
872
+	 * Registers how core classes are loaded.
873
+	 * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
874
+	 *        'EE_Request_Handler' => 'load_core'
875
+	 *        'EE_Messages_Queue'  => 'load_lib'
876
+	 *        'EEH_Debug_Tools'    => 'load_helper'
877
+	 * or, if greater control is required, by providing a custom closure. For example:
878
+	 *        'Some_Class' => function () {
879
+	 *            return new Some_Class();
880
+	 *        },
881
+	 * This is required for instantiating dependencies
882
+	 * where an interface has been type hinted in a class constructor. For example:
883
+	 *        'Required_Interface' => function () {
884
+	 *            return new A_Class_That_Implements_Required_Interface();
885
+	 *        },
886
+	 */
887
+	protected function _register_core_class_loaders()
888
+	{
889
+		$this->_class_loaders = array(
890
+			// load_core
891
+			'EE_Dependency_Map'                            => function () {
892
+				return $this;
893
+			},
894
+			'EE_Capabilities'                              => 'load_core',
895
+			'EE_Encryption'                                => 'load_core',
896
+			'EE_Front_Controller'                          => 'load_core',
897
+			'EE_Module_Request_Router'                     => 'load_core',
898
+			'EE_Registry'                                  => 'load_core',
899
+			'EE_Request'                                   => function () {
900
+				return $this->legacy_request;
901
+			},
902
+			'EventEspresso\core\services\request\Request'  => function () {
903
+				return $this->request;
904
+			},
905
+			'EventEspresso\core\services\request\Response' => function () {
906
+				return $this->response;
907
+			},
908
+			'EE_Base'                                      => 'load_core',
909
+			'EE_Request_Handler'                           => 'load_core',
910
+			'EE_Session'                                   => 'load_core',
911
+			'EE_Cron_Tasks'                                => 'load_core',
912
+			'EE_System'                                    => 'load_core',
913
+			'EE_Maintenance_Mode'                          => 'load_core',
914
+			'EE_Register_CPTs'                             => 'load_core',
915
+			'EE_Admin'                                     => 'load_core',
916
+			'EE_CPT_Strategy'                              => 'load_core',
917
+			// load_class
918
+			'EE_Registration_Processor'                    => 'load_class',
919
+			// load_lib
920
+			'EE_Message_Resource_Manager'                  => 'load_lib',
921
+			'EE_Message_Type_Collection'                   => 'load_lib',
922
+			'EE_Message_Type_Collection_Loader'            => 'load_lib',
923
+			'EE_Messenger_Collection'                      => 'load_lib',
924
+			'EE_Messenger_Collection_Loader'               => 'load_lib',
925
+			'EE_Messages_Processor'                        => 'load_lib',
926
+			'EE_Message_Repository'                        => 'load_lib',
927
+			'EE_Messages_Queue'                            => 'load_lib',
928
+			'EE_Messages_Data_Handler_Collection'          => 'load_lib',
929
+			'EE_Message_Template_Group_Collection'         => 'load_lib',
930
+			'EE_Payment_Method_Manager'                    => 'load_lib',
931
+			'EE_DMS_Core_4_1_0'                            => 'load_dms',
932
+			'EE_DMS_Core_4_2_0'                            => 'load_dms',
933
+			'EE_DMS_Core_4_3_0'                            => 'load_dms',
934
+			'EE_DMS_Core_4_5_0'                            => 'load_dms',
935
+			'EE_DMS_Core_4_6_0'                            => 'load_dms',
936
+			'EE_DMS_Core_4_7_0'                            => 'load_dms',
937
+			'EE_DMS_Core_4_8_0'                            => 'load_dms',
938
+			'EE_DMS_Core_4_9_0'                            => 'load_dms',
939
+			'EE_DMS_Core_4_10_0'                            => 'load_dms',
940
+			'EE_Messages_Generator'                        => function () {
941
+				return EE_Registry::instance()->load_lib(
942
+					'Messages_Generator',
943
+					array(),
944
+					false,
945
+					false
946
+				);
947
+			},
948
+			'EE_Messages_Template_Defaults'                => function ($arguments = array()) {
949
+				return EE_Registry::instance()->load_lib(
950
+					'Messages_Template_Defaults',
951
+					$arguments,
952
+					false,
953
+					false
954
+				);
955
+			},
956
+			// load_helper
957
+			'EEH_Parse_Shortcodes'                         => function () {
958
+				if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
959
+					return new EEH_Parse_Shortcodes();
960
+				}
961
+				return null;
962
+			},
963
+			'EE_Template_Config'                           => function () {
964
+				return EE_Config::instance()->template_settings;
965
+			},
966
+			'EE_Currency_Config'                           => function () {
967
+				return EE_Config::instance()->currency;
968
+			},
969
+			'EE_Registration_Config'                       => function () {
970
+				return EE_Config::instance()->registration;
971
+			},
972
+			'EE_Core_Config'                               => function () {
973
+				return EE_Config::instance()->core;
974
+			},
975
+			'EventEspresso\core\services\loaders\Loader'   => function () {
976
+				return LoaderFactory::getLoader();
977
+			},
978
+			'EE_Network_Config'                            => function () {
979
+				return EE_Network_Config::instance();
980
+			},
981
+			'EE_Config'                                    => function () {
982
+				return EE_Config::instance();
983
+			},
984
+			'EventEspresso\core\domain\Domain'             => function () {
985
+				return DomainFactory::getEventEspressoCoreDomain();
986
+			},
987
+			'EE_Admin_Config'                              => function () {
988
+				return EE_Config::instance()->admin;
989
+			},
990
+			'EE_Organization_Config'                       => function () {
991
+				return EE_Config::instance()->organization;
992
+			},
993
+			'EE_Network_Core_Config'                       => function () {
994
+				return EE_Network_Config::instance()->core;
995
+			},
996
+			'EE_Environment_Config'                        => function () {
997
+				return EE_Config::instance()->environment;
998
+			},
999
+		);
1000
+	}
1001
+
1002
+
1003
+	/**
1004
+	 * can be used for supplying alternate names for classes,
1005
+	 * or for connecting interface names to instantiable classes
1006
+	 */
1007
+	protected function _register_core_aliases()
1008
+	{
1009
+		$aliases = array(
1010
+			'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
1011
+			'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
1012
+			'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
1013
+			'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1014
+			'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1015
+			'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1016
+			'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1017
+			'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1018
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1019
+			'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1020
+			'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1021
+			'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
1022
+			'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
1023
+			'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1024
+			'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1025
+			'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
1026
+			'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
1027
+			'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
1028
+			'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1029
+			'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1030
+			'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1031
+			'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1032
+			'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1033
+			'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1034
+			'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1035
+			'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1036
+			'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1037
+			'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1038
+			'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1039
+			'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1040
+			'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1041
+			'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1042
+			'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1043
+			'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1044
+			'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1045
+			'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1046
+			'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1047
+			'Registration_Processor'                                                       => 'EE_Registration_Processor',
1048
+		);
1049
+		foreach ($aliases as $alias => $fqn) {
1050
+			if (is_array($fqn)) {
1051
+				foreach ($fqn as $class => $for_class) {
1052
+					$this->class_cache->addAlias($class, $alias, $for_class);
1053
+				}
1054
+				continue;
1055
+			}
1056
+			$this->class_cache->addAlias($fqn, $alias);
1057
+		}
1058
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1059
+			$this->class_cache->addAlias(
1060
+				'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1061
+				'EventEspresso\core\services\notices\NoticeConverterInterface'
1062
+			);
1063
+		}
1064
+	}
1065
+
1066
+
1067
+	/**
1068
+	 * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1069
+	 * request Primarily used by unit tests.
1070
+	 */
1071
+	public function reset()
1072
+	{
1073
+		$this->_register_core_class_loaders();
1074
+		$this->_register_core_dependencies();
1075
+	}
1076
+
1077
+
1078
+	/**
1079
+	 * PLZ NOTE: a better name for this method would be is_alias()
1080
+	 * because it returns TRUE if the provided fully qualified name IS an alias
1081
+	 * WHY?
1082
+	 * Because if a class is type hinting for a concretion,
1083
+	 * then why would we need to find another class to supply it?
1084
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1085
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1086
+	 * Don't go looking for some substitute.
1087
+	 * Whereas if a class is type hinting for an interface...
1088
+	 * then we need to find an actual class to use.
1089
+	 * So the interface IS the alias for some other FQN,
1090
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1091
+	 * represents some other class.
1092
+	 *
1093
+	 * @deprecated 4.9.62.p
1094
+	 * @param string $fqn
1095
+	 * @param string $for_class
1096
+	 * @return bool
1097
+	 */
1098
+	public function has_alias($fqn = '', $for_class = '')
1099
+	{
1100
+		return $this->isAlias($fqn, $for_class);
1101
+	}
1102
+
1103
+
1104
+	/**
1105
+	 * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1106
+	 * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1107
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
1108
+	 *  for example:
1109
+	 *      if the following two entries were added to the _aliases array:
1110
+	 *          array(
1111
+	 *              'interface_alias'           => 'some\namespace\interface'
1112
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
1113
+	 *          )
1114
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1115
+	 *      to load an instance of 'some\namespace\classname'
1116
+	 *
1117
+	 * @deprecated 4.9.62.p
1118
+	 * @param string $alias
1119
+	 * @param string $for_class
1120
+	 * @return string
1121
+	 */
1122
+	public function get_alias($alias = '', $for_class = '')
1123
+	{
1124
+		return $this->getFqnForAlias($alias, $for_class);
1125
+	}
1126 1126
 }
Please login to merge, or discard this patch.
modules/core_rest_api/EED_Core_Rest_Api.module.php 2 patches
Spacing   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -123,7 +123,7 @@  discard block
 block discarded – undo
123 123
      */
124 124
     protected static function _set_hooks_for_changes()
125 125
     {
126
-        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
126
+        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES.'rest_api'.DS.'changes'), false);
127 127
         foreach ($folder_contents as $classname_in_namespace => $filepath) {
128 128
             // ignore the base parent class
129 129
             // and legacy named classes
@@ -132,7 +132,7 @@  discard block
 block discarded – undo
132 132
             ) {
133 133
                 continue;
134 134
             }
135
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
135
+            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\'.$classname_in_namespace;
136 136
             if (class_exists($full_classname)) {
137 137
                 $instance_of_class = new $full_classname;
138 138
                 if ($instance_of_class instanceof ChangesInBase) {
@@ -177,10 +177,10 @@  discard block
 block discarded – undo
177 177
                      * }
178 178
                      */
179 179
                     // skip route options
180
-                    if (! is_numeric($endpoint_key)) {
180
+                    if ( ! is_numeric($endpoint_key)) {
181 181
                         continue;
182 182
                     }
183
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
183
+                    if ( ! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
184 184
                         throw new EE_Error(
185 185
                             esc_html__(
186 186
                             // @codingStandardsIgnoreStart
@@ -201,7 +201,7 @@  discard block
 block discarded – undo
201 201
                     }
202 202
                     if (isset($data_for_single_endpoint['callback_args'])) {
203 203
                         $callback_args = $data_for_single_endpoint['callback_args'];
204
-                        $single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
204
+                        $single_endpoint_args['callback'] = function(\WP_REST_Request $request) use (
205 205
                             $callback,
206 206
                             $callback_args
207 207
                         ) {
@@ -220,7 +220,7 @@  discard block
 block discarded – undo
220 220
                     $schema_route_data = $data_for_multiple_endpoints['schema'];
221 221
                     $schema_callback = $schema_route_data['schema_callback'];
222 222
                     $callback_args = $schema_route_data['callback_args'];
223
-                    $multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
223
+                    $multiple_endpoint_args['schema'] = function() use ($schema_callback, $callback_args) {
224 224
                         return call_user_func_array(
225 225
                             $schema_callback,
226 226
                             $callback_args
@@ -262,7 +262,7 @@  discard block
 block discarded – undo
262 262
     {
263 263
         // delete the saved EE REST API routes
264 264
         foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
265
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
265
+            delete_option(EED_Core_Rest_Api::saved_routes_option_names.$version);
266 266
         }
267 267
     }
268 268
 
@@ -281,7 +281,7 @@  discard block
 block discarded – undo
281 281
     {
282 282
         $ee_routes = array();
283 283
         foreach (self::versions_served() as $version => $hidden_endpoints) {
284
-            $ee_routes[ self::ee_api_namespace . $version ] = self::_get_ee_route_data_for_version(
284
+            $ee_routes[self::ee_api_namespace.$version] = self::_get_ee_route_data_for_version(
285 285
                 $version,
286 286
                 $hidden_endpoints
287 287
             );
@@ -301,8 +301,8 @@  discard block
 block discarded – undo
301 301
      */
302 302
     protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
303 303
     {
304
-        $ee_routes = get_option(self::saved_routes_option_names . $version, null);
305
-        if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
304
+        $ee_routes = get_option(self::saved_routes_option_names.$version, null);
305
+        if ( ! $ee_routes || EED_Core_Rest_Api::debugMode()) {
306 306
             $ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
307 307
         }
308 308
         return $ee_routes;
@@ -329,7 +329,7 @@  discard block
 block discarded – undo
329 329
                 $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
330 330
             )
331 331
         );
332
-        $option_name = self::saved_routes_option_names . $version;
332
+        $option_name = self::saved_routes_option_names.$version;
333 333
         if (get_option($option_name)) {
334 334
             update_option($option_name, $routes, true);
335 335
         } else {
@@ -374,8 +374,8 @@  discard block
 block discarded – undo
374 374
     {
375 375
         $model_routes = array();
376 376
         foreach (self::versions_served() as $version => $hidden_endpoint) {
377
-            $model_routes[ EED_Core_Rest_Api::ee_api_namespace
378
-                           . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
377
+            $model_routes[EED_Core_Rest_Api::ee_api_namespace
378
+                           . $version] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
379 379
         }
380 380
         return $model_routes;
381 381
     }
@@ -444,13 +444,13 @@  discard block
 block discarded – undo
444 444
         foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
445 445
             $model = \EE_Registry::instance()->load_model($model_name);
446 446
             // if this isn't a valid model then let's skip iterate to the next item in the loop.
447
-            if (! $model instanceof EEM_Base) {
447
+            if ( ! $model instanceof EEM_Base) {
448 448
                 continue;
449 449
             }
450 450
             // yes we could just register one route for ALL models, but then they wouldn't show up in the index
451 451
             $plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
452 452
             $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
453
-            $model_routes[ $plural_model_route ] = array(
453
+            $model_routes[$plural_model_route] = array(
454 454
                 array(
455 455
                     'callback'        => array(
456 456
                         'EventEspresso\core\libraries\rest_api\controllers\model\Read',
@@ -461,7 +461,7 @@  discard block
 block discarded – undo
461 461
                     'hidden_endpoint' => $hidden_endpoint,
462 462
                     'args'            => $this->_get_read_query_params($model, $version),
463 463
                     '_links'          => array(
464
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
464
+                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace.$version.$singular_model_route),
465 465
                     ),
466 466
                 ),
467 467
                 'schema' => array(
@@ -472,7 +472,7 @@  discard block
 block discarded – undo
472 472
                     'callback_args'   => array($version, $model_name),
473 473
                 ),
474 474
             );
475
-            $model_routes[ $singular_model_route ] = array(
475
+            $model_routes[$singular_model_route] = array(
476 476
                 array(
477 477
                     'callback'        => array(
478 478
                         'EventEspresso\core\libraries\rest_api\controllers\model\Read',
@@ -489,7 +489,7 @@  discard block
 block discarded – undo
489 489
                 EED_Core_Rest_Api::should_have_write_endpoints($model),
490 490
                 $model
491 491
             )) {
492
-                $model_routes[ $plural_model_route ][] = array(
492
+                $model_routes[$plural_model_route][] = array(
493 493
                     'callback'        => array(
494 494
                         'EventEspresso\core\libraries\rest_api\controllers\model\Write',
495 495
                         'handleRequestInsert',
@@ -499,8 +499,8 @@  discard block
 block discarded – undo
499 499
                     'hidden_endpoint' => $hidden_endpoint,
500 500
                     'args'            => $this->_get_write_params($model_name, $model_version_info, true),
501 501
                 );
502
-                $model_routes[ $singular_model_route ] = array_merge(
503
-                    $model_routes[ $singular_model_route ],
502
+                $model_routes[$singular_model_route] = array_merge(
503
+                    $model_routes[$singular_model_route],
504 504
                     array(
505 505
                         array(
506 506
                             'callback'        => array(
@@ -531,7 +531,7 @@  discard block
 block discarded – undo
531 531
                     '(?P<id>[^\/]+)',
532 532
                     $relation_obj
533 533
                 );
534
-                $model_routes[ $related_route ] = array(
534
+                $model_routes[$related_route] = array(
535 535
                     array(
536 536
                         'callback'        => array(
537 537
                             'EventEspresso\core\libraries\rest_api\controllers\model\Read',
@@ -544,8 +544,8 @@  discard block
 block discarded – undo
544 544
                     ),
545 545
                 );
546 546
 
547
-                $related_write_route = $related_route . '/' . '(?P<related_id>[^\/]+)';
548
-                $model_routes[ $related_write_route ] = array(
547
+                $related_write_route = $related_route.'/'.'(?P<related_id>[^\/]+)';
548
+                $model_routes[$related_write_route] = array(
549 549
                     array(
550 550
                         'callback'        => array(
551 551
                             'EventEspresso\core\libraries\rest_api\controllers\model\Write',
@@ -598,7 +598,7 @@  discard block
 block discarded – undo
598 598
      */
599 599
     public static function get_entity_route($model, $id)
600 600
     {
601
-        return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
601
+        return EED_Core_Rest_Api::get_collection_route($model).'/'.$id;
602 602
     }
603 603
 
604 604
 
@@ -618,7 +618,7 @@  discard block
 block discarded – undo
618 618
             $relation_obj->get_other_model()->get_this_model_name(),
619 619
             $relation_obj
620 620
         );
621
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
621
+        return EED_Core_Rest_Api::get_entity_route($model, $id).'/'.$related_model_name_endpoint_part;
622 622
     }
623 623
 
624 624
 
@@ -632,7 +632,7 @@  discard block
 block discarded – undo
632 632
      */
633 633
     public static function get_versioned_route_to($relative_route, $version = '4.8.36')
634 634
     {
635
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
635
+        return '/'.EED_Core_Rest_Api::ee_api_namespace.$version.'/'.$relative_route;
636 636
     }
637 637
 
638 638
 
@@ -646,7 +646,7 @@  discard block
 block discarded – undo
646 646
     {
647 647
         $routes = array();
648 648
         foreach (self::versions_served() as $version => $hidden_endpoint) {
649
-            $routes[ self::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
649
+            $routes[self::ee_api_namespace.$version] = $this->_get_rpc_route_data_for_version(
650 650
                 $version,
651 651
                 $hidden_endpoint
652 652
             );
@@ -769,12 +769,12 @@  discard block
 block discarded – undo
769 769
     {
770 770
         // if they're related through a HABTM relation, check for any non-FKs
771 771
         $all_relation_settings = $source_model->relation_settings();
772
-        $relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
772
+        $relation_settings = $all_relation_settings[$related_model->get_this_model_name()];
773 773
         $params = array();
774 774
         if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
775 775
             foreach ($relation_settings->getNonKeyFields() as $field) {
776 776
                 /* @var $field EE_Model_Field_Base */
777
-                $params[ $field->get_name() ] = array(
777
+                $params[$field->get_name()] = array(
778 778
                     'required' => ! $field->is_nullable(),
779 779
                     'default' => ModelDataTranslator::prepareFieldValueForJson($field, $field->get_default_value(), $version),
780 780
                     'type' => $field->getSchemaType(),
@@ -799,7 +799,7 @@  discard block
 block discarded – undo
799 799
     {
800 800
         $default_orderby = array();
801 801
         foreach ($model->get_combined_primary_key_fields() as $key_field) {
802
-            $default_orderby[ $key_field->get_name() ] = 'ASC';
802
+            $default_orderby[$key_field->get_name()] = 'ASC';
803 803
         }
804 804
         return array_merge(
805 805
             $this->_get_response_selection_query_params($model, $version),
@@ -833,7 +833,7 @@  discard block
 block discarded – undo
833 833
                     'type'              => array(
834 834
                         'object',
835 835
                         'string',
836
-                    ),// because we accept a variety of types, WP core validation and sanitization
836
+                    ), // because we accept a variety of types, WP core validation and sanitization
837 837
                     // freaks out. We'll just validate this argument while handling the request
838 838
                     'validate_callback' => null,
839 839
                     'sanitize_callback' => null,
@@ -931,7 +931,7 @@  discard block
 block discarded – undo
931 931
                 $sanitize_callback = null;
932 932
             }
933 933
             $arg_info['sanitize_callback'] = $sanitize_callback;
934
-            $args_info[ $field_name ] = $arg_info;
934
+            $args_info[$field_name] = $arg_info;
935 935
             if ($field_obj instanceof EE_Datetime_Field) {
936 936
                 $gmt_arg_info = $arg_info;
937 937
                 $gmt_arg_info['description'] = sprintf(
@@ -942,7 +942,7 @@  discard block
 block discarded – undo
942 942
                     $field_obj->get_nicename(),
943 943
                     $field_name
944 944
                 );
945
-                $args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
945
+                $args_info[$field_name.'_gmt'] = $gmt_arg_info;
946 946
             }
947 947
         }
948 948
         return $args_info;
@@ -965,16 +965,16 @@  discard block
 block discarded – undo
965 965
     public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
966 966
     {
967 967
         $attributes = $request->get_attributes();
968
-        if (! isset($attributes['args'][ $param ])
969
-            || ! is_array($attributes['args'][ $param ])) {
968
+        if ( ! isset($attributes['args'][$param])
969
+            || ! is_array($attributes['args'][$param])) {
970 970
             $validation_result = true;
971 971
         } else {
972
-            $args = $attributes['args'][ $param ];
972
+            $args = $attributes['args'][$param];
973 973
             if ((
974 974
                     $value === ''
975 975
                     || $value === null
976 976
                 )
977
-                && (! isset($args['required'])
977
+                && ( ! isset($args['required'])
978 978
                     || $args['required'] === false
979 979
                 )
980 980
             ) {
@@ -984,7 +984,7 @@  discard block
 block discarded – undo
984 984
                       && $args['format'] === 'email'
985 985
             ) {
986 986
                 $validation_result = true;
987
-                if (! self::_validate_email($value)) {
987
+                if ( ! self::_validate_email($value)) {
988 988
                     $validation_result = new WP_Error(
989 989
                         'rest_invalid_param',
990 990
                         esc_html__(
@@ -1034,7 +1034,7 @@  discard block
 block discarded – undo
1034 1034
     {
1035 1035
         $config_routes = array();
1036 1036
         foreach (self::versions_served() as $version => $hidden_endpoint) {
1037
-            $config_routes[ self::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1037
+            $config_routes[self::ee_api_namespace.$version] = $this->_get_config_route_data_for_version(
1038 1038
                 $version,
1039 1039
                 $hidden_endpoint
1040 1040
             );
@@ -1089,7 +1089,7 @@  discard block
 block discarded – undo
1089 1089
     {
1090 1090
         $meta_routes = array();
1091 1091
         foreach (self::versions_served() as $version => $hidden_endpoint) {
1092
-            $meta_routes[ self::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1092
+            $meta_routes[self::ee_api_namespace.$version] = $this->_get_meta_route_data_for_version(
1093 1093
                 $version,
1094 1094
                 $hidden_endpoint
1095 1095
             );
@@ -1141,7 +1141,7 @@  discard block
 block discarded – undo
1141 1141
             foreach ($relative_urls as $resource_name => $endpoints) {
1142 1142
                 foreach ($endpoints as $key => $endpoint) {
1143 1143
                     // skip schema and other route options
1144
-                    if (! is_numeric($key)) {
1144
+                    if ( ! is_numeric($key)) {
1145 1145
                         continue;
1146 1146
                     }
1147 1147
                     // by default, hide "hidden_endpoint"s, unless the request indicates
@@ -1150,9 +1150,9 @@  discard block
 block discarded – undo
1150 1150
                     if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1151 1151
                         || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1152 1152
                     ) {
1153
-                        $full_route = '/' . ltrim($namespace, '/');
1154
-                        $full_route .= '/' . ltrim($resource_name, '/');
1155
-                        unset($route_data[ $full_route ]);
1153
+                        $full_route = '/'.ltrim($namespace, '/');
1154
+                        $full_route .= '/'.ltrim($resource_name, '/');
1155
+                        unset($route_data[$full_route]);
1156 1156
                     }
1157 1157
                 }
1158 1158
             }
@@ -1226,19 +1226,19 @@  discard block
 block discarded – undo
1226 1226
 
1227 1227
             if ($key_versioned_endpoint === $latest_version) {
1228 1228
                 // don't hide the latest version in the index
1229
-                $versions_served[ $key_versioned_endpoint ] = false;
1229
+                $versions_served[$key_versioned_endpoint] = false;
1230 1230
             } elseif (version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1231 1231
                 && version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1232 1232
             ) {
1233 1233
                 // include, but hide, previous versions which are still supported
1234
-                $versions_served[ $key_versioned_endpoint ] = true;
1234
+                $versions_served[$key_versioned_endpoint] = true;
1235 1235
             } elseif (apply_filters(
1236 1236
                 'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1237 1237
                 false,
1238 1238
                 $possibly_served_versions
1239 1239
             )) {
1240 1240
                 // if a version is no longer supported, don't include it in index or list of versions served
1241
-                $versions_served[ $key_versioned_endpoint ] = true;
1241
+                $versions_served[$key_versioned_endpoint] = true;
1242 1242
             }
1243 1243
         }
1244 1244
         return $versions_served;
@@ -1296,7 +1296,7 @@  discard block
 block discarded – undo
1296 1296
         $model_names = self::model_names_with_plural_routes($version);
1297 1297
         $collection_routes = array();
1298 1298
         foreach ($model_names as $model_name => $model_class_name) {
1299
-            $collection_routes[ strtolower($model_name) ] = '/' . self::ee_api_namespace . $version . '/'
1299
+            $collection_routes[strtolower($model_name)] = '/'.self::ee_api_namespace.$version.'/'
1300 1300
                                                             . EEH_Inflector::pluralize_and_lower($model_name);
1301 1301
         }
1302 1302
         return $collection_routes;
@@ -1317,9 +1317,9 @@  discard block
 block discarded – undo
1317 1317
             $primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1318 1318
             foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1319 1319
                 if (count($primary_keys) > 1) {
1320
-                    $primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1320
+                    $primary_key_items[strtolower($model_name)][] = $primary_key_name;
1321 1321
                 } else {
1322
-                    $primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1322
+                    $primary_key_items[strtolower($model_name)] = $primary_key_name;
1323 1323
                 }
1324 1324
             }
1325 1325
         }
Please login to merge, or discard this patch.
Indentation   +1329 added lines, -1329 removed lines patch added patch discarded remove patch
@@ -23,1333 +23,1333 @@
 block discarded – undo
23 23
 class EED_Core_Rest_Api extends \EED_Module
24 24
 {
25 25
 
26
-    const ee_api_namespace = Domain::API_NAMESPACE;
27
-
28
-    const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
29
-
30
-    const saved_routes_option_names = 'ee_core_routes';
31
-
32
-    /**
33
-     * string used in _links response bodies to make them globally unique.
34
-     *
35
-     * @see http://v2.wp-api.org/extending/linking/
36
-     */
37
-    const ee_api_link_namespace = 'https://api.eventespresso.com/';
38
-
39
-    /**
40
-     * @var CalculatedModelFields
41
-     */
42
-    protected static $_field_calculator;
43
-
44
-
45
-    /**
46
-     * @return EED_Core_Rest_Api|EED_Module
47
-     */
48
-    public static function instance()
49
-    {
50
-        self::$_field_calculator = LoaderFactory::getLoader()->load('EventEspresso\core\libraries\rest_api\CalculatedModelFields');
51
-        return parent::get_instance(__CLASS__);
52
-    }
53
-
54
-
55
-    /**
56
-     *    set_hooks - for hooking into EE Core, other modules, etc
57
-     *
58
-     * @access    public
59
-     * @return    void
60
-     */
61
-    public static function set_hooks()
62
-    {
63
-        self::set_hooks_both();
64
-    }
65
-
66
-
67
-    /**
68
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
69
-     *
70
-     * @access    public
71
-     * @return    void
72
-     */
73
-    public static function set_hooks_admin()
74
-    {
75
-        self::set_hooks_both();
76
-    }
77
-
78
-
79
-    public static function set_hooks_both()
80
-    {
81
-        add_action('rest_api_init', array('EED_Core_Rest_Api', 'register_routes'), 10);
82
-        add_action('rest_api_init', array('EED_Core_Rest_Api', 'set_hooks_rest_api'), 5);
83
-        add_filter('rest_route_data', array('EED_Core_Rest_Api', 'hide_old_endpoints'), 10, 2);
84
-        add_filter(
85
-            'rest_index',
86
-            array('EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex')
87
-        );
88
-        EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
89
-    }
90
-
91
-
92
-    /**
93
-     * sets up hooks which only need to be included as part of REST API requests;
94
-     * other requests like to the frontend or admin etc don't need them
95
-     *
96
-     * @throws \EE_Error
97
-     */
98
-    public static function set_hooks_rest_api()
99
-    {
100
-        // set hooks which account for changes made to the API
101
-        EED_Core_Rest_Api::_set_hooks_for_changes();
102
-    }
103
-
104
-
105
-    /**
106
-     * public wrapper of _set_hooks_for_changes.
107
-     * Loads all the hooks which make requests to old versions of the API
108
-     * appear the same as they always did
109
-     *
110
-     * @throws EE_Error
111
-     */
112
-    public static function set_hooks_for_changes()
113
-    {
114
-        self::_set_hooks_for_changes();
115
-    }
116
-
117
-
118
-    /**
119
-     * Loads all the hooks which make requests to old versions of the API
120
-     * appear the same as they always did
121
-     *
122
-     * @throws EE_Error
123
-     */
124
-    protected static function _set_hooks_for_changes()
125
-    {
126
-        $folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
127
-        foreach ($folder_contents as $classname_in_namespace => $filepath) {
128
-            // ignore the base parent class
129
-            // and legacy named classes
130
-            if ($classname_in_namespace === 'ChangesInBase'
131
-                || strpos($classname_in_namespace, 'Changes_In_') === 0
132
-            ) {
133
-                continue;
134
-            }
135
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
136
-            if (class_exists($full_classname)) {
137
-                $instance_of_class = new $full_classname;
138
-                if ($instance_of_class instanceof ChangesInBase) {
139
-                    $instance_of_class->setHooks();
140
-                }
141
-            }
142
-        }
143
-    }
144
-
145
-
146
-    /**
147
-     * Filters the WP routes to add our EE-related ones. This takes a bit of time
148
-     * so we actually prefer to only do it when an EE plugin is activated or upgraded
149
-     *
150
-     * @throws \EE_Error
151
-     */
152
-    public static function register_routes()
153
-    {
154
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
155
-            foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
156
-                /**
157
-                 * @var array     $data_for_multiple_endpoints numerically indexed array
158
-                 *                                         but can also contain route options like {
159
-                 * @type array    $schema                      {
160
-                 * @type callable $schema_callback
161
-                 * @type array    $callback_args               arguments that will be passed to the callback, after the
162
-                 * WP_REST_Request of course
163
-                 * }
164
-                 * }
165
-                 */
166
-                // when registering routes, register all the endpoints' data at the same time
167
-                $multiple_endpoint_args = array();
168
-                foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
169
-                    /**
170
-                     * @var array     $data_for_single_endpoint {
171
-                     * @type callable $callback
172
-                     * @type string methods
173
-                     * @type array args
174
-                     * @type array _links
175
-                     * @type array    $callback_args            arguments that will be passed to the callback, after the
176
-                     * WP_REST_Request of course
177
-                     * }
178
-                     */
179
-                    // skip route options
180
-                    if (! is_numeric($endpoint_key)) {
181
-                        continue;
182
-                    }
183
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
184
-                        throw new EE_Error(
185
-                            esc_html__(
186
-                            // @codingStandardsIgnoreStart
187
-                                'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
188
-                                // @codingStandardsIgnoreEnd
189
-                                'event_espresso'
190
-                            )
191
-                        );
192
-                    }
193
-                    $callback = $data_for_single_endpoint['callback'];
194
-                    $single_endpoint_args = array(
195
-                        'methods' => $data_for_single_endpoint['methods'],
196
-                        'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
197
-                            : array(),
198
-                    );
199
-                    if (isset($data_for_single_endpoint['_links'])) {
200
-                        $single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
201
-                    }
202
-                    if (isset($data_for_single_endpoint['callback_args'])) {
203
-                        $callback_args = $data_for_single_endpoint['callback_args'];
204
-                        $single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
205
-                            $callback,
206
-                            $callback_args
207
-                        ) {
208
-                            array_unshift($callback_args, $request);
209
-                            return call_user_func_array(
210
-                                $callback,
211
-                                $callback_args
212
-                            );
213
-                        };
214
-                    } else {
215
-                        $single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
216
-                    }
217
-                    $multiple_endpoint_args[] = $single_endpoint_args;
218
-                }
219
-                if (isset($data_for_multiple_endpoints['schema'])) {
220
-                    $schema_route_data = $data_for_multiple_endpoints['schema'];
221
-                    $schema_callback = $schema_route_data['schema_callback'];
222
-                    $callback_args = $schema_route_data['callback_args'];
223
-                    $multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
224
-                        return call_user_func_array(
225
-                            $schema_callback,
226
-                            $callback_args
227
-                        );
228
-                    };
229
-                }
230
-                register_rest_route(
231
-                    $namespace,
232
-                    $relative_route,
233
-                    $multiple_endpoint_args
234
-                );
235
-            }
236
-        }
237
-    }
238
-
239
-
240
-    /**
241
-     * Checks if there was a version change or something that merits invalidating the cached
242
-     * route data. If so, invalidates the cached route data so that it gets refreshed
243
-     * next time the WP API is used
244
-     */
245
-    public static function invalidate_cached_route_data_on_version_change()
246
-    {
247
-        if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
248
-            EED_Core_Rest_Api::invalidate_cached_route_data();
249
-        }
250
-        foreach (EE_Registry::instance()->addons as $addon) {
251
-            if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
252
-                EED_Core_Rest_Api::invalidate_cached_route_data();
253
-            }
254
-        }
255
-    }
256
-
257
-
258
-    /**
259
-     * Removes the cached route data so it will get refreshed next time the WP API is used
260
-     */
261
-    public static function invalidate_cached_route_data()
262
-    {
263
-        // delete the saved EE REST API routes
264
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
265
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
266
-        }
267
-    }
268
-
269
-
270
-    /**
271
-     * Gets the EE route data
272
-     *
273
-     * @return array top-level key is the namespace, next-level key is the route and its value is array{
274
-     * @throws \EE_Error
275
-     * @type string|array $callback
276
-     * @type string       $methods
277
-     * @type boolean      $hidden_endpoint
278
-     * }
279
-     */
280
-    public static function get_ee_route_data()
281
-    {
282
-        $ee_routes = array();
283
-        foreach (self::versions_served() as $version => $hidden_endpoints) {
284
-            $ee_routes[ self::ee_api_namespace . $version ] = self::_get_ee_route_data_for_version(
285
-                $version,
286
-                $hidden_endpoints
287
-            );
288
-        }
289
-        return $ee_routes;
290
-    }
291
-
292
-
293
-    /**
294
-     * Gets the EE route data from the wp options if it exists already,
295
-     * otherwise re-generates it and saves it to the option
296
-     *
297
-     * @param string  $version
298
-     * @param boolean $hidden_endpoints
299
-     * @return array
300
-     * @throws \EE_Error
301
-     */
302
-    protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
303
-    {
304
-        $ee_routes = get_option(self::saved_routes_option_names . $version, null);
305
-        if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
306
-            $ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
307
-        }
308
-        return $ee_routes;
309
-    }
310
-
311
-
312
-    /**
313
-     * Saves the EE REST API route data to a wp option and returns it
314
-     *
315
-     * @param string  $version
316
-     * @param boolean $hidden_endpoints
317
-     * @return mixed|null
318
-     * @throws \EE_Error
319
-     */
320
-    protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
321
-    {
322
-        $instance = self::instance();
323
-        $routes = apply_filters(
324
-            'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
325
-            array_replace_recursive(
326
-                $instance->_get_config_route_data_for_version($version, $hidden_endpoints),
327
-                $instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
328
-                $instance->_get_model_route_data_for_version($version, $hidden_endpoints),
329
-                $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
330
-            )
331
-        );
332
-        $option_name = self::saved_routes_option_names . $version;
333
-        if (get_option($option_name)) {
334
-            update_option($option_name, $routes, true);
335
-        } else {
336
-            add_option($option_name, $routes, null, 'no');
337
-        }
338
-        return $routes;
339
-    }
340
-
341
-
342
-    /**
343
-     * Calculates all the EE routes and saves it to a WordPress option so we don't
344
-     * need to calculate it on every request
345
-     *
346
-     * @deprecated since version 4.9.1
347
-     * @return void
348
-     */
349
-    public static function save_ee_routes()
350
-    {
351
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
352
-            $instance = self::instance();
353
-            $routes = apply_filters(
354
-                'EED_Core_Rest_Api__save_ee_routes__routes',
355
-                array_replace_recursive(
356
-                    $instance->_register_config_routes(),
357
-                    $instance->_register_meta_routes(),
358
-                    $instance->_register_model_routes(),
359
-                    $instance->_register_rpc_routes()
360
-                )
361
-            );
362
-            update_option(self::saved_routes_option_names, $routes, true);
363
-        }
364
-    }
365
-
366
-
367
-    /**
368
-     * Gets all the route information relating to EE models
369
-     *
370
-     * @return array @see get_ee_route_data
371
-     * @deprecated since version 4.9.1
372
-     */
373
-    protected function _register_model_routes()
374
-    {
375
-        $model_routes = array();
376
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
377
-            $model_routes[ EED_Core_Rest_Api::ee_api_namespace
378
-                           . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
379
-        }
380
-        return $model_routes;
381
-    }
382
-
383
-
384
-    /**
385
-     * Decides whether or not to add write endpoints for this model.
386
-     *
387
-     * Currently, this defaults to exclude all global tables and models
388
-     * which would allow inserting WP core data (we don't want to duplicate
389
-     * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
390
-     *
391
-     * @param EEM_Base $model
392
-     * @return bool
393
-     */
394
-    public static function should_have_write_endpoints(EEM_Base $model)
395
-    {
396
-        if ($model->is_wp_core_model()) {
397
-            return false;
398
-        }
399
-        foreach ($model->get_tables() as $table) {
400
-            if ($table->is_global()) {
401
-                return false;
402
-            }
403
-        }
404
-        return true;
405
-    }
406
-
407
-
408
-    /**
409
-     * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
410
-     * in this versioned namespace of EE4
411
-     *
412
-     * @param $version
413
-     * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
414
-     */
415
-    public static function model_names_with_plural_routes($version)
416
-    {
417
-        $model_version_info = new ModelVersionInfo($version);
418
-        $models_to_register = $model_version_info->modelsForRequestedVersion();
419
-        // let's not bother having endpoints for extra metas
420
-        unset(
421
-            $models_to_register['Extra_Meta'],
422
-            $models_to_register['Extra_Join'],
423
-            $models_to_register['Post_Meta']
424
-        );
425
-        return apply_filters(
426
-            'FHEE__EED_Core_REST_API___register_model_routes',
427
-            $models_to_register
428
-        );
429
-    }
430
-
431
-
432
-    /**
433
-     * Gets the route data for EE models in the specified version
434
-     *
435
-     * @param string  $version
436
-     * @param boolean $hidden_endpoint
437
-     * @return array
438
-     * @throws EE_Error
439
-     */
440
-    protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
441
-    {
442
-        $model_routes = array();
443
-        $model_version_info = new ModelVersionInfo($version);
444
-        foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
445
-            $model = \EE_Registry::instance()->load_model($model_name);
446
-            // if this isn't a valid model then let's skip iterate to the next item in the loop.
447
-            if (! $model instanceof EEM_Base) {
448
-                continue;
449
-            }
450
-            // yes we could just register one route for ALL models, but then they wouldn't show up in the index
451
-            $plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
452
-            $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
453
-            $model_routes[ $plural_model_route ] = array(
454
-                array(
455
-                    'callback'        => array(
456
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
457
-                        'handleRequestGetAll',
458
-                    ),
459
-                    'callback_args'   => array($version, $model_name),
460
-                    'methods'         => WP_REST_Server::READABLE,
461
-                    'hidden_endpoint' => $hidden_endpoint,
462
-                    'args'            => $this->_get_read_query_params($model, $version),
463
-                    '_links'          => array(
464
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
465
-                    ),
466
-                ),
467
-                'schema' => array(
468
-                    'schema_callback' => array(
469
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
470
-                        'handleSchemaRequest',
471
-                    ),
472
-                    'callback_args'   => array($version, $model_name),
473
-                ),
474
-            );
475
-            $model_routes[ $singular_model_route ] = array(
476
-                array(
477
-                    'callback'        => array(
478
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
479
-                        'handleRequestGetOne',
480
-                    ),
481
-                    'callback_args'   => array($version, $model_name),
482
-                    'methods'         => WP_REST_Server::READABLE,
483
-                    'hidden_endpoint' => $hidden_endpoint,
484
-                    'args'            => $this->_get_response_selection_query_params($model, $version, true),
485
-                ),
486
-            );
487
-            if (apply_filters(
488
-                'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
489
-                EED_Core_Rest_Api::should_have_write_endpoints($model),
490
-                $model
491
-            )) {
492
-                $model_routes[ $plural_model_route ][] = array(
493
-                    'callback'        => array(
494
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Write',
495
-                        'handleRequestInsert',
496
-                    ),
497
-                    'callback_args'   => array($version, $model_name),
498
-                    'methods'         => WP_REST_Server::CREATABLE,
499
-                    'hidden_endpoint' => $hidden_endpoint,
500
-                    'args'            => $this->_get_write_params($model_name, $model_version_info, true),
501
-                );
502
-                $model_routes[ $singular_model_route ] = array_merge(
503
-                    $model_routes[ $singular_model_route ],
504
-                    array(
505
-                        array(
506
-                            'callback'        => array(
507
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
508
-                                'handleRequestUpdate',
509
-                            ),
510
-                            'callback_args'   => array($version, $model_name),
511
-                            'methods'         => WP_REST_Server::EDITABLE,
512
-                            'hidden_endpoint' => $hidden_endpoint,
513
-                            'args'            => $this->_get_write_params($model_name, $model_version_info),
514
-                        ),
515
-                        array(
516
-                            'callback'        => array(
517
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
518
-                                'handleRequestDelete',
519
-                            ),
520
-                            'callback_args'   => array($version, $model_name),
521
-                            'methods'         => WP_REST_Server::DELETABLE,
522
-                            'hidden_endpoint' => $hidden_endpoint,
523
-                            'args'            => $this->_get_delete_query_params($model, $version),
524
-                        ),
525
-                    )
526
-                );
527
-            }
528
-            foreach ($model->relation_settings() as $relation_name => $relation_obj) {
529
-                $related_route = EED_Core_Rest_Api::get_relation_route_via(
530
-                    $model,
531
-                    '(?P<id>[^\/]+)',
532
-                    $relation_obj
533
-                );
534
-                $model_routes[ $related_route ] = array(
535
-                    array(
536
-                        'callback'        => array(
537
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Read',
538
-                            'handleRequestGetRelated',
539
-                        ),
540
-                        'callback_args'   => array($version, $model_name, $relation_name),
541
-                        'methods'         => WP_REST_Server::READABLE,
542
-                        'hidden_endpoint' => $hidden_endpoint,
543
-                        'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
544
-                    ),
545
-                );
546
-
547
-                $related_write_route = $related_route . '/' . '(?P<related_id>[^\/]+)';
548
-                $model_routes[ $related_write_route ] = array(
549
-                    array(
550
-                        'callback'        => array(
551
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Write',
552
-                            'handleRequestAddRelation',
553
-                        ),
554
-                        'callback_args'   => array($version, $model_name, $relation_name),
555
-                        'methods'         => WP_REST_Server::EDITABLE,
556
-                        'hidden_endpoint' => $hidden_endpoint,
557
-                        'args'            => $this->_get_add_relation_query_params($model, $relation_obj->get_other_model(), $version)
558
-                    ),
559
-                    array(
560
-                        'callback'        => array(
561
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Write',
562
-                            'handleRequestRemoveRelation',
563
-                        ),
564
-                        'callback_args'   => array($version, $model_name, $relation_name),
565
-                        'methods'         => WP_REST_Server::DELETABLE,
566
-                        'hidden_endpoint' => $hidden_endpoint,
567
-                        'args'            => array()
568
-                    ),
569
-                );
570
-            }
571
-        }
572
-        return $model_routes;
573
-    }
574
-
575
-
576
-    /**
577
-     * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
578
-     * excluding the preceding slash.
579
-     * Eg you pass get_plural_route_to('Event') = 'events'
580
-     *
581
-     * @param EEM_Base $model
582
-     * @return string
583
-     */
584
-    public static function get_collection_route(EEM_Base $model)
585
-    {
586
-        return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
587
-    }
588
-
589
-
590
-    /**
591
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
592
-     * excluding the preceding slash.
593
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
594
-     *
595
-     * @param EEM_Base $model eg Event or Venue
596
-     * @param string   $id
597
-     * @return string
598
-     */
599
-    public static function get_entity_route($model, $id)
600
-    {
601
-        return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
602
-    }
603
-
604
-
605
-    /**
606
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
607
-     * excluding the preceding slash.
608
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
609
-     *
610
-     * @param EEM_Base               $model eg Event or Venue
611
-     * @param string                 $id
612
-     * @param EE_Model_Relation_Base $relation_obj
613
-     * @return string
614
-     */
615
-    public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
616
-    {
617
-        $related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
618
-            $relation_obj->get_other_model()->get_this_model_name(),
619
-            $relation_obj
620
-        );
621
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
622
-    }
623
-
624
-
625
-    /**
626
-     * Adds onto the $relative_route the EE4 REST API versioned namespace.
627
-     * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
628
-     *
629
-     * @param string $relative_route
630
-     * @param string $version
631
-     * @return string
632
-     */
633
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36')
634
-    {
635
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
636
-    }
637
-
638
-
639
-    /**
640
-     * Adds all the RPC-style routes (remote procedure call-like routes, ie
641
-     * routes that don't conform to the traditional REST CRUD-style).
642
-     *
643
-     * @deprecated since 4.9.1
644
-     */
645
-    protected function _register_rpc_routes()
646
-    {
647
-        $routes = array();
648
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
649
-            $routes[ self::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
650
-                $version,
651
-                $hidden_endpoint
652
-            );
653
-        }
654
-        return $routes;
655
-    }
656
-
657
-
658
-    /**
659
-     * @param string  $version
660
-     * @param boolean $hidden_endpoint
661
-     * @return array
662
-     */
663
-    protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
664
-    {
665
-        $this_versions_routes = array();
666
-        // checkin endpoint
667
-        $this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = array(
668
-            array(
669
-                'callback'        => array(
670
-                    'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
671
-                    'handleRequestToggleCheckin',
672
-                ),
673
-                'methods'         => WP_REST_Server::CREATABLE,
674
-                'hidden_endpoint' => $hidden_endpoint,
675
-                'args'            => array(
676
-                    'force' => array(
677
-                        'required'    => false,
678
-                        'default'     => false,
679
-                        'description' => __(
680
-                        // @codingStandardsIgnoreStart
681
-                            'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
682
-                            // @codingStandardsIgnoreEnd
683
-                            'event_espresso'
684
-                        ),
685
-                    ),
686
-                ),
687
-                'callback_args'   => array($version),
688
-            ),
689
-        );
690
-        return apply_filters(
691
-            'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
692
-            $this_versions_routes,
693
-            $version,
694
-            $hidden_endpoint
695
-        );
696
-    }
697
-
698
-
699
-    /**
700
-     * Gets the query params that can be used when request one or many
701
-     *
702
-     * @param EEM_Base $model
703
-     * @param string   $version
704
-     * @return array
705
-     */
706
-    protected function _get_response_selection_query_params(\EEM_Base $model, $version, $single_only = false)
707
-    {
708
-        $query_params = array(
709
-            'include'   => array(
710
-                'required' => false,
711
-                'default'  => '*',
712
-                'type'     => 'string',
713
-            ),
714
-            'calculate' => array(
715
-                'required'          => false,
716
-                'default'           => '',
717
-                'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
718
-                'type'              => 'string',
719
-                // because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
720
-                // freaks out. We'll just validate this argument while handling the request
721
-                'validate_callback' => null,
722
-                'sanitize_callback' => null,
723
-            ),
724
-            'password' => array(
725
-                'required' => false,
726
-                'default' => '',
727
-                'type' => 'string'
728
-            )
729
-        );
730
-        return apply_filters(
731
-            'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
732
-            $query_params,
733
-            $model,
734
-            $version
735
-        );
736
-    }
737
-
738
-
739
-    /**
740
-     * Gets the parameters acceptable for delete requests
741
-     *
742
-     * @param \EEM_Base $model
743
-     * @param string    $version
744
-     * @return array
745
-     */
746
-    protected function _get_delete_query_params(\EEM_Base $model, $version)
747
-    {
748
-        $params_for_delete = array(
749
-            'allow_blocking' => array(
750
-                'required' => false,
751
-                'default'  => true,
752
-                'type'     => 'boolean',
753
-            ),
754
-        );
755
-        $params_for_delete['force'] = array(
756
-            'required' => false,
757
-            'default'  => false,
758
-            'type'     => 'boolean',
759
-        );
760
-        return apply_filters(
761
-            'FHEE__EED_Core_Rest_Api___get_delete_query_params',
762
-            $params_for_delete,
763
-            $model,
764
-            $version
765
-        );
766
-    }
767
-
768
-    protected function _get_add_relation_query_params(\EEM_Base $source_model, \EEM_Base $related_model, $version)
769
-    {
770
-        // if they're related through a HABTM relation, check for any non-FKs
771
-        $all_relation_settings = $source_model->relation_settings();
772
-        $relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
773
-        $params = array();
774
-        if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
775
-            foreach ($relation_settings->getNonKeyFields() as $field) {
776
-                /* @var $field EE_Model_Field_Base */
777
-                $params[ $field->get_name() ] = array(
778
-                    'required' => ! $field->is_nullable(),
779
-                    'default' => ModelDataTranslator::prepareFieldValueForJson($field, $field->get_default_value(), $version),
780
-                    'type' => $field->getSchemaType(),
781
-                    'validate_callbaack' => null,
782
-                    'sanitize_callback' => null
783
-                );
784
-            }
785
-        }
786
-        return $params;
787
-    }
788
-
789
-
790
-    /**
791
-     * Gets info about reading query params that are acceptable
792
-     *
793
-     * @param \EEM_Base $model eg 'Event' or 'Venue'
794
-     * @param  string   $version
795
-     * @return array    describing the args acceptable when querying this model
796
-     * @throws EE_Error
797
-     */
798
-    protected function _get_read_query_params(\EEM_Base $model, $version)
799
-    {
800
-        $default_orderby = array();
801
-        foreach ($model->get_combined_primary_key_fields() as $key_field) {
802
-            $default_orderby[ $key_field->get_name() ] = 'ASC';
803
-        }
804
-        return array_merge(
805
-            $this->_get_response_selection_query_params($model, $version),
806
-            array(
807
-                'where'    => array(
808
-                    'required'          => false,
809
-                    'default'           => array(),
810
-                    'type'              => 'object',
811
-                    // because we accept an almost infinite list of possible where conditions, WP
812
-                    // core validation and sanitization freaks out. We'll just validate this argument
813
-                    // while handling the request
814
-                    'validate_callback' => null,
815
-                    'sanitize_callback' => null,
816
-                ),
817
-                'limit'    => array(
818
-                    'required'          => false,
819
-                    'default'           => EED_Core_Rest_Api::get_default_query_limit(),
820
-                    'type'              => array(
821
-                        'array',
822
-                        'string',
823
-                        'integer',
824
-                    ),
825
-                    // because we accept a variety of types, WP core validation and sanitization
826
-                    // freaks out. We'll just validate this argument while handling the request
827
-                    'validate_callback' => null,
828
-                    'sanitize_callback' => null,
829
-                ),
830
-                'order_by' => array(
831
-                    'required'          => false,
832
-                    'default'           => $default_orderby,
833
-                    'type'              => array(
834
-                        'object',
835
-                        'string',
836
-                    ),// because we accept a variety of types, WP core validation and sanitization
837
-                    // freaks out. We'll just validate this argument while handling the request
838
-                    'validate_callback' => null,
839
-                    'sanitize_callback' => null,
840
-                ),
841
-                'group_by' => array(
842
-                    'required'          => false,
843
-                    'default'           => null,
844
-                    'type'              => array(
845
-                        'object',
846
-                        'string',
847
-                    ),
848
-                    // because we accept  an almost infinite list of possible groupings,
849
-                    // WP core validation and sanitization
850
-                    // freaks out. We'll just validate this argument while handling the request
851
-                    'validate_callback' => null,
852
-                    'sanitize_callback' => null,
853
-                ),
854
-                'having'   => array(
855
-                    'required'          => false,
856
-                    'default'           => null,
857
-                    'type'              => 'object',
858
-                    // because we accept an almost infinite list of possible where conditions, WP
859
-                    // core validation and sanitization freaks out. We'll just validate this argument
860
-                    // while handling the request
861
-                    'validate_callback' => null,
862
-                    'sanitize_callback' => null,
863
-                ),
864
-                'caps'     => array(
865
-                    'required' => false,
866
-                    'default'  => EEM_Base::caps_read,
867
-                    'type'     => 'string',
868
-                    'enum'     => array(
869
-                        EEM_Base::caps_read,
870
-                        EEM_Base::caps_read_admin,
871
-                        EEM_Base::caps_edit,
872
-                        EEM_Base::caps_delete,
873
-                    ),
874
-                ),
875
-            )
876
-        );
877
-    }
878
-
879
-
880
-    /**
881
-     * Gets parameter information for a model regarding writing data
882
-     *
883
-     * @param string           $model_name
884
-     * @param ModelVersionInfo $model_version_info
885
-     * @param boolean          $create                                       whether this is for request to create (in
886
-     *                                                                       which case we need all required params) or
887
-     *                                                                       just to update (in which case we don't
888
-     *                                                                       need those on every request)
889
-     * @return array
890
-     */
891
-    protected function _get_write_params(
892
-        $model_name,
893
-        ModelVersionInfo $model_version_info,
894
-        $create = false
895
-    ) {
896
-        $model = EE_Registry::instance()->load_model($model_name);
897
-        $fields = $model_version_info->fieldsOnModelInThisVersion($model);
898
-        $args_info = array();
899
-        foreach ($fields as $field_name => $field_obj) {
900
-            if ($field_obj->is_auto_increment()) {
901
-                // totally ignore auto increment IDs
902
-                continue;
903
-            }
904
-            $arg_info = $field_obj->getSchema();
905
-            $required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
906
-            $arg_info['required'] = $required;
907
-            // remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
908
-            unset($arg_info['readonly']);
909
-            $schema_properties = $field_obj->getSchemaProperties();
910
-            if (isset($schema_properties['raw'])
911
-                && $field_obj->getSchemaType() === 'object'
912
-            ) {
913
-                // if there's a "raw" form of this argument, use those properties instead
914
-                $arg_info = array_replace(
915
-                    $arg_info,
916
-                    $schema_properties['raw']
917
-                );
918
-            }
919
-            $arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
920
-                $field_obj,
921
-                $field_obj->get_default_value(),
922
-                $model_version_info->requestedVersion()
923
-            );
924
-            // we do our own validation and sanitization within the controller
925
-            if (function_exists('rest_validate_value_from_schema')) {
926
-                $sanitize_callback = array(
927
-                    'EED_Core_Rest_Api',
928
-                    'default_sanitize_callback',
929
-                );
930
-            } else {
931
-                $sanitize_callback = null;
932
-            }
933
-            $arg_info['sanitize_callback'] = $sanitize_callback;
934
-            $args_info[ $field_name ] = $arg_info;
935
-            if ($field_obj instanceof EE_Datetime_Field) {
936
-                $gmt_arg_info = $arg_info;
937
-                $gmt_arg_info['description'] = sprintf(
938
-                    esc_html__(
939
-                        '%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
940
-                        'event_espresso'
941
-                    ),
942
-                    $field_obj->get_nicename(),
943
-                    $field_name
944
-                );
945
-                $args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
946
-            }
947
-        }
948
-        return $args_info;
949
-    }
950
-
951
-
952
-    /**
953
-     * Replacement for WP API's 'rest_parse_request_arg'.
954
-     * If the value is blank but not required, don't bother validating it.
955
-     * Also, it uses our email validation instead of WP API's default.
956
-     *
957
-     * @param                 $value
958
-     * @param WP_REST_Request $request
959
-     * @param                 $param
960
-     * @return bool|true|WP_Error
961
-     * @throws InvalidArgumentException
962
-     * @throws InvalidInterfaceException
963
-     * @throws InvalidDataTypeException
964
-     */
965
-    public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
966
-    {
967
-        $attributes = $request->get_attributes();
968
-        if (! isset($attributes['args'][ $param ])
969
-            || ! is_array($attributes['args'][ $param ])) {
970
-            $validation_result = true;
971
-        } else {
972
-            $args = $attributes['args'][ $param ];
973
-            if ((
974
-                    $value === ''
975
-                    || $value === null
976
-                )
977
-                && (! isset($args['required'])
978
-                    || $args['required'] === false
979
-                )
980
-            ) {
981
-                // not required and not provided? that's cool
982
-                $validation_result = true;
983
-            } elseif (isset($args['format'])
984
-                      && $args['format'] === 'email'
985
-            ) {
986
-                $validation_result = true;
987
-                if (! self::_validate_email($value)) {
988
-                    $validation_result = new WP_Error(
989
-                        'rest_invalid_param',
990
-                        esc_html__(
991
-                            'The email address is not valid or does not exist.',
992
-                            'event_espresso'
993
-                        )
994
-                    );
995
-                }
996
-            } else {
997
-                $validation_result = rest_validate_value_from_schema($value, $args, $param);
998
-            }
999
-        }
1000
-        if (is_wp_error($validation_result)) {
1001
-            return $validation_result;
1002
-        }
1003
-        return rest_sanitize_request_arg($value, $request, $param);
1004
-    }
1005
-
1006
-
1007
-    /**
1008
-     * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
1009
-     *
1010
-     * @param $email
1011
-     * @return bool
1012
-     * @throws InvalidArgumentException
1013
-     * @throws InvalidInterfaceException
1014
-     * @throws InvalidDataTypeException
1015
-     */
1016
-    protected static function _validate_email($email)
1017
-    {
1018
-        try {
1019
-            EmailAddressFactory::create($email);
1020
-            return true;
1021
-        } catch (EmailValidationException $e) {
1022
-            return false;
1023
-        }
1024
-    }
1025
-
1026
-
1027
-    /**
1028
-     * Gets routes for the config
1029
-     *
1030
-     * @return array @see _register_model_routes
1031
-     * @deprecated since version 4.9.1
1032
-     */
1033
-    protected function _register_config_routes()
1034
-    {
1035
-        $config_routes = array();
1036
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1037
-            $config_routes[ self::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1038
-                $version,
1039
-                $hidden_endpoint
1040
-            );
1041
-        }
1042
-        return $config_routes;
1043
-    }
1044
-
1045
-
1046
-    /**
1047
-     * Gets routes for the config for the specified version
1048
-     *
1049
-     * @param string  $version
1050
-     * @param boolean $hidden_endpoint
1051
-     * @return array
1052
-     */
1053
-    protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1054
-    {
1055
-        return array(
1056
-            'config'    => array(
1057
-                array(
1058
-                    'callback'        => array(
1059
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1060
-                        'handleRequest',
1061
-                    ),
1062
-                    'methods'         => WP_REST_Server::READABLE,
1063
-                    'hidden_endpoint' => $hidden_endpoint,
1064
-                    'callback_args'   => array($version),
1065
-                ),
1066
-            ),
1067
-            'site_info' => array(
1068
-                array(
1069
-                    'callback'        => array(
1070
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1071
-                        'handleRequestSiteInfo',
1072
-                    ),
1073
-                    'methods'         => WP_REST_Server::READABLE,
1074
-                    'hidden_endpoint' => $hidden_endpoint,
1075
-                    'callback_args'   => array($version),
1076
-                ),
1077
-            ),
1078
-        );
1079
-    }
1080
-
1081
-
1082
-    /**
1083
-     * Gets the meta info routes
1084
-     *
1085
-     * @return array @see _register_model_routes
1086
-     * @deprecated since version 4.9.1
1087
-     */
1088
-    protected function _register_meta_routes()
1089
-    {
1090
-        $meta_routes = array();
1091
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1092
-            $meta_routes[ self::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1093
-                $version,
1094
-                $hidden_endpoint
1095
-            );
1096
-        }
1097
-        return $meta_routes;
1098
-    }
1099
-
1100
-
1101
-    /**
1102
-     * @param string  $version
1103
-     * @param boolean $hidden_endpoint
1104
-     * @return array
1105
-     */
1106
-    protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1107
-    {
1108
-        return array(
1109
-            'resources' => array(
1110
-                array(
1111
-                    'callback'        => array(
1112
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1113
-                        'handleRequestModelsMeta',
1114
-                    ),
1115
-                    'methods'         => WP_REST_Server::READABLE,
1116
-                    'hidden_endpoint' => $hidden_endpoint,
1117
-                    'callback_args'   => array($version),
1118
-                ),
1119
-            ),
1120
-        );
1121
-    }
1122
-
1123
-
1124
-    /**
1125
-     * Tries to hide old 4.6 endpoints from the
1126
-     *
1127
-     * @param array $route_data
1128
-     * @return array
1129
-     * @throws \EE_Error
1130
-     */
1131
-    public static function hide_old_endpoints($route_data)
1132
-    {
1133
-        // allow API clients to override which endpoints get hidden, in case
1134
-        // they want to discover particular endpoints
1135
-        // also, we don't have access to the request so we have to just grab it from the superglobal
1136
-        $force_show_ee_namespace = ltrim(
1137
-            EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1138
-            '/'
1139
-        );
1140
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1141
-            foreach ($relative_urls as $resource_name => $endpoints) {
1142
-                foreach ($endpoints as $key => $endpoint) {
1143
-                    // skip schema and other route options
1144
-                    if (! is_numeric($key)) {
1145
-                        continue;
1146
-                    }
1147
-                    // by default, hide "hidden_endpoint"s, unless the request indicates
1148
-                    // to $force_show_ee_namespace, in which case only show that one
1149
-                    // namespace's endpoints (and hide all others)
1150
-                    if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1151
-                        || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1152
-                    ) {
1153
-                        $full_route = '/' . ltrim($namespace, '/');
1154
-                        $full_route .= '/' . ltrim($resource_name, '/');
1155
-                        unset($route_data[ $full_route ]);
1156
-                    }
1157
-                }
1158
-            }
1159
-        }
1160
-        return $route_data;
1161
-    }
1162
-
1163
-
1164
-    /**
1165
-     * Returns an array describing which versions of core support serving requests for.
1166
-     * Keys are core versions' major and minor version, and values are the
1167
-     * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1168
-     * data by just removing a few models and fields from the responses. However, 4.15 might remove
1169
-     * the answers table entirely, in which case it would be very difficult for
1170
-     * it to serve 4.6-style responses.
1171
-     * Versions of core that are missing from this array are unknowns.
1172
-     * previous ver
1173
-     *
1174
-     * @return array
1175
-     */
1176
-    public static function version_compatibilities()
1177
-    {
1178
-        return apply_filters(
1179
-            'FHEE__EED_Core_REST_API__version_compatibilities',
1180
-            array(
1181
-                '4.8.29' => '4.8.29',
1182
-                '4.8.33' => '4.8.29',
1183
-                '4.8.34' => '4.8.29',
1184
-                '4.8.36' => '4.8.29',
1185
-            )
1186
-        );
1187
-    }
1188
-
1189
-
1190
-    /**
1191
-     * Gets the latest API version served. Eg if there
1192
-     * are two versions served of the API, 4.8.29 and 4.8.32, and
1193
-     * we are on core version 4.8.34, it will return the string "4.8.32"
1194
-     *
1195
-     * @return string
1196
-     */
1197
-    public static function latest_rest_api_version()
1198
-    {
1199
-        $versions_served = \EED_Core_Rest_Api::versions_served();
1200
-        $versions_served_keys = array_keys($versions_served);
1201
-        return end($versions_served_keys);
1202
-    }
1203
-
1204
-
1205
-    /**
1206
-     * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1207
-     * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1208
-     * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1209
-     * We also indicate whether or not this version should be put in the index or not
1210
-     *
1211
-     * @return array keys are API version numbers (just major and minor numbers), and values
1212
-     * are whether or not they should be hidden
1213
-     */
1214
-    public static function versions_served()
1215
-    {
1216
-        $versions_served = array();
1217
-        $possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1218
-        $lowest_compatible_version = end($possibly_served_versions);
1219
-        reset($possibly_served_versions);
1220
-        $versions_served_historically = array_keys($possibly_served_versions);
1221
-        $latest_version = end($versions_served_historically);
1222
-        reset($versions_served_historically);
1223
-        // for each version of core we have ever served:
1224
-        foreach ($versions_served_historically as $key_versioned_endpoint) {
1225
-            // if it's not above the current core version, and it's compatible with the current version of core
1226
-
1227
-            if ($key_versioned_endpoint === $latest_version) {
1228
-                // don't hide the latest version in the index
1229
-                $versions_served[ $key_versioned_endpoint ] = false;
1230
-            } elseif (version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1231
-                && version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1232
-            ) {
1233
-                // include, but hide, previous versions which are still supported
1234
-                $versions_served[ $key_versioned_endpoint ] = true;
1235
-            } elseif (apply_filters(
1236
-                'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1237
-                false,
1238
-                $possibly_served_versions
1239
-            )) {
1240
-                // if a version is no longer supported, don't include it in index or list of versions served
1241
-                $versions_served[ $key_versioned_endpoint ] = true;
1242
-            }
1243
-        }
1244
-        return $versions_served;
1245
-    }
1246
-
1247
-
1248
-    /**
1249
-     * Gets the major and minor version of EE core's version string
1250
-     *
1251
-     * @return string
1252
-     */
1253
-    public static function core_version()
1254
-    {
1255
-        return apply_filters(
1256
-            'FHEE__EED_Core_REST_API__core_version',
1257
-            implode(
1258
-                '.',
1259
-                array_slice(
1260
-                    explode(
1261
-                        '.',
1262
-                        espresso_version()
1263
-                    ),
1264
-                    0,
1265
-                    3
1266
-                )
1267
-            )
1268
-        );
1269
-    }
1270
-
1271
-
1272
-    /**
1273
-     * Gets the default limit that should be used when querying for resources
1274
-     *
1275
-     * @return int
1276
-     */
1277
-    public static function get_default_query_limit()
1278
-    {
1279
-        // we actually don't use a const because we want folks to always use
1280
-        // this method, not the const directly
1281
-        return apply_filters(
1282
-            'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1283
-            50
1284
-        );
1285
-    }
1286
-
1287
-
1288
-    /**
1289
-     *
1290
-     * @param string $version api version string (i.e. '4.8.36')
1291
-     * @return array
1292
-     */
1293
-    public static function getCollectionRoutesIndexedByModelName($version = '')
1294
-    {
1295
-        $version = empty($version) ? self::latest_rest_api_version() : $version;
1296
-        $model_names = self::model_names_with_plural_routes($version);
1297
-        $collection_routes = array();
1298
-        foreach ($model_names as $model_name => $model_class_name) {
1299
-            $collection_routes[ strtolower($model_name) ] = '/' . self::ee_api_namespace . $version . '/'
1300
-                                                            . EEH_Inflector::pluralize_and_lower($model_name);
1301
-        }
1302
-        return $collection_routes;
1303
-    }
1304
-
1305
-
1306
-    /**
1307
-     * Returns an array of primary key names indexed by model names.
1308
-     * @param string $version
1309
-     * @return array
1310
-     */
1311
-    public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1312
-    {
1313
-        $version = empty($version) ? self::latest_rest_api_version() : $version;
1314
-        $model_names = self::model_names_with_plural_routes($version);
1315
-        $primary_key_items = array();
1316
-        foreach ($model_names as $model_name => $model_class_name) {
1317
-            $primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1318
-            foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1319
-                if (count($primary_keys) > 1) {
1320
-                    $primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1321
-                } else {
1322
-                    $primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1323
-                }
1324
-            }
1325
-        }
1326
-        return $primary_key_items;
1327
-    }
1328
-
1329
-    /**
1330
-     * Determines the EE REST API debug mode is activated, or not.
1331
-     * @since 4.9.76.p
1332
-     * @return bool
1333
-     */
1334
-    public static function debugMode()
1335
-    {
1336
-        static $debug_mode = null; // could be class prop
1337
-        if ($debug_mode === null) {
1338
-            $debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1339
-        }
1340
-        return $debug_mode;
1341
-    }
1342
-
1343
-
1344
-
1345
-    /**
1346
-     *    run - initial module setup
1347
-     *
1348
-     * @access    public
1349
-     * @param  WP $WP
1350
-     * @return    void
1351
-     */
1352
-    public function run($WP)
1353
-    {
1354
-    }
26
+	const ee_api_namespace = Domain::API_NAMESPACE;
27
+
28
+	const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
29
+
30
+	const saved_routes_option_names = 'ee_core_routes';
31
+
32
+	/**
33
+	 * string used in _links response bodies to make them globally unique.
34
+	 *
35
+	 * @see http://v2.wp-api.org/extending/linking/
36
+	 */
37
+	const ee_api_link_namespace = 'https://api.eventespresso.com/';
38
+
39
+	/**
40
+	 * @var CalculatedModelFields
41
+	 */
42
+	protected static $_field_calculator;
43
+
44
+
45
+	/**
46
+	 * @return EED_Core_Rest_Api|EED_Module
47
+	 */
48
+	public static function instance()
49
+	{
50
+		self::$_field_calculator = LoaderFactory::getLoader()->load('EventEspresso\core\libraries\rest_api\CalculatedModelFields');
51
+		return parent::get_instance(__CLASS__);
52
+	}
53
+
54
+
55
+	/**
56
+	 *    set_hooks - for hooking into EE Core, other modules, etc
57
+	 *
58
+	 * @access    public
59
+	 * @return    void
60
+	 */
61
+	public static function set_hooks()
62
+	{
63
+		self::set_hooks_both();
64
+	}
65
+
66
+
67
+	/**
68
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
69
+	 *
70
+	 * @access    public
71
+	 * @return    void
72
+	 */
73
+	public static function set_hooks_admin()
74
+	{
75
+		self::set_hooks_both();
76
+	}
77
+
78
+
79
+	public static function set_hooks_both()
80
+	{
81
+		add_action('rest_api_init', array('EED_Core_Rest_Api', 'register_routes'), 10);
82
+		add_action('rest_api_init', array('EED_Core_Rest_Api', 'set_hooks_rest_api'), 5);
83
+		add_filter('rest_route_data', array('EED_Core_Rest_Api', 'hide_old_endpoints'), 10, 2);
84
+		add_filter(
85
+			'rest_index',
86
+			array('EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex')
87
+		);
88
+		EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
89
+	}
90
+
91
+
92
+	/**
93
+	 * sets up hooks which only need to be included as part of REST API requests;
94
+	 * other requests like to the frontend or admin etc don't need them
95
+	 *
96
+	 * @throws \EE_Error
97
+	 */
98
+	public static function set_hooks_rest_api()
99
+	{
100
+		// set hooks which account for changes made to the API
101
+		EED_Core_Rest_Api::_set_hooks_for_changes();
102
+	}
103
+
104
+
105
+	/**
106
+	 * public wrapper of _set_hooks_for_changes.
107
+	 * Loads all the hooks which make requests to old versions of the API
108
+	 * appear the same as they always did
109
+	 *
110
+	 * @throws EE_Error
111
+	 */
112
+	public static function set_hooks_for_changes()
113
+	{
114
+		self::_set_hooks_for_changes();
115
+	}
116
+
117
+
118
+	/**
119
+	 * Loads all the hooks which make requests to old versions of the API
120
+	 * appear the same as they always did
121
+	 *
122
+	 * @throws EE_Error
123
+	 */
124
+	protected static function _set_hooks_for_changes()
125
+	{
126
+		$folder_contents = EEH_File::get_contents_of_folders(array(EE_LIBRARIES . 'rest_api' . DS . 'changes'), false);
127
+		foreach ($folder_contents as $classname_in_namespace => $filepath) {
128
+			// ignore the base parent class
129
+			// and legacy named classes
130
+			if ($classname_in_namespace === 'ChangesInBase'
131
+				|| strpos($classname_in_namespace, 'Changes_In_') === 0
132
+			) {
133
+				continue;
134
+			}
135
+			$full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
136
+			if (class_exists($full_classname)) {
137
+				$instance_of_class = new $full_classname;
138
+				if ($instance_of_class instanceof ChangesInBase) {
139
+					$instance_of_class->setHooks();
140
+				}
141
+			}
142
+		}
143
+	}
144
+
145
+
146
+	/**
147
+	 * Filters the WP routes to add our EE-related ones. This takes a bit of time
148
+	 * so we actually prefer to only do it when an EE plugin is activated or upgraded
149
+	 *
150
+	 * @throws \EE_Error
151
+	 */
152
+	public static function register_routes()
153
+	{
154
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
155
+			foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
156
+				/**
157
+				 * @var array     $data_for_multiple_endpoints numerically indexed array
158
+				 *                                         but can also contain route options like {
159
+				 * @type array    $schema                      {
160
+				 * @type callable $schema_callback
161
+				 * @type array    $callback_args               arguments that will be passed to the callback, after the
162
+				 * WP_REST_Request of course
163
+				 * }
164
+				 * }
165
+				 */
166
+				// when registering routes, register all the endpoints' data at the same time
167
+				$multiple_endpoint_args = array();
168
+				foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
169
+					/**
170
+					 * @var array     $data_for_single_endpoint {
171
+					 * @type callable $callback
172
+					 * @type string methods
173
+					 * @type array args
174
+					 * @type array _links
175
+					 * @type array    $callback_args            arguments that will be passed to the callback, after the
176
+					 * WP_REST_Request of course
177
+					 * }
178
+					 */
179
+					// skip route options
180
+					if (! is_numeric($endpoint_key)) {
181
+						continue;
182
+					}
183
+					if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
184
+						throw new EE_Error(
185
+							esc_html__(
186
+							// @codingStandardsIgnoreStart
187
+								'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
188
+								// @codingStandardsIgnoreEnd
189
+								'event_espresso'
190
+							)
191
+						);
192
+					}
193
+					$callback = $data_for_single_endpoint['callback'];
194
+					$single_endpoint_args = array(
195
+						'methods' => $data_for_single_endpoint['methods'],
196
+						'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
197
+							: array(),
198
+					);
199
+					if (isset($data_for_single_endpoint['_links'])) {
200
+						$single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
201
+					}
202
+					if (isset($data_for_single_endpoint['callback_args'])) {
203
+						$callback_args = $data_for_single_endpoint['callback_args'];
204
+						$single_endpoint_args['callback'] = function (\WP_REST_Request $request) use (
205
+							$callback,
206
+							$callback_args
207
+						) {
208
+							array_unshift($callback_args, $request);
209
+							return call_user_func_array(
210
+								$callback,
211
+								$callback_args
212
+							);
213
+						};
214
+					} else {
215
+						$single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
216
+					}
217
+					$multiple_endpoint_args[] = $single_endpoint_args;
218
+				}
219
+				if (isset($data_for_multiple_endpoints['schema'])) {
220
+					$schema_route_data = $data_for_multiple_endpoints['schema'];
221
+					$schema_callback = $schema_route_data['schema_callback'];
222
+					$callback_args = $schema_route_data['callback_args'];
223
+					$multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
224
+						return call_user_func_array(
225
+							$schema_callback,
226
+							$callback_args
227
+						);
228
+					};
229
+				}
230
+				register_rest_route(
231
+					$namespace,
232
+					$relative_route,
233
+					$multiple_endpoint_args
234
+				);
235
+			}
236
+		}
237
+	}
238
+
239
+
240
+	/**
241
+	 * Checks if there was a version change or something that merits invalidating the cached
242
+	 * route data. If so, invalidates the cached route data so that it gets refreshed
243
+	 * next time the WP API is used
244
+	 */
245
+	public static function invalidate_cached_route_data_on_version_change()
246
+	{
247
+		if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
248
+			EED_Core_Rest_Api::invalidate_cached_route_data();
249
+		}
250
+		foreach (EE_Registry::instance()->addons as $addon) {
251
+			if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
252
+				EED_Core_Rest_Api::invalidate_cached_route_data();
253
+			}
254
+		}
255
+	}
256
+
257
+
258
+	/**
259
+	 * Removes the cached route data so it will get refreshed next time the WP API is used
260
+	 */
261
+	public static function invalidate_cached_route_data()
262
+	{
263
+		// delete the saved EE REST API routes
264
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
265
+			delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
266
+		}
267
+	}
268
+
269
+
270
+	/**
271
+	 * Gets the EE route data
272
+	 *
273
+	 * @return array top-level key is the namespace, next-level key is the route and its value is array{
274
+	 * @throws \EE_Error
275
+	 * @type string|array $callback
276
+	 * @type string       $methods
277
+	 * @type boolean      $hidden_endpoint
278
+	 * }
279
+	 */
280
+	public static function get_ee_route_data()
281
+	{
282
+		$ee_routes = array();
283
+		foreach (self::versions_served() as $version => $hidden_endpoints) {
284
+			$ee_routes[ self::ee_api_namespace . $version ] = self::_get_ee_route_data_for_version(
285
+				$version,
286
+				$hidden_endpoints
287
+			);
288
+		}
289
+		return $ee_routes;
290
+	}
291
+
292
+
293
+	/**
294
+	 * Gets the EE route data from the wp options if it exists already,
295
+	 * otherwise re-generates it and saves it to the option
296
+	 *
297
+	 * @param string  $version
298
+	 * @param boolean $hidden_endpoints
299
+	 * @return array
300
+	 * @throws \EE_Error
301
+	 */
302
+	protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
303
+	{
304
+		$ee_routes = get_option(self::saved_routes_option_names . $version, null);
305
+		if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
306
+			$ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
307
+		}
308
+		return $ee_routes;
309
+	}
310
+
311
+
312
+	/**
313
+	 * Saves the EE REST API route data to a wp option and returns it
314
+	 *
315
+	 * @param string  $version
316
+	 * @param boolean $hidden_endpoints
317
+	 * @return mixed|null
318
+	 * @throws \EE_Error
319
+	 */
320
+	protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
321
+	{
322
+		$instance = self::instance();
323
+		$routes = apply_filters(
324
+			'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
325
+			array_replace_recursive(
326
+				$instance->_get_config_route_data_for_version($version, $hidden_endpoints),
327
+				$instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
328
+				$instance->_get_model_route_data_for_version($version, $hidden_endpoints),
329
+				$instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
330
+			)
331
+		);
332
+		$option_name = self::saved_routes_option_names . $version;
333
+		if (get_option($option_name)) {
334
+			update_option($option_name, $routes, true);
335
+		} else {
336
+			add_option($option_name, $routes, null, 'no');
337
+		}
338
+		return $routes;
339
+	}
340
+
341
+
342
+	/**
343
+	 * Calculates all the EE routes and saves it to a WordPress option so we don't
344
+	 * need to calculate it on every request
345
+	 *
346
+	 * @deprecated since version 4.9.1
347
+	 * @return void
348
+	 */
349
+	public static function save_ee_routes()
350
+	{
351
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
352
+			$instance = self::instance();
353
+			$routes = apply_filters(
354
+				'EED_Core_Rest_Api__save_ee_routes__routes',
355
+				array_replace_recursive(
356
+					$instance->_register_config_routes(),
357
+					$instance->_register_meta_routes(),
358
+					$instance->_register_model_routes(),
359
+					$instance->_register_rpc_routes()
360
+				)
361
+			);
362
+			update_option(self::saved_routes_option_names, $routes, true);
363
+		}
364
+	}
365
+
366
+
367
+	/**
368
+	 * Gets all the route information relating to EE models
369
+	 *
370
+	 * @return array @see get_ee_route_data
371
+	 * @deprecated since version 4.9.1
372
+	 */
373
+	protected function _register_model_routes()
374
+	{
375
+		$model_routes = array();
376
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
377
+			$model_routes[ EED_Core_Rest_Api::ee_api_namespace
378
+						   . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
379
+		}
380
+		return $model_routes;
381
+	}
382
+
383
+
384
+	/**
385
+	 * Decides whether or not to add write endpoints for this model.
386
+	 *
387
+	 * Currently, this defaults to exclude all global tables and models
388
+	 * which would allow inserting WP core data (we don't want to duplicate
389
+	 * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
390
+	 *
391
+	 * @param EEM_Base $model
392
+	 * @return bool
393
+	 */
394
+	public static function should_have_write_endpoints(EEM_Base $model)
395
+	{
396
+		if ($model->is_wp_core_model()) {
397
+			return false;
398
+		}
399
+		foreach ($model->get_tables() as $table) {
400
+			if ($table->is_global()) {
401
+				return false;
402
+			}
403
+		}
404
+		return true;
405
+	}
406
+
407
+
408
+	/**
409
+	 * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
410
+	 * in this versioned namespace of EE4
411
+	 *
412
+	 * @param $version
413
+	 * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
414
+	 */
415
+	public static function model_names_with_plural_routes($version)
416
+	{
417
+		$model_version_info = new ModelVersionInfo($version);
418
+		$models_to_register = $model_version_info->modelsForRequestedVersion();
419
+		// let's not bother having endpoints for extra metas
420
+		unset(
421
+			$models_to_register['Extra_Meta'],
422
+			$models_to_register['Extra_Join'],
423
+			$models_to_register['Post_Meta']
424
+		);
425
+		return apply_filters(
426
+			'FHEE__EED_Core_REST_API___register_model_routes',
427
+			$models_to_register
428
+		);
429
+	}
430
+
431
+
432
+	/**
433
+	 * Gets the route data for EE models in the specified version
434
+	 *
435
+	 * @param string  $version
436
+	 * @param boolean $hidden_endpoint
437
+	 * @return array
438
+	 * @throws EE_Error
439
+	 */
440
+	protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
441
+	{
442
+		$model_routes = array();
443
+		$model_version_info = new ModelVersionInfo($version);
444
+		foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
445
+			$model = \EE_Registry::instance()->load_model($model_name);
446
+			// if this isn't a valid model then let's skip iterate to the next item in the loop.
447
+			if (! $model instanceof EEM_Base) {
448
+				continue;
449
+			}
450
+			// yes we could just register one route for ALL models, but then they wouldn't show up in the index
451
+			$plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
452
+			$singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
453
+			$model_routes[ $plural_model_route ] = array(
454
+				array(
455
+					'callback'        => array(
456
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
457
+						'handleRequestGetAll',
458
+					),
459
+					'callback_args'   => array($version, $model_name),
460
+					'methods'         => WP_REST_Server::READABLE,
461
+					'hidden_endpoint' => $hidden_endpoint,
462
+					'args'            => $this->_get_read_query_params($model, $version),
463
+					'_links'          => array(
464
+						'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
465
+					),
466
+				),
467
+				'schema' => array(
468
+					'schema_callback' => array(
469
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
470
+						'handleSchemaRequest',
471
+					),
472
+					'callback_args'   => array($version, $model_name),
473
+				),
474
+			);
475
+			$model_routes[ $singular_model_route ] = array(
476
+				array(
477
+					'callback'        => array(
478
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
479
+						'handleRequestGetOne',
480
+					),
481
+					'callback_args'   => array($version, $model_name),
482
+					'methods'         => WP_REST_Server::READABLE,
483
+					'hidden_endpoint' => $hidden_endpoint,
484
+					'args'            => $this->_get_response_selection_query_params($model, $version, true),
485
+				),
486
+			);
487
+			if (apply_filters(
488
+				'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
489
+				EED_Core_Rest_Api::should_have_write_endpoints($model),
490
+				$model
491
+			)) {
492
+				$model_routes[ $plural_model_route ][] = array(
493
+					'callback'        => array(
494
+						'EventEspresso\core\libraries\rest_api\controllers\model\Write',
495
+						'handleRequestInsert',
496
+					),
497
+					'callback_args'   => array($version, $model_name),
498
+					'methods'         => WP_REST_Server::CREATABLE,
499
+					'hidden_endpoint' => $hidden_endpoint,
500
+					'args'            => $this->_get_write_params($model_name, $model_version_info, true),
501
+				);
502
+				$model_routes[ $singular_model_route ] = array_merge(
503
+					$model_routes[ $singular_model_route ],
504
+					array(
505
+						array(
506
+							'callback'        => array(
507
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
508
+								'handleRequestUpdate',
509
+							),
510
+							'callback_args'   => array($version, $model_name),
511
+							'methods'         => WP_REST_Server::EDITABLE,
512
+							'hidden_endpoint' => $hidden_endpoint,
513
+							'args'            => $this->_get_write_params($model_name, $model_version_info),
514
+						),
515
+						array(
516
+							'callback'        => array(
517
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
518
+								'handleRequestDelete',
519
+							),
520
+							'callback_args'   => array($version, $model_name),
521
+							'methods'         => WP_REST_Server::DELETABLE,
522
+							'hidden_endpoint' => $hidden_endpoint,
523
+							'args'            => $this->_get_delete_query_params($model, $version),
524
+						),
525
+					)
526
+				);
527
+			}
528
+			foreach ($model->relation_settings() as $relation_name => $relation_obj) {
529
+				$related_route = EED_Core_Rest_Api::get_relation_route_via(
530
+					$model,
531
+					'(?P<id>[^\/]+)',
532
+					$relation_obj
533
+				);
534
+				$model_routes[ $related_route ] = array(
535
+					array(
536
+						'callback'        => array(
537
+							'EventEspresso\core\libraries\rest_api\controllers\model\Read',
538
+							'handleRequestGetRelated',
539
+						),
540
+						'callback_args'   => array($version, $model_name, $relation_name),
541
+						'methods'         => WP_REST_Server::READABLE,
542
+						'hidden_endpoint' => $hidden_endpoint,
543
+						'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
544
+					),
545
+				);
546
+
547
+				$related_write_route = $related_route . '/' . '(?P<related_id>[^\/]+)';
548
+				$model_routes[ $related_write_route ] = array(
549
+					array(
550
+						'callback'        => array(
551
+							'EventEspresso\core\libraries\rest_api\controllers\model\Write',
552
+							'handleRequestAddRelation',
553
+						),
554
+						'callback_args'   => array($version, $model_name, $relation_name),
555
+						'methods'         => WP_REST_Server::EDITABLE,
556
+						'hidden_endpoint' => $hidden_endpoint,
557
+						'args'            => $this->_get_add_relation_query_params($model, $relation_obj->get_other_model(), $version)
558
+					),
559
+					array(
560
+						'callback'        => array(
561
+							'EventEspresso\core\libraries\rest_api\controllers\model\Write',
562
+							'handleRequestRemoveRelation',
563
+						),
564
+						'callback_args'   => array($version, $model_name, $relation_name),
565
+						'methods'         => WP_REST_Server::DELETABLE,
566
+						'hidden_endpoint' => $hidden_endpoint,
567
+						'args'            => array()
568
+					),
569
+				);
570
+			}
571
+		}
572
+		return $model_routes;
573
+	}
574
+
575
+
576
+	/**
577
+	 * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
578
+	 * excluding the preceding slash.
579
+	 * Eg you pass get_plural_route_to('Event') = 'events'
580
+	 *
581
+	 * @param EEM_Base $model
582
+	 * @return string
583
+	 */
584
+	public static function get_collection_route(EEM_Base $model)
585
+	{
586
+		return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
587
+	}
588
+
589
+
590
+	/**
591
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
592
+	 * excluding the preceding slash.
593
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
594
+	 *
595
+	 * @param EEM_Base $model eg Event or Venue
596
+	 * @param string   $id
597
+	 * @return string
598
+	 */
599
+	public static function get_entity_route($model, $id)
600
+	{
601
+		return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
602
+	}
603
+
604
+
605
+	/**
606
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
607
+	 * excluding the preceding slash.
608
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
609
+	 *
610
+	 * @param EEM_Base               $model eg Event or Venue
611
+	 * @param string                 $id
612
+	 * @param EE_Model_Relation_Base $relation_obj
613
+	 * @return string
614
+	 */
615
+	public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
616
+	{
617
+		$related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
618
+			$relation_obj->get_other_model()->get_this_model_name(),
619
+			$relation_obj
620
+		);
621
+		return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
622
+	}
623
+
624
+
625
+	/**
626
+	 * Adds onto the $relative_route the EE4 REST API versioned namespace.
627
+	 * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
628
+	 *
629
+	 * @param string $relative_route
630
+	 * @param string $version
631
+	 * @return string
632
+	 */
633
+	public static function get_versioned_route_to($relative_route, $version = '4.8.36')
634
+	{
635
+		return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
636
+	}
637
+
638
+
639
+	/**
640
+	 * Adds all the RPC-style routes (remote procedure call-like routes, ie
641
+	 * routes that don't conform to the traditional REST CRUD-style).
642
+	 *
643
+	 * @deprecated since 4.9.1
644
+	 */
645
+	protected function _register_rpc_routes()
646
+	{
647
+		$routes = array();
648
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
649
+			$routes[ self::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
650
+				$version,
651
+				$hidden_endpoint
652
+			);
653
+		}
654
+		return $routes;
655
+	}
656
+
657
+
658
+	/**
659
+	 * @param string  $version
660
+	 * @param boolean $hidden_endpoint
661
+	 * @return array
662
+	 */
663
+	protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
664
+	{
665
+		$this_versions_routes = array();
666
+		// checkin endpoint
667
+		$this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = array(
668
+			array(
669
+				'callback'        => array(
670
+					'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
671
+					'handleRequestToggleCheckin',
672
+				),
673
+				'methods'         => WP_REST_Server::CREATABLE,
674
+				'hidden_endpoint' => $hidden_endpoint,
675
+				'args'            => array(
676
+					'force' => array(
677
+						'required'    => false,
678
+						'default'     => false,
679
+						'description' => __(
680
+						// @codingStandardsIgnoreStart
681
+							'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
682
+							// @codingStandardsIgnoreEnd
683
+							'event_espresso'
684
+						),
685
+					),
686
+				),
687
+				'callback_args'   => array($version),
688
+			),
689
+		);
690
+		return apply_filters(
691
+			'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
692
+			$this_versions_routes,
693
+			$version,
694
+			$hidden_endpoint
695
+		);
696
+	}
697
+
698
+
699
+	/**
700
+	 * Gets the query params that can be used when request one or many
701
+	 *
702
+	 * @param EEM_Base $model
703
+	 * @param string   $version
704
+	 * @return array
705
+	 */
706
+	protected function _get_response_selection_query_params(\EEM_Base $model, $version, $single_only = false)
707
+	{
708
+		$query_params = array(
709
+			'include'   => array(
710
+				'required' => false,
711
+				'default'  => '*',
712
+				'type'     => 'string',
713
+			),
714
+			'calculate' => array(
715
+				'required'          => false,
716
+				'default'           => '',
717
+				'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
718
+				'type'              => 'string',
719
+				// because we accept a CSV'd list of the enumerated strings, WP core validation and sanitization
720
+				// freaks out. We'll just validate this argument while handling the request
721
+				'validate_callback' => null,
722
+				'sanitize_callback' => null,
723
+			),
724
+			'password' => array(
725
+				'required' => false,
726
+				'default' => '',
727
+				'type' => 'string'
728
+			)
729
+		);
730
+		return apply_filters(
731
+			'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
732
+			$query_params,
733
+			$model,
734
+			$version
735
+		);
736
+	}
737
+
738
+
739
+	/**
740
+	 * Gets the parameters acceptable for delete requests
741
+	 *
742
+	 * @param \EEM_Base $model
743
+	 * @param string    $version
744
+	 * @return array
745
+	 */
746
+	protected function _get_delete_query_params(\EEM_Base $model, $version)
747
+	{
748
+		$params_for_delete = array(
749
+			'allow_blocking' => array(
750
+				'required' => false,
751
+				'default'  => true,
752
+				'type'     => 'boolean',
753
+			),
754
+		);
755
+		$params_for_delete['force'] = array(
756
+			'required' => false,
757
+			'default'  => false,
758
+			'type'     => 'boolean',
759
+		);
760
+		return apply_filters(
761
+			'FHEE__EED_Core_Rest_Api___get_delete_query_params',
762
+			$params_for_delete,
763
+			$model,
764
+			$version
765
+		);
766
+	}
767
+
768
+	protected function _get_add_relation_query_params(\EEM_Base $source_model, \EEM_Base $related_model, $version)
769
+	{
770
+		// if they're related through a HABTM relation, check for any non-FKs
771
+		$all_relation_settings = $source_model->relation_settings();
772
+		$relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
773
+		$params = array();
774
+		if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
775
+			foreach ($relation_settings->getNonKeyFields() as $field) {
776
+				/* @var $field EE_Model_Field_Base */
777
+				$params[ $field->get_name() ] = array(
778
+					'required' => ! $field->is_nullable(),
779
+					'default' => ModelDataTranslator::prepareFieldValueForJson($field, $field->get_default_value(), $version),
780
+					'type' => $field->getSchemaType(),
781
+					'validate_callbaack' => null,
782
+					'sanitize_callback' => null
783
+				);
784
+			}
785
+		}
786
+		return $params;
787
+	}
788
+
789
+
790
+	/**
791
+	 * Gets info about reading query params that are acceptable
792
+	 *
793
+	 * @param \EEM_Base $model eg 'Event' or 'Venue'
794
+	 * @param  string   $version
795
+	 * @return array    describing the args acceptable when querying this model
796
+	 * @throws EE_Error
797
+	 */
798
+	protected function _get_read_query_params(\EEM_Base $model, $version)
799
+	{
800
+		$default_orderby = array();
801
+		foreach ($model->get_combined_primary_key_fields() as $key_field) {
802
+			$default_orderby[ $key_field->get_name() ] = 'ASC';
803
+		}
804
+		return array_merge(
805
+			$this->_get_response_selection_query_params($model, $version),
806
+			array(
807
+				'where'    => array(
808
+					'required'          => false,
809
+					'default'           => array(),
810
+					'type'              => 'object',
811
+					// because we accept an almost infinite list of possible where conditions, WP
812
+					// core validation and sanitization freaks out. We'll just validate this argument
813
+					// while handling the request
814
+					'validate_callback' => null,
815
+					'sanitize_callback' => null,
816
+				),
817
+				'limit'    => array(
818
+					'required'          => false,
819
+					'default'           => EED_Core_Rest_Api::get_default_query_limit(),
820
+					'type'              => array(
821
+						'array',
822
+						'string',
823
+						'integer',
824
+					),
825
+					// because we accept a variety of types, WP core validation and sanitization
826
+					// freaks out. We'll just validate this argument while handling the request
827
+					'validate_callback' => null,
828
+					'sanitize_callback' => null,
829
+				),
830
+				'order_by' => array(
831
+					'required'          => false,
832
+					'default'           => $default_orderby,
833
+					'type'              => array(
834
+						'object',
835
+						'string',
836
+					),// because we accept a variety of types, WP core validation and sanitization
837
+					// freaks out. We'll just validate this argument while handling the request
838
+					'validate_callback' => null,
839
+					'sanitize_callback' => null,
840
+				),
841
+				'group_by' => array(
842
+					'required'          => false,
843
+					'default'           => null,
844
+					'type'              => array(
845
+						'object',
846
+						'string',
847
+					),
848
+					// because we accept  an almost infinite list of possible groupings,
849
+					// WP core validation and sanitization
850
+					// freaks out. We'll just validate this argument while handling the request
851
+					'validate_callback' => null,
852
+					'sanitize_callback' => null,
853
+				),
854
+				'having'   => array(
855
+					'required'          => false,
856
+					'default'           => null,
857
+					'type'              => 'object',
858
+					// because we accept an almost infinite list of possible where conditions, WP
859
+					// core validation and sanitization freaks out. We'll just validate this argument
860
+					// while handling the request
861
+					'validate_callback' => null,
862
+					'sanitize_callback' => null,
863
+				),
864
+				'caps'     => array(
865
+					'required' => false,
866
+					'default'  => EEM_Base::caps_read,
867
+					'type'     => 'string',
868
+					'enum'     => array(
869
+						EEM_Base::caps_read,
870
+						EEM_Base::caps_read_admin,
871
+						EEM_Base::caps_edit,
872
+						EEM_Base::caps_delete,
873
+					),
874
+				),
875
+			)
876
+		);
877
+	}
878
+
879
+
880
+	/**
881
+	 * Gets parameter information for a model regarding writing data
882
+	 *
883
+	 * @param string           $model_name
884
+	 * @param ModelVersionInfo $model_version_info
885
+	 * @param boolean          $create                                       whether this is for request to create (in
886
+	 *                                                                       which case we need all required params) or
887
+	 *                                                                       just to update (in which case we don't
888
+	 *                                                                       need those on every request)
889
+	 * @return array
890
+	 */
891
+	protected function _get_write_params(
892
+		$model_name,
893
+		ModelVersionInfo $model_version_info,
894
+		$create = false
895
+	) {
896
+		$model = EE_Registry::instance()->load_model($model_name);
897
+		$fields = $model_version_info->fieldsOnModelInThisVersion($model);
898
+		$args_info = array();
899
+		foreach ($fields as $field_name => $field_obj) {
900
+			if ($field_obj->is_auto_increment()) {
901
+				// totally ignore auto increment IDs
902
+				continue;
903
+			}
904
+			$arg_info = $field_obj->getSchema();
905
+			$required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
906
+			$arg_info['required'] = $required;
907
+			// remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
908
+			unset($arg_info['readonly']);
909
+			$schema_properties = $field_obj->getSchemaProperties();
910
+			if (isset($schema_properties['raw'])
911
+				&& $field_obj->getSchemaType() === 'object'
912
+			) {
913
+				// if there's a "raw" form of this argument, use those properties instead
914
+				$arg_info = array_replace(
915
+					$arg_info,
916
+					$schema_properties['raw']
917
+				);
918
+			}
919
+			$arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
920
+				$field_obj,
921
+				$field_obj->get_default_value(),
922
+				$model_version_info->requestedVersion()
923
+			);
924
+			// we do our own validation and sanitization within the controller
925
+			if (function_exists('rest_validate_value_from_schema')) {
926
+				$sanitize_callback = array(
927
+					'EED_Core_Rest_Api',
928
+					'default_sanitize_callback',
929
+				);
930
+			} else {
931
+				$sanitize_callback = null;
932
+			}
933
+			$arg_info['sanitize_callback'] = $sanitize_callback;
934
+			$args_info[ $field_name ] = $arg_info;
935
+			if ($field_obj instanceof EE_Datetime_Field) {
936
+				$gmt_arg_info = $arg_info;
937
+				$gmt_arg_info['description'] = sprintf(
938
+					esc_html__(
939
+						'%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
940
+						'event_espresso'
941
+					),
942
+					$field_obj->get_nicename(),
943
+					$field_name
944
+				);
945
+				$args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
946
+			}
947
+		}
948
+		return $args_info;
949
+	}
950
+
951
+
952
+	/**
953
+	 * Replacement for WP API's 'rest_parse_request_arg'.
954
+	 * If the value is blank but not required, don't bother validating it.
955
+	 * Also, it uses our email validation instead of WP API's default.
956
+	 *
957
+	 * @param                 $value
958
+	 * @param WP_REST_Request $request
959
+	 * @param                 $param
960
+	 * @return bool|true|WP_Error
961
+	 * @throws InvalidArgumentException
962
+	 * @throws InvalidInterfaceException
963
+	 * @throws InvalidDataTypeException
964
+	 */
965
+	public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
966
+	{
967
+		$attributes = $request->get_attributes();
968
+		if (! isset($attributes['args'][ $param ])
969
+			|| ! is_array($attributes['args'][ $param ])) {
970
+			$validation_result = true;
971
+		} else {
972
+			$args = $attributes['args'][ $param ];
973
+			if ((
974
+					$value === ''
975
+					|| $value === null
976
+				)
977
+				&& (! isset($args['required'])
978
+					|| $args['required'] === false
979
+				)
980
+			) {
981
+				// not required and not provided? that's cool
982
+				$validation_result = true;
983
+			} elseif (isset($args['format'])
984
+					  && $args['format'] === 'email'
985
+			) {
986
+				$validation_result = true;
987
+				if (! self::_validate_email($value)) {
988
+					$validation_result = new WP_Error(
989
+						'rest_invalid_param',
990
+						esc_html__(
991
+							'The email address is not valid or does not exist.',
992
+							'event_espresso'
993
+						)
994
+					);
995
+				}
996
+			} else {
997
+				$validation_result = rest_validate_value_from_schema($value, $args, $param);
998
+			}
999
+		}
1000
+		if (is_wp_error($validation_result)) {
1001
+			return $validation_result;
1002
+		}
1003
+		return rest_sanitize_request_arg($value, $request, $param);
1004
+	}
1005
+
1006
+
1007
+	/**
1008
+	 * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
1009
+	 *
1010
+	 * @param $email
1011
+	 * @return bool
1012
+	 * @throws InvalidArgumentException
1013
+	 * @throws InvalidInterfaceException
1014
+	 * @throws InvalidDataTypeException
1015
+	 */
1016
+	protected static function _validate_email($email)
1017
+	{
1018
+		try {
1019
+			EmailAddressFactory::create($email);
1020
+			return true;
1021
+		} catch (EmailValidationException $e) {
1022
+			return false;
1023
+		}
1024
+	}
1025
+
1026
+
1027
+	/**
1028
+	 * Gets routes for the config
1029
+	 *
1030
+	 * @return array @see _register_model_routes
1031
+	 * @deprecated since version 4.9.1
1032
+	 */
1033
+	protected function _register_config_routes()
1034
+	{
1035
+		$config_routes = array();
1036
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1037
+			$config_routes[ self::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1038
+				$version,
1039
+				$hidden_endpoint
1040
+			);
1041
+		}
1042
+		return $config_routes;
1043
+	}
1044
+
1045
+
1046
+	/**
1047
+	 * Gets routes for the config for the specified version
1048
+	 *
1049
+	 * @param string  $version
1050
+	 * @param boolean $hidden_endpoint
1051
+	 * @return array
1052
+	 */
1053
+	protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1054
+	{
1055
+		return array(
1056
+			'config'    => array(
1057
+				array(
1058
+					'callback'        => array(
1059
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1060
+						'handleRequest',
1061
+					),
1062
+					'methods'         => WP_REST_Server::READABLE,
1063
+					'hidden_endpoint' => $hidden_endpoint,
1064
+					'callback_args'   => array($version),
1065
+				),
1066
+			),
1067
+			'site_info' => array(
1068
+				array(
1069
+					'callback'        => array(
1070
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1071
+						'handleRequestSiteInfo',
1072
+					),
1073
+					'methods'         => WP_REST_Server::READABLE,
1074
+					'hidden_endpoint' => $hidden_endpoint,
1075
+					'callback_args'   => array($version),
1076
+				),
1077
+			),
1078
+		);
1079
+	}
1080
+
1081
+
1082
+	/**
1083
+	 * Gets the meta info routes
1084
+	 *
1085
+	 * @return array @see _register_model_routes
1086
+	 * @deprecated since version 4.9.1
1087
+	 */
1088
+	protected function _register_meta_routes()
1089
+	{
1090
+		$meta_routes = array();
1091
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1092
+			$meta_routes[ self::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1093
+				$version,
1094
+				$hidden_endpoint
1095
+			);
1096
+		}
1097
+		return $meta_routes;
1098
+	}
1099
+
1100
+
1101
+	/**
1102
+	 * @param string  $version
1103
+	 * @param boolean $hidden_endpoint
1104
+	 * @return array
1105
+	 */
1106
+	protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1107
+	{
1108
+		return array(
1109
+			'resources' => array(
1110
+				array(
1111
+					'callback'        => array(
1112
+						'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1113
+						'handleRequestModelsMeta',
1114
+					),
1115
+					'methods'         => WP_REST_Server::READABLE,
1116
+					'hidden_endpoint' => $hidden_endpoint,
1117
+					'callback_args'   => array($version),
1118
+				),
1119
+			),
1120
+		);
1121
+	}
1122
+
1123
+
1124
+	/**
1125
+	 * Tries to hide old 4.6 endpoints from the
1126
+	 *
1127
+	 * @param array $route_data
1128
+	 * @return array
1129
+	 * @throws \EE_Error
1130
+	 */
1131
+	public static function hide_old_endpoints($route_data)
1132
+	{
1133
+		// allow API clients to override which endpoints get hidden, in case
1134
+		// they want to discover particular endpoints
1135
+		// also, we don't have access to the request so we have to just grab it from the superglobal
1136
+		$force_show_ee_namespace = ltrim(
1137
+			EEH_Array::is_set($_REQUEST, 'force_show_ee_namespace', ''),
1138
+			'/'
1139
+		);
1140
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1141
+			foreach ($relative_urls as $resource_name => $endpoints) {
1142
+				foreach ($endpoints as $key => $endpoint) {
1143
+					// skip schema and other route options
1144
+					if (! is_numeric($key)) {
1145
+						continue;
1146
+					}
1147
+					// by default, hide "hidden_endpoint"s, unless the request indicates
1148
+					// to $force_show_ee_namespace, in which case only show that one
1149
+					// namespace's endpoints (and hide all others)
1150
+					if (($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1151
+						|| ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1152
+					) {
1153
+						$full_route = '/' . ltrim($namespace, '/');
1154
+						$full_route .= '/' . ltrim($resource_name, '/');
1155
+						unset($route_data[ $full_route ]);
1156
+					}
1157
+				}
1158
+			}
1159
+		}
1160
+		return $route_data;
1161
+	}
1162
+
1163
+
1164
+	/**
1165
+	 * Returns an array describing which versions of core support serving requests for.
1166
+	 * Keys are core versions' major and minor version, and values are the
1167
+	 * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1168
+	 * data by just removing a few models and fields from the responses. However, 4.15 might remove
1169
+	 * the answers table entirely, in which case it would be very difficult for
1170
+	 * it to serve 4.6-style responses.
1171
+	 * Versions of core that are missing from this array are unknowns.
1172
+	 * previous ver
1173
+	 *
1174
+	 * @return array
1175
+	 */
1176
+	public static function version_compatibilities()
1177
+	{
1178
+		return apply_filters(
1179
+			'FHEE__EED_Core_REST_API__version_compatibilities',
1180
+			array(
1181
+				'4.8.29' => '4.8.29',
1182
+				'4.8.33' => '4.8.29',
1183
+				'4.8.34' => '4.8.29',
1184
+				'4.8.36' => '4.8.29',
1185
+			)
1186
+		);
1187
+	}
1188
+
1189
+
1190
+	/**
1191
+	 * Gets the latest API version served. Eg if there
1192
+	 * are two versions served of the API, 4.8.29 and 4.8.32, and
1193
+	 * we are on core version 4.8.34, it will return the string "4.8.32"
1194
+	 *
1195
+	 * @return string
1196
+	 */
1197
+	public static function latest_rest_api_version()
1198
+	{
1199
+		$versions_served = \EED_Core_Rest_Api::versions_served();
1200
+		$versions_served_keys = array_keys($versions_served);
1201
+		return end($versions_served_keys);
1202
+	}
1203
+
1204
+
1205
+	/**
1206
+	 * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1207
+	 * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1208
+	 * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1209
+	 * We also indicate whether or not this version should be put in the index or not
1210
+	 *
1211
+	 * @return array keys are API version numbers (just major and minor numbers), and values
1212
+	 * are whether or not they should be hidden
1213
+	 */
1214
+	public static function versions_served()
1215
+	{
1216
+		$versions_served = array();
1217
+		$possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1218
+		$lowest_compatible_version = end($possibly_served_versions);
1219
+		reset($possibly_served_versions);
1220
+		$versions_served_historically = array_keys($possibly_served_versions);
1221
+		$latest_version = end($versions_served_historically);
1222
+		reset($versions_served_historically);
1223
+		// for each version of core we have ever served:
1224
+		foreach ($versions_served_historically as $key_versioned_endpoint) {
1225
+			// if it's not above the current core version, and it's compatible with the current version of core
1226
+
1227
+			if ($key_versioned_endpoint === $latest_version) {
1228
+				// don't hide the latest version in the index
1229
+				$versions_served[ $key_versioned_endpoint ] = false;
1230
+			} elseif (version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1231
+				&& version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1232
+			) {
1233
+				// include, but hide, previous versions which are still supported
1234
+				$versions_served[ $key_versioned_endpoint ] = true;
1235
+			} elseif (apply_filters(
1236
+				'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1237
+				false,
1238
+				$possibly_served_versions
1239
+			)) {
1240
+				// if a version is no longer supported, don't include it in index or list of versions served
1241
+				$versions_served[ $key_versioned_endpoint ] = true;
1242
+			}
1243
+		}
1244
+		return $versions_served;
1245
+	}
1246
+
1247
+
1248
+	/**
1249
+	 * Gets the major and minor version of EE core's version string
1250
+	 *
1251
+	 * @return string
1252
+	 */
1253
+	public static function core_version()
1254
+	{
1255
+		return apply_filters(
1256
+			'FHEE__EED_Core_REST_API__core_version',
1257
+			implode(
1258
+				'.',
1259
+				array_slice(
1260
+					explode(
1261
+						'.',
1262
+						espresso_version()
1263
+					),
1264
+					0,
1265
+					3
1266
+				)
1267
+			)
1268
+		);
1269
+	}
1270
+
1271
+
1272
+	/**
1273
+	 * Gets the default limit that should be used when querying for resources
1274
+	 *
1275
+	 * @return int
1276
+	 */
1277
+	public static function get_default_query_limit()
1278
+	{
1279
+		// we actually don't use a const because we want folks to always use
1280
+		// this method, not the const directly
1281
+		return apply_filters(
1282
+			'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1283
+			50
1284
+		);
1285
+	}
1286
+
1287
+
1288
+	/**
1289
+	 *
1290
+	 * @param string $version api version string (i.e. '4.8.36')
1291
+	 * @return array
1292
+	 */
1293
+	public static function getCollectionRoutesIndexedByModelName($version = '')
1294
+	{
1295
+		$version = empty($version) ? self::latest_rest_api_version() : $version;
1296
+		$model_names = self::model_names_with_plural_routes($version);
1297
+		$collection_routes = array();
1298
+		foreach ($model_names as $model_name => $model_class_name) {
1299
+			$collection_routes[ strtolower($model_name) ] = '/' . self::ee_api_namespace . $version . '/'
1300
+															. EEH_Inflector::pluralize_and_lower($model_name);
1301
+		}
1302
+		return $collection_routes;
1303
+	}
1304
+
1305
+
1306
+	/**
1307
+	 * Returns an array of primary key names indexed by model names.
1308
+	 * @param string $version
1309
+	 * @return array
1310
+	 */
1311
+	public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1312
+	{
1313
+		$version = empty($version) ? self::latest_rest_api_version() : $version;
1314
+		$model_names = self::model_names_with_plural_routes($version);
1315
+		$primary_key_items = array();
1316
+		foreach ($model_names as $model_name => $model_class_name) {
1317
+			$primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1318
+			foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1319
+				if (count($primary_keys) > 1) {
1320
+					$primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1321
+				} else {
1322
+					$primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1323
+				}
1324
+			}
1325
+		}
1326
+		return $primary_key_items;
1327
+	}
1328
+
1329
+	/**
1330
+	 * Determines the EE REST API debug mode is activated, or not.
1331
+	 * @since 4.9.76.p
1332
+	 * @return bool
1333
+	 */
1334
+	public static function debugMode()
1335
+	{
1336
+		static $debug_mode = null; // could be class prop
1337
+		if ($debug_mode === null) {
1338
+			$debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1339
+		}
1340
+		return $debug_mode;
1341
+	}
1342
+
1343
+
1344
+
1345
+	/**
1346
+	 *    run - initial module setup
1347
+	 *
1348
+	 * @access    public
1349
+	 * @param  WP $WP
1350
+	 * @return    void
1351
+	 */
1352
+	public function run($WP)
1353
+	{
1354
+	}
1355 1355
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Event.model.php 3 patches
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -2,7 +2,6 @@
 block discarded – undo
2 2
 
3 3
 use EventEspresso\core\exceptions\InvalidDataTypeException;
4 4
 use EventEspresso\core\exceptions\InvalidInterfaceException;
5
-use EventEspresso\core\services\orm\ModelFieldFactory;
6 5
 
7 6
 /**
8 7
  * EEM_Event Model
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -278,7 +278,7 @@  discard block
 block discarded – undo
278 278
             'WP_User'                => new EE_Belongs_To_Relation(),
279 279
         );
280 280
         // this model is generally available for reading
281
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
281
+        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
282 282
         $this->model_chain_to_password = '';
283 283
         parent::__construct($timezone);
284 284
     }
@@ -371,7 +371,7 @@  discard block
 block discarded – undo
371 371
      */
372 372
     public function get_all_event_question_groups($EVT_ID = 0)
373 373
     {
374
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
374
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
375 375
             EE_Error::add_error(
376 376
                 esc_html__(
377 377
                     'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
@@ -405,7 +405,7 @@  discard block
 block discarded – undo
405 405
      */
406 406
     public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
407 407
     {
408
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
408
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
409 409
             EE_Error::add_error(
410 410
                 esc_html__(
411 411
                     // @codingStandardsIgnoreStart
@@ -448,7 +448,7 @@  discard block
 block discarded – undo
448 448
      */
449 449
     public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
450 450
     {
451
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
451
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
452 452
             EE_Error::add_error(
453 453
                 esc_html__(
454 454
                     'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
@@ -861,11 +861,11 @@  discard block
 block discarded – undo
861 861
         $questions = array();
862 862
         // get all question groups for event
863 863
         $qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
864
-        if (! empty($qgs)) {
864
+        if ( ! empty($qgs)) {
865 865
             foreach ($qgs as $qg) {
866 866
                 $qsts = $qg->questions();
867
-                $questions[ $qg->ID() ] = $qg->model_field_array();
868
-                $questions[ $qg->ID() ]['QSG_questions'] = array();
867
+                $questions[$qg->ID()] = $qg->model_field_array();
868
+                $questions[$qg->ID()]['QSG_questions'] = array();
869 869
                 foreach ($qsts as $qst) {
870 870
                     if ($qst->is_system_question()) {
871 871
                         continue;
@@ -879,26 +879,26 @@  discard block
 block discarded – undo
879 879
                     $answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
880 880
                     $qst_name = $qstn_id = $qst->ID();
881 881
                     $ans_id = $answer->ID();
882
-                    $qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
882
+                    $qst_name = ! empty($ans_id) ? '['.$qst_name.']['.$ans_id.']' : '['.$qst_name.']';
883 883
                     $input_name = '';
884 884
                     $input_id = sanitize_key($qst->display_text());
885 885
                     $input_class = '';
886
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
887
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
886
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()] = $qst->model_field_array();
887
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_name'] = 'qstn'
888 888
                                                                                            . $input_name
889 889
                                                                                            . $qst_name;
890
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
891
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
892
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
893
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
894
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
890
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_id'] = $input_id.'-'.$qstn_id;
891
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_class'] = $input_class;
892
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'] = array();
893
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['qst_obj'] = $qst;
894
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['ans_obj'] = $answer;
895 895
                     // leave responses as-is, don't convert stuff into html entities please!
896
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
896
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['htmlentities'] = false;
897 897
                     if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
898 898
                         $QSOs = $qst->options(true, $answer->value());
899 899
                         if (is_array($QSOs)) {
900 900
                             foreach ($QSOs as $QSO_ID => $QSO) {
901
-                                $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
901
+                                $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'][$QSO_ID] = $QSO->model_field_array();
902 902
                             }
903 903
                         }
904 904
                     }
Please login to merge, or discard this patch.
Indentation   +909 added lines, -909 removed lines patch added patch discarded remove patch
@@ -15,913 +15,913 @@
 block discarded – undo
15 15
 class EEM_Event extends EEM_CPT_Base
16 16
 {
17 17
 
18
-    /**
19
-     * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
20
-     * event
21
-     */
22
-    const sold_out = 'sold_out';
23
-
24
-    /**
25
-     * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
26
-     * date)
27
-     */
28
-    const postponed = 'postponed';
29
-
30
-    /**
31
-     * constant used by status(), indicating that the event will no longer occur
32
-     */
33
-    const cancelled = 'cancelled';
34
-
35
-
36
-    /**
37
-     * @var string
38
-     */
39
-    protected static $_default_reg_status;
40
-
41
-
42
-    /**
43
-     * This is the default for the additional limit field.
44
-     * @var int
45
-     */
46
-    protected static $_default_additional_limit = 10;
47
-
48
-
49
-    /**
50
-     * private instance of the Event object
51
-     *
52
-     * @var EEM_Event
53
-     */
54
-    protected static $_instance;
55
-
56
-
57
-
58
-
59
-    /**
60
-     * Adds a relationship to Term_Taxonomy for each CPT_Base
61
-     *
62
-     * @param string $timezone
63
-     * @throws \EE_Error
64
-     */
65
-    protected function __construct($timezone = null)
66
-    {
67
-        EE_Registry::instance()->load_model('Registration');
68
-        $this->singular_item = esc_html__('Event', 'event_espresso');
69
-        $this->plural_item = esc_html__('Events', 'event_espresso');
70
-        // to remove Cancelled events from the frontend, copy the following filter to your functions.php file
71
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
72
-        // to remove Postponed events from the frontend, copy the following filter to your functions.php file
73
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
74
-        // to remove Sold Out events from the frontend, copy the following filter to your functions.php file
75
-        //  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
76
-        $this->_custom_stati = apply_filters(
77
-            'AFEE__EEM_Event__construct___custom_stati',
78
-            array(
79
-                EEM_Event::cancelled => array(
80
-                    'label'  => esc_html__('Cancelled', 'event_espresso'),
81
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
82
-                ),
83
-                EEM_Event::postponed => array(
84
-                    'label'  => esc_html__('Postponed', 'event_espresso'),
85
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
86
-                ),
87
-                EEM_Event::sold_out  => array(
88
-                    'label'  => esc_html__('Sold Out', 'event_espresso'),
89
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
90
-                ),
91
-            )
92
-        );
93
-        self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
94
-            : self::$_default_reg_status;
95
-        $this->_tables = array(
96
-            'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
97
-            'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
98
-        );
99
-        $this->_fields = array(
100
-            'Event_CPT'  => array(
101
-                'EVT_ID'         => new EE_Primary_Key_Int_Field(
102
-                    'ID',
103
-                    esc_html__('Post ID for Event', 'event_espresso')
104
-                ),
105
-                'EVT_name'       => new EE_Plain_Text_Field(
106
-                    'post_title',
107
-                    esc_html__('Event Name', 'event_espresso'),
108
-                    false,
109
-                    ''
110
-                ),
111
-                'EVT_desc'       => new EE_Post_Content_Field(
112
-                    'post_content',
113
-                    esc_html__('Event Description', 'event_espresso'),
114
-                    false,
115
-                    ''
116
-                ),
117
-                'EVT_slug'       => new EE_Slug_Field(
118
-                    'post_name',
119
-                    esc_html__('Event Slug', 'event_espresso'),
120
-                    false,
121
-                    ''
122
-                ),
123
-                'EVT_created'    => new EE_Datetime_Field(
124
-                    'post_date',
125
-                    esc_html__('Date/Time Event Created', 'event_espresso'),
126
-                    false,
127
-                    EE_Datetime_Field::now
128
-                ),
129
-                'EVT_short_desc' => new EE_Simple_HTML_Field(
130
-                    'post_excerpt',
131
-                    esc_html__('Event Short Description', 'event_espresso'),
132
-                    false,
133
-                    ''
134
-                ),
135
-                'EVT_modified'   => new EE_Datetime_Field(
136
-                    'post_modified',
137
-                    esc_html__('Date/Time Event Modified', 'event_espresso'),
138
-                    false,
139
-                    EE_Datetime_Field::now
140
-                ),
141
-                'EVT_wp_user'    => new EE_WP_User_Field(
142
-                    'post_author',
143
-                    esc_html__('Event Creator ID', 'event_espresso'),
144
-                    false
145
-                ),
146
-                'parent'         => new EE_Integer_Field(
147
-                    'post_parent',
148
-                    esc_html__('Event Parent ID', 'event_espresso'),
149
-                    false,
150
-                    0
151
-                ),
152
-                'EVT_order'      => new EE_Integer_Field(
153
-                    'menu_order',
154
-                    esc_html__('Event Menu Order', 'event_espresso'),
155
-                    false,
156
-                    1
157
-                ),
158
-                'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
159
-                // EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
160
-                'status'         => new EE_WP_Post_Status_Field(
161
-                    'post_status',
162
-                    esc_html__('Event Status', 'event_espresso'),
163
-                    false,
164
-                    'draft',
165
-                    $this->_custom_stati
166
-                ),
167
-                'password' => new EE_Password_Field(
168
-                    'post_password',
169
-                    __('Password', 'event_espresso'),
170
-                    false,
171
-                    '',
172
-                    array(
173
-                        'EVT_desc',
174
-                        'EVT_short_desc',
175
-                        'EVT_display_desc',
176
-                        'EVT_display_ticket_selector',
177
-                        'EVT_visible_on',
178
-                        'EVT_additional_limit',
179
-                        'EVT_default_registration_status',
180
-                        'EVT_member_only',
181
-                        'EVT_phone',
182
-                        'EVT_allow_overflow',
183
-                        'EVT_timezone_string',
184
-                        'EVT_external_URL',
185
-                        'EVT_donations'
186
-                    )
187
-                )
188
-            ),
189
-            'Event_Meta' => array(
190
-                'EVTM_ID'                         => new EE_DB_Only_Float_Field(
191
-                    'EVTM_ID',
192
-                    esc_html__('Event Meta Row ID', 'event_espresso'),
193
-                    false
194
-                ),
195
-                'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
196
-                    'EVT_ID',
197
-                    esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
198
-                    false
199
-                ),
200
-                'EVT_display_desc'                => new EE_Boolean_Field(
201
-                    'EVT_display_desc',
202
-                    esc_html__('Display Description Flag', 'event_espresso'),
203
-                    false,
204
-                    true
205
-                ),
206
-                'EVT_display_ticket_selector'     => new EE_Boolean_Field(
207
-                    'EVT_display_ticket_selector',
208
-                    esc_html__('Display Ticket Selector Flag', 'event_espresso'),
209
-                    false,
210
-                    true
211
-                ),
212
-                'EVT_visible_on'                  => new EE_Datetime_Field(
213
-                    'EVT_visible_on',
214
-                    esc_html__('Event Visible Date', 'event_espresso'),
215
-                    true,
216
-                    EE_Datetime_Field::now
217
-                ),
218
-                'EVT_additional_limit'            => new EE_Integer_Field(
219
-                    'EVT_additional_limit',
220
-                    esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
221
-                    true,
222
-                    self::$_default_additional_limit
223
-                ),
224
-                'EVT_default_registration_status' => new EE_Enum_Text_Field(
225
-                    'EVT_default_registration_status',
226
-                    esc_html__('Default Registration Status on this Event', 'event_espresso'),
227
-                    false,
228
-                    EEM_Event::$_default_reg_status,
229
-                    EEM_Registration::reg_status_array()
230
-                ),
231
-                'EVT_member_only'                 => new EE_Boolean_Field(
232
-                    'EVT_member_only',
233
-                    esc_html__('Member-Only Event Flag', 'event_espresso'),
234
-                    false,
235
-                    false
236
-                ),
237
-                'EVT_phone'                       => new EE_Plain_Text_Field(
238
-                    'EVT_phone',
239
-                    esc_html__('Event Phone Number', 'event_espresso'),
240
-                    false,
241
-                    ''
242
-                ),
243
-                'EVT_allow_overflow'              => new EE_Boolean_Field(
244
-                    'EVT_allow_overflow',
245
-                    esc_html__('Allow Overflow on Event', 'event_espresso'),
246
-                    false,
247
-                    false
248
-                ),
249
-                'EVT_timezone_string'             => new EE_Plain_Text_Field(
250
-                    'EVT_timezone_string',
251
-                    esc_html__('Timezone (name) for Event times', 'event_espresso'),
252
-                    false,
253
-                    ''
254
-                ),
255
-                'EVT_external_URL'                => new EE_Plain_Text_Field(
256
-                    'EVT_external_URL',
257
-                    esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
258
-                    true
259
-                ),
260
-                'EVT_donations'                   => new EE_Boolean_Field(
261
-                    'EVT_donations',
262
-                    esc_html__('Accept Donations?', 'event_espresso'),
263
-                    false,
264
-                    false
265
-                ),
266
-            ),
267
-        );
268
-        $this->_model_relations = array(
269
-            'Registration'           => new EE_Has_Many_Relation(),
270
-            'Datetime'               => new EE_Has_Many_Relation(),
271
-            'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
272
-            'Event_Question_Group'   => new EE_Has_Many_Relation(),
273
-            'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
274
-            'Term_Relationship'      => new EE_Has_Many_Relation(),
275
-            'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
276
-            'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
277
-            'Attendee'               => new EE_HABTM_Relation('Registration'),
278
-            'WP_User'                => new EE_Belongs_To_Relation(),
279
-        );
280
-        // this model is generally available for reading
281
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
282
-        $this->model_chain_to_password = '';
283
-        parent::__construct($timezone);
284
-    }
285
-
286
-
287
-
288
-    /**
289
-     * @param string $default_reg_status
290
-     */
291
-    public static function set_default_reg_status($default_reg_status)
292
-    {
293
-        self::$_default_reg_status = $default_reg_status;
294
-        // if EEM_Event has already been instantiated,
295
-        // then we need to reset the `EVT_default_reg_status` field to use the new default.
296
-        if (self::$_instance instanceof EEM_Event) {
297
-            $default_reg_status = new EE_Enum_Text_Field(
298
-                'EVT_default_registration_status',
299
-                esc_html__('Default Registration Status on this Event', 'event_espresso'),
300
-                false,
301
-                $default_reg_status,
302
-                EEM_Registration::reg_status_array()
303
-            );
304
-            $default_reg_status->_construct_finalize(
305
-                'Event_Meta',
306
-                'EVT_default_registration_status',
307
-                'EEM_Event'
308
-            );
309
-            self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
310
-        }
311
-    }
312
-
313
-
314
-    /**
315
-     * Used to override the default for the additional limit field.
316
-     * @param $additional_limit
317
-     */
318
-    public static function set_default_additional_limit($additional_limit)
319
-    {
320
-        self::$_default_additional_limit = (int) $additional_limit;
321
-        if (self::$_instance instanceof EEM_Event) {
322
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
323
-                'EVT_additional_limit',
324
-                __('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
325
-                true,
326
-                self::$_default_additional_limit
327
-            );
328
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
329
-                'Event_Meta',
330
-                'EVT_additional_limit',
331
-                'EEM_Event'
332
-            );
333
-        }
334
-    }
335
-
336
-
337
-    /**
338
-     * Return what is currently set as the default additional limit for the event.
339
-     * @return int
340
-     */
341
-    public static function get_default_additional_limit()
342
-    {
343
-        return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
344
-    }
345
-
346
-
347
-    /**
348
-     * get_question_groups
349
-     *
350
-     * @return array
351
-     * @throws \EE_Error
352
-     */
353
-    public function get_all_question_groups()
354
-    {
355
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
356
-            array(
357
-                array('QSG_deleted' => false),
358
-                'order_by' => array('QSG_order' => 'ASC'),
359
-            )
360
-        );
361
-    }
362
-
363
-
364
-
365
-    /**
366
-     * get_question_groups
367
-     *
368
-     * @param int $EVT_ID
369
-     * @return array|bool
370
-     * @throws \EE_Error
371
-     */
372
-    public function get_all_event_question_groups($EVT_ID = 0)
373
-    {
374
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
375
-            EE_Error::add_error(
376
-                esc_html__(
377
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
378
-                    'event_espresso'
379
-                ),
380
-                __FILE__,
381
-                __FUNCTION__,
382
-                __LINE__
383
-            );
384
-            return false;
385
-        }
386
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
387
-            array(
388
-                array('EVT_ID' => $EVT_ID),
389
-            )
390
-        );
391
-    }
392
-
393
-
394
-    /**
395
-     * get_question_groups
396
-     *
397
-     * @param int $EVT_ID
398
-     * @param boolean $for_primary_attendee
399
-     * @return array|bool
400
-     * @throws EE_Error
401
-     * @throws InvalidArgumentException
402
-     * @throws ReflectionException
403
-     * @throws InvalidDataTypeException
404
-     * @throws InvalidInterfaceException
405
-     */
406
-    public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
407
-    {
408
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
409
-            EE_Error::add_error(
410
-                esc_html__(
411
-                    // @codingStandardsIgnoreStart
412
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
413
-                    // @codingStandardsIgnoreEnd
414
-                    'event_espresso'
415
-                ),
416
-                __FILE__,
417
-                __FUNCTION__,
418
-                __LINE__
419
-            );
420
-            return false;
421
-        }
422
-        $query_params = [
423
-            [
424
-                'EVT_ID' => $EVT_ID,
425
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true
426
-            ]
427
-        ];
428
-        if ($for_primary_attendee) {
429
-            $query_params[0]['EQG_primary'] = true;
430
-        } else {
431
-            $query_params[0]['EQG_additional'] = true;
432
-        }
433
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
434
-    }
435
-
436
-
437
-    /**
438
-     * get_question_groups
439
-     *
440
-     * @param int $EVT_ID
441
-     * @param EE_Registration $registration
442
-     * @return array|bool
443
-     * @throws EE_Error
444
-     * @throws InvalidArgumentException
445
-     * @throws InvalidDataTypeException
446
-     * @throws InvalidInterfaceException
447
-     * @throws ReflectionException
448
-     */
449
-    public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
450
-    {
451
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
452
-            EE_Error::add_error(
453
-                esc_html__(
454
-                    'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
455
-                    'event_espresso'
456
-                ),
457
-                __FILE__,
458
-                __FUNCTION__,
459
-                __LINE__
460
-            );
461
-            return false;
462
-        }
463
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
464
-            [
465
-                [
466
-                    'Event_Question_Group.EVT_ID'      => $EVT_ID,
467
-                    'Event_Question_Group.'
468
-                        . EEM_Event_Question_Group::instance()->fieldNameForContext(
469
-                            $registration->is_primary_registrant()
470
-                        ) => true
471
-                ],
472
-                'order_by' => ['QSG_order' => 'ASC'],
473
-            ]
474
-        );
475
-    }
476
-
477
-
478
-
479
-    /**
480
-     * get_question_target_db_column
481
-     *
482
-     * @param string $QSG_IDs csv list of $QSG IDs
483
-     * @return array|bool
484
-     * @throws \EE_Error
485
-     */
486
-    public function get_questions_in_groups($QSG_IDs = '')
487
-    {
488
-        if (empty($QSG_IDs)) {
489
-            EE_Error::add_error(
490
-                esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
491
-                __FILE__,
492
-                __FUNCTION__,
493
-                __LINE__
494
-            );
495
-            return false;
496
-        }
497
-        return EE_Registry::instance()->load_model('Question')->get_all(
498
-            array(
499
-                array(
500
-                    'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
501
-                    'QST_deleted'           => false,
502
-                    'QST_admin_only'        => is_admin(),
503
-                ),
504
-                'order_by' => 'QST_order',
505
-            )
506
-        );
507
-    }
508
-
509
-
510
-
511
-    /**
512
-     * get_options_for_question
513
-     *
514
-     * @param string $QST_IDs csv list of $QST IDs
515
-     * @return array|bool
516
-     * @throws \EE_Error
517
-     */
518
-    public function get_options_for_question($QST_IDs)
519
-    {
520
-        if (empty($QST_IDs)) {
521
-            EE_Error::add_error(
522
-                esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
523
-                __FILE__,
524
-                __FUNCTION__,
525
-                __LINE__
526
-            );
527
-            return false;
528
-        }
529
-        return EE_Registry::instance()->load_model('Question_Option')->get_all(
530
-            array(
531
-                array(
532
-                    'Question.QST_ID' => array('IN', $QST_IDs),
533
-                    'QSO_deleted'     => false,
534
-                ),
535
-                'order_by' => 'QSO_ID',
536
-            )
537
-        );
538
-    }
539
-
540
-
541
-
542
-
543
-
544
-
545
-
546
-    /**
547
-     * Gets all events that are published
548
-     * and have event start time earlier than now and an event end time later than now
549
-     *
550
-     * @param  array $query_params An array of query params to further filter on
551
-     *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
552
-     * @param bool   $count        whether to return the count or not (default FALSE)
553
-     * @return EE_Event[]|int
554
-     * @throws \EE_Error
555
-     */
556
-    public function get_active_events($query_params, $count = false)
557
-    {
558
-        if (array_key_exists(0, $query_params)) {
559
-            $where_params = $query_params[0];
560
-            unset($query_params[0]);
561
-        } else {
562
-            $where_params = array();
563
-        }
564
-        // if we have count make sure we don't include group by
565
-        if ($count && isset($query_params['group_by'])) {
566
-            unset($query_params['group_by']);
567
-        }
568
-        // let's add specific query_params for active_events
569
-        // keep in mind this will override any sent status in the query AND any date queries.
570
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
571
-        // if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
572
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
573
-            $where_params['Datetime.DTT_EVT_start******'] = array(
574
-                '<',
575
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
576
-            );
577
-        } else {
578
-            $where_params['Datetime.DTT_EVT_start'] = array(
579
-                '<',
580
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
581
-            );
582
-        }
583
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
584
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
585
-                '>',
586
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
587
-            );
588
-        } else {
589
-            $where_params['Datetime.DTT_EVT_end'] = array(
590
-                '>',
591
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
592
-            );
593
-        }
594
-        $query_params[0] = $where_params;
595
-        // don't use $query_params with count()
596
-        // because we don't want to include additional query clauses like "GROUP BY"
597
-        return $count
598
-            ? $this->count(array($where_params), 'EVT_ID', true)
599
-            : $this->get_all($query_params);
600
-    }
601
-
602
-
603
-
604
-    /**
605
-     * get all events that are published and have an event start time later than now
606
-     *
607
-     * @param  array $query_params An array of query params to further filter on
608
-     *                             (Note that status and DTT_EVT_start will be overridden)
609
-     * @param bool   $count        whether to return the count or not (default FALSE)
610
-     * @return EE_Event[]|int
611
-     * @throws \EE_Error
612
-     */
613
-    public function get_upcoming_events($query_params, $count = false)
614
-    {
615
-        if (array_key_exists(0, $query_params)) {
616
-            $where_params = $query_params[0];
617
-            unset($query_params[0]);
618
-        } else {
619
-            $where_params = array();
620
-        }
621
-        // if we have count make sure we don't include group by
622
-        if ($count && isset($query_params['group_by'])) {
623
-            unset($query_params['group_by']);
624
-        }
625
-        // let's add specific query_params for active_events
626
-        // keep in mind this will override any sent status in the query AND any date queries.
627
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
628
-        // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
629
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
630
-            $where_params['Datetime.DTT_EVT_start*****'] = array(
631
-                '>',
632
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
633
-            );
634
-        } else {
635
-            $where_params['Datetime.DTT_EVT_start'] = array(
636
-                '>',
637
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
638
-            );
639
-        }
640
-        $query_params[0] = $where_params;
641
-        // don't use $query_params with count()
642
-        // because we don't want to include additional query clauses like "GROUP BY"
643
-        return $count
644
-            ? $this->count(array($where_params), 'EVT_ID', true)
645
-            : $this->get_all($query_params);
646
-    }
647
-
648
-
649
-
650
-    /**
651
-     * Gets all events that are published
652
-     * and have an event end time later than now
653
-     *
654
-     * @param  array $query_params An array of query params to further filter on
655
-     *                             (note that status and DTT_EVT_end will be overridden)
656
-     * @param bool   $count        whether to return the count or not (default FALSE)
657
-     * @return EE_Event[]|int
658
-     * @throws \EE_Error
659
-     */
660
-    public function get_active_and_upcoming_events($query_params, $count = false)
661
-    {
662
-        if (array_key_exists(0, $query_params)) {
663
-            $where_params = $query_params[0];
664
-            unset($query_params[0]);
665
-        } else {
666
-            $where_params = array();
667
-        }
668
-        // if we have count make sure we don't include group by
669
-        if ($count && isset($query_params['group_by'])) {
670
-            unset($query_params['group_by']);
671
-        }
672
-        // let's add specific query_params for active_events
673
-        // keep in mind this will override any sent status in the query AND any date queries.
674
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
675
-        // add where params for DTT_EVT_end
676
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
677
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
678
-                '>',
679
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
680
-            );
681
-        } else {
682
-            $where_params['Datetime.DTT_EVT_end'] = array(
683
-                '>',
684
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
685
-            );
686
-        }
687
-        $query_params[0] = $where_params;
688
-        // don't use $query_params with count()
689
-        // because we don't want to include additional query clauses like "GROUP BY"
690
-        return $count
691
-            ? $this->count(array($where_params), 'EVT_ID', true)
692
-            : $this->get_all($query_params);
693
-    }
694
-
695
-
696
-
697
-    /**
698
-     * This only returns events that are expired.
699
-     * They may still be published but all their datetimes have expired.
700
-     *
701
-     * @param  array $query_params An array of query params to further filter on
702
-     *                             (note that status and DTT_EVT_end will be overridden)
703
-     * @param bool   $count        whether to return the count or not (default FALSE)
704
-     * @return EE_Event[]|int
705
-     * @throws \EE_Error
706
-     */
707
-    public function get_expired_events($query_params, $count = false)
708
-    {
709
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
710
-        // if we have count make sure we don't include group by
711
-        if ($count && isset($query_params['group_by'])) {
712
-            unset($query_params['group_by']);
713
-        }
714
-        // let's add specific query_params for active_events
715
-        // keep in mind this will override any sent status in the query AND any date queries.
716
-        if (isset($where_params['status'])) {
717
-            unset($where_params['status']);
718
-        }
719
-        $exclude_query = $query_params;
720
-        if (isset($exclude_query[0])) {
721
-            unset($exclude_query[0]);
722
-        }
723
-        $exclude_query[0] = array(
724
-            'Datetime.DTT_EVT_end' => array(
725
-                '>',
726
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
727
-            ),
728
-        );
729
-        // first get all events that have datetimes where its not expired.
730
-        $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
731
-        $event_ids = array_keys($event_ids);
732
-        // if we have any additional query_params, let's add them to the 'AND' condition
733
-        $and_condition = array(
734
-            'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
735
-            'EVT_ID'               => array('NOT IN', $event_ids),
736
-        );
737
-        if (isset($where_params['OR'])) {
738
-            $and_condition['OR'] = $where_params['OR'];
739
-            unset($where_params['OR']);
740
-        }
741
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
742
-            $and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
743
-            unset($where_params['Datetime.DTT_EVT_end']);
744
-        }
745
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
746
-            $and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
747
-            unset($where_params['Datetime.DTT_EVT_start']);
748
-        }
749
-        // merge remaining $where params with the and conditions.
750
-        $where_params['AND'] = array_merge($and_condition, $where_params);
751
-        $query_params[0] = $where_params;
752
-        // don't use $query_params with count()
753
-        // because we don't want to include additional query clauses like "GROUP BY"
754
-        return $count
755
-            ? $this->count(array($where_params), 'EVT_ID', true)
756
-            : $this->get_all($query_params);
757
-    }
758
-
759
-
760
-
761
-    /**
762
-     * This basically just returns the events that do not have the publish status.
763
-     *
764
-     * @param  array   $query_params An array of query params to further filter on
765
-     *                               (note that status will be overwritten)
766
-     * @param  boolean $count        whether to return the count or not (default FALSE)
767
-     * @return EE_Event[]|int
768
-     * @throws \EE_Error
769
-     */
770
-    public function get_inactive_events($query_params, $count = false)
771
-    {
772
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
773
-        // let's add in specific query_params for inactive events.
774
-        if (isset($where_params['status'])) {
775
-            unset($where_params['status']);
776
-        }
777
-        // if we have count make sure we don't include group by
778
-        if ($count && isset($query_params['group_by'])) {
779
-            unset($query_params['group_by']);
780
-        }
781
-        // if we have any additional query_params, let's add them to the 'AND' condition
782
-        $where_params['AND']['status'] = array('!=', 'publish');
783
-        if (isset($where_params['OR'])) {
784
-            $where_params['AND']['OR'] = $where_params['OR'];
785
-            unset($where_params['OR']);
786
-        }
787
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
788
-            $where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
789
-            unset($where_params['Datetime.DTT_EVT_end']);
790
-        }
791
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
792
-            $where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
793
-            unset($where_params['Datetime.DTT_EVT_start']);
794
-        }
795
-        $query_params[0] = $where_params;
796
-        // don't use $query_params with count()
797
-        // because we don't want to include additional query clauses like "GROUP BY"
798
-        return $count
799
-            ? $this->count(array($where_params), 'EVT_ID', true)
800
-            : $this->get_all($query_params);
801
-    }
802
-
803
-
804
-
805
-    /**
806
-     * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
807
-     * because we don't want to override any existing global default prices but instead insert NEW prices that get
808
-     * attached to the event. See parent for param descriptions
809
-     *
810
-     * @param        $id_or_obj
811
-     * @param        $other_model_id_or_obj
812
-     * @param string $relationName
813
-     * @param array  $where_query
814
-     * @return EE_Base_Class
815
-     * @throws EE_Error
816
-     */
817
-    public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
818
-    {
819
-        if ($relationName === 'Price') {
820
-            // let's get the PRC object for the given ID to make sure that we aren't dealing with a default
821
-            $prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
822
-            // if EVT_ID = 0, then this is a default
823
-            if ((int) $prc_chk->get('EVT_ID') === 0) {
824
-                // let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
825
-                $prc_chk->set('PRC_ID', 0);
826
-            }
827
-            // run parent
828
-            return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
829
-        }
830
-        // otherwise carry on as normal
831
-        return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
832
-    }
833
-
834
-
835
-
836
-    /******************** DEPRECATED METHODS ********************/
837
-
838
-
839
-
840
-    /**
841
-     * _get_question_target_db_column
842
-     *
843
-     * @deprecated as of 4.8.32.rc.001. Instead consider using
844
-     *             EE_Registration_Custom_Questions_Form located in
845
-     *             admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
846
-     * @access     public
847
-     * @param    EE_Registration $registration (so existing answers for registration are included)
848
-     * @param    int             $EVT_ID       so all question groups are included for event (not just answers from
849
-     *                                         registration).
850
-     * @throws EE_Error
851
-     * @return    array
852
-     */
853
-    public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
854
-    {
855
-        if (empty($EVT_ID)) {
856
-            throw new EE_Error(__(
857
-                'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
858
-                'event_espresso'
859
-            ));
860
-        }
861
-        $questions = array();
862
-        // get all question groups for event
863
-        $qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
864
-        if (! empty($qgs)) {
865
-            foreach ($qgs as $qg) {
866
-                $qsts = $qg->questions();
867
-                $questions[ $qg->ID() ] = $qg->model_field_array();
868
-                $questions[ $qg->ID() ]['QSG_questions'] = array();
869
-                foreach ($qsts as $qst) {
870
-                    if ($qst->is_system_question()) {
871
-                        continue;
872
-                    }
873
-                    $answer = EEM_Answer::instance()->get_one(array(
874
-                        array(
875
-                            'QST_ID' => $qst->ID(),
876
-                            'REG_ID' => $registration->ID(),
877
-                        ),
878
-                    ));
879
-                    $answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
880
-                    $qst_name = $qstn_id = $qst->ID();
881
-                    $ans_id = $answer->ID();
882
-                    $qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
883
-                    $input_name = '';
884
-                    $input_id = sanitize_key($qst->display_text());
885
-                    $input_class = '';
886
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
887
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
888
-                                                                                           . $input_name
889
-                                                                                           . $qst_name;
890
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
891
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
892
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
893
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
894
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
895
-                    // leave responses as-is, don't convert stuff into html entities please!
896
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
897
-                    if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
898
-                        $QSOs = $qst->options(true, $answer->value());
899
-                        if (is_array($QSOs)) {
900
-                            foreach ($QSOs as $QSO_ID => $QSO) {
901
-                                $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
902
-                            }
903
-                        }
904
-                    }
905
-                }
906
-            }
907
-        }
908
-        return $questions;
909
-    }
910
-
911
-
912
-    /**
913
-     * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
914
-     *                             or an stdClass where each property is the name of a column,
915
-     * @return EE_Base_Class
916
-     * @throws \EE_Error
917
-     */
918
-    public function instantiate_class_from_array_or_object($cols_n_values)
919
-    {
920
-        $classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
921
-        if ($classInstance instanceof EE_Event) {
922
-            // events have their timezone defined in the DB, so use it immediately
923
-            $this->set_timezone($classInstance->get_timezone());
924
-        }
925
-        return $classInstance;
926
-    }
18
+	/**
19
+	 * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
20
+	 * event
21
+	 */
22
+	const sold_out = 'sold_out';
23
+
24
+	/**
25
+	 * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
26
+	 * date)
27
+	 */
28
+	const postponed = 'postponed';
29
+
30
+	/**
31
+	 * constant used by status(), indicating that the event will no longer occur
32
+	 */
33
+	const cancelled = 'cancelled';
34
+
35
+
36
+	/**
37
+	 * @var string
38
+	 */
39
+	protected static $_default_reg_status;
40
+
41
+
42
+	/**
43
+	 * This is the default for the additional limit field.
44
+	 * @var int
45
+	 */
46
+	protected static $_default_additional_limit = 10;
47
+
48
+
49
+	/**
50
+	 * private instance of the Event object
51
+	 *
52
+	 * @var EEM_Event
53
+	 */
54
+	protected static $_instance;
55
+
56
+
57
+
58
+
59
+	/**
60
+	 * Adds a relationship to Term_Taxonomy for each CPT_Base
61
+	 *
62
+	 * @param string $timezone
63
+	 * @throws \EE_Error
64
+	 */
65
+	protected function __construct($timezone = null)
66
+	{
67
+		EE_Registry::instance()->load_model('Registration');
68
+		$this->singular_item = esc_html__('Event', 'event_espresso');
69
+		$this->plural_item = esc_html__('Events', 'event_espresso');
70
+		// to remove Cancelled events from the frontend, copy the following filter to your functions.php file
71
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
72
+		// to remove Postponed events from the frontend, copy the following filter to your functions.php file
73
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
74
+		// to remove Sold Out events from the frontend, copy the following filter to your functions.php file
75
+		//  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
76
+		$this->_custom_stati = apply_filters(
77
+			'AFEE__EEM_Event__construct___custom_stati',
78
+			array(
79
+				EEM_Event::cancelled => array(
80
+					'label'  => esc_html__('Cancelled', 'event_espresso'),
81
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
82
+				),
83
+				EEM_Event::postponed => array(
84
+					'label'  => esc_html__('Postponed', 'event_espresso'),
85
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
86
+				),
87
+				EEM_Event::sold_out  => array(
88
+					'label'  => esc_html__('Sold Out', 'event_espresso'),
89
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
90
+				),
91
+			)
92
+		);
93
+		self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
94
+			: self::$_default_reg_status;
95
+		$this->_tables = array(
96
+			'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
97
+			'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
98
+		);
99
+		$this->_fields = array(
100
+			'Event_CPT'  => array(
101
+				'EVT_ID'         => new EE_Primary_Key_Int_Field(
102
+					'ID',
103
+					esc_html__('Post ID for Event', 'event_espresso')
104
+				),
105
+				'EVT_name'       => new EE_Plain_Text_Field(
106
+					'post_title',
107
+					esc_html__('Event Name', 'event_espresso'),
108
+					false,
109
+					''
110
+				),
111
+				'EVT_desc'       => new EE_Post_Content_Field(
112
+					'post_content',
113
+					esc_html__('Event Description', 'event_espresso'),
114
+					false,
115
+					''
116
+				),
117
+				'EVT_slug'       => new EE_Slug_Field(
118
+					'post_name',
119
+					esc_html__('Event Slug', 'event_espresso'),
120
+					false,
121
+					''
122
+				),
123
+				'EVT_created'    => new EE_Datetime_Field(
124
+					'post_date',
125
+					esc_html__('Date/Time Event Created', 'event_espresso'),
126
+					false,
127
+					EE_Datetime_Field::now
128
+				),
129
+				'EVT_short_desc' => new EE_Simple_HTML_Field(
130
+					'post_excerpt',
131
+					esc_html__('Event Short Description', 'event_espresso'),
132
+					false,
133
+					''
134
+				),
135
+				'EVT_modified'   => new EE_Datetime_Field(
136
+					'post_modified',
137
+					esc_html__('Date/Time Event Modified', 'event_espresso'),
138
+					false,
139
+					EE_Datetime_Field::now
140
+				),
141
+				'EVT_wp_user'    => new EE_WP_User_Field(
142
+					'post_author',
143
+					esc_html__('Event Creator ID', 'event_espresso'),
144
+					false
145
+				),
146
+				'parent'         => new EE_Integer_Field(
147
+					'post_parent',
148
+					esc_html__('Event Parent ID', 'event_espresso'),
149
+					false,
150
+					0
151
+				),
152
+				'EVT_order'      => new EE_Integer_Field(
153
+					'menu_order',
154
+					esc_html__('Event Menu Order', 'event_espresso'),
155
+					false,
156
+					1
157
+				),
158
+				'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
159
+				// EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
160
+				'status'         => new EE_WP_Post_Status_Field(
161
+					'post_status',
162
+					esc_html__('Event Status', 'event_espresso'),
163
+					false,
164
+					'draft',
165
+					$this->_custom_stati
166
+				),
167
+				'password' => new EE_Password_Field(
168
+					'post_password',
169
+					__('Password', 'event_espresso'),
170
+					false,
171
+					'',
172
+					array(
173
+						'EVT_desc',
174
+						'EVT_short_desc',
175
+						'EVT_display_desc',
176
+						'EVT_display_ticket_selector',
177
+						'EVT_visible_on',
178
+						'EVT_additional_limit',
179
+						'EVT_default_registration_status',
180
+						'EVT_member_only',
181
+						'EVT_phone',
182
+						'EVT_allow_overflow',
183
+						'EVT_timezone_string',
184
+						'EVT_external_URL',
185
+						'EVT_donations'
186
+					)
187
+				)
188
+			),
189
+			'Event_Meta' => array(
190
+				'EVTM_ID'                         => new EE_DB_Only_Float_Field(
191
+					'EVTM_ID',
192
+					esc_html__('Event Meta Row ID', 'event_espresso'),
193
+					false
194
+				),
195
+				'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
196
+					'EVT_ID',
197
+					esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
198
+					false
199
+				),
200
+				'EVT_display_desc'                => new EE_Boolean_Field(
201
+					'EVT_display_desc',
202
+					esc_html__('Display Description Flag', 'event_espresso'),
203
+					false,
204
+					true
205
+				),
206
+				'EVT_display_ticket_selector'     => new EE_Boolean_Field(
207
+					'EVT_display_ticket_selector',
208
+					esc_html__('Display Ticket Selector Flag', 'event_espresso'),
209
+					false,
210
+					true
211
+				),
212
+				'EVT_visible_on'                  => new EE_Datetime_Field(
213
+					'EVT_visible_on',
214
+					esc_html__('Event Visible Date', 'event_espresso'),
215
+					true,
216
+					EE_Datetime_Field::now
217
+				),
218
+				'EVT_additional_limit'            => new EE_Integer_Field(
219
+					'EVT_additional_limit',
220
+					esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
221
+					true,
222
+					self::$_default_additional_limit
223
+				),
224
+				'EVT_default_registration_status' => new EE_Enum_Text_Field(
225
+					'EVT_default_registration_status',
226
+					esc_html__('Default Registration Status on this Event', 'event_espresso'),
227
+					false,
228
+					EEM_Event::$_default_reg_status,
229
+					EEM_Registration::reg_status_array()
230
+				),
231
+				'EVT_member_only'                 => new EE_Boolean_Field(
232
+					'EVT_member_only',
233
+					esc_html__('Member-Only Event Flag', 'event_espresso'),
234
+					false,
235
+					false
236
+				),
237
+				'EVT_phone'                       => new EE_Plain_Text_Field(
238
+					'EVT_phone',
239
+					esc_html__('Event Phone Number', 'event_espresso'),
240
+					false,
241
+					''
242
+				),
243
+				'EVT_allow_overflow'              => new EE_Boolean_Field(
244
+					'EVT_allow_overflow',
245
+					esc_html__('Allow Overflow on Event', 'event_espresso'),
246
+					false,
247
+					false
248
+				),
249
+				'EVT_timezone_string'             => new EE_Plain_Text_Field(
250
+					'EVT_timezone_string',
251
+					esc_html__('Timezone (name) for Event times', 'event_espresso'),
252
+					false,
253
+					''
254
+				),
255
+				'EVT_external_URL'                => new EE_Plain_Text_Field(
256
+					'EVT_external_URL',
257
+					esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
258
+					true
259
+				),
260
+				'EVT_donations'                   => new EE_Boolean_Field(
261
+					'EVT_donations',
262
+					esc_html__('Accept Donations?', 'event_espresso'),
263
+					false,
264
+					false
265
+				),
266
+			),
267
+		);
268
+		$this->_model_relations = array(
269
+			'Registration'           => new EE_Has_Many_Relation(),
270
+			'Datetime'               => new EE_Has_Many_Relation(),
271
+			'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
272
+			'Event_Question_Group'   => new EE_Has_Many_Relation(),
273
+			'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
274
+			'Term_Relationship'      => new EE_Has_Many_Relation(),
275
+			'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
276
+			'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
277
+			'Attendee'               => new EE_HABTM_Relation('Registration'),
278
+			'WP_User'                => new EE_Belongs_To_Relation(),
279
+		);
280
+		// this model is generally available for reading
281
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
282
+		$this->model_chain_to_password = '';
283
+		parent::__construct($timezone);
284
+	}
285
+
286
+
287
+
288
+	/**
289
+	 * @param string $default_reg_status
290
+	 */
291
+	public static function set_default_reg_status($default_reg_status)
292
+	{
293
+		self::$_default_reg_status = $default_reg_status;
294
+		// if EEM_Event has already been instantiated,
295
+		// then we need to reset the `EVT_default_reg_status` field to use the new default.
296
+		if (self::$_instance instanceof EEM_Event) {
297
+			$default_reg_status = new EE_Enum_Text_Field(
298
+				'EVT_default_registration_status',
299
+				esc_html__('Default Registration Status on this Event', 'event_espresso'),
300
+				false,
301
+				$default_reg_status,
302
+				EEM_Registration::reg_status_array()
303
+			);
304
+			$default_reg_status->_construct_finalize(
305
+				'Event_Meta',
306
+				'EVT_default_registration_status',
307
+				'EEM_Event'
308
+			);
309
+			self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
310
+		}
311
+	}
312
+
313
+
314
+	/**
315
+	 * Used to override the default for the additional limit field.
316
+	 * @param $additional_limit
317
+	 */
318
+	public static function set_default_additional_limit($additional_limit)
319
+	{
320
+		self::$_default_additional_limit = (int) $additional_limit;
321
+		if (self::$_instance instanceof EEM_Event) {
322
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
323
+				'EVT_additional_limit',
324
+				__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
325
+				true,
326
+				self::$_default_additional_limit
327
+			);
328
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
329
+				'Event_Meta',
330
+				'EVT_additional_limit',
331
+				'EEM_Event'
332
+			);
333
+		}
334
+	}
335
+
336
+
337
+	/**
338
+	 * Return what is currently set as the default additional limit for the event.
339
+	 * @return int
340
+	 */
341
+	public static function get_default_additional_limit()
342
+	{
343
+		return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
344
+	}
345
+
346
+
347
+	/**
348
+	 * get_question_groups
349
+	 *
350
+	 * @return array
351
+	 * @throws \EE_Error
352
+	 */
353
+	public function get_all_question_groups()
354
+	{
355
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
356
+			array(
357
+				array('QSG_deleted' => false),
358
+				'order_by' => array('QSG_order' => 'ASC'),
359
+			)
360
+		);
361
+	}
362
+
363
+
364
+
365
+	/**
366
+	 * get_question_groups
367
+	 *
368
+	 * @param int $EVT_ID
369
+	 * @return array|bool
370
+	 * @throws \EE_Error
371
+	 */
372
+	public function get_all_event_question_groups($EVT_ID = 0)
373
+	{
374
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
375
+			EE_Error::add_error(
376
+				esc_html__(
377
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
378
+					'event_espresso'
379
+				),
380
+				__FILE__,
381
+				__FUNCTION__,
382
+				__LINE__
383
+			);
384
+			return false;
385
+		}
386
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
387
+			array(
388
+				array('EVT_ID' => $EVT_ID),
389
+			)
390
+		);
391
+	}
392
+
393
+
394
+	/**
395
+	 * get_question_groups
396
+	 *
397
+	 * @param int $EVT_ID
398
+	 * @param boolean $for_primary_attendee
399
+	 * @return array|bool
400
+	 * @throws EE_Error
401
+	 * @throws InvalidArgumentException
402
+	 * @throws ReflectionException
403
+	 * @throws InvalidDataTypeException
404
+	 * @throws InvalidInterfaceException
405
+	 */
406
+	public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
407
+	{
408
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
409
+			EE_Error::add_error(
410
+				esc_html__(
411
+					// @codingStandardsIgnoreStart
412
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
413
+					// @codingStandardsIgnoreEnd
414
+					'event_espresso'
415
+				),
416
+				__FILE__,
417
+				__FUNCTION__,
418
+				__LINE__
419
+			);
420
+			return false;
421
+		}
422
+		$query_params = [
423
+			[
424
+				'EVT_ID' => $EVT_ID,
425
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true
426
+			]
427
+		];
428
+		if ($for_primary_attendee) {
429
+			$query_params[0]['EQG_primary'] = true;
430
+		} else {
431
+			$query_params[0]['EQG_additional'] = true;
432
+		}
433
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
434
+	}
435
+
436
+
437
+	/**
438
+	 * get_question_groups
439
+	 *
440
+	 * @param int $EVT_ID
441
+	 * @param EE_Registration $registration
442
+	 * @return array|bool
443
+	 * @throws EE_Error
444
+	 * @throws InvalidArgumentException
445
+	 * @throws InvalidDataTypeException
446
+	 * @throws InvalidInterfaceException
447
+	 * @throws ReflectionException
448
+	 */
449
+	public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
450
+	{
451
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
452
+			EE_Error::add_error(
453
+				esc_html__(
454
+					'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
455
+					'event_espresso'
456
+				),
457
+				__FILE__,
458
+				__FUNCTION__,
459
+				__LINE__
460
+			);
461
+			return false;
462
+		}
463
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
464
+			[
465
+				[
466
+					'Event_Question_Group.EVT_ID'      => $EVT_ID,
467
+					'Event_Question_Group.'
468
+						. EEM_Event_Question_Group::instance()->fieldNameForContext(
469
+							$registration->is_primary_registrant()
470
+						) => true
471
+				],
472
+				'order_by' => ['QSG_order' => 'ASC'],
473
+			]
474
+		);
475
+	}
476
+
477
+
478
+
479
+	/**
480
+	 * get_question_target_db_column
481
+	 *
482
+	 * @param string $QSG_IDs csv list of $QSG IDs
483
+	 * @return array|bool
484
+	 * @throws \EE_Error
485
+	 */
486
+	public function get_questions_in_groups($QSG_IDs = '')
487
+	{
488
+		if (empty($QSG_IDs)) {
489
+			EE_Error::add_error(
490
+				esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
491
+				__FILE__,
492
+				__FUNCTION__,
493
+				__LINE__
494
+			);
495
+			return false;
496
+		}
497
+		return EE_Registry::instance()->load_model('Question')->get_all(
498
+			array(
499
+				array(
500
+					'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
501
+					'QST_deleted'           => false,
502
+					'QST_admin_only'        => is_admin(),
503
+				),
504
+				'order_by' => 'QST_order',
505
+			)
506
+		);
507
+	}
508
+
509
+
510
+
511
+	/**
512
+	 * get_options_for_question
513
+	 *
514
+	 * @param string $QST_IDs csv list of $QST IDs
515
+	 * @return array|bool
516
+	 * @throws \EE_Error
517
+	 */
518
+	public function get_options_for_question($QST_IDs)
519
+	{
520
+		if (empty($QST_IDs)) {
521
+			EE_Error::add_error(
522
+				esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
523
+				__FILE__,
524
+				__FUNCTION__,
525
+				__LINE__
526
+			);
527
+			return false;
528
+		}
529
+		return EE_Registry::instance()->load_model('Question_Option')->get_all(
530
+			array(
531
+				array(
532
+					'Question.QST_ID' => array('IN', $QST_IDs),
533
+					'QSO_deleted'     => false,
534
+				),
535
+				'order_by' => 'QSO_ID',
536
+			)
537
+		);
538
+	}
539
+
540
+
541
+
542
+
543
+
544
+
545
+
546
+	/**
547
+	 * Gets all events that are published
548
+	 * and have event start time earlier than now and an event end time later than now
549
+	 *
550
+	 * @param  array $query_params An array of query params to further filter on
551
+	 *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
552
+	 * @param bool   $count        whether to return the count or not (default FALSE)
553
+	 * @return EE_Event[]|int
554
+	 * @throws \EE_Error
555
+	 */
556
+	public function get_active_events($query_params, $count = false)
557
+	{
558
+		if (array_key_exists(0, $query_params)) {
559
+			$where_params = $query_params[0];
560
+			unset($query_params[0]);
561
+		} else {
562
+			$where_params = array();
563
+		}
564
+		// if we have count make sure we don't include group by
565
+		if ($count && isset($query_params['group_by'])) {
566
+			unset($query_params['group_by']);
567
+		}
568
+		// let's add specific query_params for active_events
569
+		// keep in mind this will override any sent status in the query AND any date queries.
570
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
571
+		// if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
572
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
573
+			$where_params['Datetime.DTT_EVT_start******'] = array(
574
+				'<',
575
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
576
+			);
577
+		} else {
578
+			$where_params['Datetime.DTT_EVT_start'] = array(
579
+				'<',
580
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
581
+			);
582
+		}
583
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
584
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
585
+				'>',
586
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
587
+			);
588
+		} else {
589
+			$where_params['Datetime.DTT_EVT_end'] = array(
590
+				'>',
591
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
592
+			);
593
+		}
594
+		$query_params[0] = $where_params;
595
+		// don't use $query_params with count()
596
+		// because we don't want to include additional query clauses like "GROUP BY"
597
+		return $count
598
+			? $this->count(array($where_params), 'EVT_ID', true)
599
+			: $this->get_all($query_params);
600
+	}
601
+
602
+
603
+
604
+	/**
605
+	 * get all events that are published and have an event start time later than now
606
+	 *
607
+	 * @param  array $query_params An array of query params to further filter on
608
+	 *                             (Note that status and DTT_EVT_start will be overridden)
609
+	 * @param bool   $count        whether to return the count or not (default FALSE)
610
+	 * @return EE_Event[]|int
611
+	 * @throws \EE_Error
612
+	 */
613
+	public function get_upcoming_events($query_params, $count = false)
614
+	{
615
+		if (array_key_exists(0, $query_params)) {
616
+			$where_params = $query_params[0];
617
+			unset($query_params[0]);
618
+		} else {
619
+			$where_params = array();
620
+		}
621
+		// if we have count make sure we don't include group by
622
+		if ($count && isset($query_params['group_by'])) {
623
+			unset($query_params['group_by']);
624
+		}
625
+		// let's add specific query_params for active_events
626
+		// keep in mind this will override any sent status in the query AND any date queries.
627
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
628
+		// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
629
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
630
+			$where_params['Datetime.DTT_EVT_start*****'] = array(
631
+				'>',
632
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
633
+			);
634
+		} else {
635
+			$where_params['Datetime.DTT_EVT_start'] = array(
636
+				'>',
637
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
638
+			);
639
+		}
640
+		$query_params[0] = $where_params;
641
+		// don't use $query_params with count()
642
+		// because we don't want to include additional query clauses like "GROUP BY"
643
+		return $count
644
+			? $this->count(array($where_params), 'EVT_ID', true)
645
+			: $this->get_all($query_params);
646
+	}
647
+
648
+
649
+
650
+	/**
651
+	 * Gets all events that are published
652
+	 * and have an event end time later than now
653
+	 *
654
+	 * @param  array $query_params An array of query params to further filter on
655
+	 *                             (note that status and DTT_EVT_end will be overridden)
656
+	 * @param bool   $count        whether to return the count or not (default FALSE)
657
+	 * @return EE_Event[]|int
658
+	 * @throws \EE_Error
659
+	 */
660
+	public function get_active_and_upcoming_events($query_params, $count = false)
661
+	{
662
+		if (array_key_exists(0, $query_params)) {
663
+			$where_params = $query_params[0];
664
+			unset($query_params[0]);
665
+		} else {
666
+			$where_params = array();
667
+		}
668
+		// if we have count make sure we don't include group by
669
+		if ($count && isset($query_params['group_by'])) {
670
+			unset($query_params['group_by']);
671
+		}
672
+		// let's add specific query_params for active_events
673
+		// keep in mind this will override any sent status in the query AND any date queries.
674
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
675
+		// add where params for DTT_EVT_end
676
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
677
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
678
+				'>',
679
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
680
+			);
681
+		} else {
682
+			$where_params['Datetime.DTT_EVT_end'] = array(
683
+				'>',
684
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
685
+			);
686
+		}
687
+		$query_params[0] = $where_params;
688
+		// don't use $query_params with count()
689
+		// because we don't want to include additional query clauses like "GROUP BY"
690
+		return $count
691
+			? $this->count(array($where_params), 'EVT_ID', true)
692
+			: $this->get_all($query_params);
693
+	}
694
+
695
+
696
+
697
+	/**
698
+	 * This only returns events that are expired.
699
+	 * They may still be published but all their datetimes have expired.
700
+	 *
701
+	 * @param  array $query_params An array of query params to further filter on
702
+	 *                             (note that status and DTT_EVT_end will be overridden)
703
+	 * @param bool   $count        whether to return the count or not (default FALSE)
704
+	 * @return EE_Event[]|int
705
+	 * @throws \EE_Error
706
+	 */
707
+	public function get_expired_events($query_params, $count = false)
708
+	{
709
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
710
+		// if we have count make sure we don't include group by
711
+		if ($count && isset($query_params['group_by'])) {
712
+			unset($query_params['group_by']);
713
+		}
714
+		// let's add specific query_params for active_events
715
+		// keep in mind this will override any sent status in the query AND any date queries.
716
+		if (isset($where_params['status'])) {
717
+			unset($where_params['status']);
718
+		}
719
+		$exclude_query = $query_params;
720
+		if (isset($exclude_query[0])) {
721
+			unset($exclude_query[0]);
722
+		}
723
+		$exclude_query[0] = array(
724
+			'Datetime.DTT_EVT_end' => array(
725
+				'>',
726
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
727
+			),
728
+		);
729
+		// first get all events that have datetimes where its not expired.
730
+		$event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
731
+		$event_ids = array_keys($event_ids);
732
+		// if we have any additional query_params, let's add them to the 'AND' condition
733
+		$and_condition = array(
734
+			'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
735
+			'EVT_ID'               => array('NOT IN', $event_ids),
736
+		);
737
+		if (isset($where_params['OR'])) {
738
+			$and_condition['OR'] = $where_params['OR'];
739
+			unset($where_params['OR']);
740
+		}
741
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
742
+			$and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
743
+			unset($where_params['Datetime.DTT_EVT_end']);
744
+		}
745
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
746
+			$and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
747
+			unset($where_params['Datetime.DTT_EVT_start']);
748
+		}
749
+		// merge remaining $where params with the and conditions.
750
+		$where_params['AND'] = array_merge($and_condition, $where_params);
751
+		$query_params[0] = $where_params;
752
+		// don't use $query_params with count()
753
+		// because we don't want to include additional query clauses like "GROUP BY"
754
+		return $count
755
+			? $this->count(array($where_params), 'EVT_ID', true)
756
+			: $this->get_all($query_params);
757
+	}
758
+
759
+
760
+
761
+	/**
762
+	 * This basically just returns the events that do not have the publish status.
763
+	 *
764
+	 * @param  array   $query_params An array of query params to further filter on
765
+	 *                               (note that status will be overwritten)
766
+	 * @param  boolean $count        whether to return the count or not (default FALSE)
767
+	 * @return EE_Event[]|int
768
+	 * @throws \EE_Error
769
+	 */
770
+	public function get_inactive_events($query_params, $count = false)
771
+	{
772
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
773
+		// let's add in specific query_params for inactive events.
774
+		if (isset($where_params['status'])) {
775
+			unset($where_params['status']);
776
+		}
777
+		// if we have count make sure we don't include group by
778
+		if ($count && isset($query_params['group_by'])) {
779
+			unset($query_params['group_by']);
780
+		}
781
+		// if we have any additional query_params, let's add them to the 'AND' condition
782
+		$where_params['AND']['status'] = array('!=', 'publish');
783
+		if (isset($where_params['OR'])) {
784
+			$where_params['AND']['OR'] = $where_params['OR'];
785
+			unset($where_params['OR']);
786
+		}
787
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
788
+			$where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
789
+			unset($where_params['Datetime.DTT_EVT_end']);
790
+		}
791
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
792
+			$where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
793
+			unset($where_params['Datetime.DTT_EVT_start']);
794
+		}
795
+		$query_params[0] = $where_params;
796
+		// don't use $query_params with count()
797
+		// because we don't want to include additional query clauses like "GROUP BY"
798
+		return $count
799
+			? $this->count(array($where_params), 'EVT_ID', true)
800
+			: $this->get_all($query_params);
801
+	}
802
+
803
+
804
+
805
+	/**
806
+	 * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
807
+	 * because we don't want to override any existing global default prices but instead insert NEW prices that get
808
+	 * attached to the event. See parent for param descriptions
809
+	 *
810
+	 * @param        $id_or_obj
811
+	 * @param        $other_model_id_or_obj
812
+	 * @param string $relationName
813
+	 * @param array  $where_query
814
+	 * @return EE_Base_Class
815
+	 * @throws EE_Error
816
+	 */
817
+	public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
818
+	{
819
+		if ($relationName === 'Price') {
820
+			// let's get the PRC object for the given ID to make sure that we aren't dealing with a default
821
+			$prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
822
+			// if EVT_ID = 0, then this is a default
823
+			if ((int) $prc_chk->get('EVT_ID') === 0) {
824
+				// let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
825
+				$prc_chk->set('PRC_ID', 0);
826
+			}
827
+			// run parent
828
+			return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
829
+		}
830
+		// otherwise carry on as normal
831
+		return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
832
+	}
833
+
834
+
835
+
836
+	/******************** DEPRECATED METHODS ********************/
837
+
838
+
839
+
840
+	/**
841
+	 * _get_question_target_db_column
842
+	 *
843
+	 * @deprecated as of 4.8.32.rc.001. Instead consider using
844
+	 *             EE_Registration_Custom_Questions_Form located in
845
+	 *             admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
846
+	 * @access     public
847
+	 * @param    EE_Registration $registration (so existing answers for registration are included)
848
+	 * @param    int             $EVT_ID       so all question groups are included for event (not just answers from
849
+	 *                                         registration).
850
+	 * @throws EE_Error
851
+	 * @return    array
852
+	 */
853
+	public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
854
+	{
855
+		if (empty($EVT_ID)) {
856
+			throw new EE_Error(__(
857
+				'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
858
+				'event_espresso'
859
+			));
860
+		}
861
+		$questions = array();
862
+		// get all question groups for event
863
+		$qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
864
+		if (! empty($qgs)) {
865
+			foreach ($qgs as $qg) {
866
+				$qsts = $qg->questions();
867
+				$questions[ $qg->ID() ] = $qg->model_field_array();
868
+				$questions[ $qg->ID() ]['QSG_questions'] = array();
869
+				foreach ($qsts as $qst) {
870
+					if ($qst->is_system_question()) {
871
+						continue;
872
+					}
873
+					$answer = EEM_Answer::instance()->get_one(array(
874
+						array(
875
+							'QST_ID' => $qst->ID(),
876
+							'REG_ID' => $registration->ID(),
877
+						),
878
+					));
879
+					$answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
880
+					$qst_name = $qstn_id = $qst->ID();
881
+					$ans_id = $answer->ID();
882
+					$qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
883
+					$input_name = '';
884
+					$input_id = sanitize_key($qst->display_text());
885
+					$input_class = '';
886
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
887
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
888
+																						   . $input_name
889
+																						   . $qst_name;
890
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
891
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
892
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
893
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
894
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
895
+					// leave responses as-is, don't convert stuff into html entities please!
896
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
897
+					if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
898
+						$QSOs = $qst->options(true, $answer->value());
899
+						if (is_array($QSOs)) {
900
+							foreach ($QSOs as $QSO_ID => $QSO) {
901
+								$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
902
+							}
903
+						}
904
+					}
905
+				}
906
+			}
907
+		}
908
+		return $questions;
909
+	}
910
+
911
+
912
+	/**
913
+	 * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
914
+	 *                             or an stdClass where each property is the name of a column,
915
+	 * @return EE_Base_Class
916
+	 * @throws \EE_Error
917
+	 */
918
+	public function instantiate_class_from_array_or_object($cols_n_values)
919
+	{
920
+		$classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
921
+		if ($classInstance instanceof EE_Event) {
922
+			// events have their timezone defined in the DB, so use it immediately
923
+			$this->set_timezone($classInstance->get_timezone());
924
+		}
925
+		return $classInstance;
926
+	}
927 927
 }
Please login to merge, or discard this patch.
registration_form/espresso_events_Registration_Form_Hooks.class.php 1 patch
Indentation   +192 added lines, -192 removed lines patch added patch discarded remove patch
@@ -16,210 +16,210 @@
 block discarded – undo
16 16
 class espresso_events_Registration_Form_Hooks extends EE_Admin_Hooks
17 17
 {
18 18
 
19
-    /**
20
-     * @var EE_Event|null
21
-     */
22
-    protected $_event;
23
-
24
-
25
-    protected function _set_hooks_properties()
26
-    {
27
-
28
-        $this->_name = 'registration_form';
29
-        $this->_metaboxes = array(
30
-            0 => array(
31
-                'page_route' => array('edit', 'create_new'),
32
-                'func'       => 'primary_questions',
33
-                'label'      => esc_html__('Questions for Primary Registrant', 'event_espresso'),
34
-                'priority'   => 'default',
35
-                'context'    => 'side',
36
-            ),
37
-        );
38
-
39
-        // hook into the handler for saving question groups
40
-        add_filter(
41
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
42
-            array($this, 'modify_callbacks'),
43
-            10
44
-        );
45
-
46
-        // hook into revision restores (we're hooking into the global action because EE_Admin_Hooks classes are already
47
-        // restricted by page)
48
-        add_action('AHEE_EE_Admin_Page_CPT__restore_revision', array($this, 'restore_revision'), 10, 2);
49
-    }
50
-
51
-
52
-    /**
53
-     * Callback for FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks hook
54
-     *
55
-     * @param $callbacks
56
-     * @return array
57
-     */
58
-    public function modify_callbacks($callbacks)
59
-    {
60
-        // now let's add the question group callback
61
-        $callbacks[] = array($this, 'primary_question_group_update');
62
-        return $callbacks;
63
-    }
64
-
65
-
66
-    /**
67
-     * Hooked into revision restores.
68
-     *
69
-     * @param $post_id
70
-     * @param $revision_id
71
-     * @return EE_Base_Class
72
-     * @throws EE_Error
73
-     * @throws InvalidArgumentException
74
-     * @throws ReflectionException
75
-     * @throws InvalidDataTypeException
76
-     * @throws InvalidInterfaceException
77
-     */
78
-    public function restore_revision($post_id, $revision_id)
79
-    {
80
-        $EVT_MDL = EE_Registry::instance()->load_model('Event');
81
-        $post_evt = $EVT_MDL->get_one_by_ID($post_id);
82
-        // restore revision for primary questions
83
-        $post_evt->restore_revision(
84
-            $revision_id,
85
-            ['Question_Group'],
86
-            ['Question_Group' => ['Event_Question_Group.EQG_primary' => true]]
87
-        );
88
-        return $post_evt;
89
-    }
90
-
91
-
92
-    /**
93
-     * Content of metabox.
94
-     *
95
-     * @param $post_id
96
-     * @param $post
97
-     * @throws EE_Error
98
-     * @throws InvalidArgumentException
99
-     * @throws InvalidDataTypeException
100
-     * @throws InvalidInterfaceException
101
-     */
102
-    public function primary_questions($post_id, $post)
103
-    {
104
-        $this->_event = $this->_adminpage_obj->get_event_object();
105
-        $event_id = $this->_event->ID();
106
-        ?>
19
+	/**
20
+	 * @var EE_Event|null
21
+	 */
22
+	protected $_event;
23
+
24
+
25
+	protected function _set_hooks_properties()
26
+	{
27
+
28
+		$this->_name = 'registration_form';
29
+		$this->_metaboxes = array(
30
+			0 => array(
31
+				'page_route' => array('edit', 'create_new'),
32
+				'func'       => 'primary_questions',
33
+				'label'      => esc_html__('Questions for Primary Registrant', 'event_espresso'),
34
+				'priority'   => 'default',
35
+				'context'    => 'side',
36
+			),
37
+		);
38
+
39
+		// hook into the handler for saving question groups
40
+		add_filter(
41
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
42
+			array($this, 'modify_callbacks'),
43
+			10
44
+		);
45
+
46
+		// hook into revision restores (we're hooking into the global action because EE_Admin_Hooks classes are already
47
+		// restricted by page)
48
+		add_action('AHEE_EE_Admin_Page_CPT__restore_revision', array($this, 'restore_revision'), 10, 2);
49
+	}
50
+
51
+
52
+	/**
53
+	 * Callback for FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks hook
54
+	 *
55
+	 * @param $callbacks
56
+	 * @return array
57
+	 */
58
+	public function modify_callbacks($callbacks)
59
+	{
60
+		// now let's add the question group callback
61
+		$callbacks[] = array($this, 'primary_question_group_update');
62
+		return $callbacks;
63
+	}
64
+
65
+
66
+	/**
67
+	 * Hooked into revision restores.
68
+	 *
69
+	 * @param $post_id
70
+	 * @param $revision_id
71
+	 * @return EE_Base_Class
72
+	 * @throws EE_Error
73
+	 * @throws InvalidArgumentException
74
+	 * @throws ReflectionException
75
+	 * @throws InvalidDataTypeException
76
+	 * @throws InvalidInterfaceException
77
+	 */
78
+	public function restore_revision($post_id, $revision_id)
79
+	{
80
+		$EVT_MDL = EE_Registry::instance()->load_model('Event');
81
+		$post_evt = $EVT_MDL->get_one_by_ID($post_id);
82
+		// restore revision for primary questions
83
+		$post_evt->restore_revision(
84
+			$revision_id,
85
+			['Question_Group'],
86
+			['Question_Group' => ['Event_Question_Group.EQG_primary' => true]]
87
+		);
88
+		return $post_evt;
89
+	}
90
+
91
+
92
+	/**
93
+	 * Content of metabox.
94
+	 *
95
+	 * @param $post_id
96
+	 * @param $post
97
+	 * @throws EE_Error
98
+	 * @throws InvalidArgumentException
99
+	 * @throws InvalidDataTypeException
100
+	 * @throws InvalidInterfaceException
101
+	 */
102
+	public function primary_questions($post_id, $post)
103
+	{
104
+		$this->_event = $this->_adminpage_obj->get_event_object();
105
+		$event_id = $this->_event->ID();
106
+		?>
107 107
         <div class="inside">
108 108
             <p><strong>
109 109
                     <?php _e('Question Groups', 'event_espresso'); ?>
110 110
                 </strong><br/>
111 111
                 <?php
112
-                printf(
113
-                    esc_html__(
114
-                        'Add a pre-populated %1$sgroup of questions%2$s to your event. The personal information group is required for all events',
115
-                        'event_espresso'
116
-                    ),
117
-                    '<a href="admin.php?page=espresso_registration_form" target="_blank">',
118
-                    '</a>'
119
-                )
120
-                ?>
112
+				printf(
113
+					esc_html__(
114
+						'Add a pre-populated %1$sgroup of questions%2$s to your event. The personal information group is required for all events',
115
+						'event_espresso'
116
+					),
117
+					'<a href="admin.php?page=espresso_registration_form" target="_blank">',
118
+					'</a>'
119
+				)
120
+				?>
121 121
             </p>
122 122
             <?php
123 123
 
124
-            $qsg_where['QSG_deleted'] = false;
125
-            $query_params = apply_filters(
126
-                'FHEE__espresso_events_Registration_Form_Hooks__primary_questions__question_group_query_parameters',
127
-                array($qsg_where, 'order_by' => array('QSG_order' => 'ASC'))
128
-            );
129
-            $QSGs = EEM_Question_Group::instance()->get_all($query_params);
130
-            $EQGs = ! empty($event_id)
131
-                ? $this->_event->get_many_related(
132
-                    'Question_Group',
133
-                    [['Event_Question_Group.EQG_primary' => true]]
134
-                )
135
-                : array();
136
-            $EQGids = array_keys($EQGs);
137
-
138
-            if (! empty($QSGs)) {
139
-                $html = count($QSGs) > 10 ? '<div style="height:250px;overflow:auto;">' : '';
140
-                foreach ($QSGs as $QSG) {
141
-                    $checked = in_array($QSG->ID(), $EQGids, true)
142
-                               || $QSG->get('QSG_system') === 1
143
-                        ? ' checked="checked"'
144
-                        : '';
145
-                    $visibility = $QSG->get('QSG_system') === 1
146
-                        ? ' style="visibility:hidden"'
147
-                        : '';
148
-                    $edit_query_args = $this->_adminpage_obj->is_caf() ? array(
149
-                        'action' => 'edit_question_group',
150
-                        'QSG_ID' => $QSG->ID(),
151
-                    ) : array('action' => 'question_groups');
152
-                    $edit_link = EE_Admin_Page::add_query_args_and_nonce(
153
-                        $edit_query_args,
154
-                        EE_FORMS_ADMIN_URL
155
-                    );
156
-
157
-                    $html .= '
124
+			$qsg_where['QSG_deleted'] = false;
125
+			$query_params = apply_filters(
126
+				'FHEE__espresso_events_Registration_Form_Hooks__primary_questions__question_group_query_parameters',
127
+				array($qsg_where, 'order_by' => array('QSG_order' => 'ASC'))
128
+			);
129
+			$QSGs = EEM_Question_Group::instance()->get_all($query_params);
130
+			$EQGs = ! empty($event_id)
131
+				? $this->_event->get_many_related(
132
+					'Question_Group',
133
+					[['Event_Question_Group.EQG_primary' => true]]
134
+				)
135
+				: array();
136
+			$EQGids = array_keys($EQGs);
137
+
138
+			if (! empty($QSGs)) {
139
+				$html = count($QSGs) > 10 ? '<div style="height:250px;overflow:auto;">' : '';
140
+				foreach ($QSGs as $QSG) {
141
+					$checked = in_array($QSG->ID(), $EQGids, true)
142
+							   || $QSG->get('QSG_system') === 1
143
+						? ' checked="checked"'
144
+						: '';
145
+					$visibility = $QSG->get('QSG_system') === 1
146
+						? ' style="visibility:hidden"'
147
+						: '';
148
+					$edit_query_args = $this->_adminpage_obj->is_caf() ? array(
149
+						'action' => 'edit_question_group',
150
+						'QSG_ID' => $QSG->ID(),
151
+					) : array('action' => 'question_groups');
152
+					$edit_link = EE_Admin_Page::add_query_args_and_nonce(
153
+						$edit_query_args,
154
+						EE_FORMS_ADMIN_URL
155
+					);
156
+
157
+					$html .= '
158 158
 					<p id="event-question-group-' . $QSG->ID() . '">
159 159
 						<input value="' . $QSG->ID() . '" type="checkbox"'
160
-                             . $visibility
161
-                             . ' name="question_groups[' . $QSG->ID() . ']"' . $checked . ' />
160
+							 . $visibility
161
+							 . ' name="question_groups[' . $QSG->ID() . ']"' . $checked . ' />
162 162
 						<a href="' . $edit_link . '" title="'
163
-                             . sprintf(
164
-                                 esc_attr__('Edit %s Group', 'event_espresso'),
165
-                                 $QSG->get('QSG_name')
166
-                             )
167
-                             . '" target="_blank">' . $QSG->get('QSG_name') . '</a>
163
+							 . sprintf(
164
+								 esc_attr__('Edit %s Group', 'event_espresso'),
165
+								 $QSG->get('QSG_name')
166
+							 )
167
+							 . '" target="_blank">' . $QSG->get('QSG_name') . '</a>
168 168
 					</p>';
169
-                }
170
-                $html .= count($QSGs) > 10 ? '</div>' : '';
171
-
172
-                echo $html;
173
-            } else {
174
-                esc_html_e(
175
-                    'There seems to be a problem with your questions. Please contact [email protected]',
176
-                    'event_espresso'
177
-                );
178
-            }
179
-            do_action('AHEE_event_editor_questions_notice');
180
-            ?>
169
+				}
170
+				$html .= count($QSGs) > 10 ? '</div>' : '';
171
+
172
+				echo $html;
173
+			} else {
174
+				esc_html_e(
175
+					'There seems to be a problem with your questions. Please contact [email protected]',
176
+					'event_espresso'
177
+				);
178
+			}
179
+			do_action('AHEE_event_editor_questions_notice');
180
+			?>
181 181
         </div>
182 182
         <?php
183
-    }
184
-
185
-
186
-    /**
187
-     * @param EE_Event $evtobj
188
-     * @param array    $data
189
-     * @return bool
190
-     * @throws EE_Error
191
-     */
192
-    public function primary_question_group_update($evtobj, $data)
193
-    {
194
-        $question_groups = ! empty($data['question_groups']) ? (array) $data['question_groups'] : array();
195
-        $added_qgs = array_keys($question_groups);
196
-        $success = array();
197
-
198
-        // let's get all current question groups associated with this event.
199
-        $current_qgs = $evtobj->get_many_related(
200
-            'Question_Group',
201
-            [['Event_Question_Group.EQG_primary' => true]]
202
-        );
203
-        $current_qgs = array_keys($current_qgs); // we just want the ids
204
-
205
-        // now let's get the groups selected in the editor and update (IF we have data)
206
-        if (! empty($question_groups)) {
207
-            foreach ($question_groups as $id => $val) {
208
-                // add to event
209
-                if ($val) {
210
-                    $qg = $evtobj->_add_relation_to($id, 'Question_Group', ['EQG_primary' => true]);
211
-                }
212
-                $success[] = ! empty($qg) ? 1 : 0;
213
-            }
214
-        }
215
-
216
-        // wait a minute... are there question groups missing in the saved groups that ARE with the current event?
217
-        $removed_qgs = array_diff($current_qgs, $added_qgs);
218
-
219
-        foreach ($removed_qgs as $qgid) {
220
-            $qg = $evtobj->_remove_relation_to($qgid, 'Question_Group', ['EQG_primary' => true]);
221
-            $success[] = ! empty($qg) ? 1 : 0;
222
-        }
223
-        return in_array(0, $success, true) ? false : true;
224
-    }
183
+	}
184
+
185
+
186
+	/**
187
+	 * @param EE_Event $evtobj
188
+	 * @param array    $data
189
+	 * @return bool
190
+	 * @throws EE_Error
191
+	 */
192
+	public function primary_question_group_update($evtobj, $data)
193
+	{
194
+		$question_groups = ! empty($data['question_groups']) ? (array) $data['question_groups'] : array();
195
+		$added_qgs = array_keys($question_groups);
196
+		$success = array();
197
+
198
+		// let's get all current question groups associated with this event.
199
+		$current_qgs = $evtobj->get_many_related(
200
+			'Question_Group',
201
+			[['Event_Question_Group.EQG_primary' => true]]
202
+		);
203
+		$current_qgs = array_keys($current_qgs); // we just want the ids
204
+
205
+		// now let's get the groups selected in the editor and update (IF we have data)
206
+		if (! empty($question_groups)) {
207
+			foreach ($question_groups as $id => $val) {
208
+				// add to event
209
+				if ($val) {
210
+					$qg = $evtobj->_add_relation_to($id, 'Question_Group', ['EQG_primary' => true]);
211
+				}
212
+				$success[] = ! empty($qg) ? 1 : 0;
213
+			}
214
+		}
215
+
216
+		// wait a minute... are there question groups missing in the saved groups that ARE with the current event?
217
+		$removed_qgs = array_diff($current_qgs, $added_qgs);
218
+
219
+		foreach ($removed_qgs as $qgid) {
220
+			$qg = $evtobj->_remove_relation_to($qgid, 'Question_Group', ['EQG_primary' => true]);
221
+			$success[] = ! empty($qg) ? 1 : 0;
222
+		}
223
+		return in_array(0, $success, true) ? false : true;
224
+	}
225 225
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Event_Question_Group.model.php 3 patches
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -32,10 +32,10 @@
 block discarded – undo
32 32
         );
33 33
         // this model is generally available for reading
34 34
         $path_to_event = 'Event';
35
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public($path_to_event);
36
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event);
37
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event);
38
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event, EEM_Base::caps_edit);
35
+        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Event_Related_Public($path_to_event);
36
+        $this->_cap_restriction_generators[EEM_Base::caps_read_admin] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event);
37
+        $this->_cap_restriction_generators[EEM_Base::caps_edit] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event);
38
+        $this->_cap_restriction_generators[EEM_Base::caps_delete] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event, EEM_Base::caps_edit);
39 39
         parent::__construct($timezone);
40 40
     }
41 41
 
Please login to merge, or discard this patch.
Indentation   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -7,72 +7,72 @@
 block discarded – undo
7 7
  */
8 8
 class EEM_Event_Question_Group extends EEM_Base
9 9
 {
10
-    /**
11
-     * Name of the field indicating an event should use the question group for the primary attendee
12
-     */
13
-    const PRIMARY = 'EQG_primary';
10
+	/**
11
+	 * Name of the field indicating an event should use the question group for the primary attendee
12
+	 */
13
+	const PRIMARY = 'EQG_primary';
14 14
 
15
-    /**
16
-     * Name of hte field indicating an event should use the question group for additional attendees
17
-     */
18
-    const ADDITIONAL = 'EQG_additional';
15
+	/**
16
+	 * Name of hte field indicating an event should use the question group for additional attendees
17
+	 */
18
+	const ADDITIONAL = 'EQG_additional';
19 19
 
20
-    // private instance of the Event_Question_Group object
21
-    protected static $_instance = null;
20
+	// private instance of the Event_Question_Group object
21
+	protected static $_instance = null;
22 22
 
23
-    protected function __construct($timezone = null)
24
-    {
25
-        $this->singular_item = __('Event to Question Group Link', 'event_espresso');
26
-        $this->plural_item = __('Event to Question Group Links', 'event_espresso');
27
-        $this->_tables = array(
28
-            'Event_Question_Group'=>new EE_Primary_Table('esp_event_question_group', 'EQG_ID')
29
-        );
30
-        $this->_fields = array(
31
-            'Event_Question_Group'=>array(
32
-                'EQG_ID'=>new EE_Primary_Key_Int_Field('EQG_ID', __('Event to Question Group Link ID', 'event_espresso')),
33
-                'EVT_ID'=>new EE_Foreign_Key_Int_Field('EVT_ID', __('Event ID', 'event_espresso'), false, 0, 'Event'),
34
-                'QSG_ID'=>new EE_Foreign_Key_Int_Field('QSG_ID', __('Question Group Id', 'event_espresso'), false, 0, 'Question_Group'),
35
-                'EQG_primary'=>new EE_Boolean_Field('EQG_primary', __('Flag indicating question is only for primary attendees', 'event_espresso'), false, false),
36
-                'EQG_additional'=>new EE_Boolean_Field('EQG_additional', __('Flag indicating question is only for additional attendees', 'event_espresso'), false, false)
37
-            )
38
-        );
39
-        $this->_model_relations = array(
40
-            'Event'=>new EE_Belongs_To_Relation(),
41
-            'Question_Group'=>new EE_Belongs_To_Relation()
42
-        );
43
-        // this model is generally available for reading
44
-        $path_to_event = 'Event';
45
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public($path_to_event);
46
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event);
47
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event);
48
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event, EEM_Base::caps_edit);
49
-        parent::__construct($timezone);
50
-    }
23
+	protected function __construct($timezone = null)
24
+	{
25
+		$this->singular_item = __('Event to Question Group Link', 'event_espresso');
26
+		$this->plural_item = __('Event to Question Group Links', 'event_espresso');
27
+		$this->_tables = array(
28
+			'Event_Question_Group'=>new EE_Primary_Table('esp_event_question_group', 'EQG_ID')
29
+		);
30
+		$this->_fields = array(
31
+			'Event_Question_Group'=>array(
32
+				'EQG_ID'=>new EE_Primary_Key_Int_Field('EQG_ID', __('Event to Question Group Link ID', 'event_espresso')),
33
+				'EVT_ID'=>new EE_Foreign_Key_Int_Field('EVT_ID', __('Event ID', 'event_espresso'), false, 0, 'Event'),
34
+				'QSG_ID'=>new EE_Foreign_Key_Int_Field('QSG_ID', __('Question Group Id', 'event_espresso'), false, 0, 'Question_Group'),
35
+				'EQG_primary'=>new EE_Boolean_Field('EQG_primary', __('Flag indicating question is only for primary attendees', 'event_espresso'), false, false),
36
+				'EQG_additional'=>new EE_Boolean_Field('EQG_additional', __('Flag indicating question is only for additional attendees', 'event_espresso'), false, false)
37
+			)
38
+		);
39
+		$this->_model_relations = array(
40
+			'Event'=>new EE_Belongs_To_Relation(),
41
+			'Question_Group'=>new EE_Belongs_To_Relation()
42
+		);
43
+		// this model is generally available for reading
44
+		$path_to_event = 'Event';
45
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public($path_to_event);
46
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event);
47
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event);
48
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ] = new EE_Restriction_Generator_Event_Related_Protected($path_to_event, EEM_Base::caps_edit);
49
+		parent::__construct($timezone);
50
+	}
51 51
 
52
-    /**
53
-     * Decides whether to use the 'EQG_primary' or newer 'EQG_additional' for use in queries, based on whether
54
-     * this is concerning primary attendees or additional attendees.
55
-     * If 1, true, or "primary" is passed in, returns EQG_primary. If 0, false, or "additional" is passed in, returns
56
-     * EQG_additional.
57
-     * @since $VID:$
58
-     * @param string|boolean|int $context
59
-     * @return string
60
-     */
61
-    public function fieldNameForContext($context)
62
-    {
63
-        // Basically do a strict switch statement.
64
-        switch (true) {
65
-            case $context === 'additional':
66
-            case $context === false:
67
-            case $context === 0:
68
-                $field_name = EEM_Event_Question_Group::ADDITIONAL;
69
-                break;
70
-            case $context === 'primary':
71
-            case $context === true:
72
-            case $context === 1:
73
-            default:
74
-                $field_name = EEM_Event_Question_Group::PRIMARY;
75
-        }
76
-        return apply_filters('FHEE__EEM_Event_Question_Group__fieldNameForContext', $field_name, $context);
77
-    }
52
+	/**
53
+	 * Decides whether to use the 'EQG_primary' or newer 'EQG_additional' for use in queries, based on whether
54
+	 * this is concerning primary attendees or additional attendees.
55
+	 * If 1, true, or "primary" is passed in, returns EQG_primary. If 0, false, or "additional" is passed in, returns
56
+	 * EQG_additional.
57
+	 * @since $VID:$
58
+	 * @param string|boolean|int $context
59
+	 * @return string
60
+	 */
61
+	public function fieldNameForContext($context)
62
+	{
63
+		// Basically do a strict switch statement.
64
+		switch (true) {
65
+			case $context === 'additional':
66
+			case $context === false:
67
+			case $context === 0:
68
+				$field_name = EEM_Event_Question_Group::ADDITIONAL;
69
+				break;
70
+			case $context === 'primary':
71
+			case $context === true:
72
+			case $context === 1:
73
+			default:
74
+				$field_name = EEM_Event_Question_Group::PRIMARY;
75
+		}
76
+		return apply_filters('FHEE__EEM_Event_Question_Group__fieldNameForContext', $field_name, $context);
77
+	}
78 78
 }
Please login to merge, or discard this patch.
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -55,7 +55,7 @@
 block discarded – undo
55 55
      * If 1, true, or "primary" is passed in, returns EQG_primary. If 0, false, or "additional" is passed in, returns
56 56
      * EQG_additional.
57 57
      * @since $VID:$
58
-     * @param string|boolean|int $context
58
+     * @param boolean $context
59 59
      * @return string
60 60
      */
61 61
     public function fieldNameForContext($context)
Please login to merge, or discard this patch.
caffeinated/admin/extend/events/Extend_Events_Admin_Page.core.php 2 patches
Indentation   +1253 added lines, -1253 removed lines patch added patch discarded remove patch
@@ -16,1257 +16,1257 @@
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     * Extend_Events_Admin_Page constructor.
21
-     *
22
-     * @param bool $routing
23
-     */
24
-    public function __construct($routing = true)
25
-    {
26
-        parent::__construct($routing);
27
-        if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
28
-            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
29
-            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
30
-            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
31
-        }
32
-    }
33
-
34
-
35
-    /**
36
-     * Sets routes.
37
-     */
38
-    protected function _extend_page_config()
39
-    {
40
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
41
-        // is there a evt_id in the request?
42
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
43
-            ? $this->_req_data['EVT_ID']
44
-            : 0;
45
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
46
-        // tkt_id?
47
-        $tkt_id = ! empty($this->_req_data['TKT_ID']) && ! is_array($this->_req_data['TKT_ID'])
48
-            ? $this->_req_data['TKT_ID']
49
-            : 0;
50
-        $new_page_routes = array(
51
-            'duplicate_event'          => array(
52
-                'func'       => '_duplicate_event',
53
-                'capability' => 'ee_edit_event',
54
-                'obj_id'     => $evt_id,
55
-                'noheader'   => true,
56
-            ),
57
-            'ticket_list_table'        => array(
58
-                'func'       => '_tickets_overview_list_table',
59
-                'capability' => 'ee_read_default_tickets',
60
-            ),
61
-            'trash_ticket'             => array(
62
-                'func'       => '_trash_or_restore_ticket',
63
-                'capability' => 'ee_delete_default_ticket',
64
-                'obj_id'     => $tkt_id,
65
-                'noheader'   => true,
66
-                'args'       => array('trash' => true),
67
-            ),
68
-            'trash_tickets'            => array(
69
-                'func'       => '_trash_or_restore_ticket',
70
-                'capability' => 'ee_delete_default_tickets',
71
-                'noheader'   => true,
72
-                'args'       => array('trash' => true),
73
-            ),
74
-            'restore_ticket'           => array(
75
-                'func'       => '_trash_or_restore_ticket',
76
-                'capability' => 'ee_delete_default_ticket',
77
-                'obj_id'     => $tkt_id,
78
-                'noheader'   => true,
79
-            ),
80
-            'restore_tickets'          => array(
81
-                'func'       => '_trash_or_restore_ticket',
82
-                'capability' => 'ee_delete_default_tickets',
83
-                'noheader'   => true,
84
-            ),
85
-            'delete_ticket'            => array(
86
-                'func'       => '_delete_ticket',
87
-                'capability' => 'ee_delete_default_ticket',
88
-                'obj_id'     => $tkt_id,
89
-                'noheader'   => true,
90
-            ),
91
-            'delete_tickets'           => array(
92
-                'func'       => '_delete_ticket',
93
-                'capability' => 'ee_delete_default_tickets',
94
-                'noheader'   => true,
95
-            ),
96
-            'import_page'              => array(
97
-                'func'       => '_import_page',
98
-                'capability' => 'import',
99
-            ),
100
-            'import'                   => array(
101
-                'func'       => '_import_events',
102
-                'capability' => 'import',
103
-                'noheader'   => true,
104
-            ),
105
-            'import_events'            => array(
106
-                'func'       => '_import_events',
107
-                'capability' => 'import',
108
-                'noheader'   => true,
109
-            ),
110
-            'export_events'            => array(
111
-                'func'       => '_events_export',
112
-                'capability' => 'export',
113
-                'noheader'   => true,
114
-            ),
115
-            'export_categories'        => array(
116
-                'func'       => '_categories_export',
117
-                'capability' => 'export',
118
-                'noheader'   => true,
119
-            ),
120
-            'sample_export_file'       => array(
121
-                'func'       => '_sample_export_file',
122
-                'capability' => 'export',
123
-                'noheader'   => true,
124
-            ),
125
-            'update_template_settings' => array(
126
-                'func'       => '_update_template_settings',
127
-                'capability' => 'manage_options',
128
-                'noheader'   => true,
129
-            ),
130
-        );
131
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
132
-        // partial route/config override
133
-        $this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
134
-        $this->_page_config['create_new']['metaboxes'][] = '_premium_event_editor_meta_boxes';
135
-        $this->_page_config['create_new']['qtips'][] = 'EE_Event_Editor_Tips';
136
-        $this->_page_config['edit']['qtips'][] = 'EE_Event_Editor_Tips';
137
-        $this->_page_config['edit']['metaboxes'][] = '_premium_event_editor_meta_boxes';
138
-        $this->_page_config['default']['list_table'] = 'Extend_Events_Admin_List_Table';
139
-        // add tickets tab but only if there are more than one default ticket!
140
-        $tkt_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
141
-            array(array('TKT_is_default' => 1)),
142
-            'TKT_ID',
143
-            true
144
-        );
145
-        if ($tkt_count > 1) {
146
-            $new_page_config = array(
147
-                'ticket_list_table' => array(
148
-                    'nav'           => array(
149
-                        'label' => esc_html__('Default Tickets', 'event_espresso'),
150
-                        'order' => 60,
151
-                    ),
152
-                    'list_table'    => 'Tickets_List_Table',
153
-                    'require_nonce' => false,
154
-                ),
155
-            );
156
-        }
157
-        // template settings
158
-        $new_page_config['template_settings'] = array(
159
-            'nav'           => array(
160
-                'label' => esc_html__('Templates', 'event_espresso'),
161
-                'order' => 30,
162
-            ),
163
-            'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
164
-            'help_tabs'     => array(
165
-                'general_settings_templates_help_tab' => array(
166
-                    'title'    => esc_html__('Templates', 'event_espresso'),
167
-                    'filename' => 'general_settings_templates',
168
-                ),
169
-            ),
170
-            'help_tour'     => array('Templates_Help_Tour'),
171
-            'require_nonce' => false,
172
-        );
173
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
174
-        // add filters and actions
175
-        // modifying _views
176
-        add_filter(
177
-            'FHEE_event_datetime_metabox_add_additional_date_time_template',
178
-            array($this, 'add_additional_datetime_button'),
179
-            10,
180
-            2
181
-        );
182
-        add_filter(
183
-            'FHEE_event_datetime_metabox_clone_button_template',
184
-            array($this, 'add_datetime_clone_button'),
185
-            10,
186
-            2
187
-        );
188
-        add_filter(
189
-            'FHEE_event_datetime_metabox_timezones_template',
190
-            array($this, 'datetime_timezones_template'),
191
-            10,
192
-            2
193
-        );
194
-        // filters for event list table
195
-        add_filter('FHEE__Extend_Events_Admin_List_Table__filters', array($this, 'list_table_filters'), 10, 2);
196
-        add_filter(
197
-            'FHEE__Events_Admin_List_Table__column_actions__action_links',
198
-            array($this, 'extra_list_table_actions'),
199
-            10,
200
-            2
201
-        );
202
-        // legend item
203
-        add_filter('FHEE__Events_Admin_Page___event_legend_items__items', array($this, 'additional_legend_items'));
204
-        add_action('admin_init', array($this, 'admin_init'));
205
-    }
206
-
207
-
208
-    /**
209
-     * admin_init
210
-     */
211
-    public function admin_init()
212
-    {
213
-        EE_Registry::$i18n_js_strings = array_merge(
214
-            EE_Registry::$i18n_js_strings,
215
-            array(
216
-                'image_confirm'          => esc_html__(
217
-                    'Do you really want to delete this image? Please remember to update your event to complete the removal.',
218
-                    'event_espresso'
219
-                ),
220
-                'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
221
-                'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
222
-                'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
223
-                'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
224
-                'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
225
-            )
226
-        );
227
-    }
228
-
229
-
230
-    /**
231
-     * Add per page screen options to the default ticket list table view.
232
-     */
233
-    protected function _add_screen_options_ticket_list_table()
234
-    {
235
-        $this->_per_page_screen_option();
236
-    }
237
-
238
-
239
-    /**
240
-     * @param string $return
241
-     * @param int    $id
242
-     * @param string $new_title
243
-     * @param string $new_slug
244
-     * @return string
245
-     */
246
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
247
-    {
248
-        $return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
249
-        // make sure this is only when editing
250
-        if (! empty($id)) {
251
-            $href = EE_Admin_Page::add_query_args_and_nonce(
252
-                array('action' => 'duplicate_event', 'EVT_ID' => $id),
253
-                $this->_admin_base_url
254
-            );
255
-            $title = esc_attr__('Duplicate Event', 'event_espresso');
256
-            $return .= '<a href="'
257
-                       . $href
258
-                       . '" title="'
259
-                       . $title
260
-                       . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
261
-                       . $title
262
-                       . '</a>';
263
-        }
264
-        return $return;
265
-    }
266
-
267
-
268
-    /**
269
-     * Set the list table views for the default ticket list table view.
270
-     */
271
-    public function _set_list_table_views_ticket_list_table()
272
-    {
273
-        $this->_views = array(
274
-            'all'     => array(
275
-                'slug'        => 'all',
276
-                'label'       => esc_html__('All', 'event_espresso'),
277
-                'count'       => 0,
278
-                'bulk_action' => array(
279
-                    'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
280
-                ),
281
-            ),
282
-            'trashed' => array(
283
-                'slug'        => 'trashed',
284
-                'label'       => esc_html__('Trash', 'event_espresso'),
285
-                'count'       => 0,
286
-                'bulk_action' => array(
287
-                    'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
288
-                    'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
289
-                ),
290
-            ),
291
-        );
292
-    }
293
-
294
-
295
-    /**
296
-     * Enqueue scripts and styles for the event editor.
297
-     */
298
-    public function load_scripts_styles_edit()
299
-    {
300
-        wp_register_script(
301
-            'ee-event-editor-heartbeat',
302
-            EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
303
-            array('ee_admin_js', 'heartbeat'),
304
-            EVENT_ESPRESSO_VERSION,
305
-            true
306
-        );
307
-        wp_enqueue_script('ee-accounting');
308
-        // styles
309
-        wp_enqueue_style('espresso-ui-theme');
310
-        wp_enqueue_script('event_editor_js');
311
-        wp_enqueue_script('ee-event-editor-heartbeat');
312
-    }
313
-
314
-
315
-    /**
316
-     * Returns template for the additional datetime.
317
-     *
318
-     * @param $template
319
-     * @param $template_args
320
-     * @return mixed
321
-     * @throws DomainException
322
-     */
323
-    public function add_additional_datetime_button($template, $template_args)
324
-    {
325
-        return EEH_Template::display_template(
326
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
327
-            $template_args,
328
-            true
329
-        );
330
-    }
331
-
332
-
333
-    /**
334
-     * Returns the template for cloning a datetime.
335
-     *
336
-     * @param $template
337
-     * @param $template_args
338
-     * @return mixed
339
-     * @throws DomainException
340
-     */
341
-    public function add_datetime_clone_button($template, $template_args)
342
-    {
343
-        return EEH_Template::display_template(
344
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
345
-            $template_args,
346
-            true
347
-        );
348
-    }
349
-
350
-
351
-    /**
352
-     * Returns the template for datetime timezones.
353
-     *
354
-     * @param $template
355
-     * @param $template_args
356
-     * @return mixed
357
-     * @throws DomainException
358
-     */
359
-    public function datetime_timezones_template($template, $template_args)
360
-    {
361
-        return EEH_Template::display_template(
362
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
363
-            $template_args,
364
-            true
365
-        );
366
-    }
367
-
368
-
369
-    /**
370
-     * Sets the views for the default list table view.
371
-     */
372
-    protected function _set_list_table_views_default()
373
-    {
374
-        parent::_set_list_table_views_default();
375
-        $new_views = array(
376
-            'today' => array(
377
-                'slug'        => 'today',
378
-                'label'       => esc_html__('Today', 'event_espresso'),
379
-                'count'       => $this->total_events_today(),
380
-                'bulk_action' => array(
381
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
382
-                ),
383
-            ),
384
-            'month' => array(
385
-                'slug'        => 'month',
386
-                'label'       => esc_html__('This Month', 'event_espresso'),
387
-                'count'       => $this->total_events_this_month(),
388
-                'bulk_action' => array(
389
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
390
-                ),
391
-            ),
392
-        );
393
-        $this->_views = array_merge($this->_views, $new_views);
394
-    }
395
-
396
-
397
-    /**
398
-     * Returns the extra action links for the default list table view.
399
-     *
400
-     * @param array     $action_links
401
-     * @param \EE_Event $event
402
-     * @return array
403
-     * @throws EE_Error
404
-     */
405
-    public function extra_list_table_actions(array $action_links, \EE_Event $event)
406
-    {
407
-        if (EE_Registry::instance()->CAP->current_user_can(
408
-            'ee_read_registrations',
409
-            'espresso_registrations_reports',
410
-            $event->ID()
411
-        )
412
-        ) {
413
-            $reports_query_args = array(
414
-                'action' => 'reports',
415
-                'EVT_ID' => $event->ID(),
416
-            );
417
-            $reports_link = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
418
-            $action_links[] = '<a href="'
419
-                              . $reports_link
420
-                              . '" title="'
421
-                              . esc_attr__('View Report', 'event_espresso')
422
-                              . '"><div class="dashicons dashicons-chart-bar"></div></a>'
423
-                              . "\n\t";
424
-        }
425
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
426
-            EE_Registry::instance()->load_helper('MSG_Template');
427
-            $action_links[] = EEH_MSG_Template::get_message_action_link(
428
-                'see_notifications_for',
429
-                null,
430
-                array('EVT_ID' => $event->ID())
431
-            );
432
-        }
433
-        return $action_links;
434
-    }
435
-
436
-
437
-    /**
438
-     * @param $items
439
-     * @return mixed
440
-     */
441
-    public function additional_legend_items($items)
442
-    {
443
-        if (EE_Registry::instance()->CAP->current_user_can(
444
-            'ee_read_registrations',
445
-            'espresso_registrations_reports'
446
-        )
447
-        ) {
448
-            $items['reports'] = array(
449
-                'class' => 'dashicons dashicons-chart-bar',
450
-                'desc'  => esc_html__('Event Reports', 'event_espresso'),
451
-            );
452
-        }
453
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
454
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
455
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
456
-                $items['view_related_messages'] = array(
457
-                    'class' => $related_for_icon['css_class'],
458
-                    'desc'  => $related_for_icon['label'],
459
-                );
460
-            }
461
-        }
462
-        return $items;
463
-    }
464
-
465
-
466
-    /**
467
-     * This is the callback method for the duplicate event route
468
-     * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
469
-     * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
470
-     * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
471
-     * After duplication the redirect is to the new event edit page.
472
-     *
473
-     * @return void
474
-     * @access protected
475
-     * @throws EE_Error If EE_Event is not available with given ID
476
-     */
477
-    protected function _duplicate_event()
478
-    {
479
-        // first make sure the ID for the event is in the request.
480
-        //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
481
-        if (! isset($this->_req_data['EVT_ID'])) {
482
-            EE_Error::add_error(
483
-                esc_html__(
484
-                    'In order to duplicate an event an Event ID is required.  None was given.',
485
-                    'event_espresso'
486
-                ),
487
-                __FILE__,
488
-                __FUNCTION__,
489
-                __LINE__
490
-            );
491
-            $this->_redirect_after_action(false, '', '', array(), true);
492
-            return;
493
-        }
494
-        // k we've got EVT_ID so let's use that to get the event we'll duplicate
495
-        $orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
496
-        if (! $orig_event instanceof EE_Event) {
497
-            throw new EE_Error(
498
-                sprintf(
499
-                    esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
500
-                    $this->_req_data['EVT_ID']
501
-                )
502
-            );
503
-        }
504
-        // k now let's clone the $orig_event before getting relations
505
-        $new_event = clone $orig_event;
506
-        // original datetimes
507
-        $orig_datetimes = $orig_event->get_many_related('Datetime');
508
-        // other original relations
509
-        $orig_ven = $orig_event->get_many_related('Venue');
510
-        // reset the ID and modify other details to make it clear this is a dupe
511
-        $new_event->set('EVT_ID', 0);
512
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
513
-        $new_event->set('EVT_name', $new_name);
514
-        $new_event->set(
515
-            'EVT_slug',
516
-            wp_unique_post_slug(
517
-                sanitize_title($orig_event->name()),
518
-                0,
519
-                'publish',
520
-                'espresso_events',
521
-                0
522
-            )
523
-        );
524
-        $new_event->set('status', 'draft');
525
-        // duplicate discussion settings
526
-        $new_event->set('comment_status', $orig_event->get('comment_status'));
527
-        $new_event->set('ping_status', $orig_event->get('ping_status'));
528
-        // save the new event
529
-        $new_event->save();
530
-        // venues
531
-        foreach ($orig_ven as $ven) {
532
-            $new_event->_add_relation_to($ven, 'Venue');
533
-        }
534
-        $new_event->save();
535
-        // now we need to get the question group relations and handle that
536
-        // first primary question groups
537
-        $orig_primary_qgs = $orig_event->get_many_related(
538
-            'Question_Group',
539
-            [['Event_Question_Group.EQG_primary' => true]]
540
-        );
541
-        if (! empty($orig_primary_qgs)) {
542
-            foreach ($orig_primary_qgs as $id => $obj) {
543
-                if ($obj instanceof EE_Question_Group) {
544
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
545
-                }
546
-            }
547
-        }
548
-        // next additional attendee question groups
549
-        $orig_additional_qgs = $orig_event->get_many_related(
550
-            'Question_Group',
551
-            [['Event_Question_Group.EQG_additional' => true]]
552
-        );
553
-        if (! empty($orig_additional_qgs)) {
554
-            foreach ($orig_additional_qgs as $id => $obj) {
555
-                if ($obj instanceof EE_Question_Group) {
556
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
557
-                }
558
-            }
559
-        }
560
-
561
-        $new_event->save();
562
-
563
-        // k now that we have the new event saved we can loop through the datetimes and start adding relations.
564
-        $cloned_tickets = array();
565
-        foreach ($orig_datetimes as $orig_dtt) {
566
-            if (! $orig_dtt instanceof EE_Datetime) {
567
-                continue;
568
-            }
569
-            $new_dtt = clone $orig_dtt;
570
-            $orig_tkts = $orig_dtt->tickets();
571
-            // save new dtt then add to event
572
-            $new_dtt->set('DTT_ID', 0);
573
-            $new_dtt->set('DTT_sold', 0);
574
-            $new_dtt->set_reserved(0);
575
-            $new_dtt->save();
576
-            $new_event->_add_relation_to($new_dtt, 'Datetime');
577
-            $new_event->save();
578
-            // now let's get the ticket relations setup.
579
-            foreach ((array) $orig_tkts as $orig_tkt) {
580
-                // it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
581
-                if (! $orig_tkt instanceof EE_Ticket) {
582
-                    continue;
583
-                }
584
-                // is this ticket archived?  If it is then let's skip
585
-                if ($orig_tkt->get('TKT_deleted')) {
586
-                    continue;
587
-                }
588
-                // does this original ticket already exist in the clone_tickets cache?
589
-                //  If so we'll just use the new ticket from it.
590
-                if (isset($cloned_tickets[ $orig_tkt->ID() ])) {
591
-                    $new_tkt = $cloned_tickets[ $orig_tkt->ID() ];
592
-                } else {
593
-                    $new_tkt = clone $orig_tkt;
594
-                    // get relations on the $orig_tkt that we need to setup.
595
-                    $orig_prices = $orig_tkt->prices();
596
-                    $new_tkt->set('TKT_ID', 0);
597
-                    $new_tkt->set('TKT_sold', 0);
598
-                    $new_tkt->set('TKT_reserved', 0);
599
-                    $new_tkt->save(); // make sure new ticket has ID.
600
-                    // price relations on new ticket need to be setup.
601
-                    foreach ($orig_prices as $orig_price) {
602
-                        $new_price = clone $orig_price;
603
-                        $new_price->set('PRC_ID', 0);
604
-                        $new_price->save();
605
-                        $new_tkt->_add_relation_to($new_price, 'Price');
606
-                        $new_tkt->save();
607
-                    }
608
-
609
-                    do_action(
610
-                        'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
611
-                        $orig_tkt,
612
-                        $new_tkt,
613
-                        $orig_prices,
614
-                        $orig_event,
615
-                        $orig_dtt,
616
-                        $new_dtt
617
-                    );
618
-                }
619
-                // k now we can add the new ticket as a relation to the new datetime
620
-                // and make sure its added to our cached $cloned_tickets array
621
-                // for use with later datetimes that have the same ticket.
622
-                $new_dtt->_add_relation_to($new_tkt, 'Ticket');
623
-                $new_dtt->save();
624
-                $cloned_tickets[ $orig_tkt->ID() ] = $new_tkt;
625
-            }
626
-        }
627
-        // clone taxonomy information
628
-        $taxonomies_to_clone_with = apply_filters(
629
-            'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
630
-            array('espresso_event_categories', 'espresso_event_type', 'post_tag')
631
-        );
632
-        // get terms for original event (notice)
633
-        $orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
634
-        // loop through terms and add them to new event.
635
-        foreach ($orig_terms as $term) {
636
-            wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
637
-        }
638
-
639
-        // duplicate other core WP_Post items for this event.
640
-        // post thumbnail (feature image).
641
-        $feature_image_id = get_post_thumbnail_id($orig_event->ID());
642
-        if ($feature_image_id) {
643
-            update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
644
-        }
645
-
646
-        // duplicate page_template setting
647
-        $page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
648
-        if ($page_template) {
649
-            update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
650
-        }
651
-
652
-        do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
653
-        // now let's redirect to the edit page for this duplicated event if we have a new event id.
654
-        if ($new_event->ID()) {
655
-            $redirect_args = array(
656
-                'post'   => $new_event->ID(),
657
-                'action' => 'edit',
658
-            );
659
-            EE_Error::add_success(
660
-                esc_html__(
661
-                    'Event successfully duplicated.  Please review the details below and make any necessary edits',
662
-                    'event_espresso'
663
-                )
664
-            );
665
-        } else {
666
-            $redirect_args = array(
667
-                'action' => 'default',
668
-            );
669
-            EE_Error::add_error(
670
-                esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
671
-                __FILE__,
672
-                __FUNCTION__,
673
-                __LINE__
674
-            );
675
-        }
676
-        $this->_redirect_after_action(false, '', '', $redirect_args, true);
677
-    }
678
-
679
-
680
-    /**
681
-     * Generates output for the import page.
682
-     *
683
-     * @throws DomainException
684
-     */
685
-    protected function _import_page()
686
-    {
687
-        $title = esc_html__('Import', 'event_espresso');
688
-        $intro = esc_html__(
689
-            'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
690
-            'event_espresso'
691
-        );
692
-        $form_url = EVENTS_ADMIN_URL;
693
-        $action = 'import_events';
694
-        $type = 'csv';
695
-        $this->_template_args['form'] = EE_Import::instance()->upload_form(
696
-            $title,
697
-            $intro,
698
-            $form_url,
699
-            $action,
700
-            $type
701
-        );
702
-        $this->_template_args['sample_file_link'] = EE_Admin_Page::add_query_args_and_nonce(
703
-            array('action' => 'sample_export_file'),
704
-            $this->_admin_base_url
705
-        );
706
-        $content = EEH_Template::display_template(
707
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
708
-            $this->_template_args,
709
-            true
710
-        );
711
-        $this->_template_args['admin_page_content'] = $content;
712
-        $this->display_admin_page_with_sidebar();
713
-    }
714
-
715
-
716
-    /**
717
-     * _import_events
718
-     * This handles displaying the screen and running imports for importing events.
719
-     *
720
-     * @return void
721
-     */
722
-    protected function _import_events()
723
-    {
724
-        require_once(EE_CLASSES . 'EE_Import.class.php');
725
-        $success = EE_Import::instance()->import();
726
-        $this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
727
-    }
728
-
729
-
730
-    /**
731
-     * _events_export
732
-     * Will export all (or just the given event) to a Excel compatible file.
733
-     *
734
-     * @access protected
735
-     * @return void
736
-     */
737
-    protected function _events_export()
738
-    {
739
-        if (isset($this->_req_data['EVT_ID'])) {
740
-            $event_ids = $this->_req_data['EVT_ID'];
741
-        } elseif (isset($this->_req_data['EVT_IDs'])) {
742
-            $event_ids = $this->_req_data['EVT_IDs'];
743
-        } else {
744
-            $event_ids = null;
745
-        }
746
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
747
-        $new_request_args = array(
748
-            'export' => 'report',
749
-            'action' => 'all_event_data',
750
-            'EVT_ID' => $event_ids,
751
-        );
752
-        $this->_req_data = array_merge($this->_req_data, $new_request_args);
753
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
754
-            require_once(EE_CLASSES . 'EE_Export.class.php');
755
-            $EE_Export = EE_Export::instance($this->_req_data);
756
-            $EE_Export->export();
757
-        }
758
-    }
759
-
760
-
761
-    /**
762
-     * handle category exports()
763
-     *
764
-     * @return void
765
-     */
766
-    protected function _categories_export()
767
-    {
768
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
769
-        $new_request_args = array(
770
-            'export'       => 'report',
771
-            'action'       => 'categories',
772
-            'category_ids' => $this->_req_data['EVT_CAT_ID'],
773
-        );
774
-        $this->_req_data = array_merge($this->_req_data, $new_request_args);
775
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
776
-            require_once(EE_CLASSES . 'EE_Export.class.php');
777
-            $EE_Export = EE_Export::instance($this->_req_data);
778
-            $EE_Export->export();
779
-        }
780
-    }
781
-
782
-
783
-    /**
784
-     * Creates a sample CSV file for importing
785
-     */
786
-    protected function _sample_export_file()
787
-    {
788
-        // require_once(EE_CLASSES . 'EE_Export.class.php');
789
-        EE_Export::instance()->export_sample();
790
-    }
791
-
792
-
793
-    /*************        Template Settings        *************/
794
-    /**
795
-     * Generates template settings page output
796
-     *
797
-     * @throws DomainException
798
-     * @throws EE_Error
799
-     */
800
-    protected function _template_settings()
801
-    {
802
-        $this->_template_args['values'] = $this->_yes_no_values;
803
-        /**
804
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
805
-         * from General_Settings_Admin_Page to here.
806
-         */
807
-        $this->_template_args = apply_filters(
808
-            'FHEE__General_Settings_Admin_Page__template_settings__template_args',
809
-            $this->_template_args
810
-        );
811
-        $this->_set_add_edit_form_tags('update_template_settings');
812
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
813
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
814
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
815
-            $this->_template_args,
816
-            true
817
-        );
818
-        $this->display_admin_page_with_sidebar();
819
-    }
820
-
821
-
822
-    /**
823
-     * Handler for updating template settings.
824
-     *
825
-     * @throws InvalidInterfaceException
826
-     * @throws InvalidDataTypeException
827
-     * @throws InvalidArgumentException
828
-     */
829
-    protected function _update_template_settings()
830
-    {
831
-        /**
832
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
833
-         * from General_Settings_Admin_Page to here.
834
-         */
835
-        EE_Registry::instance()->CFG->template_settings = apply_filters(
836
-            'FHEE__General_Settings_Admin_Page__update_template_settings__data',
837
-            EE_Registry::instance()->CFG->template_settings,
838
-            $this->_req_data
839
-        );
840
-        // update custom post type slugs and detect if we need to flush rewrite rules
841
-        $old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
842
-        EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
843
-            ? EE_Registry::instance()->CFG->core->event_cpt_slug
844
-            : EEH_URL::slugify($this->_req_data['event_cpt_slug'], 'events');
845
-        $what = 'Template Settings';
846
-        $success = $this->_update_espresso_configuration(
847
-            $what,
848
-            EE_Registry::instance()->CFG->template_settings,
849
-            __FILE__,
850
-            __FUNCTION__,
851
-            __LINE__
852
-        );
853
-        if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
854
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
855
-            $rewrite_rules = LoaderFactory::getLoader()->getShared(
856
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
857
-            );
858
-            $rewrite_rules->flush();
859
-        }
860
-        $this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
861
-    }
862
-
863
-
864
-    /**
865
-     * _premium_event_editor_meta_boxes
866
-     * add all metaboxes related to the event_editor
867
-     *
868
-     * @access protected
869
-     * @return void
870
-     * @throws EE_Error
871
-     */
872
-    protected function _premium_event_editor_meta_boxes()
873
-    {
874
-        $this->verify_cpt_object();
875
-        add_meta_box(
876
-            'espresso_event_editor_event_options',
877
-            esc_html__('Event Registration Options', 'event_espresso'),
878
-            array($this, 'registration_options_meta_box'),
879
-            $this->page_slug,
880
-            'side',
881
-            'core'
882
-        );
883
-    }
884
-
885
-
886
-    /**
887
-     * override caf metabox
888
-     *
889
-     * @return void
890
-     * @throws DomainException
891
-     */
892
-    public function registration_options_meta_box()
893
-    {
894
-        $yes_no_values = array(
895
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
896
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
897
-        );
898
-        $default_reg_status_values = EEM_Registration::reg_status_array(
899
-            array(
900
-                EEM_Registration::status_id_cancelled,
901
-                EEM_Registration::status_id_declined,
902
-                EEM_Registration::status_id_incomplete,
903
-                EEM_Registration::status_id_wait_list,
904
-            ),
905
-            true
906
-        );
907
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
908
-        $template_args['_event'] = $this->_cpt_model_obj;
909
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
910
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
911
-            'default_reg_status',
912
-            $default_reg_status_values,
913
-            $this->_cpt_model_obj->default_registration_status()
914
-        );
915
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
916
-            'display_desc',
917
-            $yes_no_values,
918
-            $this->_cpt_model_obj->display_description()
919
-        );
920
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
921
-            'display_ticket_selector',
922
-            $yes_no_values,
923
-            $this->_cpt_model_obj->display_ticket_selector(),
924
-            '',
925
-            '',
926
-            false
927
-        );
928
-        $template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
929
-            'EVT_default_registration_status',
930
-            $default_reg_status_values,
931
-            $this->_cpt_model_obj->default_registration_status()
932
-        );
933
-        $template_args['additional_registration_options'] = apply_filters(
934
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
935
-            '',
936
-            $template_args,
937
-            $yes_no_values,
938
-            $default_reg_status_values
939
-        );
940
-        EEH_Template::display_template(
941
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
942
-            $template_args
943
-        );
944
-    }
945
-
946
-
947
-
948
-    /**
949
-     * wp_list_table_mods for caf
950
-     * ============================
951
-     */
952
-    /**
953
-     * hook into list table filters and provide filters for caffeinated list table
954
-     *
955
-     * @param  array $old_filters    any existing filters present
956
-     * @param  array $list_table_obj the list table object
957
-     * @return array                  new filters
958
-     */
959
-    public function list_table_filters($old_filters, $list_table_obj)
960
-    {
961
-        $filters = array();
962
-        // first month/year filters
963
-        $filters[] = $this->espresso_event_months_dropdown();
964
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
965
-        // active status dropdown
966
-        if ($status !== 'draft') {
967
-            $filters[] = $this->active_status_dropdown(
968
-                isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
969
-            );
970
-        }
971
-        // category filter
972
-        $filters[] = $this->category_dropdown();
973
-        return array_merge($old_filters, $filters);
974
-    }
975
-
976
-
977
-    /**
978
-     * espresso_event_months_dropdown
979
-     *
980
-     * @access public
981
-     * @return string                dropdown listing month/year selections for events.
982
-     */
983
-    public function espresso_event_months_dropdown()
984
-    {
985
-        // what we need to do is get all PRIMARY datetimes for all events to filter on.
986
-        // Note we need to include any other filters that are set!
987
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
988
-        // categories?
989
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
990
-            ? $this->_req_data['EVT_CAT']
991
-            : null;
992
-        // active status?
993
-        $active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
994
-        $cur_date = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
995
-        return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
996
-    }
997
-
998
-
999
-    /**
1000
-     * returns a list of "active" statuses on the event
1001
-     *
1002
-     * @param  string $current_value whatever the current active status is
1003
-     * @return string
1004
-     */
1005
-    public function active_status_dropdown($current_value = '')
1006
-    {
1007
-        $select_name = 'active_status';
1008
-        $values = array(
1009
-            'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1010
-            'active'   => esc_html__('Active', 'event_espresso'),
1011
-            'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1012
-            'expired'  => esc_html__('Expired', 'event_espresso'),
1013
-            'inactive' => esc_html__('Inactive', 'event_espresso'),
1014
-        );
1015
-        $id = 'id="espresso-active-status-dropdown-filter"';
1016
-        $class = 'wide';
1017
-        return EEH_Form_Fields::select_input($select_name, $values, $current_value, $id, $class);
1018
-    }
1019
-
1020
-
1021
-    /**
1022
-     * output a dropdown of the categories for the category filter on the event admin list table
1023
-     *
1024
-     * @access  public
1025
-     * @return string html
1026
-     */
1027
-    public function category_dropdown()
1028
-    {
1029
-        $cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1030
-        return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1031
-    }
1032
-
1033
-
1034
-    /**
1035
-     * get total number of events today
1036
-     *
1037
-     * @access public
1038
-     * @return int
1039
-     * @throws EE_Error
1040
-     */
1041
-    public function total_events_today()
1042
-    {
1043
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1044
-            'DTT_EVT_start',
1045
-            date('Y-m-d') . ' 00:00:00',
1046
-            'Y-m-d H:i:s',
1047
-            'UTC'
1048
-        );
1049
-        $end = EEM_Datetime::instance()->convert_datetime_for_query(
1050
-            'DTT_EVT_start',
1051
-            date('Y-m-d') . ' 23:59:59',
1052
-            'Y-m-d H:i:s',
1053
-            'UTC'
1054
-        );
1055
-        $where = array(
1056
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1057
-        );
1058
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1059
-        return $count;
1060
-    }
1061
-
1062
-
1063
-    /**
1064
-     * get total number of events this month
1065
-     *
1066
-     * @access public
1067
-     * @return int
1068
-     * @throws EE_Error
1069
-     */
1070
-    public function total_events_this_month()
1071
-    {
1072
-        // Dates
1073
-        $this_year_r = date('Y');
1074
-        $this_month_r = date('m');
1075
-        $days_this_month = date('t');
1076
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1077
-            'DTT_EVT_start',
1078
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1079
-            'Y-m-d H:i:s',
1080
-            'UTC'
1081
-        );
1082
-        $end = EEM_Datetime::instance()->convert_datetime_for_query(
1083
-            'DTT_EVT_start',
1084
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1085
-            'Y-m-d H:i:s',
1086
-            'UTC'
1087
-        );
1088
-        $where = array(
1089
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1090
-        );
1091
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1092
-        return $count;
1093
-    }
1094
-
1095
-
1096
-    /** DEFAULT TICKETS STUFF **/
1097
-
1098
-    /**
1099
-     * Output default tickets list table view.
1100
-     */
1101
-    public function _tickets_overview_list_table()
1102
-    {
1103
-        $this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1104
-        $this->display_admin_list_table_page_with_no_sidebar();
1105
-    }
1106
-
1107
-
1108
-    /**
1109
-     * @param int  $per_page
1110
-     * @param bool $count
1111
-     * @param bool $trashed
1112
-     * @return \EE_Soft_Delete_Base_Class[]|int
1113
-     */
1114
-    public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1115
-    {
1116
-        $orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1117
-        $order = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1118
-        switch ($orderby) {
1119
-            case 'TKT_name':
1120
-                $orderby = array('TKT_name' => $order);
1121
-                break;
1122
-            case 'TKT_price':
1123
-                $orderby = array('TKT_price' => $order);
1124
-                break;
1125
-            case 'TKT_uses':
1126
-                $orderby = array('TKT_uses' => $order);
1127
-                break;
1128
-            case 'TKT_min':
1129
-                $orderby = array('TKT_min' => $order);
1130
-                break;
1131
-            case 'TKT_max':
1132
-                $orderby = array('TKT_max' => $order);
1133
-                break;
1134
-            case 'TKT_qty':
1135
-                $orderby = array('TKT_qty' => $order);
1136
-                break;
1137
-        }
1138
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1139
-            ? $this->_req_data['paged']
1140
-            : 1;
1141
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1142
-            ? $this->_req_data['perpage']
1143
-            : $per_page;
1144
-        $_where = array(
1145
-            'TKT_is_default' => 1,
1146
-            'TKT_deleted'    => $trashed,
1147
-        );
1148
-        $offset = ($current_page - 1) * $per_page;
1149
-        $limit = array($offset, $per_page);
1150
-        if (isset($this->_req_data['s'])) {
1151
-            $sstr = '%' . $this->_req_data['s'] . '%';
1152
-            $_where['OR'] = array(
1153
-                'TKT_name'        => array('LIKE', $sstr),
1154
-                'TKT_description' => array('LIKE', $sstr),
1155
-            );
1156
-        }
1157
-        $query_params = array(
1158
-            $_where,
1159
-            'order_by' => $orderby,
1160
-            'limit'    => $limit,
1161
-            'group_by' => 'TKT_ID',
1162
-        );
1163
-        if ($count) {
1164
-            return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1165
-        } else {
1166
-            return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1167
-        }
1168
-    }
1169
-
1170
-
1171
-    /**
1172
-     * @param bool $trash
1173
-     * @throws EE_Error
1174
-     */
1175
-    protected function _trash_or_restore_ticket($trash = false)
1176
-    {
1177
-        $success = 1;
1178
-        $TKT = EEM_Ticket::instance();
1179
-        // checkboxes?
1180
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1181
-            // if array has more than one element then success message should be plural
1182
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1183
-            // cycle thru the boxes
1184
-            while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1185
-                if ($trash) {
1186
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1187
-                        $success = 0;
1188
-                    }
1189
-                } else {
1190
-                    if (! $TKT->restore_by_ID($TKT_ID)) {
1191
-                        $success = 0;
1192
-                    }
1193
-                }
1194
-            }
1195
-        } else {
1196
-            // grab single id and trash
1197
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1198
-            if ($trash) {
1199
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1200
-                    $success = 0;
1201
-                }
1202
-            } else {
1203
-                if (! $TKT->restore_by_ID($TKT_ID)) {
1204
-                    $success = 0;
1205
-                }
1206
-            }
1207
-        }
1208
-        $action_desc = $trash ? 'moved to the trash' : 'restored';
1209
-        $query_args = array(
1210
-            'action' => 'ticket_list_table',
1211
-            'status' => $trash ? '' : 'trashed',
1212
-        );
1213
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1214
-    }
1215
-
1216
-
1217
-    /**
1218
-     * Handles trashing default ticket.
1219
-     */
1220
-    protected function _delete_ticket()
1221
-    {
1222
-        $success = 1;
1223
-        // checkboxes?
1224
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1225
-            // if array has more than one element then success message should be plural
1226
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1227
-            // cycle thru the boxes
1228
-            while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1229
-                // delete
1230
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1231
-                    $success = 0;
1232
-                }
1233
-            }
1234
-        } else {
1235
-            // grab single id and trash
1236
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1237
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1238
-                $success = 0;
1239
-            }
1240
-        }
1241
-        $action_desc = 'deleted';
1242
-        $query_args = array(
1243
-            'action' => 'ticket_list_table',
1244
-            'status' => 'trashed',
1245
-        );
1246
-        // fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1247
-        if (EEM_Ticket::instance()->count_deleted_and_undeleted(
1248
-            array(array('TKT_is_default' => 1)),
1249
-            'TKT_ID',
1250
-            true
1251
-        )
1252
-        ) {
1253
-            $query_args = array();
1254
-        }
1255
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1256
-    }
1257
-
1258
-
1259
-    /**
1260
-     * @param int $TKT_ID
1261
-     * @return bool|int
1262
-     * @throws EE_Error
1263
-     */
1264
-    protected function _delete_the_ticket($TKT_ID)
1265
-    {
1266
-        $tkt = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1267
-        $tkt->_remove_relations('Datetime');
1268
-        // delete all related prices first
1269
-        $tkt->delete_related_permanently('Price');
1270
-        return $tkt->delete_permanently();
1271
-    }
19
+	/**
20
+	 * Extend_Events_Admin_Page constructor.
21
+	 *
22
+	 * @param bool $routing
23
+	 */
24
+	public function __construct($routing = true)
25
+	{
26
+		parent::__construct($routing);
27
+		if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
28
+			define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
29
+			define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
30
+			define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
31
+		}
32
+	}
33
+
34
+
35
+	/**
36
+	 * Sets routes.
37
+	 */
38
+	protected function _extend_page_config()
39
+	{
40
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
41
+		// is there a evt_id in the request?
42
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
43
+			? $this->_req_data['EVT_ID']
44
+			: 0;
45
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
46
+		// tkt_id?
47
+		$tkt_id = ! empty($this->_req_data['TKT_ID']) && ! is_array($this->_req_data['TKT_ID'])
48
+			? $this->_req_data['TKT_ID']
49
+			: 0;
50
+		$new_page_routes = array(
51
+			'duplicate_event'          => array(
52
+				'func'       => '_duplicate_event',
53
+				'capability' => 'ee_edit_event',
54
+				'obj_id'     => $evt_id,
55
+				'noheader'   => true,
56
+			),
57
+			'ticket_list_table'        => array(
58
+				'func'       => '_tickets_overview_list_table',
59
+				'capability' => 'ee_read_default_tickets',
60
+			),
61
+			'trash_ticket'             => array(
62
+				'func'       => '_trash_or_restore_ticket',
63
+				'capability' => 'ee_delete_default_ticket',
64
+				'obj_id'     => $tkt_id,
65
+				'noheader'   => true,
66
+				'args'       => array('trash' => true),
67
+			),
68
+			'trash_tickets'            => array(
69
+				'func'       => '_trash_or_restore_ticket',
70
+				'capability' => 'ee_delete_default_tickets',
71
+				'noheader'   => true,
72
+				'args'       => array('trash' => true),
73
+			),
74
+			'restore_ticket'           => array(
75
+				'func'       => '_trash_or_restore_ticket',
76
+				'capability' => 'ee_delete_default_ticket',
77
+				'obj_id'     => $tkt_id,
78
+				'noheader'   => true,
79
+			),
80
+			'restore_tickets'          => array(
81
+				'func'       => '_trash_or_restore_ticket',
82
+				'capability' => 'ee_delete_default_tickets',
83
+				'noheader'   => true,
84
+			),
85
+			'delete_ticket'            => array(
86
+				'func'       => '_delete_ticket',
87
+				'capability' => 'ee_delete_default_ticket',
88
+				'obj_id'     => $tkt_id,
89
+				'noheader'   => true,
90
+			),
91
+			'delete_tickets'           => array(
92
+				'func'       => '_delete_ticket',
93
+				'capability' => 'ee_delete_default_tickets',
94
+				'noheader'   => true,
95
+			),
96
+			'import_page'              => array(
97
+				'func'       => '_import_page',
98
+				'capability' => 'import',
99
+			),
100
+			'import'                   => array(
101
+				'func'       => '_import_events',
102
+				'capability' => 'import',
103
+				'noheader'   => true,
104
+			),
105
+			'import_events'            => array(
106
+				'func'       => '_import_events',
107
+				'capability' => 'import',
108
+				'noheader'   => true,
109
+			),
110
+			'export_events'            => array(
111
+				'func'       => '_events_export',
112
+				'capability' => 'export',
113
+				'noheader'   => true,
114
+			),
115
+			'export_categories'        => array(
116
+				'func'       => '_categories_export',
117
+				'capability' => 'export',
118
+				'noheader'   => true,
119
+			),
120
+			'sample_export_file'       => array(
121
+				'func'       => '_sample_export_file',
122
+				'capability' => 'export',
123
+				'noheader'   => true,
124
+			),
125
+			'update_template_settings' => array(
126
+				'func'       => '_update_template_settings',
127
+				'capability' => 'manage_options',
128
+				'noheader'   => true,
129
+			),
130
+		);
131
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
132
+		// partial route/config override
133
+		$this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
134
+		$this->_page_config['create_new']['metaboxes'][] = '_premium_event_editor_meta_boxes';
135
+		$this->_page_config['create_new']['qtips'][] = 'EE_Event_Editor_Tips';
136
+		$this->_page_config['edit']['qtips'][] = 'EE_Event_Editor_Tips';
137
+		$this->_page_config['edit']['metaboxes'][] = '_premium_event_editor_meta_boxes';
138
+		$this->_page_config['default']['list_table'] = 'Extend_Events_Admin_List_Table';
139
+		// add tickets tab but only if there are more than one default ticket!
140
+		$tkt_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
141
+			array(array('TKT_is_default' => 1)),
142
+			'TKT_ID',
143
+			true
144
+		);
145
+		if ($tkt_count > 1) {
146
+			$new_page_config = array(
147
+				'ticket_list_table' => array(
148
+					'nav'           => array(
149
+						'label' => esc_html__('Default Tickets', 'event_espresso'),
150
+						'order' => 60,
151
+					),
152
+					'list_table'    => 'Tickets_List_Table',
153
+					'require_nonce' => false,
154
+				),
155
+			);
156
+		}
157
+		// template settings
158
+		$new_page_config['template_settings'] = array(
159
+			'nav'           => array(
160
+				'label' => esc_html__('Templates', 'event_espresso'),
161
+				'order' => 30,
162
+			),
163
+			'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
164
+			'help_tabs'     => array(
165
+				'general_settings_templates_help_tab' => array(
166
+					'title'    => esc_html__('Templates', 'event_espresso'),
167
+					'filename' => 'general_settings_templates',
168
+				),
169
+			),
170
+			'help_tour'     => array('Templates_Help_Tour'),
171
+			'require_nonce' => false,
172
+		);
173
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
174
+		// add filters and actions
175
+		// modifying _views
176
+		add_filter(
177
+			'FHEE_event_datetime_metabox_add_additional_date_time_template',
178
+			array($this, 'add_additional_datetime_button'),
179
+			10,
180
+			2
181
+		);
182
+		add_filter(
183
+			'FHEE_event_datetime_metabox_clone_button_template',
184
+			array($this, 'add_datetime_clone_button'),
185
+			10,
186
+			2
187
+		);
188
+		add_filter(
189
+			'FHEE_event_datetime_metabox_timezones_template',
190
+			array($this, 'datetime_timezones_template'),
191
+			10,
192
+			2
193
+		);
194
+		// filters for event list table
195
+		add_filter('FHEE__Extend_Events_Admin_List_Table__filters', array($this, 'list_table_filters'), 10, 2);
196
+		add_filter(
197
+			'FHEE__Events_Admin_List_Table__column_actions__action_links',
198
+			array($this, 'extra_list_table_actions'),
199
+			10,
200
+			2
201
+		);
202
+		// legend item
203
+		add_filter('FHEE__Events_Admin_Page___event_legend_items__items', array($this, 'additional_legend_items'));
204
+		add_action('admin_init', array($this, 'admin_init'));
205
+	}
206
+
207
+
208
+	/**
209
+	 * admin_init
210
+	 */
211
+	public function admin_init()
212
+	{
213
+		EE_Registry::$i18n_js_strings = array_merge(
214
+			EE_Registry::$i18n_js_strings,
215
+			array(
216
+				'image_confirm'          => esc_html__(
217
+					'Do you really want to delete this image? Please remember to update your event to complete the removal.',
218
+					'event_espresso'
219
+				),
220
+				'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
221
+				'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
222
+				'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
223
+				'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
224
+				'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
225
+			)
226
+		);
227
+	}
228
+
229
+
230
+	/**
231
+	 * Add per page screen options to the default ticket list table view.
232
+	 */
233
+	protected function _add_screen_options_ticket_list_table()
234
+	{
235
+		$this->_per_page_screen_option();
236
+	}
237
+
238
+
239
+	/**
240
+	 * @param string $return
241
+	 * @param int    $id
242
+	 * @param string $new_title
243
+	 * @param string $new_slug
244
+	 * @return string
245
+	 */
246
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
247
+	{
248
+		$return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
249
+		// make sure this is only when editing
250
+		if (! empty($id)) {
251
+			$href = EE_Admin_Page::add_query_args_and_nonce(
252
+				array('action' => 'duplicate_event', 'EVT_ID' => $id),
253
+				$this->_admin_base_url
254
+			);
255
+			$title = esc_attr__('Duplicate Event', 'event_espresso');
256
+			$return .= '<a href="'
257
+					   . $href
258
+					   . '" title="'
259
+					   . $title
260
+					   . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
261
+					   . $title
262
+					   . '</a>';
263
+		}
264
+		return $return;
265
+	}
266
+
267
+
268
+	/**
269
+	 * Set the list table views for the default ticket list table view.
270
+	 */
271
+	public function _set_list_table_views_ticket_list_table()
272
+	{
273
+		$this->_views = array(
274
+			'all'     => array(
275
+				'slug'        => 'all',
276
+				'label'       => esc_html__('All', 'event_espresso'),
277
+				'count'       => 0,
278
+				'bulk_action' => array(
279
+					'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
280
+				),
281
+			),
282
+			'trashed' => array(
283
+				'slug'        => 'trashed',
284
+				'label'       => esc_html__('Trash', 'event_espresso'),
285
+				'count'       => 0,
286
+				'bulk_action' => array(
287
+					'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
288
+					'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
289
+				),
290
+			),
291
+		);
292
+	}
293
+
294
+
295
+	/**
296
+	 * Enqueue scripts and styles for the event editor.
297
+	 */
298
+	public function load_scripts_styles_edit()
299
+	{
300
+		wp_register_script(
301
+			'ee-event-editor-heartbeat',
302
+			EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
303
+			array('ee_admin_js', 'heartbeat'),
304
+			EVENT_ESPRESSO_VERSION,
305
+			true
306
+		);
307
+		wp_enqueue_script('ee-accounting');
308
+		// styles
309
+		wp_enqueue_style('espresso-ui-theme');
310
+		wp_enqueue_script('event_editor_js');
311
+		wp_enqueue_script('ee-event-editor-heartbeat');
312
+	}
313
+
314
+
315
+	/**
316
+	 * Returns template for the additional datetime.
317
+	 *
318
+	 * @param $template
319
+	 * @param $template_args
320
+	 * @return mixed
321
+	 * @throws DomainException
322
+	 */
323
+	public function add_additional_datetime_button($template, $template_args)
324
+	{
325
+		return EEH_Template::display_template(
326
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
327
+			$template_args,
328
+			true
329
+		);
330
+	}
331
+
332
+
333
+	/**
334
+	 * Returns the template for cloning a datetime.
335
+	 *
336
+	 * @param $template
337
+	 * @param $template_args
338
+	 * @return mixed
339
+	 * @throws DomainException
340
+	 */
341
+	public function add_datetime_clone_button($template, $template_args)
342
+	{
343
+		return EEH_Template::display_template(
344
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
345
+			$template_args,
346
+			true
347
+		);
348
+	}
349
+
350
+
351
+	/**
352
+	 * Returns the template for datetime timezones.
353
+	 *
354
+	 * @param $template
355
+	 * @param $template_args
356
+	 * @return mixed
357
+	 * @throws DomainException
358
+	 */
359
+	public function datetime_timezones_template($template, $template_args)
360
+	{
361
+		return EEH_Template::display_template(
362
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
363
+			$template_args,
364
+			true
365
+		);
366
+	}
367
+
368
+
369
+	/**
370
+	 * Sets the views for the default list table view.
371
+	 */
372
+	protected function _set_list_table_views_default()
373
+	{
374
+		parent::_set_list_table_views_default();
375
+		$new_views = array(
376
+			'today' => array(
377
+				'slug'        => 'today',
378
+				'label'       => esc_html__('Today', 'event_espresso'),
379
+				'count'       => $this->total_events_today(),
380
+				'bulk_action' => array(
381
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
382
+				),
383
+			),
384
+			'month' => array(
385
+				'slug'        => 'month',
386
+				'label'       => esc_html__('This Month', 'event_espresso'),
387
+				'count'       => $this->total_events_this_month(),
388
+				'bulk_action' => array(
389
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
390
+				),
391
+			),
392
+		);
393
+		$this->_views = array_merge($this->_views, $new_views);
394
+	}
395
+
396
+
397
+	/**
398
+	 * Returns the extra action links for the default list table view.
399
+	 *
400
+	 * @param array     $action_links
401
+	 * @param \EE_Event $event
402
+	 * @return array
403
+	 * @throws EE_Error
404
+	 */
405
+	public function extra_list_table_actions(array $action_links, \EE_Event $event)
406
+	{
407
+		if (EE_Registry::instance()->CAP->current_user_can(
408
+			'ee_read_registrations',
409
+			'espresso_registrations_reports',
410
+			$event->ID()
411
+		)
412
+		) {
413
+			$reports_query_args = array(
414
+				'action' => 'reports',
415
+				'EVT_ID' => $event->ID(),
416
+			);
417
+			$reports_link = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
418
+			$action_links[] = '<a href="'
419
+							  . $reports_link
420
+							  . '" title="'
421
+							  . esc_attr__('View Report', 'event_espresso')
422
+							  . '"><div class="dashicons dashicons-chart-bar"></div></a>'
423
+							  . "\n\t";
424
+		}
425
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
426
+			EE_Registry::instance()->load_helper('MSG_Template');
427
+			$action_links[] = EEH_MSG_Template::get_message_action_link(
428
+				'see_notifications_for',
429
+				null,
430
+				array('EVT_ID' => $event->ID())
431
+			);
432
+		}
433
+		return $action_links;
434
+	}
435
+
436
+
437
+	/**
438
+	 * @param $items
439
+	 * @return mixed
440
+	 */
441
+	public function additional_legend_items($items)
442
+	{
443
+		if (EE_Registry::instance()->CAP->current_user_can(
444
+			'ee_read_registrations',
445
+			'espresso_registrations_reports'
446
+		)
447
+		) {
448
+			$items['reports'] = array(
449
+				'class' => 'dashicons dashicons-chart-bar',
450
+				'desc'  => esc_html__('Event Reports', 'event_espresso'),
451
+			);
452
+		}
453
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
454
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
455
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
456
+				$items['view_related_messages'] = array(
457
+					'class' => $related_for_icon['css_class'],
458
+					'desc'  => $related_for_icon['label'],
459
+				);
460
+			}
461
+		}
462
+		return $items;
463
+	}
464
+
465
+
466
+	/**
467
+	 * This is the callback method for the duplicate event route
468
+	 * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
469
+	 * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
470
+	 * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
471
+	 * After duplication the redirect is to the new event edit page.
472
+	 *
473
+	 * @return void
474
+	 * @access protected
475
+	 * @throws EE_Error If EE_Event is not available with given ID
476
+	 */
477
+	protected function _duplicate_event()
478
+	{
479
+		// first make sure the ID for the event is in the request.
480
+		//  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
481
+		if (! isset($this->_req_data['EVT_ID'])) {
482
+			EE_Error::add_error(
483
+				esc_html__(
484
+					'In order to duplicate an event an Event ID is required.  None was given.',
485
+					'event_espresso'
486
+				),
487
+				__FILE__,
488
+				__FUNCTION__,
489
+				__LINE__
490
+			);
491
+			$this->_redirect_after_action(false, '', '', array(), true);
492
+			return;
493
+		}
494
+		// k we've got EVT_ID so let's use that to get the event we'll duplicate
495
+		$orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
496
+		if (! $orig_event instanceof EE_Event) {
497
+			throw new EE_Error(
498
+				sprintf(
499
+					esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
500
+					$this->_req_data['EVT_ID']
501
+				)
502
+			);
503
+		}
504
+		// k now let's clone the $orig_event before getting relations
505
+		$new_event = clone $orig_event;
506
+		// original datetimes
507
+		$orig_datetimes = $orig_event->get_many_related('Datetime');
508
+		// other original relations
509
+		$orig_ven = $orig_event->get_many_related('Venue');
510
+		// reset the ID and modify other details to make it clear this is a dupe
511
+		$new_event->set('EVT_ID', 0);
512
+		$new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
513
+		$new_event->set('EVT_name', $new_name);
514
+		$new_event->set(
515
+			'EVT_slug',
516
+			wp_unique_post_slug(
517
+				sanitize_title($orig_event->name()),
518
+				0,
519
+				'publish',
520
+				'espresso_events',
521
+				0
522
+			)
523
+		);
524
+		$new_event->set('status', 'draft');
525
+		// duplicate discussion settings
526
+		$new_event->set('comment_status', $orig_event->get('comment_status'));
527
+		$new_event->set('ping_status', $orig_event->get('ping_status'));
528
+		// save the new event
529
+		$new_event->save();
530
+		// venues
531
+		foreach ($orig_ven as $ven) {
532
+			$new_event->_add_relation_to($ven, 'Venue');
533
+		}
534
+		$new_event->save();
535
+		// now we need to get the question group relations and handle that
536
+		// first primary question groups
537
+		$orig_primary_qgs = $orig_event->get_many_related(
538
+			'Question_Group',
539
+			[['Event_Question_Group.EQG_primary' => true]]
540
+		);
541
+		if (! empty($orig_primary_qgs)) {
542
+			foreach ($orig_primary_qgs as $id => $obj) {
543
+				if ($obj instanceof EE_Question_Group) {
544
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
545
+				}
546
+			}
547
+		}
548
+		// next additional attendee question groups
549
+		$orig_additional_qgs = $orig_event->get_many_related(
550
+			'Question_Group',
551
+			[['Event_Question_Group.EQG_additional' => true]]
552
+		);
553
+		if (! empty($orig_additional_qgs)) {
554
+			foreach ($orig_additional_qgs as $id => $obj) {
555
+				if ($obj instanceof EE_Question_Group) {
556
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
557
+				}
558
+			}
559
+		}
560
+
561
+		$new_event->save();
562
+
563
+		// k now that we have the new event saved we can loop through the datetimes and start adding relations.
564
+		$cloned_tickets = array();
565
+		foreach ($orig_datetimes as $orig_dtt) {
566
+			if (! $orig_dtt instanceof EE_Datetime) {
567
+				continue;
568
+			}
569
+			$new_dtt = clone $orig_dtt;
570
+			$orig_tkts = $orig_dtt->tickets();
571
+			// save new dtt then add to event
572
+			$new_dtt->set('DTT_ID', 0);
573
+			$new_dtt->set('DTT_sold', 0);
574
+			$new_dtt->set_reserved(0);
575
+			$new_dtt->save();
576
+			$new_event->_add_relation_to($new_dtt, 'Datetime');
577
+			$new_event->save();
578
+			// now let's get the ticket relations setup.
579
+			foreach ((array) $orig_tkts as $orig_tkt) {
580
+				// it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
581
+				if (! $orig_tkt instanceof EE_Ticket) {
582
+					continue;
583
+				}
584
+				// is this ticket archived?  If it is then let's skip
585
+				if ($orig_tkt->get('TKT_deleted')) {
586
+					continue;
587
+				}
588
+				// does this original ticket already exist in the clone_tickets cache?
589
+				//  If so we'll just use the new ticket from it.
590
+				if (isset($cloned_tickets[ $orig_tkt->ID() ])) {
591
+					$new_tkt = $cloned_tickets[ $orig_tkt->ID() ];
592
+				} else {
593
+					$new_tkt = clone $orig_tkt;
594
+					// get relations on the $orig_tkt that we need to setup.
595
+					$orig_prices = $orig_tkt->prices();
596
+					$new_tkt->set('TKT_ID', 0);
597
+					$new_tkt->set('TKT_sold', 0);
598
+					$new_tkt->set('TKT_reserved', 0);
599
+					$new_tkt->save(); // make sure new ticket has ID.
600
+					// price relations on new ticket need to be setup.
601
+					foreach ($orig_prices as $orig_price) {
602
+						$new_price = clone $orig_price;
603
+						$new_price->set('PRC_ID', 0);
604
+						$new_price->save();
605
+						$new_tkt->_add_relation_to($new_price, 'Price');
606
+						$new_tkt->save();
607
+					}
608
+
609
+					do_action(
610
+						'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
611
+						$orig_tkt,
612
+						$new_tkt,
613
+						$orig_prices,
614
+						$orig_event,
615
+						$orig_dtt,
616
+						$new_dtt
617
+					);
618
+				}
619
+				// k now we can add the new ticket as a relation to the new datetime
620
+				// and make sure its added to our cached $cloned_tickets array
621
+				// for use with later datetimes that have the same ticket.
622
+				$new_dtt->_add_relation_to($new_tkt, 'Ticket');
623
+				$new_dtt->save();
624
+				$cloned_tickets[ $orig_tkt->ID() ] = $new_tkt;
625
+			}
626
+		}
627
+		// clone taxonomy information
628
+		$taxonomies_to_clone_with = apply_filters(
629
+			'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
630
+			array('espresso_event_categories', 'espresso_event_type', 'post_tag')
631
+		);
632
+		// get terms for original event (notice)
633
+		$orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
634
+		// loop through terms and add them to new event.
635
+		foreach ($orig_terms as $term) {
636
+			wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
637
+		}
638
+
639
+		// duplicate other core WP_Post items for this event.
640
+		// post thumbnail (feature image).
641
+		$feature_image_id = get_post_thumbnail_id($orig_event->ID());
642
+		if ($feature_image_id) {
643
+			update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
644
+		}
645
+
646
+		// duplicate page_template setting
647
+		$page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
648
+		if ($page_template) {
649
+			update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
650
+		}
651
+
652
+		do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
653
+		// now let's redirect to the edit page for this duplicated event if we have a new event id.
654
+		if ($new_event->ID()) {
655
+			$redirect_args = array(
656
+				'post'   => $new_event->ID(),
657
+				'action' => 'edit',
658
+			);
659
+			EE_Error::add_success(
660
+				esc_html__(
661
+					'Event successfully duplicated.  Please review the details below and make any necessary edits',
662
+					'event_espresso'
663
+				)
664
+			);
665
+		} else {
666
+			$redirect_args = array(
667
+				'action' => 'default',
668
+			);
669
+			EE_Error::add_error(
670
+				esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
671
+				__FILE__,
672
+				__FUNCTION__,
673
+				__LINE__
674
+			);
675
+		}
676
+		$this->_redirect_after_action(false, '', '', $redirect_args, true);
677
+	}
678
+
679
+
680
+	/**
681
+	 * Generates output for the import page.
682
+	 *
683
+	 * @throws DomainException
684
+	 */
685
+	protected function _import_page()
686
+	{
687
+		$title = esc_html__('Import', 'event_espresso');
688
+		$intro = esc_html__(
689
+			'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
690
+			'event_espresso'
691
+		);
692
+		$form_url = EVENTS_ADMIN_URL;
693
+		$action = 'import_events';
694
+		$type = 'csv';
695
+		$this->_template_args['form'] = EE_Import::instance()->upload_form(
696
+			$title,
697
+			$intro,
698
+			$form_url,
699
+			$action,
700
+			$type
701
+		);
702
+		$this->_template_args['sample_file_link'] = EE_Admin_Page::add_query_args_and_nonce(
703
+			array('action' => 'sample_export_file'),
704
+			$this->_admin_base_url
705
+		);
706
+		$content = EEH_Template::display_template(
707
+			EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
708
+			$this->_template_args,
709
+			true
710
+		);
711
+		$this->_template_args['admin_page_content'] = $content;
712
+		$this->display_admin_page_with_sidebar();
713
+	}
714
+
715
+
716
+	/**
717
+	 * _import_events
718
+	 * This handles displaying the screen and running imports for importing events.
719
+	 *
720
+	 * @return void
721
+	 */
722
+	protected function _import_events()
723
+	{
724
+		require_once(EE_CLASSES . 'EE_Import.class.php');
725
+		$success = EE_Import::instance()->import();
726
+		$this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
727
+	}
728
+
729
+
730
+	/**
731
+	 * _events_export
732
+	 * Will export all (or just the given event) to a Excel compatible file.
733
+	 *
734
+	 * @access protected
735
+	 * @return void
736
+	 */
737
+	protected function _events_export()
738
+	{
739
+		if (isset($this->_req_data['EVT_ID'])) {
740
+			$event_ids = $this->_req_data['EVT_ID'];
741
+		} elseif (isset($this->_req_data['EVT_IDs'])) {
742
+			$event_ids = $this->_req_data['EVT_IDs'];
743
+		} else {
744
+			$event_ids = null;
745
+		}
746
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
747
+		$new_request_args = array(
748
+			'export' => 'report',
749
+			'action' => 'all_event_data',
750
+			'EVT_ID' => $event_ids,
751
+		);
752
+		$this->_req_data = array_merge($this->_req_data, $new_request_args);
753
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
754
+			require_once(EE_CLASSES . 'EE_Export.class.php');
755
+			$EE_Export = EE_Export::instance($this->_req_data);
756
+			$EE_Export->export();
757
+		}
758
+	}
759
+
760
+
761
+	/**
762
+	 * handle category exports()
763
+	 *
764
+	 * @return void
765
+	 */
766
+	protected function _categories_export()
767
+	{
768
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
769
+		$new_request_args = array(
770
+			'export'       => 'report',
771
+			'action'       => 'categories',
772
+			'category_ids' => $this->_req_data['EVT_CAT_ID'],
773
+		);
774
+		$this->_req_data = array_merge($this->_req_data, $new_request_args);
775
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
776
+			require_once(EE_CLASSES . 'EE_Export.class.php');
777
+			$EE_Export = EE_Export::instance($this->_req_data);
778
+			$EE_Export->export();
779
+		}
780
+	}
781
+
782
+
783
+	/**
784
+	 * Creates a sample CSV file for importing
785
+	 */
786
+	protected function _sample_export_file()
787
+	{
788
+		// require_once(EE_CLASSES . 'EE_Export.class.php');
789
+		EE_Export::instance()->export_sample();
790
+	}
791
+
792
+
793
+	/*************        Template Settings        *************/
794
+	/**
795
+	 * Generates template settings page output
796
+	 *
797
+	 * @throws DomainException
798
+	 * @throws EE_Error
799
+	 */
800
+	protected function _template_settings()
801
+	{
802
+		$this->_template_args['values'] = $this->_yes_no_values;
803
+		/**
804
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
805
+		 * from General_Settings_Admin_Page to here.
806
+		 */
807
+		$this->_template_args = apply_filters(
808
+			'FHEE__General_Settings_Admin_Page__template_settings__template_args',
809
+			$this->_template_args
810
+		);
811
+		$this->_set_add_edit_form_tags('update_template_settings');
812
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
813
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
814
+			EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
815
+			$this->_template_args,
816
+			true
817
+		);
818
+		$this->display_admin_page_with_sidebar();
819
+	}
820
+
821
+
822
+	/**
823
+	 * Handler for updating template settings.
824
+	 *
825
+	 * @throws InvalidInterfaceException
826
+	 * @throws InvalidDataTypeException
827
+	 * @throws InvalidArgumentException
828
+	 */
829
+	protected function _update_template_settings()
830
+	{
831
+		/**
832
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
833
+		 * from General_Settings_Admin_Page to here.
834
+		 */
835
+		EE_Registry::instance()->CFG->template_settings = apply_filters(
836
+			'FHEE__General_Settings_Admin_Page__update_template_settings__data',
837
+			EE_Registry::instance()->CFG->template_settings,
838
+			$this->_req_data
839
+		);
840
+		// update custom post type slugs and detect if we need to flush rewrite rules
841
+		$old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
842
+		EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
843
+			? EE_Registry::instance()->CFG->core->event_cpt_slug
844
+			: EEH_URL::slugify($this->_req_data['event_cpt_slug'], 'events');
845
+		$what = 'Template Settings';
846
+		$success = $this->_update_espresso_configuration(
847
+			$what,
848
+			EE_Registry::instance()->CFG->template_settings,
849
+			__FILE__,
850
+			__FUNCTION__,
851
+			__LINE__
852
+		);
853
+		if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
854
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
855
+			$rewrite_rules = LoaderFactory::getLoader()->getShared(
856
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
857
+			);
858
+			$rewrite_rules->flush();
859
+		}
860
+		$this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
861
+	}
862
+
863
+
864
+	/**
865
+	 * _premium_event_editor_meta_boxes
866
+	 * add all metaboxes related to the event_editor
867
+	 *
868
+	 * @access protected
869
+	 * @return void
870
+	 * @throws EE_Error
871
+	 */
872
+	protected function _premium_event_editor_meta_boxes()
873
+	{
874
+		$this->verify_cpt_object();
875
+		add_meta_box(
876
+			'espresso_event_editor_event_options',
877
+			esc_html__('Event Registration Options', 'event_espresso'),
878
+			array($this, 'registration_options_meta_box'),
879
+			$this->page_slug,
880
+			'side',
881
+			'core'
882
+		);
883
+	}
884
+
885
+
886
+	/**
887
+	 * override caf metabox
888
+	 *
889
+	 * @return void
890
+	 * @throws DomainException
891
+	 */
892
+	public function registration_options_meta_box()
893
+	{
894
+		$yes_no_values = array(
895
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
896
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
897
+		);
898
+		$default_reg_status_values = EEM_Registration::reg_status_array(
899
+			array(
900
+				EEM_Registration::status_id_cancelled,
901
+				EEM_Registration::status_id_declined,
902
+				EEM_Registration::status_id_incomplete,
903
+				EEM_Registration::status_id_wait_list,
904
+			),
905
+			true
906
+		);
907
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
908
+		$template_args['_event'] = $this->_cpt_model_obj;
909
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
910
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
911
+			'default_reg_status',
912
+			$default_reg_status_values,
913
+			$this->_cpt_model_obj->default_registration_status()
914
+		);
915
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
916
+			'display_desc',
917
+			$yes_no_values,
918
+			$this->_cpt_model_obj->display_description()
919
+		);
920
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
921
+			'display_ticket_selector',
922
+			$yes_no_values,
923
+			$this->_cpt_model_obj->display_ticket_selector(),
924
+			'',
925
+			'',
926
+			false
927
+		);
928
+		$template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
929
+			'EVT_default_registration_status',
930
+			$default_reg_status_values,
931
+			$this->_cpt_model_obj->default_registration_status()
932
+		);
933
+		$template_args['additional_registration_options'] = apply_filters(
934
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
935
+			'',
936
+			$template_args,
937
+			$yes_no_values,
938
+			$default_reg_status_values
939
+		);
940
+		EEH_Template::display_template(
941
+			EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
942
+			$template_args
943
+		);
944
+	}
945
+
946
+
947
+
948
+	/**
949
+	 * wp_list_table_mods for caf
950
+	 * ============================
951
+	 */
952
+	/**
953
+	 * hook into list table filters and provide filters for caffeinated list table
954
+	 *
955
+	 * @param  array $old_filters    any existing filters present
956
+	 * @param  array $list_table_obj the list table object
957
+	 * @return array                  new filters
958
+	 */
959
+	public function list_table_filters($old_filters, $list_table_obj)
960
+	{
961
+		$filters = array();
962
+		// first month/year filters
963
+		$filters[] = $this->espresso_event_months_dropdown();
964
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
965
+		// active status dropdown
966
+		if ($status !== 'draft') {
967
+			$filters[] = $this->active_status_dropdown(
968
+				isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
969
+			);
970
+		}
971
+		// category filter
972
+		$filters[] = $this->category_dropdown();
973
+		return array_merge($old_filters, $filters);
974
+	}
975
+
976
+
977
+	/**
978
+	 * espresso_event_months_dropdown
979
+	 *
980
+	 * @access public
981
+	 * @return string                dropdown listing month/year selections for events.
982
+	 */
983
+	public function espresso_event_months_dropdown()
984
+	{
985
+		// what we need to do is get all PRIMARY datetimes for all events to filter on.
986
+		// Note we need to include any other filters that are set!
987
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
988
+		// categories?
989
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
990
+			? $this->_req_data['EVT_CAT']
991
+			: null;
992
+		// active status?
993
+		$active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
994
+		$cur_date = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
995
+		return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
996
+	}
997
+
998
+
999
+	/**
1000
+	 * returns a list of "active" statuses on the event
1001
+	 *
1002
+	 * @param  string $current_value whatever the current active status is
1003
+	 * @return string
1004
+	 */
1005
+	public function active_status_dropdown($current_value = '')
1006
+	{
1007
+		$select_name = 'active_status';
1008
+		$values = array(
1009
+			'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1010
+			'active'   => esc_html__('Active', 'event_espresso'),
1011
+			'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1012
+			'expired'  => esc_html__('Expired', 'event_espresso'),
1013
+			'inactive' => esc_html__('Inactive', 'event_espresso'),
1014
+		);
1015
+		$id = 'id="espresso-active-status-dropdown-filter"';
1016
+		$class = 'wide';
1017
+		return EEH_Form_Fields::select_input($select_name, $values, $current_value, $id, $class);
1018
+	}
1019
+
1020
+
1021
+	/**
1022
+	 * output a dropdown of the categories for the category filter on the event admin list table
1023
+	 *
1024
+	 * @access  public
1025
+	 * @return string html
1026
+	 */
1027
+	public function category_dropdown()
1028
+	{
1029
+		$cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1030
+		return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1031
+	}
1032
+
1033
+
1034
+	/**
1035
+	 * get total number of events today
1036
+	 *
1037
+	 * @access public
1038
+	 * @return int
1039
+	 * @throws EE_Error
1040
+	 */
1041
+	public function total_events_today()
1042
+	{
1043
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1044
+			'DTT_EVT_start',
1045
+			date('Y-m-d') . ' 00:00:00',
1046
+			'Y-m-d H:i:s',
1047
+			'UTC'
1048
+		);
1049
+		$end = EEM_Datetime::instance()->convert_datetime_for_query(
1050
+			'DTT_EVT_start',
1051
+			date('Y-m-d') . ' 23:59:59',
1052
+			'Y-m-d H:i:s',
1053
+			'UTC'
1054
+		);
1055
+		$where = array(
1056
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1057
+		);
1058
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1059
+		return $count;
1060
+	}
1061
+
1062
+
1063
+	/**
1064
+	 * get total number of events this month
1065
+	 *
1066
+	 * @access public
1067
+	 * @return int
1068
+	 * @throws EE_Error
1069
+	 */
1070
+	public function total_events_this_month()
1071
+	{
1072
+		// Dates
1073
+		$this_year_r = date('Y');
1074
+		$this_month_r = date('m');
1075
+		$days_this_month = date('t');
1076
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1077
+			'DTT_EVT_start',
1078
+			$this_year_r . '-' . $this_month_r . '-01 00:00:00',
1079
+			'Y-m-d H:i:s',
1080
+			'UTC'
1081
+		);
1082
+		$end = EEM_Datetime::instance()->convert_datetime_for_query(
1083
+			'DTT_EVT_start',
1084
+			$this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1085
+			'Y-m-d H:i:s',
1086
+			'UTC'
1087
+		);
1088
+		$where = array(
1089
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1090
+		);
1091
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1092
+		return $count;
1093
+	}
1094
+
1095
+
1096
+	/** DEFAULT TICKETS STUFF **/
1097
+
1098
+	/**
1099
+	 * Output default tickets list table view.
1100
+	 */
1101
+	public function _tickets_overview_list_table()
1102
+	{
1103
+		$this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1104
+		$this->display_admin_list_table_page_with_no_sidebar();
1105
+	}
1106
+
1107
+
1108
+	/**
1109
+	 * @param int  $per_page
1110
+	 * @param bool $count
1111
+	 * @param bool $trashed
1112
+	 * @return \EE_Soft_Delete_Base_Class[]|int
1113
+	 */
1114
+	public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1115
+	{
1116
+		$orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1117
+		$order = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1118
+		switch ($orderby) {
1119
+			case 'TKT_name':
1120
+				$orderby = array('TKT_name' => $order);
1121
+				break;
1122
+			case 'TKT_price':
1123
+				$orderby = array('TKT_price' => $order);
1124
+				break;
1125
+			case 'TKT_uses':
1126
+				$orderby = array('TKT_uses' => $order);
1127
+				break;
1128
+			case 'TKT_min':
1129
+				$orderby = array('TKT_min' => $order);
1130
+				break;
1131
+			case 'TKT_max':
1132
+				$orderby = array('TKT_max' => $order);
1133
+				break;
1134
+			case 'TKT_qty':
1135
+				$orderby = array('TKT_qty' => $order);
1136
+				break;
1137
+		}
1138
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1139
+			? $this->_req_data['paged']
1140
+			: 1;
1141
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1142
+			? $this->_req_data['perpage']
1143
+			: $per_page;
1144
+		$_where = array(
1145
+			'TKT_is_default' => 1,
1146
+			'TKT_deleted'    => $trashed,
1147
+		);
1148
+		$offset = ($current_page - 1) * $per_page;
1149
+		$limit = array($offset, $per_page);
1150
+		if (isset($this->_req_data['s'])) {
1151
+			$sstr = '%' . $this->_req_data['s'] . '%';
1152
+			$_where['OR'] = array(
1153
+				'TKT_name'        => array('LIKE', $sstr),
1154
+				'TKT_description' => array('LIKE', $sstr),
1155
+			);
1156
+		}
1157
+		$query_params = array(
1158
+			$_where,
1159
+			'order_by' => $orderby,
1160
+			'limit'    => $limit,
1161
+			'group_by' => 'TKT_ID',
1162
+		);
1163
+		if ($count) {
1164
+			return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1165
+		} else {
1166
+			return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1167
+		}
1168
+	}
1169
+
1170
+
1171
+	/**
1172
+	 * @param bool $trash
1173
+	 * @throws EE_Error
1174
+	 */
1175
+	protected function _trash_or_restore_ticket($trash = false)
1176
+	{
1177
+		$success = 1;
1178
+		$TKT = EEM_Ticket::instance();
1179
+		// checkboxes?
1180
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1181
+			// if array has more than one element then success message should be plural
1182
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1183
+			// cycle thru the boxes
1184
+			while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1185
+				if ($trash) {
1186
+					if (! $TKT->delete_by_ID($TKT_ID)) {
1187
+						$success = 0;
1188
+					}
1189
+				} else {
1190
+					if (! $TKT->restore_by_ID($TKT_ID)) {
1191
+						$success = 0;
1192
+					}
1193
+				}
1194
+			}
1195
+		} else {
1196
+			// grab single id and trash
1197
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1198
+			if ($trash) {
1199
+				if (! $TKT->delete_by_ID($TKT_ID)) {
1200
+					$success = 0;
1201
+				}
1202
+			} else {
1203
+				if (! $TKT->restore_by_ID($TKT_ID)) {
1204
+					$success = 0;
1205
+				}
1206
+			}
1207
+		}
1208
+		$action_desc = $trash ? 'moved to the trash' : 'restored';
1209
+		$query_args = array(
1210
+			'action' => 'ticket_list_table',
1211
+			'status' => $trash ? '' : 'trashed',
1212
+		);
1213
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1214
+	}
1215
+
1216
+
1217
+	/**
1218
+	 * Handles trashing default ticket.
1219
+	 */
1220
+	protected function _delete_ticket()
1221
+	{
1222
+		$success = 1;
1223
+		// checkboxes?
1224
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1225
+			// if array has more than one element then success message should be plural
1226
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1227
+			// cycle thru the boxes
1228
+			while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1229
+				// delete
1230
+				if (! $this->_delete_the_ticket($TKT_ID)) {
1231
+					$success = 0;
1232
+				}
1233
+			}
1234
+		} else {
1235
+			// grab single id and trash
1236
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1237
+			if (! $this->_delete_the_ticket($TKT_ID)) {
1238
+				$success = 0;
1239
+			}
1240
+		}
1241
+		$action_desc = 'deleted';
1242
+		$query_args = array(
1243
+			'action' => 'ticket_list_table',
1244
+			'status' => 'trashed',
1245
+		);
1246
+		// fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1247
+		if (EEM_Ticket::instance()->count_deleted_and_undeleted(
1248
+			array(array('TKT_is_default' => 1)),
1249
+			'TKT_ID',
1250
+			true
1251
+		)
1252
+		) {
1253
+			$query_args = array();
1254
+		}
1255
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1256
+	}
1257
+
1258
+
1259
+	/**
1260
+	 * @param int $TKT_ID
1261
+	 * @return bool|int
1262
+	 * @throws EE_Error
1263
+	 */
1264
+	protected function _delete_the_ticket($TKT_ID)
1265
+	{
1266
+		$tkt = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1267
+		$tkt->_remove_relations('Datetime');
1268
+		// delete all related prices first
1269
+		$tkt->delete_related_permanently('Price');
1270
+		return $tkt->delete_permanently();
1271
+	}
1272 1272
 }
Please login to merge, or discard this patch.
Spacing   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -24,10 +24,10 @@  discard block
 block discarded – undo
24 24
     public function __construct($routing = true)
25 25
     {
26 26
         parent::__construct($routing);
27
-        if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
28
-            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
29
-            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
30
-            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
27
+        if ( ! defined('EVENTS_CAF_TEMPLATE_PATH')) {
28
+            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND.'events/templates/');
29
+            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND.'events/assets/');
30
+            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL.'events/assets/');
31 31
         }
32 32
     }
33 33
 
@@ -37,7 +37,7 @@  discard block
 block discarded – undo
37 37
      */
38 38
     protected function _extend_page_config()
39 39
     {
40
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
40
+        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND.'events';
41 41
         // is there a evt_id in the request?
42 42
         $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
43 43
             ? $this->_req_data['EVT_ID']
@@ -247,7 +247,7 @@  discard block
 block discarded – undo
247 247
     {
248 248
         $return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
249 249
         // make sure this is only when editing
250
-        if (! empty($id)) {
250
+        if ( ! empty($id)) {
251 251
             $href = EE_Admin_Page::add_query_args_and_nonce(
252 252
                 array('action' => 'duplicate_event', 'EVT_ID' => $id),
253 253
                 $this->_admin_base_url
@@ -299,7 +299,7 @@  discard block
 block discarded – undo
299 299
     {
300 300
         wp_register_script(
301 301
             'ee-event-editor-heartbeat',
302
-            EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
302
+            EVENTS_CAF_ASSETS_URL.'event-editor-heartbeat.js',
303 303
             array('ee_admin_js', 'heartbeat'),
304 304
             EVENT_ESPRESSO_VERSION,
305 305
             true
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
     public function add_additional_datetime_button($template, $template_args)
324 324
     {
325 325
         return EEH_Template::display_template(
326
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
326
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_add_additional_time.template.php',
327 327
             $template_args,
328 328
             true
329 329
         );
@@ -341,7 +341,7 @@  discard block
 block discarded – undo
341 341
     public function add_datetime_clone_button($template, $template_args)
342 342
     {
343 343
         return EEH_Template::display_template(
344
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
344
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_metabox_clone_button.template.php',
345 345
             $template_args,
346 346
             true
347 347
         );
@@ -359,7 +359,7 @@  discard block
 block discarded – undo
359 359
     public function datetime_timezones_template($template, $template_args)
360 360
     {
361 361
         return EEH_Template::display_template(
362
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
362
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_timezones.template.php',
363 363
             $template_args,
364 364
             true
365 365
         );
@@ -478,7 +478,7 @@  discard block
 block discarded – undo
478 478
     {
479 479
         // first make sure the ID for the event is in the request.
480 480
         //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
481
-        if (! isset($this->_req_data['EVT_ID'])) {
481
+        if ( ! isset($this->_req_data['EVT_ID'])) {
482 482
             EE_Error::add_error(
483 483
                 esc_html__(
484 484
                     'In order to duplicate an event an Event ID is required.  None was given.',
@@ -493,7 +493,7 @@  discard block
 block discarded – undo
493 493
         }
494 494
         // k we've got EVT_ID so let's use that to get the event we'll duplicate
495 495
         $orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
496
-        if (! $orig_event instanceof EE_Event) {
496
+        if ( ! $orig_event instanceof EE_Event) {
497 497
             throw new EE_Error(
498 498
                 sprintf(
499 499
                     esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
@@ -509,7 +509,7 @@  discard block
 block discarded – undo
509 509
         $orig_ven = $orig_event->get_many_related('Venue');
510 510
         // reset the ID and modify other details to make it clear this is a dupe
511 511
         $new_event->set('EVT_ID', 0);
512
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
512
+        $new_name = $new_event->name().' '.esc_html__('**DUPLICATE**', 'event_espresso');
513 513
         $new_event->set('EVT_name', $new_name);
514 514
         $new_event->set(
515 515
             'EVT_slug',
@@ -538,7 +538,7 @@  discard block
 block discarded – undo
538 538
             'Question_Group',
539 539
             [['Event_Question_Group.EQG_primary' => true]]
540 540
         );
541
-        if (! empty($orig_primary_qgs)) {
541
+        if ( ! empty($orig_primary_qgs)) {
542 542
             foreach ($orig_primary_qgs as $id => $obj) {
543 543
                 if ($obj instanceof EE_Question_Group) {
544 544
                     $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
@@ -550,7 +550,7 @@  discard block
 block discarded – undo
550 550
             'Question_Group',
551 551
             [['Event_Question_Group.EQG_additional' => true]]
552 552
         );
553
-        if (! empty($orig_additional_qgs)) {
553
+        if ( ! empty($orig_additional_qgs)) {
554 554
             foreach ($orig_additional_qgs as $id => $obj) {
555 555
                 if ($obj instanceof EE_Question_Group) {
556 556
                     $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
@@ -563,7 +563,7 @@  discard block
 block discarded – undo
563 563
         // k now that we have the new event saved we can loop through the datetimes and start adding relations.
564 564
         $cloned_tickets = array();
565 565
         foreach ($orig_datetimes as $orig_dtt) {
566
-            if (! $orig_dtt instanceof EE_Datetime) {
566
+            if ( ! $orig_dtt instanceof EE_Datetime) {
567 567
                 continue;
568 568
             }
569 569
             $new_dtt = clone $orig_dtt;
@@ -578,7 +578,7 @@  discard block
 block discarded – undo
578 578
             // now let's get the ticket relations setup.
579 579
             foreach ((array) $orig_tkts as $orig_tkt) {
580 580
                 // it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
581
-                if (! $orig_tkt instanceof EE_Ticket) {
581
+                if ( ! $orig_tkt instanceof EE_Ticket) {
582 582
                     continue;
583 583
                 }
584 584
                 // is this ticket archived?  If it is then let's skip
@@ -587,8 +587,8 @@  discard block
 block discarded – undo
587 587
                 }
588 588
                 // does this original ticket already exist in the clone_tickets cache?
589 589
                 //  If so we'll just use the new ticket from it.
590
-                if (isset($cloned_tickets[ $orig_tkt->ID() ])) {
591
-                    $new_tkt = $cloned_tickets[ $orig_tkt->ID() ];
590
+                if (isset($cloned_tickets[$orig_tkt->ID()])) {
591
+                    $new_tkt = $cloned_tickets[$orig_tkt->ID()];
592 592
                 } else {
593 593
                     $new_tkt = clone $orig_tkt;
594 594
                     // get relations on the $orig_tkt that we need to setup.
@@ -621,7 +621,7 @@  discard block
 block discarded – undo
621 621
                 // for use with later datetimes that have the same ticket.
622 622
                 $new_dtt->_add_relation_to($new_tkt, 'Ticket');
623 623
                 $new_dtt->save();
624
-                $cloned_tickets[ $orig_tkt->ID() ] = $new_tkt;
624
+                $cloned_tickets[$orig_tkt->ID()] = $new_tkt;
625 625
             }
626 626
         }
627 627
         // clone taxonomy information
@@ -704,7 +704,7 @@  discard block
 block discarded – undo
704 704
             $this->_admin_base_url
705 705
         );
706 706
         $content = EEH_Template::display_template(
707
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
707
+            EVENTS_CAF_TEMPLATE_PATH.'import_page.template.php',
708 708
             $this->_template_args,
709 709
             true
710 710
         );
@@ -721,7 +721,7 @@  discard block
 block discarded – undo
721 721
      */
722 722
     protected function _import_events()
723 723
     {
724
-        require_once(EE_CLASSES . 'EE_Import.class.php');
724
+        require_once(EE_CLASSES.'EE_Import.class.php');
725 725
         $success = EE_Import::instance()->import();
726 726
         $this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
727 727
     }
@@ -750,8 +750,8 @@  discard block
 block discarded – undo
750 750
             'EVT_ID' => $event_ids,
751 751
         );
752 752
         $this->_req_data = array_merge($this->_req_data, $new_request_args);
753
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
754
-            require_once(EE_CLASSES . 'EE_Export.class.php');
753
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
754
+            require_once(EE_CLASSES.'EE_Export.class.php');
755 755
             $EE_Export = EE_Export::instance($this->_req_data);
756 756
             $EE_Export->export();
757 757
         }
@@ -772,8 +772,8 @@  discard block
 block discarded – undo
772 772
             'category_ids' => $this->_req_data['EVT_CAT_ID'],
773 773
         );
774 774
         $this->_req_data = array_merge($this->_req_data, $new_request_args);
775
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
776
-            require_once(EE_CLASSES . 'EE_Export.class.php');
775
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
776
+            require_once(EE_CLASSES.'EE_Export.class.php');
777 777
             $EE_Export = EE_Export::instance($this->_req_data);
778 778
             $EE_Export->export();
779 779
         }
@@ -811,7 +811,7 @@  discard block
 block discarded – undo
811 811
         $this->_set_add_edit_form_tags('update_template_settings');
812 812
         $this->_set_publish_post_box_vars(null, false, false, null, false);
813 813
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
814
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
814
+            EVENTS_CAF_TEMPLATE_PATH.'template_settings.template.php',
815 815
             $this->_template_args,
816 816
             true
817 817
         );
@@ -938,7 +938,7 @@  discard block
 block discarded – undo
938 938
             $default_reg_status_values
939 939
         );
940 940
         EEH_Template::display_template(
941
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
941
+            EVENTS_CAF_TEMPLATE_PATH.'event_registration_options.template.php',
942 942
             $template_args
943 943
         );
944 944
     }
@@ -1042,13 +1042,13 @@  discard block
 block discarded – undo
1042 1042
     {
1043 1043
         $start = EEM_Datetime::instance()->convert_datetime_for_query(
1044 1044
             'DTT_EVT_start',
1045
-            date('Y-m-d') . ' 00:00:00',
1045
+            date('Y-m-d').' 00:00:00',
1046 1046
             'Y-m-d H:i:s',
1047 1047
             'UTC'
1048 1048
         );
1049 1049
         $end = EEM_Datetime::instance()->convert_datetime_for_query(
1050 1050
             'DTT_EVT_start',
1051
-            date('Y-m-d') . ' 23:59:59',
1051
+            date('Y-m-d').' 23:59:59',
1052 1052
             'Y-m-d H:i:s',
1053 1053
             'UTC'
1054 1054
         );
@@ -1075,13 +1075,13 @@  discard block
 block discarded – undo
1075 1075
         $days_this_month = date('t');
1076 1076
         $start = EEM_Datetime::instance()->convert_datetime_for_query(
1077 1077
             'DTT_EVT_start',
1078
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1078
+            $this_year_r.'-'.$this_month_r.'-01 00:00:00',
1079 1079
             'Y-m-d H:i:s',
1080 1080
             'UTC'
1081 1081
         );
1082 1082
         $end = EEM_Datetime::instance()->convert_datetime_for_query(
1083 1083
             'DTT_EVT_start',
1084
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1084
+            $this_year_r.'-'.$this_month_r.'-'.$days_this_month.' 23:59:59',
1085 1085
             'Y-m-d H:i:s',
1086 1086
             'UTC'
1087 1087
         );
@@ -1148,7 +1148,7 @@  discard block
 block discarded – undo
1148 1148
         $offset = ($current_page - 1) * $per_page;
1149 1149
         $limit = array($offset, $per_page);
1150 1150
         if (isset($this->_req_data['s'])) {
1151
-            $sstr = '%' . $this->_req_data['s'] . '%';
1151
+            $sstr = '%'.$this->_req_data['s'].'%';
1152 1152
             $_where['OR'] = array(
1153 1153
                 'TKT_name'        => array('LIKE', $sstr),
1154 1154
                 'TKT_description' => array('LIKE', $sstr),
@@ -1177,17 +1177,17 @@  discard block
 block discarded – undo
1177 1177
         $success = 1;
1178 1178
         $TKT = EEM_Ticket::instance();
1179 1179
         // checkboxes?
1180
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1180
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1181 1181
             // if array has more than one element then success message should be plural
1182 1182
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1183 1183
             // cycle thru the boxes
1184 1184
             while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1185 1185
                 if ($trash) {
1186
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1186
+                    if ( ! $TKT->delete_by_ID($TKT_ID)) {
1187 1187
                         $success = 0;
1188 1188
                     }
1189 1189
                 } else {
1190
-                    if (! $TKT->restore_by_ID($TKT_ID)) {
1190
+                    if ( ! $TKT->restore_by_ID($TKT_ID)) {
1191 1191
                         $success = 0;
1192 1192
                     }
1193 1193
                 }
@@ -1196,11 +1196,11 @@  discard block
 block discarded – undo
1196 1196
             // grab single id and trash
1197 1197
             $TKT_ID = absint($this->_req_data['TKT_ID']);
1198 1198
             if ($trash) {
1199
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1199
+                if ( ! $TKT->delete_by_ID($TKT_ID)) {
1200 1200
                     $success = 0;
1201 1201
                 }
1202 1202
             } else {
1203
-                if (! $TKT->restore_by_ID($TKT_ID)) {
1203
+                if ( ! $TKT->restore_by_ID($TKT_ID)) {
1204 1204
                     $success = 0;
1205 1205
                 }
1206 1206
             }
@@ -1221,20 +1221,20 @@  discard block
 block discarded – undo
1221 1221
     {
1222 1222
         $success = 1;
1223 1223
         // checkboxes?
1224
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1224
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1225 1225
             // if array has more than one element then success message should be plural
1226 1226
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1227 1227
             // cycle thru the boxes
1228 1228
             while (list($TKT_ID, $value) = each($this->_req_data['checkbox'])) {
1229 1229
                 // delete
1230
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1230
+                if ( ! $this->_delete_the_ticket($TKT_ID)) {
1231 1231
                     $success = 0;
1232 1232
                 }
1233 1233
             }
1234 1234
         } else {
1235 1235
             // grab single id and trash
1236 1236
             $TKT_ID = absint($this->_req_data['TKT_ID']);
1237
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1237
+            if ( ! $this->_delete_the_ticket($TKT_ID)) {
1238 1238
                 $success = 0;
1239 1239
             }
1240 1240
         }
Please login to merge, or discard this patch.
registration_form/espresso_events_Registration_Form_Hooks_Extend.class.php 2 patches
Indentation   +189 added lines, -189 removed lines patch added patch discarded remove patch
@@ -16,208 +16,208 @@
 block discarded – undo
16 16
 class espresso_events_Registration_Form_Hooks_Extend extends espresso_events_Registration_Form_Hooks
17 17
 {
18 18
 
19
-    /**
20
-     * extending the properties set in espresso_events_Registration_From_Hooks
21
-     *
22
-     * @access protected
23
-     * @return void
24
-     */
25
-    protected function _extend_properties()
26
-    {
27
-        $this->_metaboxes = array_merge(
28
-            $this->_metaboxes,
29
-            array(
30
-                1 => array(
31
-                    'page_route' => array('create_new', 'edit'),
32
-                    'func'       => 'additional_questions',
33
-                    'label'      => esc_html__('Questions for Additional Registrants', 'event_espresso'),
34
-                    'priority'   => 'default',
35
-                    'context'    => 'side',
36
-                ),
37
-            )
38
-        );
39
-        $this->_scripts_styles = array(
40
-            'registers' => array(
41
-                'extended-event-editor' => array(
42
-                    'url'     => EE_CORE_CAF_ADMIN_EXTEND_URL
43
-                                 . 'registration_form/assets/event-editor-question-groups.js',
44
-                    'depends' => array('jquery'),
45
-                ),
46
-            ),
47
-            'enqueues'  => array(
48
-                'extended-event-editor' => array('edit', 'create_new'),
49
-            ),
50
-        );
51
-    }
52
-
53
-
54
-    /**
55
-     * @param Callable[] $callbacks
56
-     * @return array
57
-     */
58
-    public function modify_callbacks($callbacks)
59
-    {
60
-        $callbacks = parent::modify_callbacks($callbacks);
61
-        $callbacks[] = array($this, 'additional_question_group_update');
62
-        return $callbacks;
63
-    }
64
-
65
-
66
-    /**
67
-     * Call back hooked into revision restores.
68
-     *
69
-     * @param $post_id
70
-     * @param $revision_id
71
-     * @return EE_Base_Class|void
72
-     * @throws EE_Error
73
-     * @throws InvalidArgumentException
74
-     * @throws InvalidDataTypeException
75
-     * @throws InvalidInterfaceException
76
-     * @throws ReflectionException
77
-     */
78
-    public function restore_revision($post_id, $revision_id)
79
-    {
80
-        $post_evt = parent::restore_revision($post_id, $revision_id);
81
-
82
-        // restore revision for additional questions
83
-        $post_evt->restore_revision(
84
-            $revision_id,
85
-            ['Question_Group'],
86
-            [
87
-                'Question_Group' => ['Event_Question_Group.EQG_additional' => true],
88
-            ]
89
-        );
90
-    }
91
-
92
-
93
-    /**
94
-     * @param $post_id
95
-     * @param $post
96
-     * @throws EE_Error
97
-     * @throws InvalidArgumentException
98
-     * @throws InvalidDataTypeException
99
-     * @throws InvalidInterfaceException
100
-     */
101
-    public function additional_questions($post_id, $post)
102
-    {
103
-        $this->_event = $this->_adminpage_obj->get_event_object();
104
-        $event_id = $this->_event->ID();
105
-        ?>
19
+	/**
20
+	 * extending the properties set in espresso_events_Registration_From_Hooks
21
+	 *
22
+	 * @access protected
23
+	 * @return void
24
+	 */
25
+	protected function _extend_properties()
26
+	{
27
+		$this->_metaboxes = array_merge(
28
+			$this->_metaboxes,
29
+			array(
30
+				1 => array(
31
+					'page_route' => array('create_new', 'edit'),
32
+					'func'       => 'additional_questions',
33
+					'label'      => esc_html__('Questions for Additional Registrants', 'event_espresso'),
34
+					'priority'   => 'default',
35
+					'context'    => 'side',
36
+				),
37
+			)
38
+		);
39
+		$this->_scripts_styles = array(
40
+			'registers' => array(
41
+				'extended-event-editor' => array(
42
+					'url'     => EE_CORE_CAF_ADMIN_EXTEND_URL
43
+								 . 'registration_form/assets/event-editor-question-groups.js',
44
+					'depends' => array('jquery'),
45
+				),
46
+			),
47
+			'enqueues'  => array(
48
+				'extended-event-editor' => array('edit', 'create_new'),
49
+			),
50
+		);
51
+	}
52
+
53
+
54
+	/**
55
+	 * @param Callable[] $callbacks
56
+	 * @return array
57
+	 */
58
+	public function modify_callbacks($callbacks)
59
+	{
60
+		$callbacks = parent::modify_callbacks($callbacks);
61
+		$callbacks[] = array($this, 'additional_question_group_update');
62
+		return $callbacks;
63
+	}
64
+
65
+
66
+	/**
67
+	 * Call back hooked into revision restores.
68
+	 *
69
+	 * @param $post_id
70
+	 * @param $revision_id
71
+	 * @return EE_Base_Class|void
72
+	 * @throws EE_Error
73
+	 * @throws InvalidArgumentException
74
+	 * @throws InvalidDataTypeException
75
+	 * @throws InvalidInterfaceException
76
+	 * @throws ReflectionException
77
+	 */
78
+	public function restore_revision($post_id, $revision_id)
79
+	{
80
+		$post_evt = parent::restore_revision($post_id, $revision_id);
81
+
82
+		// restore revision for additional questions
83
+		$post_evt->restore_revision(
84
+			$revision_id,
85
+			['Question_Group'],
86
+			[
87
+				'Question_Group' => ['Event_Question_Group.EQG_additional' => true],
88
+			]
89
+		);
90
+	}
91
+
92
+
93
+	/**
94
+	 * @param $post_id
95
+	 * @param $post
96
+	 * @throws EE_Error
97
+	 * @throws InvalidArgumentException
98
+	 * @throws InvalidDataTypeException
99
+	 * @throws InvalidInterfaceException
100
+	 */
101
+	public function additional_questions($post_id, $post)
102
+	{
103
+		$this->_event = $this->_adminpage_obj->get_event_object();
104
+		$event_id = $this->_event->ID();
105
+		?>
106 106
         <div class="inside">
107 107
             <p><strong>
108 108
                     <?php _e('Question Groups', 'event_espresso'); ?>
109 109
                 </strong><br/>
110 110
                 <?php
111
-                printf(
112
-                    esc_html__(
113
-                        'Add a pre-populated %1$sgroup of questions%2$s to your event.',
114
-                        'event_espresso'
115
-                    ),
116
-                    '<a href="admin.php?page=espresso_registration_form" target="_blank">',
117
-                    '</a>'
118
-                );
119
-                ?>
111
+				printf(
112
+					esc_html__(
113
+						'Add a pre-populated %1$sgroup of questions%2$s to your event.',
114
+						'event_espresso'
115
+					),
116
+					'<a href="admin.php?page=espresso_registration_form" target="_blank">',
117
+					'</a>'
118
+				);
119
+				?>
120 120
             </p>
121 121
             <?php
122 122
 
123
-            $qsg_where['QSG_deleted'] = false;
124
-            $query_params = apply_filters(
125
-                'FHEE__espresso_events_Registration_Form_Hooks_Extend__additional_questions__question_group_query_parameters',
126
-                array($qsg_where, 'order_by' => array('QSG_order' => 'ASC'))
127
-            );
128
-            $QSGs = EEM_Question_Group::instance()->get_all($query_params);
129
-            $EQGs = ! empty($event_id)
130
-                ? $this->_event->get_many_related(
131
-                    'Question_Group',
132
-                    [['Event_Question_Group.EQG_additional' => true]]
133
-                )
134
-                : [];
135
-            $EQGids = array_keys($EQGs);
136
-
137
-            if (! empty($QSGs)) {
138
-                $html = count($QSGs) > 10 ? '<div style="height:250px;overflow:auto;">' : '';
139
-                foreach ($QSGs as $QSG) {
140
-                    $checked = in_array($QSG->ID(), $EQGids, true) ? ' checked="checked" ' : '';
141
-                    $edit_link = EE_Admin_Page::add_query_args_and_nonce(
142
-                        array(
143
-                            'action' => 'edit_question_group',
144
-                            'QSG_ID' => $QSG->ID(),
145
-                        ),
146
-                        EE_FORMS_ADMIN_URL
147
-                    );
148
-
149
-                    $html .= '
123
+			$qsg_where['QSG_deleted'] = false;
124
+			$query_params = apply_filters(
125
+				'FHEE__espresso_events_Registration_Form_Hooks_Extend__additional_questions__question_group_query_parameters',
126
+				array($qsg_where, 'order_by' => array('QSG_order' => 'ASC'))
127
+			);
128
+			$QSGs = EEM_Question_Group::instance()->get_all($query_params);
129
+			$EQGs = ! empty($event_id)
130
+				? $this->_event->get_many_related(
131
+					'Question_Group',
132
+					[['Event_Question_Group.EQG_additional' => true]]
133
+				)
134
+				: [];
135
+			$EQGids = array_keys($EQGs);
136
+
137
+			if (! empty($QSGs)) {
138
+				$html = count($QSGs) > 10 ? '<div style="height:250px;overflow:auto;">' : '';
139
+				foreach ($QSGs as $QSG) {
140
+					$checked = in_array($QSG->ID(), $EQGids, true) ? ' checked="checked" ' : '';
141
+					$edit_link = EE_Admin_Page::add_query_args_and_nonce(
142
+						array(
143
+							'action' => 'edit_question_group',
144
+							'QSG_ID' => $QSG->ID(),
145
+						),
146
+						EE_FORMS_ADMIN_URL
147
+					);
148
+
149
+					$html .= '
150 150
 					<p id="event-question-group-' . $QSG->ID() . '">
151 151
 						<input value="' . $QSG->ID() . '"'
152
-                             . ' type="checkbox" name="add_attendee_question_groups[' . $QSG->ID() . ']"' . $checked . ' />
152
+							 . ' type="checkbox" name="add_attendee_question_groups[' . $QSG->ID() . ']"' . $checked . ' />
153 153
 						<a href="' . $edit_link . '" title="'
154
-                             . sprintf(
155
-                                 esc_attr__('Edit %s Group', 'event_espresso'),
156
-                                 $QSG->get('QSG_name')
157
-                             )
158
-                             . '" target="_blank">' . $QSG->get('QSG_name') . '</a>
154
+							 . sprintf(
155
+								 esc_attr__('Edit %s Group', 'event_espresso'),
156
+								 $QSG->get('QSG_name')
157
+							 )
158
+							 . '" target="_blank">' . $QSG->get('QSG_name') . '</a>
159 159
 					</p>';
160
-                    if ($QSG->ID() === 2) {
161
-                        $html .= '
160
+					if ($QSG->ID() === 2) {
161
+						$html .= '
162 162
 					<p id="question-group-requirements-notice-pg" class="important-notice small-text" style="display: none;">'
163
-                                 . esc_html__(
164
-                                     'The Personal Information question group is required whenever the Address Information question group is activated.',
165
-                                     'event_espresso'
166
-                                 )
167
-                                 . '</p>';
168
-                    }
169
-                }
170
-                $html .= count($QSGs) > 10 ? '</div>' : '';
171
-
172
-                echo $html;
173
-            } else {
174
-                esc_html_e(
175
-                    'There seems to be a problem with your questions. Please contact [email protected]',
176
-                    'event_espresso'
177
-                );
178
-            }
179
-            do_action('AHEE__espresso_events_Registration_Form_Hooks__additional_questions__after_content');
180
-            ?>
163
+								 . esc_html__(
164
+									 'The Personal Information question group is required whenever the Address Information question group is activated.',
165
+									 'event_espresso'
166
+								 )
167
+								 . '</p>';
168
+					}
169
+				}
170
+				$html .= count($QSGs) > 10 ? '</div>' : '';
171
+
172
+				echo $html;
173
+			} else {
174
+				esc_html_e(
175
+					'There seems to be a problem with your questions. Please contact [email protected]',
176
+					'event_espresso'
177
+				);
178
+			}
179
+			do_action('AHEE__espresso_events_Registration_Form_Hooks__additional_questions__after_content');
180
+			?>
181 181
         </div>
182 182
         <?php
183
-    }
184
-
185
-
186
-    public function additional_question_group_update($evtobj, $data)
187
-    {
188
-        $question_groups = ! empty($data['add_attendee_question_groups'])
189
-            ? (array) $data['add_attendee_question_groups']
190
-            : [];
191
-        $added_qgs = array_keys($question_groups);
192
-        $success = [];
193
-
194
-        // let's get all current question groups associated with this event.
195
-        $current_qgs = $evtobj->get_many_related(
196
-            'Question_Group',
197
-            [['Event_Question_Group.EQG_additional' => true]]
198
-        );
199
-        $current_qgs = array_keys($current_qgs); // we just want the ids
200
-
201
-        // now let's get the groups selected in the editor and update (IF we have data)
202
-        if (! empty($question_groups)) {
203
-            foreach ($question_groups as $qgid) {
204
-                // add to event
205
-                if ($qgid) {
206
-                    $qg = $evtobj->add_question_group($qgid, false);
207
-                }
208
-                $success[] = ! empty($qg) ? 1 : 0;
209
-            }
210
-        }
211
-
212
-        // wait a minute... are there question groups missing in the saved groups that ARE with the current event?
213
-        $removed_qgs = array_diff($current_qgs, $added_qgs);
214
-
215
-        foreach ($removed_qgs as $qgid) {
216
-            $qg = $evtobj->remove_question_group($qgid, false);
217
-            $success[] = ! empty($qg) ? 1 : 0;
218
-        }
219
-
220
-
221
-        return in_array(0, $success, true) ? false : true;
222
-    }
183
+	}
184
+
185
+
186
+	public function additional_question_group_update($evtobj, $data)
187
+	{
188
+		$question_groups = ! empty($data['add_attendee_question_groups'])
189
+			? (array) $data['add_attendee_question_groups']
190
+			: [];
191
+		$added_qgs = array_keys($question_groups);
192
+		$success = [];
193
+
194
+		// let's get all current question groups associated with this event.
195
+		$current_qgs = $evtobj->get_many_related(
196
+			'Question_Group',
197
+			[['Event_Question_Group.EQG_additional' => true]]
198
+		);
199
+		$current_qgs = array_keys($current_qgs); // we just want the ids
200
+
201
+		// now let's get the groups selected in the editor and update (IF we have data)
202
+		if (! empty($question_groups)) {
203
+			foreach ($question_groups as $qgid) {
204
+				// add to event
205
+				if ($qgid) {
206
+					$qg = $evtobj->add_question_group($qgid, false);
207
+				}
208
+				$success[] = ! empty($qg) ? 1 : 0;
209
+			}
210
+		}
211
+
212
+		// wait a minute... are there question groups missing in the saved groups that ARE with the current event?
213
+		$removed_qgs = array_diff($current_qgs, $added_qgs);
214
+
215
+		foreach ($removed_qgs as $qgid) {
216
+			$qg = $evtobj->remove_question_group($qgid, false);
217
+			$success[] = ! empty($qg) ? 1 : 0;
218
+		}
219
+
220
+
221
+		return in_array(0, $success, true) ? false : true;
222
+	}
223 223
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -134,7 +134,7 @@  discard block
 block discarded – undo
134 134
                 : [];
135 135
             $EQGids = array_keys($EQGs);
136 136
 
137
-            if (! empty($QSGs)) {
137
+            if ( ! empty($QSGs)) {
138 138
                 $html = count($QSGs) > 10 ? '<div style="height:250px;overflow:auto;">' : '';
139 139
                 foreach ($QSGs as $QSG) {
140 140
                     $checked = in_array($QSG->ID(), $EQGids, true) ? ' checked="checked" ' : '';
@@ -147,15 +147,15 @@  discard block
 block discarded – undo
147 147
                     );
148 148
 
149 149
                     $html .= '
150
-					<p id="event-question-group-' . $QSG->ID() . '">
151
-						<input value="' . $QSG->ID() . '"'
152
-                             . ' type="checkbox" name="add_attendee_question_groups[' . $QSG->ID() . ']"' . $checked . ' />
153
-						<a href="' . $edit_link . '" title="'
150
+					<p id="event-question-group-' . $QSG->ID().'">
151
+						<input value="' . $QSG->ID().'"'
152
+                             . ' type="checkbox" name="add_attendee_question_groups['.$QSG->ID().']"'.$checked.' />
153
+						<a href="' . $edit_link.'" title="'
154 154
                              . sprintf(
155 155
                                  esc_attr__('Edit %s Group', 'event_espresso'),
156 156
                                  $QSG->get('QSG_name')
157 157
                              )
158
-                             . '" target="_blank">' . $QSG->get('QSG_name') . '</a>
158
+                             . '" target="_blank">'.$QSG->get('QSG_name').'</a>
159 159
 					</p>';
160 160
                     if ($QSG->ID() === 2) {
161 161
                         $html .= '
@@ -199,7 +199,7 @@  discard block
 block discarded – undo
199 199
         $current_qgs = array_keys($current_qgs); // we just want the ids
200 200
 
201 201
         // now let's get the groups selected in the editor and update (IF we have data)
202
-        if (! empty($question_groups)) {
202
+        if ( ! empty($question_groups)) {
203 203
             foreach ($question_groups as $qgid) {
204 204
                 // add to event
205 205
                 if ($qgid) {
Please login to merge, or discard this patch.