Completed
Branch dependabot/composer/wp-graphql... (5a0e42)
by
unknown
18:09 queued 13:06
created
core/helpers/EEH_Inflector.helper.php 2 patches
Indentation   +380 added lines, -380 removed lines patch added patch discarded remove patch
@@ -33,384 +33,384 @@
 block discarded – undo
33 33
  */
34 34
 class EEH_Inflector
35 35
 {
36
-    // ------ CLASS METHODS ------ //
37
-    // ---- Public methods ---- //
38
-    // {{{ pluralize()
39
-
40
-    /**
41
-     * Just calls self::pluralize and strtolower on $word and returns it
42
-     * @param string $word
43
-     * @return string
44
-     */
45
-    public static function pluralize_and_lower($word)
46
-    {
47
-        return strtolower(self::pluralize($word));
48
-    }
49
-
50
-
51
-
52
-    /**
53
-     * @param string $word
54
-     * @return mixed
55
-     */
56
-    public static function singularize_and_upper($word)
57
-    {
58
-        return str_replace(' ', '_', self::humanize(self::singularize($word), 'all'));
59
-    }
60
-
61
-
62
-
63
-    /**
64
-     * Pluralizes English nouns.
65
-     *
66
-     * @access public
67
-     * @static
68
-     * @param    string    $word    English noun to pluralize
69
-     * @return string Plural noun
70
-     */
71
-    public static function pluralize($word)
72
-    {
73
-        $plural = array(
74
-            '/(quiz)$/i'               => '\1zes',
75
-            '/^(ox)$/i'                => '\1en',
76
-            '/([m|l])ouse$/i'          => '\1ice',
77
-            '/(matr|vert|ind)ix|ex$/i' => '\1ices',
78
-            '/(x|ch|ss|sh)$/i'         => '\1es',
79
-            '/([^aeiouy]|qu)ies$/i'    => '\1y',
80
-            '/([^aeiouy]|qu)y$/i'      => '\1ies',
81
-            '/(hive)$/i'               => '\1s',
82
-            '/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
83
-            '/sis$/i'                  => 'ses',
84
-            '/([ti])um$/i'             => '\1a',
85
-            '/(buffal|tomat)o$/i'      => '\1oes',
86
-            '/(bu)s$/i'                => '\1ses',
87
-            '/(alias|status)/i'        => '\1es',
88
-            '/(octop|vir)us$/i'        => '\1i',
89
-            '/(ax|test)is$/i'          => '\1es',
90
-            '/s$/i'                    => 's',
91
-            '/$/'                      => 's');
92
-
93
-        $uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep');
94
-
95
-        $irregular = array(
96
-            'person' => 'people',
97
-            'man'    => 'men',
98
-            'child'  => 'children',
99
-            'sex'    => 'sexes',
100
-            'move'   => 'moves');
101
-
102
-        $lowercased_word = strtolower($word);
103
-
104
-        foreach ($uncountable as $_uncountable) {
105
-            if (
106
-                substr($lowercased_word, (-1 * strlen($_uncountable))) == $_uncountable && // even though the word "price" ends in "rice", it can be pluralized, so check the previous character isnt a letter
107
-                    ! ctype_alpha($lowercased_word[ strlen($lowercased_word) - strlen($_uncountable) ])
108
-            ) {
109
-                return $word;
110
-            }
111
-        }
112
-
113
-        foreach ($irregular as $_plural => $_singular) {
114
-            if (preg_match('/(' . $_plural . ')$/i', $word, $arr)) {
115
-                return preg_replace('/(' . $_plural . ')$/i', substr($arr[0], 0, 1) . substr($_singular, 1), $word);
116
-            }
117
-        }
118
-
119
-        foreach ($plural as $rule => $replacement) {
120
-            if (preg_match($rule, $word)) {
121
-                return preg_replace($rule, $replacement, $word);
122
-            }
123
-        }
124
-        return false;
125
-    }
126
-
127
-    // }}}
128
-    // {{{ singularize()
129
-
130
-    /**
131
-     * Singularizes English nouns.
132
-     *
133
-     * @access public
134
-     * @static
135
-     * @param    string    $word    English noun to singularize
136
-     * @return string Singular noun.
137
-     */
138
-    public static function singularize($word)
139
-    {
140
-        $singular = array(
141
-            '/(quiz)zes$/i'                                                    => '\1',
142
-            '/(matr)ices$/i'                                                   => '\1ix',
143
-            '/(vert|ind)ices$/i'                                               => '\1ex',
144
-            '/^(ox)en/i'                                                       => '\1',
145
-            '/(alias|status)es$/i'                                             => '\1',
146
-            '/([octop|vir])i$/i'                                               => '\1us',
147
-            '/(cris|ax|test)es$/i'                                             => '\1is',
148
-            '/(shoe)s$/i'                                                      => '\1',
149
-            '/(o)es$/i'                                                        => '\1',
150
-            '/(bus)es$/i'                                                      => '\1',
151
-            '/([m|l])ice$/i'                                                   => '\1ouse',
152
-            '/(x|ch|ss|sh)es$/i'                                               => '\1',
153
-            '/(m)ovies$/i'                                                     => '\1ovie',
154
-            '/(s)eries$/i'                                                     => '\1eries',
155
-            '/([^aeiouy]|qu)ies$/i'                                            => '\1y',
156
-            '/([lr])ves$/i'                                                    => '\1f',
157
-            '/(tive)s$/i'                                                      => '\1',
158
-            '/(hive)s$/i'                                                      => '\1',
159
-            '/([^f])ves$/i'                                                    => '\1fe',
160
-            '/(^analy)ses$/i'                                                  => '\1sis',
161
-            '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis',
162
-            '/([ti])a$/i'                                                      => '\1um',
163
-            '/(n)ews$/i'                                                       => '\1ews',
164
-            '/s$/i'                                                            => '',
165
-        );
166
-
167
-        $uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep');
168
-
169
-        $irregular = array(
170
-            'person' => 'people',
171
-            'man'    => 'men',
172
-            'child'  => 'children',
173
-            'sex'    => 'sexes',
174
-            'move'   => 'moves');
175
-
176
-        $lowercased_word = strtolower($word);
177
-        foreach ($uncountable as $_uncountable) {
178
-            if (substr($lowercased_word, (-1 * strlen($_uncountable))) == $_uncountable) {
179
-                return $word;
180
-            }
181
-        }
182
-
183
-        foreach ($irregular as $_plural => $_singular) {
184
-            if (preg_match('/(' . $_singular . ')$/i', $word, $arr)) {
185
-                return preg_replace('/(' . $_singular . ')$/i', substr($arr[0], 0, 1) . substr($_plural, 1), $word);
186
-            }
187
-        }
188
-
189
-        foreach ($singular as $rule => $replacement) {
190
-            if (preg_match($rule, $word)) {
191
-                return preg_replace($rule, $replacement, $word);
192
-            }
193
-        }
194
-
195
-        return $word;
196
-    }
197
-
198
-    // }}}
199
-    // {{{ titleize()
200
-
201
-    /**
202
-     * Converts an underscored or CamelCase word into a English
203
-     * sentence.
204
-     *
205
-     * The titleize static function converts text like "WelcomePage",
206
-     * "welcome_page" or  "welcome page" to this "Welcome
207
-     * Page".
208
-     * If second parameter is set to 'first' it will only
209
-     * capitalize the first character of the title.
210
-     *
211
-     * @access public
212
-     * @static
213
-     * @param    string    $word    Word to format as tile
214
-     * @param    string    $uppercase    If set to 'first' it will only uppercase the
215
-     * first character. Otherwise it will uppercase all
216
-     * the words in the title.
217
-     * @return string Text formatted as title
218
-     */
219
-    public static function titleize($word, $uppercase = '')
220
-    {
221
-        $uppercase = $uppercase === 'first' ? 'ucfirst' : 'ucwords';
222
-        return $uppercase(EEH_Inflector::humanize(EEH_Inflector::underscore($word)));
223
-    }
224
-
225
-    // }}}
226
-    // {{{ camelize()
227
-
228
-    /**
229
-     * Returns given word as CamelCased
230
-     *
231
-     * Converts a word like "send_email" to "SendEmail". It
232
-     * will remove non alphanumeric character from the word, so
233
-     * "who's online" will be converted to "WhoSOnline"
234
-     *
235
-     * @access public
236
-     * @static
237
-     * @see variablize
238
-     * @param    string    $word    Word to convert to camel case
239
-     * @return string UpperCamelCasedWord
240
-     */
241
-    public static function camelize($word)
242
-    {
243
-        return str_replace(' ', '', ucwords(preg_replace('/[^A-Z^a-z^0-9]+/', ' ', $word)));
244
-    }
245
-
246
-
247
-
248
-    /**
249
-     * Camelizes all but the first word. This is handy converting a method which followed EE4 legacy naming convention
250
-     * with the new PSR-based naming conventions
251
-     * @param $word
252
-     * @return string
253
-     */
254
-    public static function camelize_all_but_first($word)
255
-    {
256
-        return lcfirst(EEH_Inflector::camelize($word));
257
-    }
258
-    // }}}
259
-    // {{{ underscore()
260
-
261
-    /**
262
-     * Converts a word "into_it_s_underscored_version"
263
-     *
264
-     * Convert any "CamelCased" or "ordinary Word" into an
265
-     * "underscored_word".
266
-     *
267
-     * This can be really useful for creating friendly URLs.
268
-     *
269
-     * @access public
270
-     * @static
271
-     * @param    string    $word    Word to underscore
272
-     * @return string Underscored word
273
-     */
274
-    public static function underscore($word)
275
-    {
276
-        return strtolower(preg_replace('/[^A-Z^a-z^0-9]+/', '_', preg_replace('/([a-zd])([A-Z])/', '1_2', preg_replace('/([A-Z]+)([A-Z][a-z])/', '1_2', $word))));
277
-    }
278
-
279
-    // }}}
280
-    // {{{ humanize()
281
-
282
-    /**
283
-     * Returns a human-readable string from $word
284
-     *
285
-     * Returns a human-readable string from $word, by replacing
286
-     * underscores with a space, and by upper-casing the initial
287
-     * character by default.
288
-     *
289
-     * If you need to uppercase all the words you just have to
290
-     * pass 'all' as a second parameter.
291
-     *
292
-     * @access public
293
-     * @static
294
-     * @param    string    $word    String to "humanize"
295
-     * @param    string    $uppercase    If set to 'all' it will uppercase all the words
296
-     * instead of just the first one.
297
-     * @return string Human-readable word
298
-     */
299
-    public static function humanize($word, $uppercase = '')
300
-    {
301
-        // make special exceptions for acronyms
302
-        $word = str_replace('wp_', 'WP_', $word);
303
-        $uppercase = $uppercase === 'all' ? 'ucwords' : 'ucfirst';
304
-        return $uppercase(str_replace('_', ' ', preg_replace('/_id$/', '', $word)));
305
-    }
306
-
307
-    // }}}
308
-    // {{{ variablize()
309
-
310
-    /**
311
-     * Same as camelize but first char is underscored
312
-     *
313
-     * Converts a word like "send_email" to "sendEmail". It
314
-     * will remove non alphanumeric character from the word, so
315
-     * "who's online" will be converted to "whoSOnline"
316
-     *
317
-     * @access public
318
-     * @static
319
-     * @see camelize
320
-     * @param    string    $word    Word to lowerCamelCase
321
-     * @return string Returns a lowerCamelCasedWord
322
-     */
323
-    public static function variablize($word)
324
-    {
325
-        $word = EEH_Inflector::camelize($word);
326
-        return strtolower($word[0]) . substr($word, 1);
327
-    }
328
-
329
-    // }}}
330
-    // {{{ tableize()
331
-
332
-    /**
333
-     * Converts a class name to its table name according to rails
334
-     * naming conventions.
335
-     *
336
-     * Converts "Person" to "people"
337
-     *
338
-     * @access public
339
-     * @static
340
-     * @see classify
341
-     * @param    string    $class_name    Class name for getting related table_name.
342
-     * @return string plural_table_name
343
-     */
344
-    public static function tableize($class_name)
345
-    {
346
-        return EEH_Inflector::pluralize(EEH_Inflector::underscore($class_name));
347
-    }
348
-
349
-    // }}}
350
-    // {{{ classify()
351
-
352
-    /**
353
-     * Converts a table name to its class name according to rails
354
-     * naming conventions.
355
-     *
356
-     * Converts "people" to "Person"
357
-     *
358
-     * @access public
359
-     * @static
360
-     * @see tableize
361
-     * @param    string    $table_name    Table name for getting related ClassName.
362
-     * @return string SingularClassName
363
-     */
364
-    public static function classify($table_name)
365
-    {
366
-        return EEH_Inflector::camelize(EEH_Inflector::singularize($table_name));
367
-    }
368
-
369
-    // }}}
370
-    // {{{ ordinalize()
371
-
372
-    /**
373
-     * Converts number to its ordinal English form.
374
-     *
375
-     * This method converts 13 to 13th, 2 to 2nd ...
376
-     *
377
-     * @access public
378
-     * @static
379
-     * @param    integer    $number    Number to get its ordinal value
380
-     * @return string Ordinal representation of given string.
381
-     */
382
-    public static function ordinalize($number)
383
-    {
384
-        if (in_array(($number % 100), range(11, 13))) {
385
-            return $number . 'th';
386
-        } else {
387
-            switch (($number % 10)) {
388
-                case 1:
389
-                    return $number . 'st';
390
-                    break;
391
-                case 2:
392
-                    return $number . 'nd';
393
-                    break;
394
-                case 3:
395
-                    return $number . 'rd';
396
-                default:
397
-                    return $number . 'th';
398
-                    break;
399
-            }
400
-        }
401
-    }
402
-
403
-
404
-
405
-    /**
406
-     * @param $string
407
-     * @return string
408
-     */
409
-    public static function add_indefinite_article($string)
410
-    {
411
-        if (strtolower($string) === 'null') {
412
-            return $string;
413
-        }
414
-        return (stripos('aeiou', $string[0]) !== false ? 'an ' : 'a ') . $string;
415
-    }
36
+	// ------ CLASS METHODS ------ //
37
+	// ---- Public methods ---- //
38
+	// {{{ pluralize()
39
+
40
+	/**
41
+	 * Just calls self::pluralize and strtolower on $word and returns it
42
+	 * @param string $word
43
+	 * @return string
44
+	 */
45
+	public static function pluralize_and_lower($word)
46
+	{
47
+		return strtolower(self::pluralize($word));
48
+	}
49
+
50
+
51
+
52
+	/**
53
+	 * @param string $word
54
+	 * @return mixed
55
+	 */
56
+	public static function singularize_and_upper($word)
57
+	{
58
+		return str_replace(' ', '_', self::humanize(self::singularize($word), 'all'));
59
+	}
60
+
61
+
62
+
63
+	/**
64
+	 * Pluralizes English nouns.
65
+	 *
66
+	 * @access public
67
+	 * @static
68
+	 * @param    string    $word    English noun to pluralize
69
+	 * @return string Plural noun
70
+	 */
71
+	public static function pluralize($word)
72
+	{
73
+		$plural = array(
74
+			'/(quiz)$/i'               => '\1zes',
75
+			'/^(ox)$/i'                => '\1en',
76
+			'/([m|l])ouse$/i'          => '\1ice',
77
+			'/(matr|vert|ind)ix|ex$/i' => '\1ices',
78
+			'/(x|ch|ss|sh)$/i'         => '\1es',
79
+			'/([^aeiouy]|qu)ies$/i'    => '\1y',
80
+			'/([^aeiouy]|qu)y$/i'      => '\1ies',
81
+			'/(hive)$/i'               => '\1s',
82
+			'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
83
+			'/sis$/i'                  => 'ses',
84
+			'/([ti])um$/i'             => '\1a',
85
+			'/(buffal|tomat)o$/i'      => '\1oes',
86
+			'/(bu)s$/i'                => '\1ses',
87
+			'/(alias|status)/i'        => '\1es',
88
+			'/(octop|vir)us$/i'        => '\1i',
89
+			'/(ax|test)is$/i'          => '\1es',
90
+			'/s$/i'                    => 's',
91
+			'/$/'                      => 's');
92
+
93
+		$uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep');
94
+
95
+		$irregular = array(
96
+			'person' => 'people',
97
+			'man'    => 'men',
98
+			'child'  => 'children',
99
+			'sex'    => 'sexes',
100
+			'move'   => 'moves');
101
+
102
+		$lowercased_word = strtolower($word);
103
+
104
+		foreach ($uncountable as $_uncountable) {
105
+			if (
106
+				substr($lowercased_word, (-1 * strlen($_uncountable))) == $_uncountable && // even though the word "price" ends in "rice", it can be pluralized, so check the previous character isnt a letter
107
+					! ctype_alpha($lowercased_word[ strlen($lowercased_word) - strlen($_uncountable) ])
108
+			) {
109
+				return $word;
110
+			}
111
+		}
112
+
113
+		foreach ($irregular as $_plural => $_singular) {
114
+			if (preg_match('/(' . $_plural . ')$/i', $word, $arr)) {
115
+				return preg_replace('/(' . $_plural . ')$/i', substr($arr[0], 0, 1) . substr($_singular, 1), $word);
116
+			}
117
+		}
118
+
119
+		foreach ($plural as $rule => $replacement) {
120
+			if (preg_match($rule, $word)) {
121
+				return preg_replace($rule, $replacement, $word);
122
+			}
123
+		}
124
+		return false;
125
+	}
126
+
127
+	// }}}
128
+	// {{{ singularize()
129
+
130
+	/**
131
+	 * Singularizes English nouns.
132
+	 *
133
+	 * @access public
134
+	 * @static
135
+	 * @param    string    $word    English noun to singularize
136
+	 * @return string Singular noun.
137
+	 */
138
+	public static function singularize($word)
139
+	{
140
+		$singular = array(
141
+			'/(quiz)zes$/i'                                                    => '\1',
142
+			'/(matr)ices$/i'                                                   => '\1ix',
143
+			'/(vert|ind)ices$/i'                                               => '\1ex',
144
+			'/^(ox)en/i'                                                       => '\1',
145
+			'/(alias|status)es$/i'                                             => '\1',
146
+			'/([octop|vir])i$/i'                                               => '\1us',
147
+			'/(cris|ax|test)es$/i'                                             => '\1is',
148
+			'/(shoe)s$/i'                                                      => '\1',
149
+			'/(o)es$/i'                                                        => '\1',
150
+			'/(bus)es$/i'                                                      => '\1',
151
+			'/([m|l])ice$/i'                                                   => '\1ouse',
152
+			'/(x|ch|ss|sh)es$/i'                                               => '\1',
153
+			'/(m)ovies$/i'                                                     => '\1ovie',
154
+			'/(s)eries$/i'                                                     => '\1eries',
155
+			'/([^aeiouy]|qu)ies$/i'                                            => '\1y',
156
+			'/([lr])ves$/i'                                                    => '\1f',
157
+			'/(tive)s$/i'                                                      => '\1',
158
+			'/(hive)s$/i'                                                      => '\1',
159
+			'/([^f])ves$/i'                                                    => '\1fe',
160
+			'/(^analy)ses$/i'                                                  => '\1sis',
161
+			'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis',
162
+			'/([ti])a$/i'                                                      => '\1um',
163
+			'/(n)ews$/i'                                                       => '\1ews',
164
+			'/s$/i'                                                            => '',
165
+		);
166
+
167
+		$uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep');
168
+
169
+		$irregular = array(
170
+			'person' => 'people',
171
+			'man'    => 'men',
172
+			'child'  => 'children',
173
+			'sex'    => 'sexes',
174
+			'move'   => 'moves');
175
+
176
+		$lowercased_word = strtolower($word);
177
+		foreach ($uncountable as $_uncountable) {
178
+			if (substr($lowercased_word, (-1 * strlen($_uncountable))) == $_uncountable) {
179
+				return $word;
180
+			}
181
+		}
182
+
183
+		foreach ($irregular as $_plural => $_singular) {
184
+			if (preg_match('/(' . $_singular . ')$/i', $word, $arr)) {
185
+				return preg_replace('/(' . $_singular . ')$/i', substr($arr[0], 0, 1) . substr($_plural, 1), $word);
186
+			}
187
+		}
188
+
189
+		foreach ($singular as $rule => $replacement) {
190
+			if (preg_match($rule, $word)) {
191
+				return preg_replace($rule, $replacement, $word);
192
+			}
193
+		}
194
+
195
+		return $word;
196
+	}
197
+
198
+	// }}}
199
+	// {{{ titleize()
200
+
201
+	/**
202
+	 * Converts an underscored or CamelCase word into a English
203
+	 * sentence.
204
+	 *
205
+	 * The titleize static function converts text like "WelcomePage",
206
+	 * "welcome_page" or  "welcome page" to this "Welcome
207
+	 * Page".
208
+	 * If second parameter is set to 'first' it will only
209
+	 * capitalize the first character of the title.
210
+	 *
211
+	 * @access public
212
+	 * @static
213
+	 * @param    string    $word    Word to format as tile
214
+	 * @param    string    $uppercase    If set to 'first' it will only uppercase the
215
+	 * first character. Otherwise it will uppercase all
216
+	 * the words in the title.
217
+	 * @return string Text formatted as title
218
+	 */
219
+	public static function titleize($word, $uppercase = '')
220
+	{
221
+		$uppercase = $uppercase === 'first' ? 'ucfirst' : 'ucwords';
222
+		return $uppercase(EEH_Inflector::humanize(EEH_Inflector::underscore($word)));
223
+	}
224
+
225
+	// }}}
226
+	// {{{ camelize()
227
+
228
+	/**
229
+	 * Returns given word as CamelCased
230
+	 *
231
+	 * Converts a word like "send_email" to "SendEmail". It
232
+	 * will remove non alphanumeric character from the word, so
233
+	 * "who's online" will be converted to "WhoSOnline"
234
+	 *
235
+	 * @access public
236
+	 * @static
237
+	 * @see variablize
238
+	 * @param    string    $word    Word to convert to camel case
239
+	 * @return string UpperCamelCasedWord
240
+	 */
241
+	public static function camelize($word)
242
+	{
243
+		return str_replace(' ', '', ucwords(preg_replace('/[^A-Z^a-z^0-9]+/', ' ', $word)));
244
+	}
245
+
246
+
247
+
248
+	/**
249
+	 * Camelizes all but the first word. This is handy converting a method which followed EE4 legacy naming convention
250
+	 * with the new PSR-based naming conventions
251
+	 * @param $word
252
+	 * @return string
253
+	 */
254
+	public static function camelize_all_but_first($word)
255
+	{
256
+		return lcfirst(EEH_Inflector::camelize($word));
257
+	}
258
+	// }}}
259
+	// {{{ underscore()
260
+
261
+	/**
262
+	 * Converts a word "into_it_s_underscored_version"
263
+	 *
264
+	 * Convert any "CamelCased" or "ordinary Word" into an
265
+	 * "underscored_word".
266
+	 *
267
+	 * This can be really useful for creating friendly URLs.
268
+	 *
269
+	 * @access public
270
+	 * @static
271
+	 * @param    string    $word    Word to underscore
272
+	 * @return string Underscored word
273
+	 */
274
+	public static function underscore($word)
275
+	{
276
+		return strtolower(preg_replace('/[^A-Z^a-z^0-9]+/', '_', preg_replace('/([a-zd])([A-Z])/', '1_2', preg_replace('/([A-Z]+)([A-Z][a-z])/', '1_2', $word))));
277
+	}
278
+
279
+	// }}}
280
+	// {{{ humanize()
281
+
282
+	/**
283
+	 * Returns a human-readable string from $word
284
+	 *
285
+	 * Returns a human-readable string from $word, by replacing
286
+	 * underscores with a space, and by upper-casing the initial
287
+	 * character by default.
288
+	 *
289
+	 * If you need to uppercase all the words you just have to
290
+	 * pass 'all' as a second parameter.
291
+	 *
292
+	 * @access public
293
+	 * @static
294
+	 * @param    string    $word    String to "humanize"
295
+	 * @param    string    $uppercase    If set to 'all' it will uppercase all the words
296
+	 * instead of just the first one.
297
+	 * @return string Human-readable word
298
+	 */
299
+	public static function humanize($word, $uppercase = '')
300
+	{
301
+		// make special exceptions for acronyms
302
+		$word = str_replace('wp_', 'WP_', $word);
303
+		$uppercase = $uppercase === 'all' ? 'ucwords' : 'ucfirst';
304
+		return $uppercase(str_replace('_', ' ', preg_replace('/_id$/', '', $word)));
305
+	}
306
+
307
+	// }}}
308
+	// {{{ variablize()
309
+
310
+	/**
311
+	 * Same as camelize but first char is underscored
312
+	 *
313
+	 * Converts a word like "send_email" to "sendEmail". It
314
+	 * will remove non alphanumeric character from the word, so
315
+	 * "who's online" will be converted to "whoSOnline"
316
+	 *
317
+	 * @access public
318
+	 * @static
319
+	 * @see camelize
320
+	 * @param    string    $word    Word to lowerCamelCase
321
+	 * @return string Returns a lowerCamelCasedWord
322
+	 */
323
+	public static function variablize($word)
324
+	{
325
+		$word = EEH_Inflector::camelize($word);
326
+		return strtolower($word[0]) . substr($word, 1);
327
+	}
328
+
329
+	// }}}
330
+	// {{{ tableize()
331
+
332
+	/**
333
+	 * Converts a class name to its table name according to rails
334
+	 * naming conventions.
335
+	 *
336
+	 * Converts "Person" to "people"
337
+	 *
338
+	 * @access public
339
+	 * @static
340
+	 * @see classify
341
+	 * @param    string    $class_name    Class name for getting related table_name.
342
+	 * @return string plural_table_name
343
+	 */
344
+	public static function tableize($class_name)
345
+	{
346
+		return EEH_Inflector::pluralize(EEH_Inflector::underscore($class_name));
347
+	}
348
+
349
+	// }}}
350
+	// {{{ classify()
351
+
352
+	/**
353
+	 * Converts a table name to its class name according to rails
354
+	 * naming conventions.
355
+	 *
356
+	 * Converts "people" to "Person"
357
+	 *
358
+	 * @access public
359
+	 * @static
360
+	 * @see tableize
361
+	 * @param    string    $table_name    Table name for getting related ClassName.
362
+	 * @return string SingularClassName
363
+	 */
364
+	public static function classify($table_name)
365
+	{
366
+		return EEH_Inflector::camelize(EEH_Inflector::singularize($table_name));
367
+	}
368
+
369
+	// }}}
370
+	// {{{ ordinalize()
371
+
372
+	/**
373
+	 * Converts number to its ordinal English form.
374
+	 *
375
+	 * This method converts 13 to 13th, 2 to 2nd ...
376
+	 *
377
+	 * @access public
378
+	 * @static
379
+	 * @param    integer    $number    Number to get its ordinal value
380
+	 * @return string Ordinal representation of given string.
381
+	 */
382
+	public static function ordinalize($number)
383
+	{
384
+		if (in_array(($number % 100), range(11, 13))) {
385
+			return $number . 'th';
386
+		} else {
387
+			switch (($number % 10)) {
388
+				case 1:
389
+					return $number . 'st';
390
+					break;
391
+				case 2:
392
+					return $number . 'nd';
393
+					break;
394
+				case 3:
395
+					return $number . 'rd';
396
+				default:
397
+					return $number . 'th';
398
+					break;
399
+			}
400
+		}
401
+	}
402
+
403
+
404
+
405
+	/**
406
+	 * @param $string
407
+	 * @return string
408
+	 */
409
+	public static function add_indefinite_article($string)
410
+	{
411
+		if (strtolower($string) === 'null') {
412
+			return $string;
413
+		}
414
+		return (stripos('aeiou', $string[0]) !== false ? 'an ' : 'a ') . $string;
415
+	}
416 416
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -104,15 +104,15 @@  discard block
 block discarded – undo
104 104
         foreach ($uncountable as $_uncountable) {
105 105
             if (
106 106
                 substr($lowercased_word, (-1 * strlen($_uncountable))) == $_uncountable && // even though the word "price" ends in "rice", it can be pluralized, so check the previous character isnt a letter
107
-                    ! ctype_alpha($lowercased_word[ strlen($lowercased_word) - strlen($_uncountable) ])
107
+                    ! ctype_alpha($lowercased_word[strlen($lowercased_word) - strlen($_uncountable)])
108 108
             ) {
109 109
                 return $word;
110 110
             }
111 111
         }
112 112
 
113 113
         foreach ($irregular as $_plural => $_singular) {
114
-            if (preg_match('/(' . $_plural . ')$/i', $word, $arr)) {
115
-                return preg_replace('/(' . $_plural . ')$/i', substr($arr[0], 0, 1) . substr($_singular, 1), $word);
114
+            if (preg_match('/('.$_plural.')$/i', $word, $arr)) {
115
+                return preg_replace('/('.$_plural.')$/i', substr($arr[0], 0, 1).substr($_singular, 1), $word);
116 116
             }
117 117
         }
118 118
 
@@ -181,8 +181,8 @@  discard block
 block discarded – undo
181 181
         }
182 182
 
183 183
         foreach ($irregular as $_plural => $_singular) {
184
-            if (preg_match('/(' . $_singular . ')$/i', $word, $arr)) {
185
-                return preg_replace('/(' . $_singular . ')$/i', substr($arr[0], 0, 1) . substr($_plural, 1), $word);
184
+            if (preg_match('/('.$_singular.')$/i', $word, $arr)) {
185
+                return preg_replace('/('.$_singular.')$/i', substr($arr[0], 0, 1).substr($_plural, 1), $word);
186 186
             }
187 187
         }
188 188
 
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
     public static function variablize($word)
324 324
     {
325 325
         $word = EEH_Inflector::camelize($word);
326
-        return strtolower($word[0]) . substr($word, 1);
326
+        return strtolower($word[0]).substr($word, 1);
327 327
     }
328 328
 
329 329
     // }}}
@@ -382,19 +382,19 @@  discard block
 block discarded – undo
382 382
     public static function ordinalize($number)
383 383
     {
384 384
         if (in_array(($number % 100), range(11, 13))) {
385
-            return $number . 'th';
385
+            return $number.'th';
386 386
         } else {
387 387
             switch (($number % 10)) {
388 388
                 case 1:
389
-                    return $number . 'st';
389
+                    return $number.'st';
390 390
                     break;
391 391
                 case 2:
392
-                    return $number . 'nd';
392
+                    return $number.'nd';
393 393
                     break;
394 394
                 case 3:
395
-                    return $number . 'rd';
395
+                    return $number.'rd';
396 396
                 default:
397
-                    return $number . 'th';
397
+                    return $number.'th';
398 398
                     break;
399 399
             }
400 400
         }
@@ -411,6 +411,6 @@  discard block
 block discarded – undo
411 411
         if (strtolower($string) === 'null') {
412 412
             return $string;
413 413
         }
414
-        return (stripos('aeiou', $string[0]) !== false ? 'an ' : 'a ') . $string;
414
+        return (stripos('aeiou', $string[0]) !== false ? 'an ' : 'a ').$string;
415 415
     }
416 416
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Parse_Shortcodes.helper.php 2 patches
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -208,14 +208,14 @@  discard block
 block discarded – undo
208 208
                 if ($sc_obj instanceof EE_Shortcodes) {
209 209
                     // we need to setup any dynamic shortcodes so that they work with the array_key_exists
210 210
                     preg_match_all('/(\[[A-Za-z0-9\_]+_\*)/', $shortcode, $matches);
211
-                    $sc_to_verify = ! empty($matches[0]) ? $matches[0][0] . ']' : $shortcode;
211
+                    $sc_to_verify = ! empty($matches[0]) ? $matches[0][0].']' : $shortcode;
212 212
 
213
-                    if (! array_key_exists($sc_to_verify, $sc_obj->get_shortcodes())) {
213
+                    if ( ! array_key_exists($sc_to_verify, $sc_obj->get_shortcodes())) {
214 214
                         continue; // the given shortcode isn't in this object
215 215
                     }
216 216
 
217 217
                     // if this isn't  a "list" type shortcode then we'll send along the data vanilla instead of in an array.
218
-                    if (! in_array($sc_to_verify, $list_type_shortcodes)) {
218
+                    if ( ! in_array($sc_to_verify, $list_type_shortcodes)) {
219 219
                         $data_send = ! is_object($this->_data) && isset($this->_data['data']) ? $this->_data['data'] : $this->_data;
220 220
                     } else {
221 221
                         $data_send = $this->_data;
@@ -271,7 +271,7 @@  discard block
 block discarded – undo
271 271
         foreach ($valid_shortcodes as $shortcode_ref) {
272 272
             $ref       = ucwords(str_replace('_', ' ', $shortcode_ref));
273 273
             $ref       = str_replace(' ', '_', $ref);
274
-            $classname = 'EE_' . $ref . '_Shortcodes';
274
+            $classname = 'EE_'.$ref.'_Shortcodes';
275 275
             if (class_exists($classname)) {
276 276
                 $this->_shortcode_objs[] = new $classname();
277 277
             }
Please login to merge, or discard this patch.
Indentation   +263 added lines, -263 removed lines patch added patch discarded remove patch
@@ -11,267 +11,267 @@
 block discarded – undo
11 11
  */
12 12
 class EEH_Parse_Shortcodes
13 13
 {
14
-    /**
15
-     * holds the template
16
-     *
17
-     * @access private
18
-     * @var mixed (string|array)
19
-     */
20
-    private $_template;
21
-
22
-
23
-    /**
24
-     * holds the incoming data object
25
-     *
26
-     * @access private
27
-     * @var object
28
-     */
29
-    private $_data;
30
-
31
-
32
-    /**
33
-     * will hold an array of EE_Shortcodes library objects.
34
-     *
35
-     * @access private
36
-     * @var EE_Shortcodes[]
37
-     */
38
-    private $_shortcode_objs = array();
39
-
40
-
41
-    public function __construct()
42
-    {
43
-    }
44
-
45
-
46
-    /**
47
-     * This kicks off the parsing of shortcodes in message templates
48
-     *
49
-     * @param  string                $template         This is the incoming string to be parsed
50
-     * @param  EE_Messages_Addressee $data             This is the incoming data object
51
-     * @param  array                 $valid_shortcodes An array of strings that correspond to EE_Shortcode libraries
52
-     * @param EE_message_type        $message_type     The message type that called the parser
53
-     * @param EE_messenger           $messenger        The active messenger for this parsing session.
54
-     * @param EE_Message             $message
55
-     * @return string                   The parsed template string
56
-     */
57
-    public function parse_message_template(
58
-        $template,
59
-        EE_Messages_Addressee $data,
60
-        $valid_shortcodes,
61
-        EE_message_type $message_type,
62
-        EE_messenger $messenger,
63
-        EE_Message $message
64
-    ) {
65
-        $extra_data = array(
66
-            'messenger'    => $messenger,
67
-            'message_type' => $message_type,
68
-            'message'      => $message,
69
-        );
70
-        $this->_init_data($template, $data, $valid_shortcodes, $extra_data);
71
-        $this->_template = is_array($template) ? $template['main'] : $template;
72
-        return $this->_parse_message_template();
73
-    }
74
-
75
-
76
-    public function parse_attendee_list_template(
77
-        $template,
78
-        EE_Registration $registration,
79
-        $valid_shortcodes,
80
-        $extra_data = array()
81
-    ) {
82
-        $this->_init_data($template, $registration, $valid_shortcodes, $extra_data);
83
-        $this->_template = is_array($template) ? $template['attendee_list'] : $template;
84
-        return $this->_parse_message_template();
85
-    }
86
-
87
-    public function parse_event_list_template($template, EE_Event $event, $valid_shortcodes, $extra_data = array())
88
-    {
89
-        $this->_init_data($template, $event, $valid_shortcodes, $extra_data);
90
-        $this->_template = is_array($template) ? $template['event_list'] : $template;
91
-        return $this->_parse_message_template();
92
-    }
93
-
94
-
95
-    public function parse_ticket_list_template($template, EE_Ticket $ticket, $valid_shortcodes, $extra_data = array())
96
-    {
97
-        $this->_init_data($template, $ticket, $valid_shortcodes, $extra_data);
98
-        $this->_template = is_array($template) ? $template['ticket_list'] : $template;
99
-        return $this->_parse_message_template();
100
-    }
101
-
102
-
103
-    public function parse_line_item_list_template(
104
-        $template,
105
-        EE_Line_Item $line_item,
106
-        $valid_shortcodes,
107
-        $extra_data = array()
108
-    ) {
109
-        $this->_init_data($template, $line_item, $valid_shortcodes, $extra_data);
110
-        $this->_template = is_array($template) ? $template['ticket_line_item_no_pms'] : $template;
111
-        return $this->_parse_message_template();
112
-    }
113
-
114
-
115
-    public function parse_payment_list_template(
116
-        $template,
117
-        EE_Payment $payment_item,
118
-        $valid_shortcodes,
119
-        $extra_data = array()
120
-    ) {
121
-        $this->_init_data($template, $payment_item, $valid_shortcodes, $extra_data);
122
-        $this->_template = is_array($template) ? $template['payment_list'] : $template;
123
-        return $this->_parse_message_template();
124
-    }
125
-
126
-
127
-    public function parse_datetime_list_template(
128
-        $template,
129
-        EE_Datetime $datetime,
130
-        $valid_shortcodes,
131
-        $extra_data = array()
132
-    ) {
133
-        $this->_init_data($template, $datetime, $valid_shortcodes, $extra_data);
134
-        $this->_template = is_array($template) ? $template['datetime_list'] : $template;
135
-        return $this->_parse_message_template();
136
-    }
137
-
138
-
139
-    public function parse_question_list_template($template, EE_Answer $answer, $valid_shortcodes, $extra_data = array())
140
-    {
141
-        $this->_init_data($template, $answer, $valid_shortcodes, $extra_data);
142
-        $this->_template = is_array($template) ? $template['question_list'] : $template;
143
-        return $this->_parse_message_template();
144
-    }
145
-
146
-
147
-    private function _init_data($template, $data, $valid_shortcodes, $extra_data = array())
148
-    {
149
-        $this->_reset_props();
150
-        $this->_data['template']   = $template;
151
-        $this->_data['data']       = $data;
152
-        $this->_data['extra_data'] = $extra_data;
153
-        $this->_set_shortcodes($valid_shortcodes);
154
-    }
155
-
156
-
157
-    private function _reset_props()
158
-    {
159
-        $this->_template       = $this->_data = null;
160
-        $this->_shortcode_objs = array();
161
-    }
162
-
163
-
164
-    /**
165
-     * takes the given template and parses it with the $_shortcodes property
166
-     *
167
-     * @access private
168
-     * @return string
169
-     */
170
-    private function _parse_message_template()
171
-    {
172
-        // now let's get a list of shortcodes that are found in the given template
173
-        preg_match_all('/(\[.+?\])/', $this->_template, $matches);
174
-        $shortcodes = (array) $matches[0]; // this should be an array of shortcodes in the template string.
175
-
176
-        $matched_code = array();
177
-        $sc_values    = array();
178
-
179
-        $list_type_shortcodes = array(
180
-            '[ATTENDEE_LIST]',
181
-            '[EVENT_LIST]',
182
-            '[TICKET_LIST]',
183
-            '[DATETIME_LIST]',
184
-            '[QUESTION_LIST]',
185
-            '[RECIPIENT_QUESTION_LIST]',
186
-            '[PRIMARY_REGISTRANT_QUESTION_LIST]',
187
-            '[RECIPIENT_TICKET_LIST]',
188
-            '[PRIMARY_REGISTRANT_TICKET_LIST]',
189
-            '[RECIPIENT_DATETIME_LIST]',
190
-            '[PRIMARY_REGISTRANT_DATETIME_LIST]',
191
-            '[TICKET_LINE_ITEM_LIST]',
192
-            '[TAX_LINE_ITEM_LIST]',
193
-            '[ADDITIONAL_LINE_ITEM_LIST]',
194
-            '[PRICE_MODIFIER_LINE_ITEM_LIST]',
195
-            '[PAYMENT_LIST_*]',
196
-        );
197
-
198
-        $list_type_shortcodes = apply_filters(
199
-            'FHEE__EEH_Parse_Shortcodes___parse_message_template__list_type_shortcodes',
200
-            $list_type_shortcodes
201
-        );
202
-
203
-        // now lets go ahead and loop through our parsers for each shortcode and setup the values
204
-        foreach ($shortcodes as $shortcode) {
205
-            foreach ($this->_shortcode_objs as $sc_obj) {
206
-                if ($sc_obj instanceof EE_Shortcodes) {
207
-                    // we need to setup any dynamic shortcodes so that they work with the array_key_exists
208
-                    preg_match_all('/(\[[A-Za-z0-9\_]+_\*)/', $shortcode, $matches);
209
-                    $sc_to_verify = ! empty($matches[0]) ? $matches[0][0] . ']' : $shortcode;
210
-
211
-                    if (! array_key_exists($sc_to_verify, $sc_obj->get_shortcodes())) {
212
-                        continue; // the given shortcode isn't in this object
213
-                    }
214
-
215
-                    // if this isn't  a "list" type shortcode then we'll send along the data vanilla instead of in an array.
216
-                    if (! in_array($sc_to_verify, $list_type_shortcodes)) {
217
-                        $data_send = ! is_object($this->_data) && isset($this->_data['data']) ? $this->_data['data'] : $this->_data;
218
-                    } else {
219
-                        $data_send = $this->_data;
220
-                    }
221
-
222
-                    // is this a conditional type shortcode?  If it is then we actually parse the template here.
223
-                    if ($this->_is_conditional_shortcode($shortcode)) {
224
-                        // most shortcode parsers are not going to have a match for this shortcode and will return an
225
-                        // empty string so we need to make sure that we're only replacing the template when there is a non empty string.
226
-                        $parsed = $sc_obj->parser($shortcode, $data_send, $this->_data['extra_data']);
227
-                        if ($parsed) {
228
-                            $this->_template = $parsed;
229
-                        }
230
-                    }
231
-
232
-                    $parsed = $sc_obj->parser($shortcode, $data_send, $this->_data['extra_data']);
233
-
234
-                    $matched_code[] = $shortcode;
235
-                    $sc_values[]    = $parsed;
236
-                }
237
-            }
238
-        }
239
-
240
-        // now we've got parsed values for all the shortcodes in the template so we can go ahead and swap the shortcodes out.
241
-        return str_replace(array_values($matched_code), array_values($sc_values), $this->_template);
242
-    }
243
-
244
-
245
-    /**
246
-     * Simply returns whether the given shortcode matches the structure for a conditional shortcode.
247
-     *
248
-     * Does it match this format: `[IF_`
249
-     *
250
-     * @param $shortcode
251
-     */
252
-    protected function _is_conditional_shortcode($shortcode)
253
-    {
254
-        return strpos($shortcode, '[IF_') === 0;
255
-    }
256
-
257
-
258
-    /**
259
-     * This sets the shortcodes property from the incoming array of valid shortcodes that corresponds to names of
260
-     * various EE_Shortcode library objects
261
-     *
262
-     * @access private
263
-     * @param array $valid_shortcodes an array of strings corresponding to EE_Shortcode Library objects
264
-     * @return void
265
-     */
266
-    private function _set_shortcodes($valid_shortcodes)
267
-    {
268
-        foreach ($valid_shortcodes as $shortcode_ref) {
269
-            $ref       = ucwords(str_replace('_', ' ', $shortcode_ref));
270
-            $ref       = str_replace(' ', '_', $ref);
271
-            $classname = 'EE_' . $ref . '_Shortcodes';
272
-            if (class_exists($classname)) {
273
-                $this->_shortcode_objs[] = new $classname();
274
-            }
275
-        }
276
-    }
14
+	/**
15
+	 * holds the template
16
+	 *
17
+	 * @access private
18
+	 * @var mixed (string|array)
19
+	 */
20
+	private $_template;
21
+
22
+
23
+	/**
24
+	 * holds the incoming data object
25
+	 *
26
+	 * @access private
27
+	 * @var object
28
+	 */
29
+	private $_data;
30
+
31
+
32
+	/**
33
+	 * will hold an array of EE_Shortcodes library objects.
34
+	 *
35
+	 * @access private
36
+	 * @var EE_Shortcodes[]
37
+	 */
38
+	private $_shortcode_objs = array();
39
+
40
+
41
+	public function __construct()
42
+	{
43
+	}
44
+
45
+
46
+	/**
47
+	 * This kicks off the parsing of shortcodes in message templates
48
+	 *
49
+	 * @param  string                $template         This is the incoming string to be parsed
50
+	 * @param  EE_Messages_Addressee $data             This is the incoming data object
51
+	 * @param  array                 $valid_shortcodes An array of strings that correspond to EE_Shortcode libraries
52
+	 * @param EE_message_type        $message_type     The message type that called the parser
53
+	 * @param EE_messenger           $messenger        The active messenger for this parsing session.
54
+	 * @param EE_Message             $message
55
+	 * @return string                   The parsed template string
56
+	 */
57
+	public function parse_message_template(
58
+		$template,
59
+		EE_Messages_Addressee $data,
60
+		$valid_shortcodes,
61
+		EE_message_type $message_type,
62
+		EE_messenger $messenger,
63
+		EE_Message $message
64
+	) {
65
+		$extra_data = array(
66
+			'messenger'    => $messenger,
67
+			'message_type' => $message_type,
68
+			'message'      => $message,
69
+		);
70
+		$this->_init_data($template, $data, $valid_shortcodes, $extra_data);
71
+		$this->_template = is_array($template) ? $template['main'] : $template;
72
+		return $this->_parse_message_template();
73
+	}
74
+
75
+
76
+	public function parse_attendee_list_template(
77
+		$template,
78
+		EE_Registration $registration,
79
+		$valid_shortcodes,
80
+		$extra_data = array()
81
+	) {
82
+		$this->_init_data($template, $registration, $valid_shortcodes, $extra_data);
83
+		$this->_template = is_array($template) ? $template['attendee_list'] : $template;
84
+		return $this->_parse_message_template();
85
+	}
86
+
87
+	public function parse_event_list_template($template, EE_Event $event, $valid_shortcodes, $extra_data = array())
88
+	{
89
+		$this->_init_data($template, $event, $valid_shortcodes, $extra_data);
90
+		$this->_template = is_array($template) ? $template['event_list'] : $template;
91
+		return $this->_parse_message_template();
92
+	}
93
+
94
+
95
+	public function parse_ticket_list_template($template, EE_Ticket $ticket, $valid_shortcodes, $extra_data = array())
96
+	{
97
+		$this->_init_data($template, $ticket, $valid_shortcodes, $extra_data);
98
+		$this->_template = is_array($template) ? $template['ticket_list'] : $template;
99
+		return $this->_parse_message_template();
100
+	}
101
+
102
+
103
+	public function parse_line_item_list_template(
104
+		$template,
105
+		EE_Line_Item $line_item,
106
+		$valid_shortcodes,
107
+		$extra_data = array()
108
+	) {
109
+		$this->_init_data($template, $line_item, $valid_shortcodes, $extra_data);
110
+		$this->_template = is_array($template) ? $template['ticket_line_item_no_pms'] : $template;
111
+		return $this->_parse_message_template();
112
+	}
113
+
114
+
115
+	public function parse_payment_list_template(
116
+		$template,
117
+		EE_Payment $payment_item,
118
+		$valid_shortcodes,
119
+		$extra_data = array()
120
+	) {
121
+		$this->_init_data($template, $payment_item, $valid_shortcodes, $extra_data);
122
+		$this->_template = is_array($template) ? $template['payment_list'] : $template;
123
+		return $this->_parse_message_template();
124
+	}
125
+
126
+
127
+	public function parse_datetime_list_template(
128
+		$template,
129
+		EE_Datetime $datetime,
130
+		$valid_shortcodes,
131
+		$extra_data = array()
132
+	) {
133
+		$this->_init_data($template, $datetime, $valid_shortcodes, $extra_data);
134
+		$this->_template = is_array($template) ? $template['datetime_list'] : $template;
135
+		return $this->_parse_message_template();
136
+	}
137
+
138
+
139
+	public function parse_question_list_template($template, EE_Answer $answer, $valid_shortcodes, $extra_data = array())
140
+	{
141
+		$this->_init_data($template, $answer, $valid_shortcodes, $extra_data);
142
+		$this->_template = is_array($template) ? $template['question_list'] : $template;
143
+		return $this->_parse_message_template();
144
+	}
145
+
146
+
147
+	private function _init_data($template, $data, $valid_shortcodes, $extra_data = array())
148
+	{
149
+		$this->_reset_props();
150
+		$this->_data['template']   = $template;
151
+		$this->_data['data']       = $data;
152
+		$this->_data['extra_data'] = $extra_data;
153
+		$this->_set_shortcodes($valid_shortcodes);
154
+	}
155
+
156
+
157
+	private function _reset_props()
158
+	{
159
+		$this->_template       = $this->_data = null;
160
+		$this->_shortcode_objs = array();
161
+	}
162
+
163
+
164
+	/**
165
+	 * takes the given template and parses it with the $_shortcodes property
166
+	 *
167
+	 * @access private
168
+	 * @return string
169
+	 */
170
+	private function _parse_message_template()
171
+	{
172
+		// now let's get a list of shortcodes that are found in the given template
173
+		preg_match_all('/(\[.+?\])/', $this->_template, $matches);
174
+		$shortcodes = (array) $matches[0]; // this should be an array of shortcodes in the template string.
175
+
176
+		$matched_code = array();
177
+		$sc_values    = array();
178
+
179
+		$list_type_shortcodes = array(
180
+			'[ATTENDEE_LIST]',
181
+			'[EVENT_LIST]',
182
+			'[TICKET_LIST]',
183
+			'[DATETIME_LIST]',
184
+			'[QUESTION_LIST]',
185
+			'[RECIPIENT_QUESTION_LIST]',
186
+			'[PRIMARY_REGISTRANT_QUESTION_LIST]',
187
+			'[RECIPIENT_TICKET_LIST]',
188
+			'[PRIMARY_REGISTRANT_TICKET_LIST]',
189
+			'[RECIPIENT_DATETIME_LIST]',
190
+			'[PRIMARY_REGISTRANT_DATETIME_LIST]',
191
+			'[TICKET_LINE_ITEM_LIST]',
192
+			'[TAX_LINE_ITEM_LIST]',
193
+			'[ADDITIONAL_LINE_ITEM_LIST]',
194
+			'[PRICE_MODIFIER_LINE_ITEM_LIST]',
195
+			'[PAYMENT_LIST_*]',
196
+		);
197
+
198
+		$list_type_shortcodes = apply_filters(
199
+			'FHEE__EEH_Parse_Shortcodes___parse_message_template__list_type_shortcodes',
200
+			$list_type_shortcodes
201
+		);
202
+
203
+		// now lets go ahead and loop through our parsers for each shortcode and setup the values
204
+		foreach ($shortcodes as $shortcode) {
205
+			foreach ($this->_shortcode_objs as $sc_obj) {
206
+				if ($sc_obj instanceof EE_Shortcodes) {
207
+					// we need to setup any dynamic shortcodes so that they work with the array_key_exists
208
+					preg_match_all('/(\[[A-Za-z0-9\_]+_\*)/', $shortcode, $matches);
209
+					$sc_to_verify = ! empty($matches[0]) ? $matches[0][0] . ']' : $shortcode;
210
+
211
+					if (! array_key_exists($sc_to_verify, $sc_obj->get_shortcodes())) {
212
+						continue; // the given shortcode isn't in this object
213
+					}
214
+
215
+					// if this isn't  a "list" type shortcode then we'll send along the data vanilla instead of in an array.
216
+					if (! in_array($sc_to_verify, $list_type_shortcodes)) {
217
+						$data_send = ! is_object($this->_data) && isset($this->_data['data']) ? $this->_data['data'] : $this->_data;
218
+					} else {
219
+						$data_send = $this->_data;
220
+					}
221
+
222
+					// is this a conditional type shortcode?  If it is then we actually parse the template here.
223
+					if ($this->_is_conditional_shortcode($shortcode)) {
224
+						// most shortcode parsers are not going to have a match for this shortcode and will return an
225
+						// empty string so we need to make sure that we're only replacing the template when there is a non empty string.
226
+						$parsed = $sc_obj->parser($shortcode, $data_send, $this->_data['extra_data']);
227
+						if ($parsed) {
228
+							$this->_template = $parsed;
229
+						}
230
+					}
231
+
232
+					$parsed = $sc_obj->parser($shortcode, $data_send, $this->_data['extra_data']);
233
+
234
+					$matched_code[] = $shortcode;
235
+					$sc_values[]    = $parsed;
236
+				}
237
+			}
238
+		}
239
+
240
+		// now we've got parsed values for all the shortcodes in the template so we can go ahead and swap the shortcodes out.
241
+		return str_replace(array_values($matched_code), array_values($sc_values), $this->_template);
242
+	}
243
+
244
+
245
+	/**
246
+	 * Simply returns whether the given shortcode matches the structure for a conditional shortcode.
247
+	 *
248
+	 * Does it match this format: `[IF_`
249
+	 *
250
+	 * @param $shortcode
251
+	 */
252
+	protected function _is_conditional_shortcode($shortcode)
253
+	{
254
+		return strpos($shortcode, '[IF_') === 0;
255
+	}
256
+
257
+
258
+	/**
259
+	 * This sets the shortcodes property from the incoming array of valid shortcodes that corresponds to names of
260
+	 * various EE_Shortcode library objects
261
+	 *
262
+	 * @access private
263
+	 * @param array $valid_shortcodes an array of strings corresponding to EE_Shortcode Library objects
264
+	 * @return void
265
+	 */
266
+	private function _set_shortcodes($valid_shortcodes)
267
+	{
268
+		foreach ($valid_shortcodes as $shortcode_ref) {
269
+			$ref       = ucwords(str_replace('_', ' ', $shortcode_ref));
270
+			$ref       = str_replace(' ', '_', $ref);
271
+			$classname = 'EE_' . $ref . '_Shortcodes';
272
+			if (class_exists($classname)) {
273
+				$this->_shortcode_objs[] = new $classname();
274
+			}
275
+		}
276
+	}
277 277
 }
Please login to merge, or discard this patch.
core/domain/values/model/CustomSelects.php 2 patches
Indentation   +336 added lines, -336 removed lines patch added patch discarded remove patch
@@ -17,340 +17,340 @@
 block discarded – undo
17 17
  */
18 18
 class CustomSelects
19 19
 {
20
-    const TYPE_SIMPLE = 'simple';
21
-    const TYPE_COMPLEX = 'complex';
22
-    const TYPE_STRUCTURED = 'structured';
23
-
24
-    private $valid_operators = array('COUNT', 'SUM');
25
-
26
-
27
-    /**
28
-     * Original incoming select array
29
-     *
30
-     * @var array
31
-     */
32
-    private $original_selects;
33
-
34
-    /**
35
-     * Select string that can be added to the query
36
-     *
37
-     * @var string
38
-     */
39
-    private $columns_to_select_expression;
40
-
41
-
42
-    /**
43
-     * An array of aliases for the columns included in the incoming select array.
44
-     *
45
-     * @var array
46
-     */
47
-    private $column_aliases_in_select;
48
-
49
-
50
-    /**
51
-     * Enum representation of the "type" of array coming into this value object.
52
-     *
53
-     * @var string
54
-     */
55
-    private $type = '';
56
-
57
-
58
-    /**
59
-     * CustomSelects constructor.
60
-     * Incoming selects can be in one of the following formats:
61
-     * ---- self::TYPE_SIMPLE array ----
62
-     * This is considered the "simple" type. In this case the array is an numerically indexed array with single or
63
-     * multiple columns to select as the values.
64
-     * eg. array( 'ATT_ID', 'REG_ID' )
65
-     * eg. array( '*' )
66
-     * If you want to use the columns in any WHERE, GROUP BY, or HAVING clauses, you must instead use the "complex" or
67
-     * "structured" method.
68
-     * ---- self::TYPE_COMPLEX array ----
69
-     * This is considered the "complex" type.  In this case the array is indexed by arbitrary strings that serve as
70
-     * column alias, and the value is an numerically indexed array where there are two values.  The first value (0) is
71
-     * the selection and the second value (1) is the data type.  Data types must be one of the types defined in
72
-     * EEM_Base::$_valid_wpdb_data_types.
73
-     * eg. array( 'count' => array('count(REG_ID)', '%d') )
74
-     * Complex array configuration allows for using the column alias in any WHERE, GROUP BY, or HAVING clauses.
75
-     * ---- self::TYPE_STRUCTURED array ---
76
-     * This is considered the "structured" type. This type is similar to the complex type except that the array attached
77
-     * to the column alias contains three values.  The first value is the qualified column name (which can include
78
-     * join syntax for models).  The second value is the operator performed on the column (i.e. 'COUNT', 'SUM' etc).,
79
-     * the third value is the data type.  Note, if the select does not have an operator, you can use an empty string for
80
-     * the second value.
81
-     * Note: for now SUM is only for simple single column expressions (i.e. SUM(Transaction.TXN_total))
82
-     * eg. array( 'registration_count' => array('Registration.REG_ID', 'count', '%d') );
83
-     * NOTE: mixing array types in the incoming $select will cause errors.
84
-     *
85
-     * @param array $selects
86
-     * @throws InvalidArgumentException
87
-     */
88
-    public function __construct(array $selects)
89
-    {
90
-        $this->original_selects = $selects;
91
-        $this->deriveType($selects);
92
-        $this->deriveParts($selects);
93
-    }
94
-
95
-
96
-    /**
97
-     * Derives what type of custom select has been sent in.
98
-     *
99
-     * @param array $selects
100
-     * @throws InvalidArgumentException
101
-     */
102
-    private function deriveType(array $selects)
103
-    {
104
-        // first if the first key for this array is an integer then its coming in as a simple format, so we'll also
105
-        // ensure all elements of the array are simple.
106
-        if (is_int(key($selects))) {
107
-            // let's ensure all keys are ints
108
-            $invalid_keys = array_filter(
109
-                array_keys($selects),
110
-                function ($value) {
111
-                    return ! is_int($value);
112
-                }
113
-            );
114
-            if (! empty($invalid_keys)) {
115
-                throw new InvalidArgumentException(
116
-                    sprintf(
117
-                        esc_html__(
118
-                            'Incoming array looks like its formatted for "%1$s" type selects, however it has elements that are not indexed numerically',
119
-                            'event_espresso'
120
-                        ),
121
-                        self::TYPE_SIMPLE
122
-                    )
123
-                );
124
-            }
125
-            $this->type = self::TYPE_SIMPLE;
126
-            return;
127
-        }
128
-        // made it here so that means we've got either complex or structured selects.  Let's find out which by popping
129
-        // the first array element off.
130
-        $first_element = reset($selects);
131
-
132
-        if (! is_array($first_element)) {
133
-            throw new InvalidArgumentException(
134
-                sprintf(
135
-                    esc_html__(
136
-                        'Incoming array looks like its formatted as a "%1$s" or "%2$s" type.  However, the values in the array must be arrays themselves and they are not.',
137
-                        'event_espresso'
138
-                    ),
139
-                    self::TYPE_COMPLEX,
140
-                    self::TYPE_STRUCTURED
141
-                )
142
-            );
143
-        }
144
-        $this->type = count($first_element) === 2
145
-            ? self::TYPE_COMPLEX
146
-            : self::TYPE_STRUCTURED;
147
-    }
148
-
149
-
150
-    /**
151
-     * Sets up the various properties for the vo depending on type.
152
-     *
153
-     * @param array $selects
154
-     * @throws InvalidArgumentException
155
-     */
156
-    private function deriveParts(array $selects)
157
-    {
158
-        $column_parts = array();
159
-        switch ($this->type) {
160
-            case self::TYPE_SIMPLE:
161
-                $column_parts = $selects;
162
-                $this->column_aliases_in_select = $selects;
163
-                break;
164
-            case self::TYPE_COMPLEX:
165
-                foreach ($selects as $alias => $parts) {
166
-                    $this->validateSelectValueForType($parts, $alias);
167
-                    $column_parts[] = "{$parts[0]} AS {$alias}";
168
-                    $this->column_aliases_in_select[] = $alias;
169
-                }
170
-                break;
171
-            case self::TYPE_STRUCTURED:
172
-                foreach ($selects as $alias => $parts) {
173
-                    $this->validateSelectValueForType($parts, $alias);
174
-                    $column_parts[] = $parts[1] !== ''
175
-                        ? $this->assembleSelectStringWithOperator($parts, $alias)
176
-                        : "{$parts[0]} AS {$alias}";
177
-                    $this->column_aliases_in_select[] = $alias;
178
-                }
179
-                break;
180
-        }
181
-        $this->columns_to_select_expression = implode(', ', $column_parts);
182
-    }
183
-
184
-
185
-    /**
186
-     * Validates self::TYPE_COMPLEX and self::TYPE_STRUCTURED select statement parts.
187
-     *
188
-     * @param array  $select_parts
189
-     * @param string $alias
190
-     * @throws InvalidArgumentException
191
-     */
192
-    private function validateSelectValueForType(array $select_parts, $alias)
193
-    {
194
-        $valid_data_types = array('%d', '%s', '%f');
195
-        if (count($select_parts) !== $this->expectedSelectPartCountForType()) {
196
-            throw new InvalidArgumentException(
197
-                sprintf(
198
-                    esc_html__(
199
-                        'The provided select part array for the %1$s column is expected to have a count of %2$d because the incoming select array is of type %3$s.  However the count was %4$d.',
200
-                        'event_espresso'
201
-                    ),
202
-                    $alias,
203
-                    $this->expectedSelectPartCountForType(),
204
-                    $this->type,
205
-                    count($select_parts)
206
-                )
207
-            );
208
-        }
209
-        // validate data type.
210
-        $data_type = $this->type === self::TYPE_COMPLEX ? $select_parts[1] : '';
211
-        $data_type = $this->type === self::TYPE_STRUCTURED ? $select_parts[2] : $data_type;
212
-
213
-        if (! in_array($data_type, $valid_data_types, true)) {
214
-            throw new InvalidArgumentException(
215
-                sprintf(
216
-                    esc_html__(
217
-                        'Datatype %1$s (for selection "%2$s" and alias "%3$s") is not a valid wpdb datatype (eg %%s)',
218
-                        'event_espresso'
219
-                    ),
220
-                    $data_type,
221
-                    $select_parts[0],
222
-                    $alias,
223
-                    implode(', ', $valid_data_types)
224
-                )
225
-            );
226
-        }
227
-    }
228
-
229
-
230
-    /**
231
-     * Each type will have an expected count of array elements, this returns what that expected count is.
232
-     *
233
-     * @param string $type
234
-     * @return int
235
-     */
236
-    private function expectedSelectPartCountForType($type = '')
237
-    {
238
-        $type = $type === '' ? $this->type : $type;
239
-        $types_count_map = array(
240
-            self::TYPE_COMPLEX    => 2,
241
-            self::TYPE_STRUCTURED => 3,
242
-        );
243
-        return isset($types_count_map[ $type ]) ? $types_count_map[ $type ] : 0;
244
-    }
245
-
246
-
247
-    /**
248
-     * Prepares the select statement part for for structured type selects.
249
-     *
250
-     * @param array  $select_parts
251
-     * @param string $alias
252
-     * @return string
253
-     * @throws InvalidArgumentException
254
-     */
255
-    private function assembleSelectStringWithOperator(array $select_parts, $alias)
256
-    {
257
-        $operator = strtoupper($select_parts[1]);
258
-        // validate operator
259
-        if (! in_array($operator, $this->valid_operators, true)) {
260
-            throw new InvalidArgumentException(
261
-                sprintf(
262
-                    esc_html__(
263
-                        'An invalid operator has been provided (%1$s) for the column %2$s.  Valid operators must be one of the following: %3$s.',
264
-                        'event_espresso'
265
-                    ),
266
-                    $operator,
267
-                    $alias,
268
-                    implode(', ', $this->valid_operators)
269
-                )
270
-            );
271
-        }
272
-        return $operator . '(' . $select_parts[0] . ') AS ' . $alias;
273
-    }
274
-
275
-
276
-    /**
277
-     * Return the datatype from the given select part.
278
-     * Remember the select_part has already been validated on object instantiation.
279
-     *
280
-     * @param array $select_part
281
-     * @return string
282
-     */
283
-    private function getDataTypeForSelectType(array $select_part)
284
-    {
285
-        switch ($this->type) {
286
-            case self::TYPE_COMPLEX:
287
-                return $select_part[1];
288
-            case self::TYPE_STRUCTURED:
289
-                return $select_part[2];
290
-            default:
291
-                return '';
292
-        }
293
-    }
294
-
295
-
296
-    /**
297
-     * Returns the original select array sent into the VO.
298
-     *
299
-     * @return array
300
-     */
301
-    public function originalSelects()
302
-    {
303
-        return $this->original_selects;
304
-    }
305
-
306
-
307
-    /**
308
-     * Returns the final assembled select expression derived from the incoming select array.
309
-     *
310
-     * @return string
311
-     */
312
-    public function columnsToSelectExpression()
313
-    {
314
-        return $this->columns_to_select_expression;
315
-    }
316
-
317
-
318
-    /**
319
-     * Returns all the column aliases derived from the incoming select array.
320
-     *
321
-     * @return array
322
-     */
323
-    public function columnAliases()
324
-    {
325
-        return $this->column_aliases_in_select;
326
-    }
327
-
328
-
329
-    /**
330
-     * Returns the enum type for the incoming select array.
331
-     *
332
-     * @return string
333
-     */
334
-    public function type()
335
-    {
336
-        return $this->type;
337
-    }
338
-
339
-
340
-    /**
341
-     * Return the datatype for the given column_alias
342
-     *
343
-     * @param string $column_alias
344
-     * @return string  (if there's no data type we return string as the default).
345
-     */
346
-    public function getDataTypeForAlias($column_alias)
347
-    {
348
-        if (
349
-            isset($this->original_selects[ $column_alias ])
350
-            && in_array($column_alias, $this->columnAliases(), true)
351
-        ) {
352
-            return $this->getDataTypeForSelectType($this->original_selects[ $column_alias ]);
353
-        }
354
-        return '%s';
355
-    }
20
+	const TYPE_SIMPLE = 'simple';
21
+	const TYPE_COMPLEX = 'complex';
22
+	const TYPE_STRUCTURED = 'structured';
23
+
24
+	private $valid_operators = array('COUNT', 'SUM');
25
+
26
+
27
+	/**
28
+	 * Original incoming select array
29
+	 *
30
+	 * @var array
31
+	 */
32
+	private $original_selects;
33
+
34
+	/**
35
+	 * Select string that can be added to the query
36
+	 *
37
+	 * @var string
38
+	 */
39
+	private $columns_to_select_expression;
40
+
41
+
42
+	/**
43
+	 * An array of aliases for the columns included in the incoming select array.
44
+	 *
45
+	 * @var array
46
+	 */
47
+	private $column_aliases_in_select;
48
+
49
+
50
+	/**
51
+	 * Enum representation of the "type" of array coming into this value object.
52
+	 *
53
+	 * @var string
54
+	 */
55
+	private $type = '';
56
+
57
+
58
+	/**
59
+	 * CustomSelects constructor.
60
+	 * Incoming selects can be in one of the following formats:
61
+	 * ---- self::TYPE_SIMPLE array ----
62
+	 * This is considered the "simple" type. In this case the array is an numerically indexed array with single or
63
+	 * multiple columns to select as the values.
64
+	 * eg. array( 'ATT_ID', 'REG_ID' )
65
+	 * eg. array( '*' )
66
+	 * If you want to use the columns in any WHERE, GROUP BY, or HAVING clauses, you must instead use the "complex" or
67
+	 * "structured" method.
68
+	 * ---- self::TYPE_COMPLEX array ----
69
+	 * This is considered the "complex" type.  In this case the array is indexed by arbitrary strings that serve as
70
+	 * column alias, and the value is an numerically indexed array where there are two values.  The first value (0) is
71
+	 * the selection and the second value (1) is the data type.  Data types must be one of the types defined in
72
+	 * EEM_Base::$_valid_wpdb_data_types.
73
+	 * eg. array( 'count' => array('count(REG_ID)', '%d') )
74
+	 * Complex array configuration allows for using the column alias in any WHERE, GROUP BY, or HAVING clauses.
75
+	 * ---- self::TYPE_STRUCTURED array ---
76
+	 * This is considered the "structured" type. This type is similar to the complex type except that the array attached
77
+	 * to the column alias contains three values.  The first value is the qualified column name (which can include
78
+	 * join syntax for models).  The second value is the operator performed on the column (i.e. 'COUNT', 'SUM' etc).,
79
+	 * the third value is the data type.  Note, if the select does not have an operator, you can use an empty string for
80
+	 * the second value.
81
+	 * Note: for now SUM is only for simple single column expressions (i.e. SUM(Transaction.TXN_total))
82
+	 * eg. array( 'registration_count' => array('Registration.REG_ID', 'count', '%d') );
83
+	 * NOTE: mixing array types in the incoming $select will cause errors.
84
+	 *
85
+	 * @param array $selects
86
+	 * @throws InvalidArgumentException
87
+	 */
88
+	public function __construct(array $selects)
89
+	{
90
+		$this->original_selects = $selects;
91
+		$this->deriveType($selects);
92
+		$this->deriveParts($selects);
93
+	}
94
+
95
+
96
+	/**
97
+	 * Derives what type of custom select has been sent in.
98
+	 *
99
+	 * @param array $selects
100
+	 * @throws InvalidArgumentException
101
+	 */
102
+	private function deriveType(array $selects)
103
+	{
104
+		// first if the first key for this array is an integer then its coming in as a simple format, so we'll also
105
+		// ensure all elements of the array are simple.
106
+		if (is_int(key($selects))) {
107
+			// let's ensure all keys are ints
108
+			$invalid_keys = array_filter(
109
+				array_keys($selects),
110
+				function ($value) {
111
+					return ! is_int($value);
112
+				}
113
+			);
114
+			if (! empty($invalid_keys)) {
115
+				throw new InvalidArgumentException(
116
+					sprintf(
117
+						esc_html__(
118
+							'Incoming array looks like its formatted for "%1$s" type selects, however it has elements that are not indexed numerically',
119
+							'event_espresso'
120
+						),
121
+						self::TYPE_SIMPLE
122
+					)
123
+				);
124
+			}
125
+			$this->type = self::TYPE_SIMPLE;
126
+			return;
127
+		}
128
+		// made it here so that means we've got either complex or structured selects.  Let's find out which by popping
129
+		// the first array element off.
130
+		$first_element = reset($selects);
131
+
132
+		if (! is_array($first_element)) {
133
+			throw new InvalidArgumentException(
134
+				sprintf(
135
+					esc_html__(
136
+						'Incoming array looks like its formatted as a "%1$s" or "%2$s" type.  However, the values in the array must be arrays themselves and they are not.',
137
+						'event_espresso'
138
+					),
139
+					self::TYPE_COMPLEX,
140
+					self::TYPE_STRUCTURED
141
+				)
142
+			);
143
+		}
144
+		$this->type = count($first_element) === 2
145
+			? self::TYPE_COMPLEX
146
+			: self::TYPE_STRUCTURED;
147
+	}
148
+
149
+
150
+	/**
151
+	 * Sets up the various properties for the vo depending on type.
152
+	 *
153
+	 * @param array $selects
154
+	 * @throws InvalidArgumentException
155
+	 */
156
+	private function deriveParts(array $selects)
157
+	{
158
+		$column_parts = array();
159
+		switch ($this->type) {
160
+			case self::TYPE_SIMPLE:
161
+				$column_parts = $selects;
162
+				$this->column_aliases_in_select = $selects;
163
+				break;
164
+			case self::TYPE_COMPLEX:
165
+				foreach ($selects as $alias => $parts) {
166
+					$this->validateSelectValueForType($parts, $alias);
167
+					$column_parts[] = "{$parts[0]} AS {$alias}";
168
+					$this->column_aliases_in_select[] = $alias;
169
+				}
170
+				break;
171
+			case self::TYPE_STRUCTURED:
172
+				foreach ($selects as $alias => $parts) {
173
+					$this->validateSelectValueForType($parts, $alias);
174
+					$column_parts[] = $parts[1] !== ''
175
+						? $this->assembleSelectStringWithOperator($parts, $alias)
176
+						: "{$parts[0]} AS {$alias}";
177
+					$this->column_aliases_in_select[] = $alias;
178
+				}
179
+				break;
180
+		}
181
+		$this->columns_to_select_expression = implode(', ', $column_parts);
182
+	}
183
+
184
+
185
+	/**
186
+	 * Validates self::TYPE_COMPLEX and self::TYPE_STRUCTURED select statement parts.
187
+	 *
188
+	 * @param array  $select_parts
189
+	 * @param string $alias
190
+	 * @throws InvalidArgumentException
191
+	 */
192
+	private function validateSelectValueForType(array $select_parts, $alias)
193
+	{
194
+		$valid_data_types = array('%d', '%s', '%f');
195
+		if (count($select_parts) !== $this->expectedSelectPartCountForType()) {
196
+			throw new InvalidArgumentException(
197
+				sprintf(
198
+					esc_html__(
199
+						'The provided select part array for the %1$s column is expected to have a count of %2$d because the incoming select array is of type %3$s.  However the count was %4$d.',
200
+						'event_espresso'
201
+					),
202
+					$alias,
203
+					$this->expectedSelectPartCountForType(),
204
+					$this->type,
205
+					count($select_parts)
206
+				)
207
+			);
208
+		}
209
+		// validate data type.
210
+		$data_type = $this->type === self::TYPE_COMPLEX ? $select_parts[1] : '';
211
+		$data_type = $this->type === self::TYPE_STRUCTURED ? $select_parts[2] : $data_type;
212
+
213
+		if (! in_array($data_type, $valid_data_types, true)) {
214
+			throw new InvalidArgumentException(
215
+				sprintf(
216
+					esc_html__(
217
+						'Datatype %1$s (for selection "%2$s" and alias "%3$s") is not a valid wpdb datatype (eg %%s)',
218
+						'event_espresso'
219
+					),
220
+					$data_type,
221
+					$select_parts[0],
222
+					$alias,
223
+					implode(', ', $valid_data_types)
224
+				)
225
+			);
226
+		}
227
+	}
228
+
229
+
230
+	/**
231
+	 * Each type will have an expected count of array elements, this returns what that expected count is.
232
+	 *
233
+	 * @param string $type
234
+	 * @return int
235
+	 */
236
+	private function expectedSelectPartCountForType($type = '')
237
+	{
238
+		$type = $type === '' ? $this->type : $type;
239
+		$types_count_map = array(
240
+			self::TYPE_COMPLEX    => 2,
241
+			self::TYPE_STRUCTURED => 3,
242
+		);
243
+		return isset($types_count_map[ $type ]) ? $types_count_map[ $type ] : 0;
244
+	}
245
+
246
+
247
+	/**
248
+	 * Prepares the select statement part for for structured type selects.
249
+	 *
250
+	 * @param array  $select_parts
251
+	 * @param string $alias
252
+	 * @return string
253
+	 * @throws InvalidArgumentException
254
+	 */
255
+	private function assembleSelectStringWithOperator(array $select_parts, $alias)
256
+	{
257
+		$operator = strtoupper($select_parts[1]);
258
+		// validate operator
259
+		if (! in_array($operator, $this->valid_operators, true)) {
260
+			throw new InvalidArgumentException(
261
+				sprintf(
262
+					esc_html__(
263
+						'An invalid operator has been provided (%1$s) for the column %2$s.  Valid operators must be one of the following: %3$s.',
264
+						'event_espresso'
265
+					),
266
+					$operator,
267
+					$alias,
268
+					implode(', ', $this->valid_operators)
269
+				)
270
+			);
271
+		}
272
+		return $operator . '(' . $select_parts[0] . ') AS ' . $alias;
273
+	}
274
+
275
+
276
+	/**
277
+	 * Return the datatype from the given select part.
278
+	 * Remember the select_part has already been validated on object instantiation.
279
+	 *
280
+	 * @param array $select_part
281
+	 * @return string
282
+	 */
283
+	private function getDataTypeForSelectType(array $select_part)
284
+	{
285
+		switch ($this->type) {
286
+			case self::TYPE_COMPLEX:
287
+				return $select_part[1];
288
+			case self::TYPE_STRUCTURED:
289
+				return $select_part[2];
290
+			default:
291
+				return '';
292
+		}
293
+	}
294
+
295
+
296
+	/**
297
+	 * Returns the original select array sent into the VO.
298
+	 *
299
+	 * @return array
300
+	 */
301
+	public function originalSelects()
302
+	{
303
+		return $this->original_selects;
304
+	}
305
+
306
+
307
+	/**
308
+	 * Returns the final assembled select expression derived from the incoming select array.
309
+	 *
310
+	 * @return string
311
+	 */
312
+	public function columnsToSelectExpression()
313
+	{
314
+		return $this->columns_to_select_expression;
315
+	}
316
+
317
+
318
+	/**
319
+	 * Returns all the column aliases derived from the incoming select array.
320
+	 *
321
+	 * @return array
322
+	 */
323
+	public function columnAliases()
324
+	{
325
+		return $this->column_aliases_in_select;
326
+	}
327
+
328
+
329
+	/**
330
+	 * Returns the enum type for the incoming select array.
331
+	 *
332
+	 * @return string
333
+	 */
334
+	public function type()
335
+	{
336
+		return $this->type;
337
+	}
338
+
339
+
340
+	/**
341
+	 * Return the datatype for the given column_alias
342
+	 *
343
+	 * @param string $column_alias
344
+	 * @return string  (if there's no data type we return string as the default).
345
+	 */
346
+	public function getDataTypeForAlias($column_alias)
347
+	{
348
+		if (
349
+			isset($this->original_selects[ $column_alias ])
350
+			&& in_array($column_alias, $this->columnAliases(), true)
351
+		) {
352
+			return $this->getDataTypeForSelectType($this->original_selects[ $column_alias ]);
353
+		}
354
+		return '%s';
355
+	}
356 356
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -107,11 +107,11 @@  discard block
 block discarded – undo
107 107
             // let's ensure all keys are ints
108 108
             $invalid_keys = array_filter(
109 109
                 array_keys($selects),
110
-                function ($value) {
110
+                function($value) {
111 111
                     return ! is_int($value);
112 112
                 }
113 113
             );
114
-            if (! empty($invalid_keys)) {
114
+            if ( ! empty($invalid_keys)) {
115 115
                 throw new InvalidArgumentException(
116 116
                     sprintf(
117 117
                         esc_html__(
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
         // the first array element off.
130 130
         $first_element = reset($selects);
131 131
 
132
-        if (! is_array($first_element)) {
132
+        if ( ! is_array($first_element)) {
133 133
             throw new InvalidArgumentException(
134 134
                 sprintf(
135 135
                     esc_html__(
@@ -210,7 +210,7 @@  discard block
 block discarded – undo
210 210
         $data_type = $this->type === self::TYPE_COMPLEX ? $select_parts[1] : '';
211 211
         $data_type = $this->type === self::TYPE_STRUCTURED ? $select_parts[2] : $data_type;
212 212
 
213
-        if (! in_array($data_type, $valid_data_types, true)) {
213
+        if ( ! in_array($data_type, $valid_data_types, true)) {
214 214
             throw new InvalidArgumentException(
215 215
                 sprintf(
216 216
                     esc_html__(
@@ -240,7 +240,7 @@  discard block
 block discarded – undo
240 240
             self::TYPE_COMPLEX    => 2,
241 241
             self::TYPE_STRUCTURED => 3,
242 242
         );
243
-        return isset($types_count_map[ $type ]) ? $types_count_map[ $type ] : 0;
243
+        return isset($types_count_map[$type]) ? $types_count_map[$type] : 0;
244 244
     }
245 245
 
246 246
 
@@ -256,7 +256,7 @@  discard block
 block discarded – undo
256 256
     {
257 257
         $operator = strtoupper($select_parts[1]);
258 258
         // validate operator
259
-        if (! in_array($operator, $this->valid_operators, true)) {
259
+        if ( ! in_array($operator, $this->valid_operators, true)) {
260 260
             throw new InvalidArgumentException(
261 261
                 sprintf(
262 262
                     esc_html__(
@@ -269,7 +269,7 @@  discard block
 block discarded – undo
269 269
                 )
270 270
             );
271 271
         }
272
-        return $operator . '(' . $select_parts[0] . ') AS ' . $alias;
272
+        return $operator.'('.$select_parts[0].') AS '.$alias;
273 273
     }
274 274
 
275 275
 
@@ -346,10 +346,10 @@  discard block
 block discarded – undo
346 346
     public function getDataTypeForAlias($column_alias)
347 347
     {
348 348
         if (
349
-            isset($this->original_selects[ $column_alias ])
349
+            isset($this->original_selects[$column_alias])
350 350
             && in_array($column_alias, $this->columnAliases(), true)
351 351
         ) {
352
-            return $this->getDataTypeForSelectType($this->original_selects[ $column_alias ]);
352
+            return $this->getDataTypeForSelectType($this->original_selects[$column_alias]);
353 353
         }
354 354
         return '%s';
355 355
     }
Please login to merge, or discard this patch.
core/services/address/CountrySubRegionDao.php 2 patches
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -80,7 +80,7 @@  discard block
 block discarded – undo
80 80
         $data = [];
81 81
         if (empty($this->countries)) {
82 82
             $this->data_version = $this->getCountrySubRegionDataVersion();
83
-            $data = $this->retrieveJsonData(self::REPO_URL . 'countries.json');
83
+            $data = $this->retrieveJsonData(self::REPO_URL.'countries.json');
84 84
         }
85 85
         if (empty($data)) {
86 86
             EE_Error::add_error(
@@ -144,7 +144,7 @@  discard block
 block discarded – undo
144 144
      */
145 145
     private function processCountryData($CNT_ISO, $countries = array())
146 146
     {
147
-        if (! empty($countries)) {
147
+        if ( ! empty($countries)) {
148 148
             foreach ($countries as $key => $country) {
149 149
                 if (
150 150
                     $country instanceof stdClass
@@ -153,7 +153,7 @@  discard block
 block discarded – undo
153 153
                     && ! empty($country->filename)
154 154
                 ) {
155 155
                     $country->sub_regions = $this->retrieveJsonData(
156
-                        self::REPO_URL . 'countries/' . $country->filename . '.json'
156
+                        self::REPO_URL.'countries/'.$country->filename.'.json'
157 157
                     );
158 158
                     return $this->saveSubRegionData($country, $country->sub_regions);
159 159
                 }
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
             foreach ($sub_regions as $sub_region) {
216 216
                 // remove country code from sub region code
217 217
                 $abbrev = str_replace(
218
-                    $country->code . '-',
218
+                    $country->code.'-',
219 219
                     '',
220 220
                     sanitize_text_field($sub_region->code)
221 221
                 );
Please login to merge, or discard this patch.
Indentation   +227 added lines, -227 removed lines patch added patch discarded remove patch
@@ -25,252 +25,252 @@
 block discarded – undo
25 25
  */
26 26
 class CountrySubRegionDao
27 27
 {
28
-    const REPO_URL = 'https://raw.githubusercontent.com/eventespresso/countries-and-subregions/master/';
28
+	const REPO_URL = 'https://raw.githubusercontent.com/eventespresso/countries-and-subregions/master/';
29 29
 
30
-    const OPTION_NAME_COUNTRY_DATA_VERSION = 'espresso-country-sub-region-data-version';
30
+	const OPTION_NAME_COUNTRY_DATA_VERSION = 'espresso-country-sub-region-data-version';
31 31
 
32
-    /**
33
-     * @var EEM_State $state_model
34
-     */
35
-    private $state_model;
32
+	/**
33
+	 * @var EEM_State $state_model
34
+	 */
35
+	private $state_model;
36 36
 
37
-    /**
38
-     * @var JsonValidator $json_validator
39
-     */
40
-    private $json_validator;
37
+	/**
38
+	 * @var JsonValidator $json_validator
39
+	 */
40
+	private $json_validator;
41 41
 
42
-    /**
43
-     * @var string $data_version
44
-     */
45
-    private $data_version;
42
+	/**
43
+	 * @var string $data_version
44
+	 */
45
+	private $data_version;
46 46
 
47
-    /**
48
-     * @var array $countries
49
-     */
50
-    private $countries = array();
47
+	/**
48
+	 * @var array $countries
49
+	 */
50
+	private $countries = array();
51 51
 
52 52
 
53
-    /**
54
-     * CountrySubRegionDao constructor.
55
-     *
56
-     * @param EEM_State     $state_model
57
-     * @param JsonValidator $json_validator
58
-     */
59
-    public function __construct(EEM_State $state_model, JsonValidator $json_validator)
60
-    {
61
-        $this->state_model = $state_model;
62
-        $this->json_validator = $json_validator;
63
-    }
53
+	/**
54
+	 * CountrySubRegionDao constructor.
55
+	 *
56
+	 * @param EEM_State     $state_model
57
+	 * @param JsonValidator $json_validator
58
+	 */
59
+	public function __construct(EEM_State $state_model, JsonValidator $json_validator)
60
+	{
61
+		$this->state_model = $state_model;
62
+		$this->json_validator = $json_validator;
63
+	}
64 64
 
65 65
 
66
-    /**
67
-     * @param EE_Country $country_object
68
-     * @return bool
69
-     * @throws EE_Error
70
-     * @throws InvalidArgumentException
71
-     * @throws InvalidDataTypeException
72
-     * @throws InvalidInterfaceException
73
-     * @throws ReflectionException
74
-     */
75
-    public function saveCountrySubRegions(EE_Country $country_object)
76
-    {
77
-        $CNT_ISO = $country_object->ID();
78
-        $has_sub_regions = $this->state_model->count(array(array('Country.CNT_ISO' => $CNT_ISO)));
79
-        $data = [];
80
-        if (empty($this->countries)) {
81
-            $this->data_version = $this->getCountrySubRegionDataVersion();
82
-            $data = $this->retrieveJsonData(self::REPO_URL . 'countries.json');
83
-        }
84
-        if (empty($data)) {
85
-            EE_Error::add_error(
86
-                'Country Subregion Data could not be retrieved',
87
-                __FILE__,
88
-                __METHOD__,
89
-                __LINE__
90
-            );
91
-        }
92
-        if (
93
-            ! $has_sub_regions
94
-            || (isset($data->version) && version_compare($data->version, $this->data_version))
95
-        ) {
96
-            if (
97
-                isset($data->countries)
98
-                && $this->processCountryData($CNT_ISO, $data->countries) > 0
99
-            ) {
100
-                $this->countries = $data->countries;
101
-                $this->updateCountrySubRegionDataVersion($data->version);
102
-                return true;
103
-            }
104
-        }
105
-        return false;
106
-    }
66
+	/**
67
+	 * @param EE_Country $country_object
68
+	 * @return bool
69
+	 * @throws EE_Error
70
+	 * @throws InvalidArgumentException
71
+	 * @throws InvalidDataTypeException
72
+	 * @throws InvalidInterfaceException
73
+	 * @throws ReflectionException
74
+	 */
75
+	public function saveCountrySubRegions(EE_Country $country_object)
76
+	{
77
+		$CNT_ISO = $country_object->ID();
78
+		$has_sub_regions = $this->state_model->count(array(array('Country.CNT_ISO' => $CNT_ISO)));
79
+		$data = [];
80
+		if (empty($this->countries)) {
81
+			$this->data_version = $this->getCountrySubRegionDataVersion();
82
+			$data = $this->retrieveJsonData(self::REPO_URL . 'countries.json');
83
+		}
84
+		if (empty($data)) {
85
+			EE_Error::add_error(
86
+				'Country Subregion Data could not be retrieved',
87
+				__FILE__,
88
+				__METHOD__,
89
+				__LINE__
90
+			);
91
+		}
92
+		if (
93
+			! $has_sub_regions
94
+			|| (isset($data->version) && version_compare($data->version, $this->data_version))
95
+		) {
96
+			if (
97
+				isset($data->countries)
98
+				&& $this->processCountryData($CNT_ISO, $data->countries) > 0
99
+			) {
100
+				$this->countries = $data->countries;
101
+				$this->updateCountrySubRegionDataVersion($data->version);
102
+				return true;
103
+			}
104
+		}
105
+		return false;
106
+	}
107 107
 
108 108
 
109
-    /**
110
-     * @since 4.9.70.p
111
-     * @return string
112
-     */
113
-    private function getCountrySubRegionDataVersion()
114
-    {
115
-        return get_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, null);
116
-    }
109
+	/**
110
+	 * @since 4.9.70.p
111
+	 * @return string
112
+	 */
113
+	private function getCountrySubRegionDataVersion()
114
+	{
115
+		return get_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, null);
116
+	}
117 117
 
118 118
 
119
-    /**
120
-     * @param string $version
121
-     */
122
-    private function updateCountrySubRegionDataVersion($version = '')
123
-    {
124
-        // add version option if it has never been added before, or update existing
125
-        if ($this->data_version === null) {
126
-            add_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version, '', false);
127
-        } else {
128
-            update_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version);
129
-        }
130
-    }
119
+	/**
120
+	 * @param string $version
121
+	 */
122
+	private function updateCountrySubRegionDataVersion($version = '')
123
+	{
124
+		// add version option if it has never been added before, or update existing
125
+		if ($this->data_version === null) {
126
+			add_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version, '', false);
127
+		} else {
128
+			update_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version);
129
+		}
130
+	}
131 131
 
132 132
 
133
-    /**
134
-     * @param string $CNT_ISO
135
-     * @param array  $countries
136
-     * @return int
137
-     * @throws EE_Error
138
-     * @throws InvalidArgumentException
139
-     * @throws InvalidDataTypeException
140
-     * @throws InvalidInterfaceException
141
-     * @throws ReflectionException
142
-     * @since 4.9.70.p
143
-     */
144
-    private function processCountryData($CNT_ISO, $countries = array())
145
-    {
146
-        if (! empty($countries)) {
147
-            foreach ($countries as $key => $country) {
148
-                if (
149
-                    $country instanceof stdClass
150
-                    && $country->code === $CNT_ISO
151
-                    && empty($country->sub_regions)
152
-                    && ! empty($country->filename)
153
-                ) {
154
-                    $country->sub_regions = $this->retrieveJsonData(
155
-                        self::REPO_URL . 'countries/' . $country->filename . '.json'
156
-                    );
157
-                    return $this->saveSubRegionData($country, $country->sub_regions);
158
-                }
159
-            }
160
-        }
161
-        return 0;
162
-    }
133
+	/**
134
+	 * @param string $CNT_ISO
135
+	 * @param array  $countries
136
+	 * @return int
137
+	 * @throws EE_Error
138
+	 * @throws InvalidArgumentException
139
+	 * @throws InvalidDataTypeException
140
+	 * @throws InvalidInterfaceException
141
+	 * @throws ReflectionException
142
+	 * @since 4.9.70.p
143
+	 */
144
+	private function processCountryData($CNT_ISO, $countries = array())
145
+	{
146
+		if (! empty($countries)) {
147
+			foreach ($countries as $key => $country) {
148
+				if (
149
+					$country instanceof stdClass
150
+					&& $country->code === $CNT_ISO
151
+					&& empty($country->sub_regions)
152
+					&& ! empty($country->filename)
153
+				) {
154
+					$country->sub_regions = $this->retrieveJsonData(
155
+						self::REPO_URL . 'countries/' . $country->filename . '.json'
156
+					);
157
+					return $this->saveSubRegionData($country, $country->sub_regions);
158
+				}
159
+			}
160
+		}
161
+		return 0;
162
+	}
163 163
 
164 164
 
165
-    /**
166
-     * @param string $url
167
-     * @return array
168
-     */
169
-    private function retrieveJsonData($url)
170
-    {
171
-        if (empty($url)) {
172
-            EE_Error::add_error(
173
-                'No URL was provided!',
174
-                __FILE__,
175
-                __METHOD__,
176
-                __LINE__
177
-            );
178
-            return array();
179
-        }
180
-        $request = wp_safe_remote_get($url);
181
-        if ($request instanceof WP_Error) {
182
-            EE_Error::add_error(
183
-                $request->get_error_message(),
184
-                __FILE__,
185
-                __METHOD__,
186
-                __LINE__
187
-            );
188
-            return array();
189
-        }
190
-        $body = wp_remote_retrieve_body($request);
191
-        $json = json_decode($body);
192
-        if ($this->json_validator->isValid(__FILE__, __METHOD__, __LINE__)) {
193
-            return $json;
194
-        }
195
-        return array();
196
-    }
165
+	/**
166
+	 * @param string $url
167
+	 * @return array
168
+	 */
169
+	private function retrieveJsonData($url)
170
+	{
171
+		if (empty($url)) {
172
+			EE_Error::add_error(
173
+				'No URL was provided!',
174
+				__FILE__,
175
+				__METHOD__,
176
+				__LINE__
177
+			);
178
+			return array();
179
+		}
180
+		$request = wp_safe_remote_get($url);
181
+		if ($request instanceof WP_Error) {
182
+			EE_Error::add_error(
183
+				$request->get_error_message(),
184
+				__FILE__,
185
+				__METHOD__,
186
+				__LINE__
187
+			);
188
+			return array();
189
+		}
190
+		$body = wp_remote_retrieve_body($request);
191
+		$json = json_decode($body);
192
+		if ($this->json_validator->isValid(__FILE__, __METHOD__, __LINE__)) {
193
+			return $json;
194
+		}
195
+		return array();
196
+	}
197 197
 
198 198
 
199
-    /**
200
-     * @param stdClass $country
201
-     * @param array    $sub_regions
202
-     * @return int
203
-     * @throws EE_Error
204
-     * @throws InvalidArgumentException
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     * @throws ReflectionException
208
-     */
209
-    private function saveSubRegionData(stdClass $country, $sub_regions = array())
210
-    {
211
-        $results = 0;
212
-        if (is_array($sub_regions)) {
213
-            $existing_sub_regions = $this->getExistingStateAbbreviations($country->code);
214
-            foreach ($sub_regions as $sub_region) {
215
-                // remove country code from sub region code
216
-                $abbrev = str_replace(
217
-                    $country->code . '-',
218
-                    '',
219
-                    sanitize_text_field($sub_region->code)
220
-                );
221
-                // but NOT if sub region code results in only a number
222
-                if (absint($abbrev) !== 0) {
223
-                    $abbrev = sanitize_text_field($sub_region->code);
224
-                }
225
-                if (
226
-                    ! in_array($abbrev, $existing_sub_regions, true)
227
-                    && $this->state_model->insert(
228
-                        [
229
-                            // STA_ID CNT_ISO STA_abbrev STA_name STA_active
230
-                            'CNT_ISO'    => $country->code,
231
-                            'STA_abbrev' => $abbrev,
232
-                            'STA_name'   => sanitize_text_field($sub_region->name),
233
-                            'STA_active' => 1,
234
-                        ]
235
-                    )
236
-                ) {
237
-                    $results++;
238
-                }
239
-            }
240
-        }
241
-        return $results;
242
-    }
199
+	/**
200
+	 * @param stdClass $country
201
+	 * @param array    $sub_regions
202
+	 * @return int
203
+	 * @throws EE_Error
204
+	 * @throws InvalidArgumentException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 * @throws ReflectionException
208
+	 */
209
+	private function saveSubRegionData(stdClass $country, $sub_regions = array())
210
+	{
211
+		$results = 0;
212
+		if (is_array($sub_regions)) {
213
+			$existing_sub_regions = $this->getExistingStateAbbreviations($country->code);
214
+			foreach ($sub_regions as $sub_region) {
215
+				// remove country code from sub region code
216
+				$abbrev = str_replace(
217
+					$country->code . '-',
218
+					'',
219
+					sanitize_text_field($sub_region->code)
220
+				);
221
+				// but NOT if sub region code results in only a number
222
+				if (absint($abbrev) !== 0) {
223
+					$abbrev = sanitize_text_field($sub_region->code);
224
+				}
225
+				if (
226
+					! in_array($abbrev, $existing_sub_regions, true)
227
+					&& $this->state_model->insert(
228
+						[
229
+							// STA_ID CNT_ISO STA_abbrev STA_name STA_active
230
+							'CNT_ISO'    => $country->code,
231
+							'STA_abbrev' => $abbrev,
232
+							'STA_name'   => sanitize_text_field($sub_region->name),
233
+							'STA_active' => 1,
234
+						]
235
+					)
236
+				) {
237
+					$results++;
238
+				}
239
+			}
240
+		}
241
+		return $results;
242
+	}
243 243
 
244 244
 
245
-    /**
246
-     * @param string $CNT_ISO
247
-     * @since 4.9.76.p
248
-     * @return array
249
-     * @throws EE_Error
250
-     * @throws InvalidArgumentException
251
-     * @throws InvalidDataTypeException
252
-     * @throws InvalidInterfaceException
253
-     * @throws ReflectionException
254
-     */
255
-    private function getExistingStateAbbreviations($CNT_ISO)
256
-    {
257
-        $existing_sub_region_IDs = [];
258
-        $existing_sub_regions = $this->state_model->get_all(array(
259
-            array(
260
-                'Country.CNT_ISO' => array(
261
-                    'IN',
262
-                    [$CNT_ISO]
263
-                )
264
-            ),
265
-            'order_by' => array('Country.CNT_name' => 'ASC', 'STA_name' => 'ASC')
266
-        ));
267
-        if (is_array($existing_sub_regions)) {
268
-            foreach ($existing_sub_regions as $existing_sub_region) {
269
-                if ($existing_sub_region instanceof EE_State) {
270
-                    $existing_sub_region_IDs[] = $existing_sub_region->abbrev();
271
-                }
272
-            }
273
-        }
274
-        return $existing_sub_region_IDs;
275
-    }
245
+	/**
246
+	 * @param string $CNT_ISO
247
+	 * @since 4.9.76.p
248
+	 * @return array
249
+	 * @throws EE_Error
250
+	 * @throws InvalidArgumentException
251
+	 * @throws InvalidDataTypeException
252
+	 * @throws InvalidInterfaceException
253
+	 * @throws ReflectionException
254
+	 */
255
+	private function getExistingStateAbbreviations($CNT_ISO)
256
+	{
257
+		$existing_sub_region_IDs = [];
258
+		$existing_sub_regions = $this->state_model->get_all(array(
259
+			array(
260
+				'Country.CNT_ISO' => array(
261
+					'IN',
262
+					[$CNT_ISO]
263
+				)
264
+			),
265
+			'order_by' => array('Country.CNT_name' => 'ASC', 'STA_name' => 'ASC')
266
+		));
267
+		if (is_array($existing_sub_regions)) {
268
+			foreach ($existing_sub_regions as $existing_sub_region) {
269
+				if ($existing_sub_region instanceof EE_State) {
270
+					$existing_sub_region_IDs[] = $existing_sub_region->abbrev();
271
+				}
272
+			}
273
+		}
274
+		return $existing_sub_region_IDs;
275
+	}
276 276
 }
Please login to merge, or discard this patch.
core/services/payment_methods/forms/PayPalSettingsForm.php 1 patch
Indentation   +191 added lines, -191 removed lines patch added patch discarded remove patch
@@ -20,202 +20,202 @@
 block discarded – undo
20 20
  */
21 21
 class PayPalSettingsForm extends EE_Payment_Method_Form
22 22
 {
23
-    /**
24
-     * @var string of HTML being the help tab link
25
-     */
26
-    protected $helpTabLink;
23
+	/**
24
+	 * @var string of HTML being the help tab link
25
+	 */
26
+	protected $helpTabLink;
27 27
 
28
-    public function __construct(array $options_array = array(), $help_tab_link = '')
29
-    {
30
-        $this->helpTabLink = $help_tab_link;
31
-        $options_array = array_replace_recursive(
32
-            array(
33
-                'extra_meta_inputs' => array(
34
-                    'api_username' => new EE_Text_Input(
35
-                        array(
36
-                            'html_label_text' => sprintf(
37
-                                // translators: %s link to help doc
38
-                                esc_html__('API Username %s', 'event_espresso'),
39
-                                $help_tab_link
40
-                            ),
41
-                            'required'        => true,
42
-                        )
43
-                    ),
44
-                    'api_password' => new EE_Text_Input(
45
-                        array(
46
-                            'html_label_text' => sprintf(
47
-                                // translators: %s link to help doc
48
-                                esc_html__('API Password %s', 'event_espresso'),
49
-                                $help_tab_link
50
-                            ),
51
-                            'required'        => true,
52
-                        )
53
-                    ),
54
-                    'api_signature' => new EE_Text_Input(
55
-                        array(
56
-                            'html_label_text' => sprintf(
57
-                                // translators: %s link to help doc
58
-                                esc_html__('API Signature %s', 'event_espresso'),
59
-                                $help_tab_link
60
-                            ),
61
-                            'required'        => true,
62
-                        )
63
-                    ),
64
-                )
65
-            ),
66
-            $options_array
67
-        );
68
-        parent::__construct($options_array);
69
-    }
28
+	public function __construct(array $options_array = array(), $help_tab_link = '')
29
+	{
30
+		$this->helpTabLink = $help_tab_link;
31
+		$options_array = array_replace_recursive(
32
+			array(
33
+				'extra_meta_inputs' => array(
34
+					'api_username' => new EE_Text_Input(
35
+						array(
36
+							'html_label_text' => sprintf(
37
+								// translators: %s link to help doc
38
+								esc_html__('API Username %s', 'event_espresso'),
39
+								$help_tab_link
40
+							),
41
+							'required'        => true,
42
+						)
43
+					),
44
+					'api_password' => new EE_Text_Input(
45
+						array(
46
+							'html_label_text' => sprintf(
47
+								// translators: %s link to help doc
48
+								esc_html__('API Password %s', 'event_espresso'),
49
+								$help_tab_link
50
+							),
51
+							'required'        => true,
52
+						)
53
+					),
54
+					'api_signature' => new EE_Text_Input(
55
+						array(
56
+							'html_label_text' => sprintf(
57
+								// translators: %s link to help doc
58
+								esc_html__('API Signature %s', 'event_espresso'),
59
+								$help_tab_link
60
+							),
61
+							'required'        => true,
62
+						)
63
+					),
64
+				)
65
+			),
66
+			$options_array
67
+		);
68
+		parent::__construct($options_array);
69
+	}
70 70
 
71
-    /**
72
-     * Tests the the PayPal API credentials work ok
73
-     * @return string of an error using the credentials, otherwise, if the credentials work, returns a blank string
74
-     * @throws EE_Error
75
-     */
76
-    protected function checkForCredentialsErrors()
77
-    {
78
-        $request_params = array(
79
-            'METHOD'    => 'GetBalance',
80
-            'VERSION'   => '204.0',
81
-            'USER'      => $this->get_input_value('api_username'),
82
-            'PWD'       => $this->get_input_value('api_password'),
83
-            'SIGNATURE' => $this->get_input_value('api_signature'),
84
-        );
85
-        $gateway_url = $this->get_input_value('PMD_debug_mode')
86
-            ? 'https://api-3t.sandbox.paypal.com/nvp'
87
-            : 'https://api-3t.paypal.com/nvp';
88
-        // Request Customer Details.
89
-        $response = wp_remote_post(
90
-            $gateway_url,
91
-            array(
92
-                'method'      => 'POST',
93
-                'timeout'     => 45,
94
-                'httpversion' => '1.1',
95
-                'cookies'     => array(),
96
-                'headers'     => array(),
97
-                'body'        => http_build_query($request_params, '', '&'),
98
-            )
99
-        );
100
-        if (is_wp_error($response) || empty($response['body'])) {
101
-            // If we got here then there was an error in this request.
102
-            // maybe is turned off. We don't know the credentials are invalid
103
-            EE_Error::add_error(
104
-                sprintf(
105
-                    // translators: %1$s Error message received from PayPal
106
-                    esc_html__(
107
-                        // @codingStandardsIgnoreStart
108
-                        'Your PayPal credentials could not be verified. The following error occurred while communicating with PayPal: %1$s',
109
-                        // @codingStandardsIgnoreEnd
110
-                        'event_espresso'
111
-                    ),
112
-                    $response->get_error_message()
113
-                ),
114
-                __FILE__,
115
-                __FUNCTION__,
116
-                __LINE__
117
-            );
118
-        }
119
-        $response_args = array();
120
-        parse_str(urldecode($response['body']), $response_args);
71
+	/**
72
+	 * Tests the the PayPal API credentials work ok
73
+	 * @return string of an error using the credentials, otherwise, if the credentials work, returns a blank string
74
+	 * @throws EE_Error
75
+	 */
76
+	protected function checkForCredentialsErrors()
77
+	{
78
+		$request_params = array(
79
+			'METHOD'    => 'GetBalance',
80
+			'VERSION'   => '204.0',
81
+			'USER'      => $this->get_input_value('api_username'),
82
+			'PWD'       => $this->get_input_value('api_password'),
83
+			'SIGNATURE' => $this->get_input_value('api_signature'),
84
+		);
85
+		$gateway_url = $this->get_input_value('PMD_debug_mode')
86
+			? 'https://api-3t.sandbox.paypal.com/nvp'
87
+			: 'https://api-3t.paypal.com/nvp';
88
+		// Request Customer Details.
89
+		$response = wp_remote_post(
90
+			$gateway_url,
91
+			array(
92
+				'method'      => 'POST',
93
+				'timeout'     => 45,
94
+				'httpversion' => '1.1',
95
+				'cookies'     => array(),
96
+				'headers'     => array(),
97
+				'body'        => http_build_query($request_params, '', '&'),
98
+			)
99
+		);
100
+		if (is_wp_error($response) || empty($response['body'])) {
101
+			// If we got here then there was an error in this request.
102
+			// maybe is turned off. We don't know the credentials are invalid
103
+			EE_Error::add_error(
104
+				sprintf(
105
+					// translators: %1$s Error message received from PayPal
106
+					esc_html__(
107
+						// @codingStandardsIgnoreStart
108
+						'Your PayPal credentials could not be verified. The following error occurred while communicating with PayPal: %1$s',
109
+						// @codingStandardsIgnoreEnd
110
+						'event_espresso'
111
+					),
112
+					$response->get_error_message()
113
+				),
114
+				__FILE__,
115
+				__FUNCTION__,
116
+				__LINE__
117
+			);
118
+		}
119
+		$response_args = array();
120
+		parse_str(urldecode($response['body']), $response_args);
121 121
 
122
-        if (empty($response_args['ACK'])) {
123
-            EE_Error::add_error(
124
-                esc_html__(
125
-                    'Your PayPal credentials could not be verified. Part of their response was missing.',
126
-                    'event_espresso'
127
-                ),
128
-                __FILE__,
129
-                __FUNCTION__,
130
-                __LINE__
131
-            );
132
-        }
133
-        if (
134
-            in_array(
135
-                $response_args['ACK'],
136
-                array(
137
-                'Success',
138
-                'SuccessWithWarning'
139
-                ),
140
-                true
141
-            )
142
-        ) {
143
-            return '';
144
-        } else {
145
-            return sprintf(
146
-                // translators: %1$s: PayPal response message, %2$s: PayPal response code
147
-                esc_html__(
148
-                    // @codingStandardsIgnoreStart
149
-                    'Your PayPal API credentials appear to be invalid. PayPal said "%1$s (%2$s)". Please see tips below.',
150
-                    // @codingStandardsIgnoreEnd
151
-                    'event_espresso'
152
-                ),
153
-                isset($response_args['L_LONGMESSAGE0'])
154
-                    ? $response_args['L_LONGMESSAGE0']
155
-                    : esc_html__('No error message received from PayPal', 'event_espresso'),
156
-                isset($response_args['L_ERRORCODE0']) ? $response_args['L_ERRORCODE0'] : 0
157
-            );
158
-        }
159
-    }
122
+		if (empty($response_args['ACK'])) {
123
+			EE_Error::add_error(
124
+				esc_html__(
125
+					'Your PayPal credentials could not be verified. Part of their response was missing.',
126
+					'event_espresso'
127
+				),
128
+				__FILE__,
129
+				__FUNCTION__,
130
+				__LINE__
131
+			);
132
+		}
133
+		if (
134
+			in_array(
135
+				$response_args['ACK'],
136
+				array(
137
+				'Success',
138
+				'SuccessWithWarning'
139
+				),
140
+				true
141
+			)
142
+		) {
143
+			return '';
144
+		} else {
145
+			return sprintf(
146
+				// translators: %1$s: PayPal response message, %2$s: PayPal response code
147
+				esc_html__(
148
+					// @codingStandardsIgnoreStart
149
+					'Your PayPal API credentials appear to be invalid. PayPal said "%1$s (%2$s)". Please see tips below.',
150
+					// @codingStandardsIgnoreEnd
151
+					'event_espresso'
152
+				),
153
+				isset($response_args['L_LONGMESSAGE0'])
154
+					? $response_args['L_LONGMESSAGE0']
155
+					: esc_html__('No error message received from PayPal', 'event_espresso'),
156
+				isset($response_args['L_ERRORCODE0']) ? $response_args['L_ERRORCODE0'] : 0
157
+			);
158
+		}
159
+	}
160 160
 
161
-    /**
162
-     * Gets the HTML to show the link to the help tab
163
-     * @return string
164
-     */
165
-    protected function helpTabLink()
166
-    {
167
-        return $this->helpTabLink;
168
-    }
161
+	/**
162
+	 * Gets the HTML to show the link to the help tab
163
+	 * @return string
164
+	 */
165
+	protected function helpTabLink()
166
+	{
167
+		return $this->helpTabLink;
168
+	}
169 169
 
170
-    /**
171
-     * Does the normal validation, but also verifies the PayPal API credentials work.
172
-     * If they don't, sets a validation error on the entire form, and adds validation errors (which are really more
173
-     * tips) on each of the inputs that could be the cause of the problem.
174
-     * @throws EE_Error
175
-     */
176
-    public function _validate()
177
-    {
178
-        parent::_validate();
179
-        $credentials_message = $this->checkForCredentialsErrors();
180
-        if ($credentials_message !== '') {
181
-            $this->add_validation_error($credentials_message);
182
-            $this->get_input('PMD_debug_mode')->add_validation_error(
183
-                esc_html__(
184
-                    // @codingStandardsIgnoreStart
185
-                    'If you are using PayPal Sandbox (test) credentials, Debug mode should be set to "Yes". Otherwise, if you are using live PayPal credentials, set this to "No".',
186
-                    // @codingStandardsIgnoreEnd
187
-                    'event_espresso'
188
-                )
189
-            );
190
-            $this->get_input('api_username')->add_validation_error(
191
-                sprintf(
192
-                    // translators: $1$s HTML for a link to the help tab
193
-                    esc_html__(
194
-                        'Are you sure this is your API username, not your login username? %1$s',
195
-                        'event_espresso'
196
-                    ),
197
-                    $this->helpTabLink()
198
-                )
199
-            );
200
-            $this->get_input('api_password')->add_validation_error(
201
-                sprintf(
202
-                    // translators: $1$s HTML for a link to the help tab
203
-                    esc_html__(
204
-                        'Are you sure this is your API password, not your login password? %1$s',
205
-                        'event_espresso'
206
-                    ),
207
-                    $this->helpTabLink()
208
-                )
209
-            );
210
-            $this->get_input('api_signature')->add_validation_error(
211
-                sprintf(
212
-                    // translators: $1$s HTML for a link to the help tab
213
-                    esc_html__('Please verify your API signature is correct. %1$s', 'event_espresso'),
214
-                    $this->helpTabLink()
215
-                )
216
-            );
217
-        }
218
-    }
170
+	/**
171
+	 * Does the normal validation, but also verifies the PayPal API credentials work.
172
+	 * If they don't, sets a validation error on the entire form, and adds validation errors (which are really more
173
+	 * tips) on each of the inputs that could be the cause of the problem.
174
+	 * @throws EE_Error
175
+	 */
176
+	public function _validate()
177
+	{
178
+		parent::_validate();
179
+		$credentials_message = $this->checkForCredentialsErrors();
180
+		if ($credentials_message !== '') {
181
+			$this->add_validation_error($credentials_message);
182
+			$this->get_input('PMD_debug_mode')->add_validation_error(
183
+				esc_html__(
184
+					// @codingStandardsIgnoreStart
185
+					'If you are using PayPal Sandbox (test) credentials, Debug mode should be set to "Yes". Otherwise, if you are using live PayPal credentials, set this to "No".',
186
+					// @codingStandardsIgnoreEnd
187
+					'event_espresso'
188
+				)
189
+			);
190
+			$this->get_input('api_username')->add_validation_error(
191
+				sprintf(
192
+					// translators: $1$s HTML for a link to the help tab
193
+					esc_html__(
194
+						'Are you sure this is your API username, not your login username? %1$s',
195
+						'event_espresso'
196
+					),
197
+					$this->helpTabLink()
198
+				)
199
+			);
200
+			$this->get_input('api_password')->add_validation_error(
201
+				sprintf(
202
+					// translators: $1$s HTML for a link to the help tab
203
+					esc_html__(
204
+						'Are you sure this is your API password, not your login password? %1$s',
205
+						'event_espresso'
206
+					),
207
+					$this->helpTabLink()
208
+				)
209
+			);
210
+			$this->get_input('api_signature')->add_validation_error(
211
+				sprintf(
212
+					// translators: $1$s HTML for a link to the help tab
213
+					esc_html__('Please verify your API signature is correct. %1$s', 'event_espresso'),
214
+					$this->helpTabLink()
215
+				)
216
+			);
217
+		}
218
+	}
219 219
 }
220 220
 // End of file PayPalSettingsForm.php
221 221
 // Location: ${NAMESPACE}/PayPalSettingsForm.php
Please login to merge, or discard this patch.
core/services/collections/CollectionDetails.php 2 patches
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -193,7 +193,7 @@  discard block
 block discarded – undo
193 193
      */
194 194
     protected function setCollectionInterface($collection_interface)
195 195
     {
196
-        if (! (interface_exists($collection_interface) || class_exists($collection_interface))) {
196
+        if ( ! (interface_exists($collection_interface) || class_exists($collection_interface))) {
197 197
             throw new InvalidInterfaceException($collection_interface);
198 198
         }
199 199
         $this->collection_interface = $collection_interface;
@@ -221,7 +221,7 @@  discard block
 block discarded – undo
221 221
      */
222 222
     protected function setCollectionName($collection_name)
223 223
     {
224
-        if (! is_string($collection_name)) {
224
+        if ( ! is_string($collection_name)) {
225 225
             throw new InvalidDataTypeException('$collection_name', $collection_name, 'string');
226 226
         }
227 227
         $this->collection_name = str_replace(
@@ -281,7 +281,7 @@  discard block
 block discarded – undo
281 281
      */
282 282
     protected function setIdentifierCallback($identifier_callback = 'identifier')
283 283
     {
284
-        if (! is_string($identifier_callback)) {
284
+        if ( ! is_string($identifier_callback)) {
285 285
             throw new InvalidDataTypeException('$identifier_callback', $identifier_callback, 'string');
286 286
         }
287 287
         $this->identifier_callback = $identifier_callback;
@@ -311,7 +311,7 @@  discard block
 block discarded – undo
311 311
         $this->file_mask = ! empty($file_mask) ? $file_mask : '*.php';
312 312
         // we know our default is a string, so if it's not a string now,
313 313
         // then that means the incoming parameter was something else
314
-        if (! is_string($this->file_mask)) {
314
+        if ( ! is_string($this->file_mask)) {
315 315
             throw new InvalidDataTypeException('$file_mask', $this->file_mask, 'string');
316 316
         }
317 317
     }
@@ -336,7 +336,7 @@  discard block
 block discarded – undo
336 336
     public function setCollectionFQCNs($collection_FQCNs)
337 337
     {
338 338
         foreach ((array) $collection_FQCNs as $collection_FQCN) {
339
-            if (! empty($collection_FQCN)) {
339
+            if ( ! empty($collection_FQCN)) {
340 340
                 if (class_exists($collection_FQCN)) {
341 341
                     $this->collection_FQCNs[] = $collection_FQCN;
342 342
                 } else {
@@ -358,7 +358,7 @@  discard block
 block discarded – undo
358 358
      */
359 359
     protected function getFQCNsFromPartialNamespace($partial_FQCN)
360 360
     {
361
-        if (! $this->file_locator instanceof FqcnLocator) {
361
+        if ( ! $this->file_locator instanceof FqcnLocator) {
362 362
             $this->file_locator = new FqcnLocator();
363 363
         }
364 364
         $this->file_locator->locate($partial_FQCN);
@@ -384,8 +384,8 @@  discard block
 block discarded – undo
384 384
     public function setCollectionPaths($collection_paths)
385 385
     {
386 386
         foreach ((array) $collection_paths as $collection_path) {
387
-            if (! empty($collection_path)) {
388
-                if (! is_readable($collection_path)) {
387
+            if ( ! empty($collection_path)) {
388
+                if ( ! is_readable($collection_path)) {
389 389
                     throw new InvalidFilePathException($collection_path);
390 390
                 }
391 391
                 $this->collection_paths[] = $collection_path;
Please login to merge, or discard this patch.
Indentation   +349 added lines, -349 removed lines patch added patch discarded remove patch
@@ -42,353 +42,353 @@
 block discarded – undo
42 42
  */
43 43
 class CollectionDetails implements CollectionDetailsInterface
44 44
 {
45
-    /**
46
-     * if $identifier_type is set to this,
47
-     * then the collection will use each object's spl_object_hash() as it's identifier
48
-     */
49
-    const ID_OBJECT_HASH = 'identifier-uses-spl-object-hash';
50
-
51
-    /**
52
-     * if $identifier_type is set to this,
53
-     * then the collection will use each object's class name as it's identifier
54
-     */
55
-    const ID_CLASS_NAME = 'identifier-uses-object-class-name';
56
-
57
-    /**
58
-     * if $identifier_type is set to this,
59
-     * then the collection will use the return value from a specified callback method on each object
60
-     */
61
-    const ID_CALLBACK_METHOD = 'identifier-uses-callback-method';
62
-
63
-    /**
64
-     * The interface used for controlling what gets added to the collection
65
-     *
66
-     * @var string $collection_interface
67
-     */
68
-    protected $collection_interface = '';
69
-
70
-    /**
71
-     * a unique name used to identify the collection in filter names
72
-     * supplied value is run through sanitize_title_with_dashes(),
73
-     * but then also converts dashes to underscores
74
-     *
75
-     * @var string $collection_name
76
-     */
77
-    protected $collection_name = '';
78
-
79
-    /**
80
-     * what the collection uses for the object identifier.
81
-     * corresponds to one of the class constants above.
82
-     * CollectionDetails::ID_OBJECT_HASH will use spl_object_hash( object ) for the identifier
83
-     * CollectionDetails::ID_CLASS_NAME will use get_class( object ) for the identifier
84
-     * CollectionDetails::ID_CALLBACK_METHOD will use a callback for the identifier
85
-     * defaults to using spl_object_hash() so that multiple objects of the same class can be added
86
-     *
87
-     * @var string $identifier_type
88
-     */
89
-    protected $identifier_type = CollectionDetails::ID_OBJECT_HASH;
90
-
91
-    /**
92
-     * the pattern applied to paths when searching for class files to add to the collection
93
-     * ie: "My_Awesome_*.class.php"
94
-     * defaults to "*.php"
95
-     *
96
-     * @var string $file_mask
97
-     */
98
-    protected $file_mask = '';
99
-
100
-    /**
101
-     * if the $identifier_type above is set to CollectionDetails::ID_CALLBACK_METHOD,
102
-     * then this specifies the method to use on each entity.
103
-     * If the callback method does not exist, then an exception will be thrown
104
-     *
105
-     * @var string $identifier_callback
106
-     */
107
-    protected $identifier_callback = '';
108
-
109
-    /**
110
-     * an array of Fully Qualified Class Names
111
-     *  for example:
112
-     *  $FQCNs = array(
113
-     *      '/Fully/Qualified/ClassNameA'
114
-     *      '/Fully/Qualified/Other/ClassNameB'
115
-     *  );
116
-     *
117
-     * @var array $collection_FQCNs
118
-     */
119
-    protected $collection_FQCNs = array();
120
-
121
-    /**
122
-     * an array of full server paths to folders containing files to be loaded into collection
123
-     *  for example:
124
-     *  $paths = array(
125
-     *      '/full/server/path/to/ClassNameA.ext.php' // for class ClassNameA
126
-     *      '/full/server/path/to/other/ClassNameB.php' // for class ClassNameB
127
-     *  );
128
-     *
129
-     * @var array $collection_paths
130
-     */
131
-    protected $collection_paths = array();
132
-
133
-    /**
134
-     * @var LocatorInterface $file_locator
135
-     */
136
-    protected $file_locator;
137
-
138
-
139
-    /**
140
-     * CollectionDetails constructor.
141
-     *
142
-     * @access public
143
-     * @param string           $collection_name
144
-     * @param string           $collection_interface
145
-     * @param array            $collection_FQCNs
146
-     * @param array            $collection_paths
147
-     * @param string           $file_mask
148
-     * @param string           $identifier_type
149
-     * @param string           $identifier_callback
150
-     * @param LocatorInterface $file_locator
151
-     * @throws CollectionDetailsException
152
-     */
153
-    public function __construct(
154
-        $collection_name,
155
-        $collection_interface,
156
-        array $collection_FQCNs = array(),
157
-        array $collection_paths = array(),
158
-        $file_mask = '',
159
-        $identifier_type = CollectionDetails::ID_OBJECT_HASH,
160
-        $identifier_callback = '',
161
-        LocatorInterface $file_locator = null
162
-    ) {
163
-        try {
164
-            $this->setCollectionName($collection_name);
165
-            $this->setCollectionInterface($collection_interface);
166
-            $this->setCollectionFQCNs($collection_FQCNs);
167
-            $this->setCollectionPaths($collection_paths);
168
-            $this->setFileMasks($file_mask);
169
-            $this->setIdentifierType($identifier_type);
170
-            $this->setIdentifierCallback($identifier_callback);
171
-            $this->file_locator = $file_locator;
172
-        } catch (Exception $exception) {
173
-            throw new CollectionDetailsException($exception);
174
-        }
175
-    }
176
-
177
-
178
-    /**
179
-     * @access public
180
-     * @return mixed
181
-     */
182
-    public function getCollectionInterface()
183
-    {
184
-        return $this->collection_interface;
185
-    }
186
-
187
-
188
-    /**
189
-     * @access protected
190
-     * @param string $collection_interface
191
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
192
-     */
193
-    protected function setCollectionInterface($collection_interface)
194
-    {
195
-        if (! (interface_exists($collection_interface) || class_exists($collection_interface))) {
196
-            throw new InvalidInterfaceException($collection_interface);
197
-        }
198
-        $this->collection_interface = $collection_interface;
199
-    }
200
-
201
-
202
-    /**
203
-     * the collection name will be used for creating dynamic filters
204
-     *
205
-     * @access public
206
-     * @return string
207
-     */
208
-    public function collectionName()
209
-    {
210
-        return $this->collection_name;
211
-    }
212
-
213
-
214
-    /**
215
-     * sanitizes collection name and converts spaces and dashes to underscores
216
-     *
217
-     * @access protected
218
-     * @param string $collection_name
219
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
220
-     */
221
-    protected function setCollectionName($collection_name)
222
-    {
223
-        if (! is_string($collection_name)) {
224
-            throw new InvalidDataTypeException('$collection_name', $collection_name, 'string');
225
-        }
226
-        $this->collection_name = str_replace(
227
-            '-',
228
-            '_',
229
-            sanitize_title_with_dashes($collection_name, '', 'save')
230
-        );
231
-    }
232
-
233
-
234
-    /**
235
-     * @access public
236
-     * @return string
237
-     */
238
-    public function identifierType()
239
-    {
240
-        return $this->identifier_type;
241
-    }
242
-
243
-
244
-    /**
245
-     * @access protected
246
-     * @param string $identifier_type
247
-     * @throws InvalidIdentifierException
248
-     */
249
-    protected function setIdentifierType($identifier_type)
250
-    {
251
-        if (
252
-            ! ($identifier_type === CollectionDetails::ID_CLASS_NAME
253
-               || $identifier_type === CollectionDetails::ID_OBJECT_HASH
254
-               || $identifier_type === CollectionDetails::ID_CALLBACK_METHOD
255
-            )
256
-        ) {
257
-            throw new InvalidIdentifierException(
258
-                $identifier_type,
259
-                'CollectionDetails::ID_CLASS_NAME or CollectionDetails::ID_OBJECT_HASH or CollectionDetails::ID_CALLBACK_METHOD'
260
-            );
261
-        }
262
-        $this->identifier_type = $identifier_type;
263
-    }
264
-
265
-
266
-    /**
267
-     * @access public
268
-     * @return string
269
-     */
270
-    public function identifierCallback()
271
-    {
272
-        return $this->identifier_callback;
273
-    }
274
-
275
-
276
-    /**
277
-     * @access protected
278
-     * @param string $identifier_callback
279
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
280
-     */
281
-    protected function setIdentifierCallback($identifier_callback = 'identifier')
282
-    {
283
-        if (! is_string($identifier_callback)) {
284
-            throw new InvalidDataTypeException('$identifier_callback', $identifier_callback, 'string');
285
-        }
286
-        $this->identifier_callback = $identifier_callback;
287
-    }
288
-
289
-
290
-    /**
291
-     * @access public
292
-     * @return string
293
-     */
294
-    public function getFileMask()
295
-    {
296
-        return $this->file_mask;
297
-    }
298
-
299
-
300
-    /**
301
-     * sets the file mask which is then used to filter what files get loaded
302
-     * when searching for classes to add to the collection. Defaults to '*.php'
303
-     *
304
-     * @access protected
305
-     * @param string $file_mask
306
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
307
-     */
308
-    protected function setFileMasks($file_mask)
309
-    {
310
-        $this->file_mask = ! empty($file_mask) ? $file_mask : '*.php';
311
-        // we know our default is a string, so if it's not a string now,
312
-        // then that means the incoming parameter was something else
313
-        if (! is_string($this->file_mask)) {
314
-            throw new InvalidDataTypeException('$file_mask', $this->file_mask, 'string');
315
-        }
316
-    }
317
-
318
-
319
-    /**
320
-     * @access public
321
-     * @return array
322
-     */
323
-    public function getCollectionFQCNs()
324
-    {
325
-        return $this->collection_FQCNs;
326
-    }
327
-
328
-
329
-    /**
330
-     * @access public
331
-     * @param string|array $collection_FQCNs
332
-     * @throws \EventEspresso\core\exceptions\InvalidClassException
333
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
334
-     */
335
-    public function setCollectionFQCNs($collection_FQCNs)
336
-    {
337
-        foreach ((array) $collection_FQCNs as $collection_FQCN) {
338
-            if (! empty($collection_FQCN)) {
339
-                if (class_exists($collection_FQCN)) {
340
-                    $this->collection_FQCNs[] = $collection_FQCN;
341
-                } else {
342
-                    foreach ($this->getFQCNsFromPartialNamespace($collection_FQCN) as $FQCN) {
343
-                        $this->collection_FQCNs[] = $FQCN;
344
-                    }
345
-                }
346
-            }
347
-        }
348
-    }
349
-
350
-
351
-    /**
352
-     * @access protected
353
-     * @param  string $partial_FQCN
354
-     * @return array
355
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
356
-     * @throws \EventEspresso\core\exceptions\InvalidClassException
357
-     */
358
-    protected function getFQCNsFromPartialNamespace($partial_FQCN)
359
-    {
360
-        if (! $this->file_locator instanceof FqcnLocator) {
361
-            $this->file_locator = new FqcnLocator();
362
-        }
363
-        $this->file_locator->locate($partial_FQCN);
364
-        return $this->file_locator->getFQCNs();
365
-    }
366
-
367
-
368
-    /**
369
-     * @access public
370
-     * @return array
371
-     */
372
-    public function getCollectionPaths()
373
-    {
374
-        return $this->collection_paths;
375
-    }
376
-
377
-
378
-    /**
379
-     * @access public
380
-     * @param string|array $collection_paths
381
-     * @throws \EventEspresso\core\exceptions\InvalidFilePathException
382
-     */
383
-    public function setCollectionPaths($collection_paths)
384
-    {
385
-        foreach ((array) $collection_paths as $collection_path) {
386
-            if (! empty($collection_path)) {
387
-                if (! is_readable($collection_path)) {
388
-                    throw new InvalidFilePathException($collection_path);
389
-                }
390
-                $this->collection_paths[] = $collection_path;
391
-            }
392
-        }
393
-    }
45
+	/**
46
+	 * if $identifier_type is set to this,
47
+	 * then the collection will use each object's spl_object_hash() as it's identifier
48
+	 */
49
+	const ID_OBJECT_HASH = 'identifier-uses-spl-object-hash';
50
+
51
+	/**
52
+	 * if $identifier_type is set to this,
53
+	 * then the collection will use each object's class name as it's identifier
54
+	 */
55
+	const ID_CLASS_NAME = 'identifier-uses-object-class-name';
56
+
57
+	/**
58
+	 * if $identifier_type is set to this,
59
+	 * then the collection will use the return value from a specified callback method on each object
60
+	 */
61
+	const ID_CALLBACK_METHOD = 'identifier-uses-callback-method';
62
+
63
+	/**
64
+	 * The interface used for controlling what gets added to the collection
65
+	 *
66
+	 * @var string $collection_interface
67
+	 */
68
+	protected $collection_interface = '';
69
+
70
+	/**
71
+	 * a unique name used to identify the collection in filter names
72
+	 * supplied value is run through sanitize_title_with_dashes(),
73
+	 * but then also converts dashes to underscores
74
+	 *
75
+	 * @var string $collection_name
76
+	 */
77
+	protected $collection_name = '';
78
+
79
+	/**
80
+	 * what the collection uses for the object identifier.
81
+	 * corresponds to one of the class constants above.
82
+	 * CollectionDetails::ID_OBJECT_HASH will use spl_object_hash( object ) for the identifier
83
+	 * CollectionDetails::ID_CLASS_NAME will use get_class( object ) for the identifier
84
+	 * CollectionDetails::ID_CALLBACK_METHOD will use a callback for the identifier
85
+	 * defaults to using spl_object_hash() so that multiple objects of the same class can be added
86
+	 *
87
+	 * @var string $identifier_type
88
+	 */
89
+	protected $identifier_type = CollectionDetails::ID_OBJECT_HASH;
90
+
91
+	/**
92
+	 * the pattern applied to paths when searching for class files to add to the collection
93
+	 * ie: "My_Awesome_*.class.php"
94
+	 * defaults to "*.php"
95
+	 *
96
+	 * @var string $file_mask
97
+	 */
98
+	protected $file_mask = '';
99
+
100
+	/**
101
+	 * if the $identifier_type above is set to CollectionDetails::ID_CALLBACK_METHOD,
102
+	 * then this specifies the method to use on each entity.
103
+	 * If the callback method does not exist, then an exception will be thrown
104
+	 *
105
+	 * @var string $identifier_callback
106
+	 */
107
+	protected $identifier_callback = '';
108
+
109
+	/**
110
+	 * an array of Fully Qualified Class Names
111
+	 *  for example:
112
+	 *  $FQCNs = array(
113
+	 *      '/Fully/Qualified/ClassNameA'
114
+	 *      '/Fully/Qualified/Other/ClassNameB'
115
+	 *  );
116
+	 *
117
+	 * @var array $collection_FQCNs
118
+	 */
119
+	protected $collection_FQCNs = array();
120
+
121
+	/**
122
+	 * an array of full server paths to folders containing files to be loaded into collection
123
+	 *  for example:
124
+	 *  $paths = array(
125
+	 *      '/full/server/path/to/ClassNameA.ext.php' // for class ClassNameA
126
+	 *      '/full/server/path/to/other/ClassNameB.php' // for class ClassNameB
127
+	 *  );
128
+	 *
129
+	 * @var array $collection_paths
130
+	 */
131
+	protected $collection_paths = array();
132
+
133
+	/**
134
+	 * @var LocatorInterface $file_locator
135
+	 */
136
+	protected $file_locator;
137
+
138
+
139
+	/**
140
+	 * CollectionDetails constructor.
141
+	 *
142
+	 * @access public
143
+	 * @param string           $collection_name
144
+	 * @param string           $collection_interface
145
+	 * @param array            $collection_FQCNs
146
+	 * @param array            $collection_paths
147
+	 * @param string           $file_mask
148
+	 * @param string           $identifier_type
149
+	 * @param string           $identifier_callback
150
+	 * @param LocatorInterface $file_locator
151
+	 * @throws CollectionDetailsException
152
+	 */
153
+	public function __construct(
154
+		$collection_name,
155
+		$collection_interface,
156
+		array $collection_FQCNs = array(),
157
+		array $collection_paths = array(),
158
+		$file_mask = '',
159
+		$identifier_type = CollectionDetails::ID_OBJECT_HASH,
160
+		$identifier_callback = '',
161
+		LocatorInterface $file_locator = null
162
+	) {
163
+		try {
164
+			$this->setCollectionName($collection_name);
165
+			$this->setCollectionInterface($collection_interface);
166
+			$this->setCollectionFQCNs($collection_FQCNs);
167
+			$this->setCollectionPaths($collection_paths);
168
+			$this->setFileMasks($file_mask);
169
+			$this->setIdentifierType($identifier_type);
170
+			$this->setIdentifierCallback($identifier_callback);
171
+			$this->file_locator = $file_locator;
172
+		} catch (Exception $exception) {
173
+			throw new CollectionDetailsException($exception);
174
+		}
175
+	}
176
+
177
+
178
+	/**
179
+	 * @access public
180
+	 * @return mixed
181
+	 */
182
+	public function getCollectionInterface()
183
+	{
184
+		return $this->collection_interface;
185
+	}
186
+
187
+
188
+	/**
189
+	 * @access protected
190
+	 * @param string $collection_interface
191
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
192
+	 */
193
+	protected function setCollectionInterface($collection_interface)
194
+	{
195
+		if (! (interface_exists($collection_interface) || class_exists($collection_interface))) {
196
+			throw new InvalidInterfaceException($collection_interface);
197
+		}
198
+		$this->collection_interface = $collection_interface;
199
+	}
200
+
201
+
202
+	/**
203
+	 * the collection name will be used for creating dynamic filters
204
+	 *
205
+	 * @access public
206
+	 * @return string
207
+	 */
208
+	public function collectionName()
209
+	{
210
+		return $this->collection_name;
211
+	}
212
+
213
+
214
+	/**
215
+	 * sanitizes collection name and converts spaces and dashes to underscores
216
+	 *
217
+	 * @access protected
218
+	 * @param string $collection_name
219
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
220
+	 */
221
+	protected function setCollectionName($collection_name)
222
+	{
223
+		if (! is_string($collection_name)) {
224
+			throw new InvalidDataTypeException('$collection_name', $collection_name, 'string');
225
+		}
226
+		$this->collection_name = str_replace(
227
+			'-',
228
+			'_',
229
+			sanitize_title_with_dashes($collection_name, '', 'save')
230
+		);
231
+	}
232
+
233
+
234
+	/**
235
+	 * @access public
236
+	 * @return string
237
+	 */
238
+	public function identifierType()
239
+	{
240
+		return $this->identifier_type;
241
+	}
242
+
243
+
244
+	/**
245
+	 * @access protected
246
+	 * @param string $identifier_type
247
+	 * @throws InvalidIdentifierException
248
+	 */
249
+	protected function setIdentifierType($identifier_type)
250
+	{
251
+		if (
252
+			! ($identifier_type === CollectionDetails::ID_CLASS_NAME
253
+			   || $identifier_type === CollectionDetails::ID_OBJECT_HASH
254
+			   || $identifier_type === CollectionDetails::ID_CALLBACK_METHOD
255
+			)
256
+		) {
257
+			throw new InvalidIdentifierException(
258
+				$identifier_type,
259
+				'CollectionDetails::ID_CLASS_NAME or CollectionDetails::ID_OBJECT_HASH or CollectionDetails::ID_CALLBACK_METHOD'
260
+			);
261
+		}
262
+		$this->identifier_type = $identifier_type;
263
+	}
264
+
265
+
266
+	/**
267
+	 * @access public
268
+	 * @return string
269
+	 */
270
+	public function identifierCallback()
271
+	{
272
+		return $this->identifier_callback;
273
+	}
274
+
275
+
276
+	/**
277
+	 * @access protected
278
+	 * @param string $identifier_callback
279
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
280
+	 */
281
+	protected function setIdentifierCallback($identifier_callback = 'identifier')
282
+	{
283
+		if (! is_string($identifier_callback)) {
284
+			throw new InvalidDataTypeException('$identifier_callback', $identifier_callback, 'string');
285
+		}
286
+		$this->identifier_callback = $identifier_callback;
287
+	}
288
+
289
+
290
+	/**
291
+	 * @access public
292
+	 * @return string
293
+	 */
294
+	public function getFileMask()
295
+	{
296
+		return $this->file_mask;
297
+	}
298
+
299
+
300
+	/**
301
+	 * sets the file mask which is then used to filter what files get loaded
302
+	 * when searching for classes to add to the collection. Defaults to '*.php'
303
+	 *
304
+	 * @access protected
305
+	 * @param string $file_mask
306
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
307
+	 */
308
+	protected function setFileMasks($file_mask)
309
+	{
310
+		$this->file_mask = ! empty($file_mask) ? $file_mask : '*.php';
311
+		// we know our default is a string, so if it's not a string now,
312
+		// then that means the incoming parameter was something else
313
+		if (! is_string($this->file_mask)) {
314
+			throw new InvalidDataTypeException('$file_mask', $this->file_mask, 'string');
315
+		}
316
+	}
317
+
318
+
319
+	/**
320
+	 * @access public
321
+	 * @return array
322
+	 */
323
+	public function getCollectionFQCNs()
324
+	{
325
+		return $this->collection_FQCNs;
326
+	}
327
+
328
+
329
+	/**
330
+	 * @access public
331
+	 * @param string|array $collection_FQCNs
332
+	 * @throws \EventEspresso\core\exceptions\InvalidClassException
333
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
334
+	 */
335
+	public function setCollectionFQCNs($collection_FQCNs)
336
+	{
337
+		foreach ((array) $collection_FQCNs as $collection_FQCN) {
338
+			if (! empty($collection_FQCN)) {
339
+				if (class_exists($collection_FQCN)) {
340
+					$this->collection_FQCNs[] = $collection_FQCN;
341
+				} else {
342
+					foreach ($this->getFQCNsFromPartialNamespace($collection_FQCN) as $FQCN) {
343
+						$this->collection_FQCNs[] = $FQCN;
344
+					}
345
+				}
346
+			}
347
+		}
348
+	}
349
+
350
+
351
+	/**
352
+	 * @access protected
353
+	 * @param  string $partial_FQCN
354
+	 * @return array
355
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
356
+	 * @throws \EventEspresso\core\exceptions\InvalidClassException
357
+	 */
358
+	protected function getFQCNsFromPartialNamespace($partial_FQCN)
359
+	{
360
+		if (! $this->file_locator instanceof FqcnLocator) {
361
+			$this->file_locator = new FqcnLocator();
362
+		}
363
+		$this->file_locator->locate($partial_FQCN);
364
+		return $this->file_locator->getFQCNs();
365
+	}
366
+
367
+
368
+	/**
369
+	 * @access public
370
+	 * @return array
371
+	 */
372
+	public function getCollectionPaths()
373
+	{
374
+		return $this->collection_paths;
375
+	}
376
+
377
+
378
+	/**
379
+	 * @access public
380
+	 * @param string|array $collection_paths
381
+	 * @throws \EventEspresso\core\exceptions\InvalidFilePathException
382
+	 */
383
+	public function setCollectionPaths($collection_paths)
384
+	{
385
+		foreach ((array) $collection_paths as $collection_path) {
386
+			if (! empty($collection_path)) {
387
+				if (! is_readable($collection_path)) {
388
+					throw new InvalidFilePathException($collection_path);
389
+				}
390
+				$this->collection_paths[] = $collection_path;
391
+			}
392
+		}
393
+	}
394 394
 }
Please login to merge, or discard this patch.
core/services/container/DependencyInjector.php 2 patches
Spacing   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -71,12 +71,12 @@  discard block
 block discarded – undo
71 71
     public function getReflectionClass($class_name)
72 72
     {
73 73
         if (
74
-            ! isset($this->reflectors[ $class_name ])
75
-            || ! $this->reflectors[ $class_name ] instanceof ReflectionClass
74
+            ! isset($this->reflectors[$class_name])
75
+            || ! $this->reflectors[$class_name] instanceof ReflectionClass
76 76
         ) {
77
-            $this->reflectors[ $class_name ] = new ReflectionClass($class_name);
77
+            $this->reflectors[$class_name] = new ReflectionClass($class_name);
78 78
         }
79
-        return $this->reflectors[ $class_name ];
79
+        return $this->reflectors[$class_name];
80 80
     }
81 81
 
82 82
 
@@ -91,12 +91,12 @@  discard block
 block discarded – undo
91 91
     protected function getConstructor(ReflectionClass $reflector)
92 92
     {
93 93
         if (
94
-            ! isset($this->constructors[ $reflector->getName() ])
95
-            || ! $this->constructors[ $reflector->getName() ] instanceof ReflectionMethod
94
+            ! isset($this->constructors[$reflector->getName()])
95
+            || ! $this->constructors[$reflector->getName()] instanceof ReflectionMethod
96 96
         ) {
97
-            $this->constructors[ $reflector->getName() ] = $reflector->getConstructor();
97
+            $this->constructors[$reflector->getName()] = $reflector->getConstructor();
98 98
         }
99
-        return $this->constructors[ $reflector->getName() ];
99
+        return $this->constructors[$reflector->getName()];
100 100
     }
101 101
 
102 102
 
@@ -110,10 +110,10 @@  discard block
 block discarded – undo
110 110
      */
111 111
     protected function getParameters(ReflectionMethod $constructor)
112 112
     {
113
-        if (! isset($this->parameters[ $constructor->class ])) {
114
-            $this->parameters[ $constructor->class ] = $constructor->getParameters();
113
+        if ( ! isset($this->parameters[$constructor->class])) {
114
+            $this->parameters[$constructor->class] = $constructor->getParameters();
115 115
         }
116
-        return $this->parameters[ $constructor->class ];
116
+        return $this->parameters[$constructor->class];
117 117
     }
118 118
 
119 119
 
@@ -148,7 +148,7 @@  discard block
 block discarded – undo
148 148
         // let's examine the constructor
149 149
         $constructor = $this->getConstructor($reflector);
150 150
         // whu? huh? nothing?
151
-        if (! $constructor) {
151
+        if ( ! $constructor) {
152 152
             return $arguments;
153 153
         }
154 154
         // get constructor parameters
@@ -161,7 +161,7 @@  discard block
 block discarded – undo
161 161
         $argument_keys = array_keys($arguments);
162 162
         // now loop thru all of the constructors expected parameters
163 163
         foreach ($params as $index => $param) {
164
-            if (! $param instanceof ReflectionParameter) {
164
+            if ( ! $param instanceof ReflectionParameter) {
165 165
                 continue;
166 166
             }
167 167
             // is this a dependency for a specific class ?
@@ -169,41 +169,41 @@  discard block
 block discarded – undo
169 169
             $param_name = $param->getName() ? $param->getName() : '';
170 170
             if (
171 171
 // param is not a class but is specified in the list of ingredients for this Recipe
172
-                is_string($param_name) && isset($ingredients[ $param_name ])
172
+                is_string($param_name) && isset($ingredients[$param_name])
173 173
             ) {
174 174
                 // attempt to inject the dependency
175
-                $resolved_parameters[ $index ] = $ingredients[ $param_name ];
175
+                $resolved_parameters[$index] = $ingredients[$param_name];
176 176
             } elseif (
177 177
 // param is specified in the list of ingredients for this Recipe
178
-                isset($ingredients[ $param_class ])
178
+                isset($ingredients[$param_class])
179 179
             ) { // attempt to inject the dependency
180
-                $resolved_parameters[ $index ] = $this->injectDependency($reflector, $ingredients[ $param_class ]);
180
+                $resolved_parameters[$index] = $this->injectDependency($reflector, $ingredients[$param_class]);
181 181
             } elseif (
182 182
 // param is not even a class
183 183
                 empty($param_class)
184 184
                 // and something already exists in the incoming arguments for this param
185
-                && isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
185
+                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
186 186
             ) {
187 187
                 // add parameter from incoming arguments
188
-                $resolved_parameters[ $index ] = $arguments[ $argument_keys[ $index ] ];
188
+                $resolved_parameters[$index] = $arguments[$argument_keys[$index]];
189 189
             } elseif (
190 190
 // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
191 191
                 ! empty($param_class)
192
-                && isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
193
-                && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
192
+                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
193
+                && $arguments[$argument_keys[$index]] instanceof $param_class
194 194
             ) {
195 195
                 // add parameter from incoming arguments
196
-                $resolved_parameters[ $index ] = $arguments[ $argument_keys[ $index ] ];
196
+                $resolved_parameters[$index] = $arguments[$argument_keys[$index]];
197 197
             } elseif (
198 198
 // parameter is type hinted as a class, and should be injected
199 199
                 ! empty($param_class)
200 200
             ) {
201 201
                 // attempt to inject the dependency
202
-                $resolved_parameters[ $index ] = $this->injectDependency($reflector, $param_class);
202
+                $resolved_parameters[$index] = $this->injectDependency($reflector, $param_class);
203 203
             } elseif ($param->isOptional()) {
204
-                $resolved_parameters[ $index ] = $param->getDefaultValue();
204
+                $resolved_parameters[$index] = $param->getDefaultValue();
205 205
             } else {
206
-                $resolved_parameters[ $index ] = null;
206
+                $resolved_parameters[$index] = null;
207 207
             }
208 208
         }
209 209
         return $resolved_parameters;
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
     private function injectDependency(ReflectionClass $reflector, $param_class)
220 220
     {
221 221
         $dependency = $this->coffee_pot->brew($param_class);
222
-        if (! $dependency instanceof $param_class) {
222
+        if ( ! $dependency instanceof $param_class) {
223 223
             throw new UnexpectedValueException(
224 224
                 sprintf(
225 225
                     esc_html__(
Please login to merge, or discard this patch.
Indentation   +207 added lines, -207 removed lines patch added patch discarded remove patch
@@ -20,216 +20,216 @@
 block discarded – undo
20 20
  */
21 21
 class DependencyInjector implements InjectorInterface
22 22
 {
23
-    /**
24
-     * @var CoffeePotInterface $coffee_pot
25
-     */
26
-    private $coffee_pot;
27
-
28
-    /**
29
-     * @var EEH_Array $array_helper
30
-     */
31
-    private $array_helper;
32
-
33
-    /**
34
-     * @var ReflectionClass[] $reflectors
35
-     */
36
-    private $reflectors;
37
-
38
-    /**
39
-     * @var ReflectionMethod[] $constructors
40
-     */
41
-    private $constructors;
42
-
43
-    /**
44
-     * @var ReflectionParameter[] $parameters
45
-     */
46
-    private $parameters;
47
-
48
-
49
-    /**
50
-     * DependencyInjector constructor
51
-     *
52
-     * @param CoffeePotInterface $coffee_pot
53
-     * @param EEH_Array          $array_helper
54
-     */
55
-    public function __construct(CoffeePotInterface $coffee_pot, EEH_Array $array_helper)
56
-    {
57
-        $this->coffee_pot = $coffee_pot;
58
-        $this->array_helper = $array_helper;
59
-    }
60
-
61
-
62
-    /**
63
-     * getReflectionClass
64
-     * checks if a ReflectionClass object has already been generated for a class
65
-     * and returns that instead of creating a new one
66
-     *
67
-     * @param string $class_name
68
-     * @return ReflectionClass
69
-     */
70
-    public function getReflectionClass($class_name)
71
-    {
72
-        if (
73
-            ! isset($this->reflectors[ $class_name ])
74
-            || ! $this->reflectors[ $class_name ] instanceof ReflectionClass
75
-        ) {
76
-            $this->reflectors[ $class_name ] = new ReflectionClass($class_name);
77
-        }
78
-        return $this->reflectors[ $class_name ];
79
-    }
80
-
81
-
82
-    /**
83
-     * getConstructor
84
-     * checks if a ReflectionMethod object has already been generated for the class constructor
85
-     * and returns that instead of creating a new one
86
-     *
87
-     * @param ReflectionClass $reflector
88
-     * @return ReflectionMethod
89
-     */
90
-    protected function getConstructor(ReflectionClass $reflector)
91
-    {
92
-        if (
93
-            ! isset($this->constructors[ $reflector->getName() ])
94
-            || ! $this->constructors[ $reflector->getName() ] instanceof ReflectionMethod
95
-        ) {
96
-            $this->constructors[ $reflector->getName() ] = $reflector->getConstructor();
97
-        }
98
-        return $this->constructors[ $reflector->getName() ];
99
-    }
100
-
101
-
102
-    /**
103
-     * getParameters
104
-     * checks if an array of ReflectionParameter objects has already been generated for the class constructor
105
-     * and returns that instead of creating a new one
106
-     *
107
-     * @param ReflectionMethod $constructor
108
-     * @return ReflectionParameter[]
109
-     */
110
-    protected function getParameters(ReflectionMethod $constructor)
111
-    {
112
-        if (! isset($this->parameters[ $constructor->class ])) {
113
-            $this->parameters[ $constructor->class ] = $constructor->getParameters();
114
-        }
115
-        return $this->parameters[ $constructor->class ];
116
-    }
117
-
118
-
119
-    /**
120
-     * resolveDependencies
121
-     * examines the constructor for the requested class to determine
122
-     * if any dependencies exist, and if they can be injected.
123
-     * If so, then those classes will be added to the array of arguments passed to the constructor
124
-     * PLZ NOTE: this is achieved by type hinting the constructor params
125
-     * For example:
126
-     *        if attempting to load a class "Foo" with the following constructor:
127
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
128
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
129
-     *        but only IF they are NOT already present in the incoming arguments array,
130
-     *        and the correct classes can be loaded
131
-     *
132
-     * @param RecipeInterface $recipe
133
-     * @param ReflectionClass $reflector
134
-     * @param array           $arguments
135
-     * @return array
136
-     * @throws UnexpectedValueException
137
-     */
138
-    public function resolveDependencies(RecipeInterface $recipe, ReflectionClass $reflector, $arguments = array())
139
-    {
140
-        // if arguments array is numerically and sequentially indexed, then we want it to remain as is,
141
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
142
-        $arguments = $this->array_helper->is_array_numerically_and_sequentially_indexed($arguments)
143
-            ? $arguments
144
-            : array($arguments);
145
-        $resolved_parameters = array();
146
-        // let's examine the constructor
147
-        // let's examine the constructor
148
-        $constructor = $this->getConstructor($reflector);
149
-        // whu? huh? nothing?
150
-        if (! $constructor) {
151
-            return $arguments;
152
-        }
153
-        // get constructor parameters
154
-        $params = $this->getParameters($constructor);
155
-        if (empty($params)) {
156
-            return $resolved_parameters;
157
-        }
158
-        $ingredients = $recipe->ingredients();
159
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
160
-        $argument_keys = array_keys($arguments);
161
-        // now loop thru all of the constructors expected parameters
162
-        foreach ($params as $index => $param) {
163
-            if (! $param instanceof ReflectionParameter) {
164
-                continue;
165
-            }
166
-            // is this a dependency for a specific class ?
167
-            $param_class = $param->getClass() ? $param->getClass()->name : '';
168
-            $param_name = $param->getName() ? $param->getName() : '';
169
-            if (
23
+	/**
24
+	 * @var CoffeePotInterface $coffee_pot
25
+	 */
26
+	private $coffee_pot;
27
+
28
+	/**
29
+	 * @var EEH_Array $array_helper
30
+	 */
31
+	private $array_helper;
32
+
33
+	/**
34
+	 * @var ReflectionClass[] $reflectors
35
+	 */
36
+	private $reflectors;
37
+
38
+	/**
39
+	 * @var ReflectionMethod[] $constructors
40
+	 */
41
+	private $constructors;
42
+
43
+	/**
44
+	 * @var ReflectionParameter[] $parameters
45
+	 */
46
+	private $parameters;
47
+
48
+
49
+	/**
50
+	 * DependencyInjector constructor
51
+	 *
52
+	 * @param CoffeePotInterface $coffee_pot
53
+	 * @param EEH_Array          $array_helper
54
+	 */
55
+	public function __construct(CoffeePotInterface $coffee_pot, EEH_Array $array_helper)
56
+	{
57
+		$this->coffee_pot = $coffee_pot;
58
+		$this->array_helper = $array_helper;
59
+	}
60
+
61
+
62
+	/**
63
+	 * getReflectionClass
64
+	 * checks if a ReflectionClass object has already been generated for a class
65
+	 * and returns that instead of creating a new one
66
+	 *
67
+	 * @param string $class_name
68
+	 * @return ReflectionClass
69
+	 */
70
+	public function getReflectionClass($class_name)
71
+	{
72
+		if (
73
+			! isset($this->reflectors[ $class_name ])
74
+			|| ! $this->reflectors[ $class_name ] instanceof ReflectionClass
75
+		) {
76
+			$this->reflectors[ $class_name ] = new ReflectionClass($class_name);
77
+		}
78
+		return $this->reflectors[ $class_name ];
79
+	}
80
+
81
+
82
+	/**
83
+	 * getConstructor
84
+	 * checks if a ReflectionMethod object has already been generated for the class constructor
85
+	 * and returns that instead of creating a new one
86
+	 *
87
+	 * @param ReflectionClass $reflector
88
+	 * @return ReflectionMethod
89
+	 */
90
+	protected function getConstructor(ReflectionClass $reflector)
91
+	{
92
+		if (
93
+			! isset($this->constructors[ $reflector->getName() ])
94
+			|| ! $this->constructors[ $reflector->getName() ] instanceof ReflectionMethod
95
+		) {
96
+			$this->constructors[ $reflector->getName() ] = $reflector->getConstructor();
97
+		}
98
+		return $this->constructors[ $reflector->getName() ];
99
+	}
100
+
101
+
102
+	/**
103
+	 * getParameters
104
+	 * checks if an array of ReflectionParameter objects has already been generated for the class constructor
105
+	 * and returns that instead of creating a new one
106
+	 *
107
+	 * @param ReflectionMethod $constructor
108
+	 * @return ReflectionParameter[]
109
+	 */
110
+	protected function getParameters(ReflectionMethod $constructor)
111
+	{
112
+		if (! isset($this->parameters[ $constructor->class ])) {
113
+			$this->parameters[ $constructor->class ] = $constructor->getParameters();
114
+		}
115
+		return $this->parameters[ $constructor->class ];
116
+	}
117
+
118
+
119
+	/**
120
+	 * resolveDependencies
121
+	 * examines the constructor for the requested class to determine
122
+	 * if any dependencies exist, and if they can be injected.
123
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
124
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
125
+	 * For example:
126
+	 *        if attempting to load a class "Foo" with the following constructor:
127
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
128
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
129
+	 *        but only IF they are NOT already present in the incoming arguments array,
130
+	 *        and the correct classes can be loaded
131
+	 *
132
+	 * @param RecipeInterface $recipe
133
+	 * @param ReflectionClass $reflector
134
+	 * @param array           $arguments
135
+	 * @return array
136
+	 * @throws UnexpectedValueException
137
+	 */
138
+	public function resolveDependencies(RecipeInterface $recipe, ReflectionClass $reflector, $arguments = array())
139
+	{
140
+		// if arguments array is numerically and sequentially indexed, then we want it to remain as is,
141
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
142
+		$arguments = $this->array_helper->is_array_numerically_and_sequentially_indexed($arguments)
143
+			? $arguments
144
+			: array($arguments);
145
+		$resolved_parameters = array();
146
+		// let's examine the constructor
147
+		// let's examine the constructor
148
+		$constructor = $this->getConstructor($reflector);
149
+		// whu? huh? nothing?
150
+		if (! $constructor) {
151
+			return $arguments;
152
+		}
153
+		// get constructor parameters
154
+		$params = $this->getParameters($constructor);
155
+		if (empty($params)) {
156
+			return $resolved_parameters;
157
+		}
158
+		$ingredients = $recipe->ingredients();
159
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
160
+		$argument_keys = array_keys($arguments);
161
+		// now loop thru all of the constructors expected parameters
162
+		foreach ($params as $index => $param) {
163
+			if (! $param instanceof ReflectionParameter) {
164
+				continue;
165
+			}
166
+			// is this a dependency for a specific class ?
167
+			$param_class = $param->getClass() ? $param->getClass()->name : '';
168
+			$param_name = $param->getName() ? $param->getName() : '';
169
+			if (
170 170
 // param is not a class but is specified in the list of ingredients for this Recipe
171
-                is_string($param_name) && isset($ingredients[ $param_name ])
172
-            ) {
173
-                // attempt to inject the dependency
174
-                $resolved_parameters[ $index ] = $ingredients[ $param_name ];
175
-            } elseif (
171
+				is_string($param_name) && isset($ingredients[ $param_name ])
172
+			) {
173
+				// attempt to inject the dependency
174
+				$resolved_parameters[ $index ] = $ingredients[ $param_name ];
175
+			} elseif (
176 176
 // param is specified in the list of ingredients for this Recipe
177
-                isset($ingredients[ $param_class ])
178
-            ) { // attempt to inject the dependency
179
-                $resolved_parameters[ $index ] = $this->injectDependency($reflector, $ingredients[ $param_class ]);
180
-            } elseif (
177
+				isset($ingredients[ $param_class ])
178
+			) { // attempt to inject the dependency
179
+				$resolved_parameters[ $index ] = $this->injectDependency($reflector, $ingredients[ $param_class ]);
180
+			} elseif (
181 181
 // param is not even a class
182
-                empty($param_class)
183
-                // and something already exists in the incoming arguments for this param
184
-                && isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
185
-            ) {
186
-                // add parameter from incoming arguments
187
-                $resolved_parameters[ $index ] = $arguments[ $argument_keys[ $index ] ];
188
-            } elseif (
182
+				empty($param_class)
183
+				// and something already exists in the incoming arguments for this param
184
+				&& isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
185
+			) {
186
+				// add parameter from incoming arguments
187
+				$resolved_parameters[ $index ] = $arguments[ $argument_keys[ $index ] ];
188
+			} elseif (
189 189
 // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
190
-                ! empty($param_class)
191
-                && isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
192
-                && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
193
-            ) {
194
-                // add parameter from incoming arguments
195
-                $resolved_parameters[ $index ] = $arguments[ $argument_keys[ $index ] ];
196
-            } elseif (
190
+				! empty($param_class)
191
+				&& isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
192
+				&& $arguments[ $argument_keys[ $index ] ] instanceof $param_class
193
+			) {
194
+				// add parameter from incoming arguments
195
+				$resolved_parameters[ $index ] = $arguments[ $argument_keys[ $index ] ];
196
+			} elseif (
197 197
 // parameter is type hinted as a class, and should be injected
198
-                ! empty($param_class)
199
-            ) {
200
-                // attempt to inject the dependency
201
-                $resolved_parameters[ $index ] = $this->injectDependency($reflector, $param_class);
202
-            } elseif ($param->isOptional()) {
203
-                $resolved_parameters[ $index ] = $param->getDefaultValue();
204
-            } else {
205
-                $resolved_parameters[ $index ] = null;
206
-            }
207
-        }
208
-        return $resolved_parameters;
209
-    }
210
-
211
-
212
-    /**
213
-     * @param ReflectionClass $reflector
214
-     * @param string          $param_class
215
-     * @return mixed
216
-     * @throws UnexpectedValueException
217
-     */
218
-    private function injectDependency(ReflectionClass $reflector, $param_class)
219
-    {
220
-        $dependency = $this->coffee_pot->brew($param_class);
221
-        if (! $dependency instanceof $param_class) {
222
-            throw new UnexpectedValueException(
223
-                sprintf(
224
-                    esc_html__(
225
-                        'Could not resolve dependency for "%1$s" for the "%2$s" class constructor.',
226
-                        'event_espresso'
227
-                    ),
228
-                    $param_class,
229
-                    $reflector->getName()
230
-                )
231
-            );
232
-        }
233
-        return $dependency;
234
-    }
198
+				! empty($param_class)
199
+			) {
200
+				// attempt to inject the dependency
201
+				$resolved_parameters[ $index ] = $this->injectDependency($reflector, $param_class);
202
+			} elseif ($param->isOptional()) {
203
+				$resolved_parameters[ $index ] = $param->getDefaultValue();
204
+			} else {
205
+				$resolved_parameters[ $index ] = null;
206
+			}
207
+		}
208
+		return $resolved_parameters;
209
+	}
210
+
211
+
212
+	/**
213
+	 * @param ReflectionClass $reflector
214
+	 * @param string          $param_class
215
+	 * @return mixed
216
+	 * @throws UnexpectedValueException
217
+	 */
218
+	private function injectDependency(ReflectionClass $reflector, $param_class)
219
+	{
220
+		$dependency = $this->coffee_pot->brew($param_class);
221
+		if (! $dependency instanceof $param_class) {
222
+			throw new UnexpectedValueException(
223
+				sprintf(
224
+					esc_html__(
225
+						'Could not resolve dependency for "%1$s" for the "%2$s" class constructor.',
226
+						'event_espresso'
227
+					),
228
+					$param_class,
229
+					$reflector->getName()
230
+				)
231
+			);
232
+		}
233
+		return $dependency;
234
+	}
235 235
 }
Please login to merge, or discard this patch.
core/data_migration_scripts/EE_Data_Migration_Script_Base.core.php 2 patches
Spacing   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -135,7 +135,7 @@  discard block
 block discarded – undo
135 135
     public function __construct(TableManager $table_manager = null, TableAnalysis $table_analysis = null)
136 136
     {
137 137
         $this->_migration_stages = (array) apply_filters(
138
-            'FHEE__' . get_class($this) . '__construct__migration_stages',
138
+            'FHEE__'.get_class($this).'__construct__migration_stages',
139 139
             $this->_migration_stages
140 140
         );
141 141
         foreach ($this->_migration_stages as $migration_stage) {
@@ -170,10 +170,10 @@  discard block
 block discarded – undo
170 170
     public function set_mapping($old_table, $old_pk, $new_table, $new_pk)
171 171
     {
172 172
         // make sure it has the needed keys
173
-        if (! isset($this->_mappings[ $old_table ]) || ! isset($this->_mappings[ $old_table ][ $new_table ])) {
174
-            $this->_mappings[ $old_table ][ $new_table ] = $this->_get_mapping_option($old_table, $new_table);
173
+        if ( ! isset($this->_mappings[$old_table]) || ! isset($this->_mappings[$old_table][$new_table])) {
174
+            $this->_mappings[$old_table][$new_table] = $this->_get_mapping_option($old_table, $new_table);
175 175
         }
176
-        $this->_mappings[ $old_table ][ $new_table ][ $old_pk ] = $new_pk;
176
+        $this->_mappings[$old_table][$new_table][$old_pk] = $new_pk;
177 177
     }
178 178
 
179 179
 
@@ -189,14 +189,14 @@  discard block
 block discarded – undo
189 189
     public function get_mapping_new_pk($old_table, $old_pk, $new_table)
190 190
     {
191 191
         if (
192
-            ! isset($this->_mappings[ $old_table ]) ||
193
-            ! isset($this->_mappings[ $old_table ][ $new_table ])
192
+            ! isset($this->_mappings[$old_table]) ||
193
+            ! isset($this->_mappings[$old_table][$new_table])
194 194
         ) {
195 195
             // try fetching the option
196
-            $this->_mappings[ $old_table ][ $new_table ] = $this->_get_mapping_option($old_table, $new_table);
196
+            $this->_mappings[$old_table][$new_table] = $this->_get_mapping_option($old_table, $new_table);
197 197
         }
198
-        return isset($this->_mappings[ $old_table ][ $new_table ][ $old_pk ])
199
-            ? $this->_mappings[ $old_table ][ $new_table ][ $old_pk ] : null;
198
+        return isset($this->_mappings[$old_table][$new_table][$old_pk])
199
+            ? $this->_mappings[$old_table][$new_table][$old_pk] : null;
200 200
     }
201 201
 
202 202
 
@@ -212,16 +212,16 @@  discard block
 block discarded – undo
212 212
     public function get_mapping_old_pk($old_table, $new_table, $new_pk)
213 213
     {
214 214
         if (
215
-            ! isset($this->_mappings[ $old_table ]) ||
216
-            ! isset($this->_mappings[ $old_table ][ $new_table ])
215
+            ! isset($this->_mappings[$old_table]) ||
216
+            ! isset($this->_mappings[$old_table][$new_table])
217 217
         ) {
218 218
             // try fetching the option
219
-            $this->_mappings[ $old_table ][ $new_table ] = $this->_get_mapping_option($old_table, $new_table);
219
+            $this->_mappings[$old_table][$new_table] = $this->_get_mapping_option($old_table, $new_table);
220 220
         }
221
-        if (isset($this->_mappings[ $old_table ][ $new_table ])) {
222
-            $new_pk_to_old_pk = array_flip($this->_mappings[ $old_table ][ $new_table ]);
223
-            if (isset($new_pk_to_old_pk[ $new_pk ])) {
224
-                return $new_pk_to_old_pk[ $new_pk ];
221
+        if (isset($this->_mappings[$old_table][$new_table])) {
222
+            $new_pk_to_old_pk = array_flip($this->_mappings[$old_table][$new_table]);
223
+            if (isset($new_pk_to_old_pk[$new_pk])) {
224
+                return $new_pk_to_old_pk[$new_pk];
225 225
             }
226 226
         }
227 227
         return null;
@@ -271,7 +271,7 @@  discard block
 block discarded – undo
271 271
         $new_table_name_sans_wp = str_replace($wpdb->prefix, "", $new_table_name);
272 272
         $migrates_to = EE_Data_Migration_Manager::instance()->script_migrates_to_version(get_class($this));
273 273
         return substr(
274
-            EE_Data_Migration_Manager::data_migration_script_mapping_option_prefix . $migrates_to ['slug'] . '_' . $migrates_to['version'] . '_' . $old_table_name_sans_wp . '_' . $new_table_name_sans_wp,
274
+            EE_Data_Migration_Manager::data_migration_script_mapping_option_prefix.$migrates_to ['slug'].'_'.$migrates_to['version'].'_'.$old_table_name_sans_wp.'_'.$new_table_name_sans_wp,
275 275
             0,
276 276
             64
277 277
         );
@@ -343,12 +343,12 @@  discard block
 block discarded – undo
343 343
                         $num_records_to_migrate_limit - $num_records_actually_migrated
344 344
                     );
345 345
                     $num_records_actually_migrated += $records_migrated_during_stage;
346
-                    $records_migrated_per_stage[ $stage->pretty_name() ] = $records_migrated_during_stage;
346
+                    $records_migrated_per_stage[$stage->pretty_name()] = $records_migrated_during_stage;
347 347
                 } catch (Exception $e) {
348 348
                     // yes if we catch an exception here, we consider that migration stage borked.
349 349
                     $stage->set_status(EE_Data_Migration_Manager::status_fatal_error);
350 350
                     $this->set_status(EE_Data_Migration_Manager::status_fatal_error);
351
-                    $stage->add_error($e->getMessage() . ". Stack-trace:" . $e->getTraceAsString());
351
+                    $stage->add_error($e->getMessage().". Stack-trace:".$e->getTraceAsString());
352 352
                     throw $e;
353 353
                 }
354 354
                 // check that the migration stage didn't mark itself as having a fatal error
@@ -421,8 +421,8 @@  discard block
 block discarded – undo
421 421
     private function _maybe_do_schema_changes($before = true)
422 422
     {
423 423
         // so this property will be either _schema_changes_after_migration_ran or _schema_changes_before_migration_ran
424
-        $property_name = '_schema_changes_' . ($before ? 'before' : 'after') . '_migration_ran';
425
-        if (! $this->{$property_name}) {
424
+        $property_name = '_schema_changes_'.($before ? 'before' : 'after').'_migration_ran';
425
+        if ( ! $this->{$property_name}) {
426 426
             try {
427 427
                 ob_start();
428 428
                 if ($before) {
@@ -659,7 +659,7 @@  discard block
 block discarded – undo
659 659
         try {
660 660
             EEH_Activation::create_table($table_name, $table_definition_sql, $engine_string, $drop_pre_existing_tables);
661 661
         } catch (EE_Error $e) {
662
-            $message = $e->getMessage() . '<br>Stack Trace:' . $e->getTraceAsString();
662
+            $message = $e->getMessage().'<br>Stack Trace:'.$e->getTraceAsString();
663 663
             $this->add_error($message);
664 664
             $this->_feedback_message .= $message;
665 665
         }
@@ -705,7 +705,7 @@  discard block
 block discarded – undo
705 705
     public function get_errors()
706 706
     {
707 707
         $all_errors = $this->_errors;
708
-        if (! is_array($all_errors)) {
708
+        if ( ! is_array($all_errors)) {
709 709
             $all_errors = array();
710 710
         }
711 711
         foreach ($this->stages() as $stage) {
@@ -739,7 +739,7 @@  discard block
 block discarded – undo
739 739
      */
740 740
     protected function stages()
741 741
     {
742
-        $stages = apply_filters('FHEE__' . get_class($this) . '__stages', $this->_migration_stages);
742
+        $stages = apply_filters('FHEE__'.get_class($this).'__stages', $this->_migration_stages);
743 743
         ksort($stages);
744 744
         return $stages;
745 745
     }
@@ -768,7 +768,7 @@  discard block
 block discarded – undo
768 768
         $properties = parent::properties_as_array();
769 769
         $properties['_migration_stages'] = array();
770 770
         foreach ($this->_migration_stages as $migration_stage_priority => $migration_stage_class) {
771
-            $properties['_migration_stages'][ $migration_stage_priority ] = $migration_stage_class->properties_as_array(
771
+            $properties['_migration_stages'][$migration_stage_priority] = $migration_stage_class->properties_as_array(
772 772
             );
773 773
         }
774 774
         unset($properties['_mappings']);
Please login to merge, or discard this patch.
Indentation   +914 added lines, -914 removed lines patch added patch discarded remove patch
@@ -15,918 +15,918 @@
 block discarded – undo
15 15
  */
16 16
 abstract class EE_Data_Migration_Script_Base extends EE_Data_Migration_Class_Base
17 17
 {
18
-    /**
19
-     * Set by client code to indicate this DMS is being ran as part of a proper migration,
20
-     * instead of being used to merely setup (or verify) the database structure.
21
-     * Defaults to TRUE, so client code that's NOT using this DMS as part of a proper migration
22
-     * should call EE_Data_Migration_Script_Base::set_migrating( FALSE )
23
-     *
24
-     * @var boolean
25
-     */
26
-    protected bool $_migrating = true;
27
-
28
-    /**
29
-     * numerically-indexed array where each value is EE_Data_Migration_Script_Stage object
30
-     *
31
-     * @var EE_Data_Migration_Script_Stage[] $migration_functions
32
-     */
33
-    protected array $_migration_stages = array();
34
-
35
-    /**
36
-     * Indicates we've already run the schema changes that needed to happen BEFORE the data migration
37
-     *
38
-     * @var boolean
39
-     */
40
-    protected ?bool $_schema_changes_before_migration_ran = null;
41
-
42
-    /**
43
-     * Indicates we've already run the schema changes that needed to happen AFTER the data migration
44
-     *
45
-     * @var boolean
46
-     */
47
-    protected ?bool $_schema_changes_after_migration_ran = null;
48
-
49
-    /**
50
-     * String which describes what's currently happening in this migration
51
-     *
52
-     * @var string|null
53
-     */
54
-    protected ?string $_feedback_message = '';
55
-
56
-    /**
57
-     * Indicates the script's priority. Like wp's add_action and add_filter, lower numbers
58
-     * correspond to earlier execution
59
-     *
60
-     * @var int
61
-     */
62
-    protected int $_priority = 5;
63
-
64
-    /**
65
-     * Multidimensional array that defines the mapping from OLD table Primary Keys
66
-     * to NEW table Primary Keys.
67
-     * Top-level array keys are OLD table names (minus the "wp_" part),
68
-     * 2nd-level array keys are NEW table names (again, minus the "wp_" part),
69
-     * 3rd-level array keys are the OLD table primary keys
70
-     * and 3rd-level array values are the NEW table primary keys
71
-     *
72
-     * @var array
73
-     */
74
-    protected array $_mappings = array();
75
-
76
-    /**
77
-     * @var EE_Data_Migration_Script_Base
78
-     */
79
-    protected EE_Data_Migration_Script_Base $previous_dms;
80
-
81
-
82
-    /**
83
-     * Returns whether this data migration script can operate on the given version of the database.
84
-     * Eg, if this migration script can migrate from 3.1.26 or higher (but not anything after 4.0.0), and
85
-     * it's passed a string like '3.1.38B', it should return true.
86
-     * If this DMS is to migrate data from an EE3 addon, you will probably want to use
87
-     * EventEspresso\core\services\database\TableAnalysis::tableExists() to check for old EE3 tables, and
88
-     * EE_Data_Migration_Manager::get_migration_ran() to check that core was already
89
-     * migrated from EE3 to EE4 (ie, this DMS probably relies on some migration data generated
90
-     * during the Core 4.1.0 DMS. If core didn't run that DMS, you probably don't want
91
-     * to run this DMS).
92
-     * If this DMS migrates data from a previous version of this EE4 addon, just
93
-     * comparing $current_database_state_of[ $this->slug() ] will probably suffice.
94
-     * If this DMS should never migrate data, because it's only used to define the initial
95
-     * database state, just return FALSE (and core's activation process will take care
96
-     * of calling its schema_changes_before_migration() and
97
-     * schema_changes_after_migration() for you. )
98
-     *
99
-     * @param array $version_array keys are EE plugin slugs (eg 'Core', 'Calendar', 'Mailchimp', etc)
100
-     * @return boolean
101
-     */
102
-    abstract public function can_migrate_from_version($version_array);
103
-
104
-
105
-    /**
106
-     * Performs database schema changes that need to occur BEFORE the data is migrated.
107
-     * Eg, if we were going to change user passwords from plaintext to encoded versions
108
-     * during this migration, this would probably add a new column called something like
109
-     * "encoded_password".
110
-     *
111
-     * @return boolean of success
112
-     */
113
-    abstract public function schema_changes_before_migration();
114
-
115
-
116
-    /**
117
-     * Performs the database schema changes that need to occur AFTER the data has been migrated.
118
-     * Usually this will mean we'll be removing old columns. Eg, if we were changing passwords
119
-     * from plaintext to encoded versions, and we had added a column called "encoded_password",
120
-     * this function would probably remove the old column "password" (which still holds the plaintext password)
121
-     * and possibly rename "encoded_password" to "password"
122
-     *
123
-     * @return boolean of success
124
-     */
125
-    abstract public function schema_changes_after_migration();
126
-
127
-
128
-    /**
129
-     * All children of this must call parent::__construct()
130
-     * at the end of their constructor or suffer the consequences!
131
-     *
132
-     * @param TableManager|null  $table_manager
133
-     * @param TableAnalysis|null $table_analysis
134
-     */
135
-    public function __construct(TableManager $table_manager = null, TableAnalysis $table_analysis = null)
136
-    {
137
-        $this->_migration_stages = (array) apply_filters(
138
-            'FHEE__' . get_class($this) . '__construct__migration_stages',
139
-            $this->_migration_stages
140
-        );
141
-        foreach ($this->_migration_stages as $migration_stage) {
142
-            if ($migration_stage instanceof EE_Data_Migration_Script_Stage) {
143
-                $migration_stage->_construct_finalize($this);
144
-            }
145
-        }
146
-        parent::__construct($table_manager, $table_analysis);
147
-    }
148
-
149
-
150
-    /**
151
-     * Place to add hooks and filters for tweaking the migrations page, in order
152
-     * to customize it
153
-     */
154
-    public function migration_page_hooks()
155
-    {
156
-        // by default none are added because we normally like the default look of the migration page
157
-    }
158
-
159
-
160
-    /**
161
-     * Sets the mapping from old table primary keys to new table primary keys.
162
-     * This mapping is automatically persisted as a property on the migration
163
-     *
164
-     * @param string     $old_table with wpdb prefix (wp_). Eg: wp_events_detail
165
-     * @param int|string $old_pk    old primary key. Eg events_detail.id's value
166
-     * @param string     $new_table with wpdb prefix (wp_). Eg: wp_posts
167
-     * @param array|int|string $new_pk    eg posts.ID
168
-     * @return void
169
-     * @throws EE_Error
170
-     */
171
-    public function set_mapping($old_table, $old_pk, $new_table, $new_pk)
172
-    {
173
-        // make sure it has the needed keys
174
-        if (! isset($this->_mappings[ $old_table ]) || ! isset($this->_mappings[ $old_table ][ $new_table ])) {
175
-            $this->_mappings[ $old_table ][ $new_table ] = $this->_get_mapping_option($old_table, $new_table);
176
-        }
177
-        $this->_mappings[ $old_table ][ $new_table ][ $old_pk ] = $new_pk;
178
-    }
179
-
180
-
181
-    /**
182
-     * Gets the new primary key, if provided with the OLD table and the primary key
183
-     * of an item in the old table, and the new table
184
-     *
185
-     * @param string     $old_table with wpdb prefix (wp_). Eg: wp_events_detail
186
-     * @param int|string $old_pk    old primary key. Eg events_detail.id's value
187
-     * @param string     $new_table with wpdb prefix (wp_). Eg: wp_posts
188
-     * @return mixed the primary key on the new table
189
-     * @throws EE_Error
190
-     */
191
-    public function get_mapping_new_pk($old_table, $old_pk, $new_table)
192
-    {
193
-        if (
194
-            ! isset($this->_mappings[ $old_table ]) ||
195
-            ! isset($this->_mappings[ $old_table ][ $new_table ])
196
-        ) {
197
-            // try fetching the option
198
-            $this->_mappings[ $old_table ][ $new_table ] = $this->_get_mapping_option($old_table, $new_table);
199
-        }
200
-        return isset($this->_mappings[ $old_table ][ $new_table ][ $old_pk ])
201
-            ? $this->_mappings[ $old_table ][ $new_table ][ $old_pk ] : null;
202
-    }
203
-
204
-
205
-    /**
206
-     * Gets the old primary key, if provided with the OLD table,
207
-     * and the new table and the primary key of an item in the new table
208
-     *
209
-     * @param string $old_table with wpdb prefix (wp_). Eg: wp_events_detail
210
-     * @param string $new_table with wpdb prefix (wp_). Eg: wp_posts
211
-     * @param mixed  $new_pk
212
-     * @return mixed
213
-     * @throws EE_Error
214
-     */
215
-    public function get_mapping_old_pk($old_table, $new_table, $new_pk)
216
-    {
217
-        if (
218
-            ! isset($this->_mappings[ $old_table ]) ||
219
-            ! isset($this->_mappings[ $old_table ][ $new_table ])
220
-        ) {
221
-            // try fetching the option
222
-            $this->_mappings[ $old_table ][ $new_table ] = $this->_get_mapping_option($old_table, $new_table);
223
-        }
224
-        if (isset($this->_mappings[ $old_table ][ $new_table ])) {
225
-            $new_pk_to_old_pk = array_flip($this->_mappings[ $old_table ][ $new_table ]);
226
-            if (isset($new_pk_to_old_pk[ $new_pk ])) {
227
-                return $new_pk_to_old_pk[ $new_pk ];
228
-            }
229
-        }
230
-        return null;
231
-    }
232
-
233
-
234
-    /**
235
-     * Gets the mapping array option specified by the table names
236
-     *
237
-     * @param string $old_table_name
238
-     * @param string $new_table_name
239
-     * @return array
240
-     * @throws EE_Error
241
-     */
242
-    protected function _get_mapping_option($old_table_name, $new_table_name)
243
-    {
244
-        return get_option($this->_get_mapping_option_name($old_table_name, $new_table_name), array());
245
-    }
246
-
247
-
248
-    /**
249
-     * Updates the mapping option specified by the table names with the array provided
250
-     *
251
-     * @param string $old_table_name
252
-     * @param string $new_table_name
253
-     * @param array  $mapping_array
254
-     * @return boolean success of updating option
255
-     * @throws EE_Error
256
-     */
257
-    protected function _set_mapping_option($old_table_name, $new_table_name, $mapping_array)
258
-    {
259
-        $success = update_option($this->_get_mapping_option_name($old_table_name, $new_table_name), $mapping_array, false);
260
-        return $success;
261
-    }
262
-
263
-
264
-    /**
265
-     * Gets the option name for this script to map from $old_table_name to $new_table_name
266
-     *
267
-     * @param string $old_table_name
268
-     * @param string $new_table_name
269
-     * @return string
270
-     * @throws EE_Error
271
-     */
272
-    protected function _get_mapping_option_name($old_table_name, $new_table_name)
273
-    {
274
-        global $wpdb;
275
-        $old_table_name_sans_wp = str_replace($wpdb->prefix, "", $old_table_name);
276
-        $new_table_name_sans_wp = str_replace($wpdb->prefix, "", $new_table_name);
277
-        $migrates_to = EE_Data_Migration_Manager::instance()->script_migrates_to_version(get_class($this));
278
-        return substr(
279
-            EE_Data_Migration_Manager::data_migration_script_mapping_option_prefix . $migrates_to ['slug'] . '_' . $migrates_to['version'] . '_' . $old_table_name_sans_wp . '_' . $new_table_name_sans_wp,
280
-            0,
281
-            64
282
-        );
283
-    }
284
-
285
-
286
-    /**
287
-     * Counts all the records that will be migrated during this data migration.
288
-     * For example, if we were changing old user passwords from plaintext to encoded versions,
289
-     * this would be a count of all users who have passwords. If we were going to also split
290
-     * attendee records into transactions, registrations, and attendee records, this would include
291
-     * the count of all attendees currently in existence in the DB (ie, users + attendees).
292
-     * If you can't determine how many records there are to migrate, just provide a guess: this
293
-     * number will only be used in calculating the percent complete. If you estimate there to be
294
-     * 100 records to migrate, and it turns out there's 120, we'll just show the migration as being at
295
-     * 99% until the function "migration_step" returns EE_Data_Migration_Script_Base::status_complete.
296
-     *
297
-     * @return int
298
-     */
299
-    protected function _count_records_to_migrate()
300
-    {
301
-        $count = 0;
302
-        foreach ($this->stages() as $stage) {
303
-            $count += $stage->count_records_to_migrate();
304
-        }
305
-        return $count;
306
-    }
307
-
308
-
309
-    /**
310
-     * Returns the number of records updated so far. Usually this is easiest to do
311
-     * by just setting a transient and updating it after each migration_step
312
-     *
313
-     * @return int
314
-     */
315
-    public function count_records_migrated()
316
-    {
317
-        $count = 0;
318
-        foreach ($this->stages() as $stage) {
319
-            $count += $stage->count_records_migrated();
320
-        }
321
-        $this->_records_migrated = $count;
322
-        return $count;
323
-    }
324
-
325
-
326
-    /**
327
-     * @param int $num_records_to_migrate_limit
328
-     * @return int
329
-     * @throws EE_Error
330
-     * @throws Exception
331
-     */
332
-    public function migration_step($num_records_to_migrate_limit)
333
-    {
334
-        // reset the feedback message
335
-        $this->_feedback_message = '';
336
-        // if we haven't yet done the 1st schema changes, do them now. buffer any output
337
-        $this->_maybe_do_schema_changes(true);
338
-
339
-        $num_records_actually_migrated = 0;
340
-        $records_migrated_per_stage = array();
341
-        // setup the 'stage' variable, which should hold the last run stage of the migration  (or none at all if nothing runs)
342
-        $stage = null;
343
-        // get the next stage that isn't complete
344
-        foreach ($this->stages() as $stage) {
345
-            if ($stage->get_status() == EE_Data_Migration_Manager::status_continue) {
346
-                try {
347
-                    $records_migrated_during_stage = $stage->migration_step(
348
-                        $num_records_to_migrate_limit - $num_records_actually_migrated
349
-                    );
350
-                    $num_records_actually_migrated += $records_migrated_during_stage;
351
-                    $records_migrated_per_stage[ $stage->pretty_name() ] = $records_migrated_during_stage;
352
-                } catch (Exception $e) {
353
-                    // yes if we catch an exception here, we consider that migration stage borked.
354
-                    $stage->set_status(EE_Data_Migration_Manager::status_fatal_error);
355
-                    $this->set_status(EE_Data_Migration_Manager::status_fatal_error);
356
-                    $stage->add_error($e->getMessage() . ". Stack-trace:" . $e->getTraceAsString());
357
-                    throw $e;
358
-                }
359
-                // check that the migration stage didn't mark itself as having a fatal error
360
-                if ($stage->is_broken()) {
361
-                    $this->set_broken();
362
-                    throw new EE_Error($stage->get_last_error());
363
-                }
364
-            }
365
-            // once we've migrated all the number we intended to (possibly from different stages), stop migrating
366
-            // or if we had a fatal error
367
-            // or if the current script stopped early- its not done, but it's done all it thinks we should do on this step
368
-            if (
369
-                $num_records_actually_migrated >= $num_records_to_migrate_limit
370
-                || $stage->is_broken()
371
-                || $stage->has_more_to_do()
372
-            ) {
373
-                break;
374
-            }
375
-        }
376
-        // check if we're all done this data migration...
377
-        // which is indicated by being done early AND the last stage claims to be done
378
-        if ($stage == null) {
379
-            // this migration script apparently has NO stages... which is super weird, but whatever
380
-            $this->set_completed();
381
-            $this->_maybe_do_schema_changes(false);
382
-        } elseif ($num_records_actually_migrated < $num_records_to_migrate_limit && ! $stage->has_more_to_do()) {
383
-            // apparently we're done, because we couldn't migrate the number we intended to
384
-            $this->set_completed();
385
-            $this->_update_feedback_message(array_reverse($records_migrated_per_stage));
386
-            // do schema changes for after the migration now
387
-            // first double-check we haven't already done this
388
-            $this->_maybe_do_schema_changes(false);
389
-        } else {
390
-            // update feedback message, keeping in mind that we show them with the most recent at the top
391
-            $this->_update_feedback_message(array_reverse($records_migrated_per_stage));
392
-        }
393
-        return $num_records_actually_migrated;
394
-    }
395
-
396
-
397
-    /**
398
-     * Updates the feedback message according to what was done during this migration stage.
399
-     *
400
-     * @param array $records_migrated_per_stage KEYS are pretty names for each stage; values are the count of records
401
-     *                                          migrated from that stage
402
-     * @return void
403
-     */
404
-    private function _update_feedback_message($records_migrated_per_stage)
405
-    {
406
-        $feedback_message_array = array();
407
-        foreach ($records_migrated_per_stage as $migration_stage_name => $num_records_migrated) {
408
-            $feedback_message_array[] = sprintf(
409
-                esc_html__("Migrated %d records successfully during %s", "event_espresso"),
410
-                $num_records_migrated,
411
-                $migration_stage_name
412
-            );
413
-        }
414
-        $this->_feedback_message .= implode("<br>", $feedback_message_array);
415
-    }
416
-
417
-
418
-    /**
419
-     * Calls either schema_changes_before_migration() (if $before==true) or schema_changes_after_migration
420
-     * (if $before==false). Buffers their outputs and stores them on the class.
421
-     *
422
-     * @param boolean $before
423
-     * @throws Exception
424
-     * @return void
425
-     */
426
-    private function _maybe_do_schema_changes($before = true)
427
-    {
428
-        // so this property will be either _schema_changes_after_migration_ran or _schema_changes_before_migration_ran
429
-        $property_name = '_schema_changes_' . ($before ? 'before' : 'after') . '_migration_ran';
430
-        if (! $this->{$property_name}) {
431
-            try {
432
-                ob_start();
433
-                if ($before) {
434
-                    $this->schema_changes_before_migration();
435
-                } else {
436
-                    $this->schema_changes_after_migration();
437
-                }
438
-                $output = ob_get_contents();
439
-                ob_end_clean();
440
-            } catch (Exception $e) {
441
-                $this->set_status(EE_Data_Migration_Manager::status_fatal_error);
442
-                throw $e;
443
-            }
444
-            // record that we've done these schema changes
445
-            $this->{$property_name} = true;
446
-            // if there were any warnings etc, record them as non-fatal errors
447
-            if ($output) {
448
-                // there were some warnings
449
-                $this->_errors[] = $output;
450
-            }
451
-        }
452
-    }
453
-
454
-
455
-    /**
456
-     * Wrapper for EEH_Activation::create_table. However, takes into account the request type when
457
-     * deciding what to pass for its 4th arg, $drop_pre_existing_tables. Using this function, instead
458
-     * of _table_should_exist_previously, indicates that this table should be new to the EE version being migrated to
459
-     * or
460
-     * activated currently. If this is a brand new activation or a migration, and we're indicating this table should
461
-     * not
462
-     * previously exist, then we want to set $drop_pre_existing_tables to TRUE (ie, we shouldn't discover that this
463
-     * table exists in the DB in EEH_Activation::create_table- if it DOES exist, something's wrong and the old table
464
-     * should be nuked.
465
-     *
466
-     * Just for a bit of context, the migration script's db_schema_changes_* methods
467
-     * are called basically in 3 cases: on brand new activation of EE4 (ie no previous version of EE existed and the
468
-     * plugin is being activated and we want to add all the brand new tables), upon reactivation of EE4 (it was
469
-     * deactivated and then reactivated, in which case we want to just verify the DB structure is ok) that table should
470
-     * be dropped), and during a migration when we're moving the DB to the state of the migration script
471
-     *
472
-     * @param string $table_name
473
-     * @param string $table_definition_sql
474
-     * @param string $engine_string
475
-     * @throws EE_Error
476
-     * @throws ReflectionException
477
-     */
478
-    protected function _table_is_new_in_this_version(
479
-        $table_name,
480
-        $table_definition_sql,
481
-        $engine_string = 'ENGINE=InnoDB'
482
-    ) {
483
-        $this->_create_table_and_catch_errors(
484
-            $table_name,
485
-            $table_definition_sql,
486
-            $engine_string,
487
-            $this->_pre_existing_table_should_be_dropped(true)
488
-        );
489
-    }
490
-
491
-
492
-    /**
493
-     * Like _table_is_new_in_this_version and _table_should_exist_previously, this function verifies the given table
494
-     * exists. But we understand that this table has CHANGED in this version since the previous version. So it's not
495
-     * completely new, but it's different. So we need to treat it like a new table in terms of verifying it's schema is
496
-     * correct on activations, migrations, upgrades; but if it exists when it shouldn't, we need to be as lenient as
497
-     * _table_should_exist_previously.
498
-     * 8656]{Assumes only this plugin could have added this table (ie, if its a new activation of this plugin, the
499
-     * table shouldn't exist).
500
-     *
501
-     * @param string $table_name
502
-     * @param string $table_definition_sql
503
-     * @param string $engine_string
504
-     * @throws EE_Error
505
-     * @throws ReflectionException
506
-     */
507
-    protected function _table_is_changed_in_this_version(
508
-        $table_name,
509
-        $table_definition_sql,
510
-        $engine_string = 'ENGINE=InnoDB'
511
-    ) {
512
-        $this->_create_table_and_catch_errors(
513
-            $table_name,
514
-            $table_definition_sql,
515
-            $engine_string,
516
-            $this->_pre_existing_table_should_be_dropped(false)
517
-        );
518
-    }
519
-
520
-
521
-    /**
522
-     * _old_table_exists
523
-     * returns TRUE if the requested table exists in the current database
524
-     *
525
-     * @param string $table_name
526
-     * @return boolean
527
-     * @throws EE_Error
528
-     */
529
-    protected function _old_table_exists($table_name)
530
-    {
531
-        return $this->_get_table_analysis()->tableExists($table_name);
532
-    }
533
-
534
-
535
-    /**
536
-     * _delete_table_if_empty
537
-     * returns TRUE if the requested table was empty and successfully empty
538
-     *
539
-     * @param string $table_name
540
-     * @return boolean
541
-     * @throws EE_Error
542
-     * @throws ReflectionException
543
-     */
544
-    protected function _delete_table_if_empty($table_name)
545
-    {
546
-        return EEH_Activation::delete_db_table_if_empty($table_name);
547
-    }
548
-
549
-
550
-    /**
551
-     * It is preferred to use _table_has_not_changed_since_previous or _table_is_changed_in_this_version
552
-     * as these are significantly more efficient or explicit.
553
-     * Please see description of _table_is_new_in_this_version. This function will only set
554
-     * EEH_Activation::create_table's $drop_pre_existing_tables to TRUE if it's a brand
555
-     * new activation. ie, a more accurate name for this method would be "_table_added_previously_by_this_plugin"
556
-     * because the table will be cleared out if this is a new activation (ie, if its a new activation, it actually
557
-     * should exist previously). Otherwise, we'll always set $drop_pre_existing_tables to FALSE because the table
558
-     * should have existed. Note, if the table is being MODIFIED in this version being activated or migrated to, then
559
-     * you want _table_is_changed_in_this_version NOT this one. We don't check this table's structure during migrations
560
-     * because apparently it hasn't changed since the previous one, right?
561
-     *
562
-     * @param string $table_name
563
-     * @param string $table_definition_sql
564
-     * @param string $engine_string
565
-     * @throws EE_Error
566
-     * @throws ReflectionException
567
-     */
568
-    protected function _table_should_exist_previously(
569
-        $table_name,
570
-        $table_definition_sql,
571
-        $engine_string = 'ENGINE=InnoDB'
572
-    ) {
573
-        $this->_create_table_and_catch_errors(
574
-            $table_name,
575
-            $table_definition_sql,
576
-            $engine_string,
577
-            $this->_pre_existing_table_should_be_dropped(false)
578
-        );
579
-    }
580
-
581
-
582
-    /**
583
-     * Exactly the same as _table_should_exist_previously(), except if this migration script is currently doing
584
-     * a migration, we skip checking this table's structure in the database and just assume it's correct.
585
-     * So this is useful only to improve efficiency when doing migrations (not a big deal for single site installs,
586
-     * but important for multisite where migrations can take a very long time otherwise).
587
-     * If the table is known to have changed since previous version, use _table_is_changed_in_this_version().
588
-     * Assumes only this plugin could have added this table (ie, if its a new activation of this plugin, the table
589
-     * shouldn't exist).
590
-     *
591
-     * @param string $table_name
592
-     * @param string $table_definition_sql
593
-     * @param string $engine_string
594
-     * @throws EE_Error
595
-     * @throws ReflectionException
596
-     */
597
-    protected function _table_has_not_changed_since_previous(
598
-        $table_name,
599
-        $table_definition_sql,
600
-        $engine_string = 'ENGINE=InnoDB'
601
-    ) {
602
-        if ($this->_currently_migrating()) {
603
-            // if we're doing a migration, and this table apparently already exists, then we don't need do anything right?
604
-            return;
605
-        }
606
-        $this->_create_table_and_catch_errors(
607
-            $table_name,
608
-            $table_definition_sql,
609
-            $engine_string,
610
-            $this->_pre_existing_table_should_be_dropped(false)
611
-        );
612
-    }
613
-
614
-    /**
615
-     * Returns whether this migration script is being used as part of an actual migration
616
-     *
617
-     * @return boolean
618
-     */
619
-    protected function _currently_migrating()
620
-    {
621
-        // we want to know if we are currently performing a migration. We could just believe what was set on the _migrating property, but let's double-check (ie the script should apply and we should be in MM)
622
-        return $this->_migrating
623
-            && DbStatus::isOffline()
624
-            && $this->can_migrate_from_version(
625
-                EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set()
626
-            );
627
-    }
628
-
629
-
630
-    /**
631
-     * Determines if a table should be dropped, based on whether it's reported to be new in $table_is_new,
632
-     * and the plugin's request type.
633
-     * Assumes only this plugin could have added the table (ie, if its a new activation of this plugin, the table
634
-     * shouldn't exist no matter what).
635
-     *
636
-     * @param boolean $table_is_new
637
-     * @return boolean
638
-     * @throws EE_Error
639
-     */
640
-    protected function _pre_existing_table_should_be_dropped($table_is_new)
641
-    {
642
-        if ($table_is_new) {
643
-            if (
644
-                $this->_get_req_type_for_plugin_corresponding_to_this_dms() == EE_System::req_type_new_activation
645
-                || $this->_currently_migrating()
646
-            ) {
647
-                return true;
648
-            } else {
649
-                return false;
650
-            }
651
-        } else {
652
-            if (
653
-                in_array(
654
-                    $this->_get_req_type_for_plugin_corresponding_to_this_dms(),
655
-                    array(EE_System::req_type_new_activation)
656
-                )
657
-            ) {
658
-                return true;
659
-            } else {
660
-                return false;
661
-            }
662
-        }
663
-    }
664
-
665
-
666
-    /**
667
-     * Just wraps EEH_Activation::create_table, but catches any errors it may throw and adds them as errors on the DMS
668
-     *
669
-     * @param string  $table_name
670
-     * @param string  $table_definition_sql
671
-     * @param string  $engine_string
672
-     * @param boolean $drop_pre_existing_tables
673
-     * @throws ReflectionException
674
-     */
675
-    private function _create_table_and_catch_errors(
676
-        $table_name,
677
-        $table_definition_sql,
678
-        $engine_string = 'ENGINE=InnoDB',
679
-        $drop_pre_existing_tables = false
680
-    ) {
681
-        try {
682
-            EEH_Activation::create_table($table_name, $table_definition_sql, $engine_string, $drop_pre_existing_tables);
683
-        } catch (EE_Error $e) {
684
-            $message = $e->getMessage() . '<br>Stack Trace:' . $e->getTraceAsString();
685
-            $this->add_error($message);
686
-            $this->_feedback_message .= $message;
687
-        }
688
-    }
689
-
690
-
691
-    /**
692
-     * Gets the request type for the plugin (core or addon) that corresponds to this DMS
693
-     *
694
-     * @return int one of EE_System::_req_type_* constants
695
-     * @throws EE_Error
696
-     */
697
-    private function _get_req_type_for_plugin_corresponding_to_this_dms()
698
-    {
699
-        if ($this->slug() == 'Core') {
700
-            return EE_System::instance()->detect_req_type();
701
-        } else {// it must be for an addon
702
-            $addon_name = $this->slug();
703
-            if (EE_Registry::instance()->get_addon_by_name($addon_name)) {
704
-                return EE_Registry::instance()->get_addon_by_name($addon_name)->detect_req_type();
705
-            } else {
706
-                throw new EE_Error(
707
-                    sprintf(
708
-                        esc_html__(
709
-                            "The DMS slug '%s' should correspond to the addon's name, which should also be '%s', but no such addon was registered. These are the registered addons' names: %s",
710
-                            "event_espresso"
711
-                        ),
712
-                        $this->slug(),
713
-                        $addon_name,
714
-                        implode(",", array_keys(EE_Registry::instance()->get_addons_by_name()))
715
-                    )
716
-                );
717
-            }
718
-        }
719
-    }
720
-
721
-
722
-    /**
723
-     * returns an array of strings describing errors by all the script's stages
724
-     *
725
-     * @return array
726
-     */
727
-    public function get_errors()
728
-    {
729
-        $all_errors = $this->_errors;
730
-        if (! is_array($all_errors)) {
731
-            $all_errors = array();
732
-        }
733
-        foreach ($this->stages() as $stage) {
734
-            $all_errors = array_merge($stage->get_errors(), $all_errors);
735
-        }
736
-        return $all_errors;
737
-    }
738
-
739
-
740
-    /**
741
-     * Indicates whether this migration script should continue
742
-     *
743
-     * @return boolean
744
-     */
745
-    public function can_continue()
746
-    {
747
-        return in_array(
748
-            $this->get_status(),
749
-            EE_Data_Migration_Manager::instance()->stati_that_indicate_to_continue_single_migration_script
750
-        );
751
-    }
752
-
753
-
754
-    /**
755
-     * Gets all the data migration stages associated with this script. Note:
756
-     * addons can filter this list to add their own stages, and because the list is
757
-     * numerically-indexed, they can insert their stage wherever they like and it will
758
-     * get ordered by the indexes
759
-     *
760
-     * @return EE_Data_Migration_Script_Stage[]
761
-     */
762
-    protected function stages()
763
-    {
764
-        $stages = apply_filters('FHEE__' . get_class($this) . '__stages', $this->_migration_stages);
765
-        ksort($stages);
766
-        return $stages;
767
-    }
768
-
769
-
770
-    /**
771
-     * Gets a string which should describe what's going on currently with this migration, which
772
-     * can be displayed to the user
773
-     *
774
-     * @return string
775
-     */
776
-    public function get_feedback_message()
777
-    {
778
-        return $this->_feedback_message;
779
-    }
780
-
781
-
782
-    /**
783
-     * A lot like "__sleep()" magic method in purpose, this is meant for persisting this class'
784
-     * properties to the DB. However, we don't want to use __sleep() because its quite
785
-     * possible that this class is defined when it goes to sleep, but NOT available when it
786
-     * awakes (eg, this class is part of an addon that is deactivated at some point).
787
-     */
788
-    public function properties_as_array()
789
-    {
790
-        $properties = parent::properties_as_array();
791
-        $properties['_migration_stages'] = array();
792
-        foreach ($this->_migration_stages as $migration_stage_priority => $migration_stage_class) {
793
-            $properties['_migration_stages'][ $migration_stage_priority ] = $migration_stage_class->properties_as_array(
794
-            );
795
-        }
796
-        unset($properties['_mappings']);
797
-        unset($properties['previous_dms']);
798
-
799
-        foreach ($this->_mappings as $old_table_name => $mapping_to_new_table) {
800
-            foreach ($mapping_to_new_table as $new_table_name => $mapping) {
801
-                $this->_set_mapping_option($old_table_name, $new_table_name, $mapping);
802
-            }
803
-        }
804
-        return $properties;
805
-    }
806
-
807
-
808
-    /**
809
-     * Sets all of the properties of this script stage to match what's in the array, which is assumed
810
-     * to have been made from the properties_as_array() function.
811
-     *
812
-     * @param array $array_of_properties like what's produced from properties_as_array() method
813
-     * @return void
814
-     */
815
-    public function instantiate_from_array_of_properties($array_of_properties)
816
-    {
817
-        $stages_properties_arrays = $array_of_properties['_migration_stages'];
818
-        unset($array_of_properties['_migration_stages']);
819
-        unset($array_of_properties['class']);
820
-        foreach ($array_of_properties as $property_name => $property_value) {
821
-            $this->{$property_name} = $property_value;
822
-        }
823
-        // _migration_stages are already instantiated, but have only default data
824
-        foreach ($this->_migration_stages as $stage) {
825
-            $stage_data = $this->_find_migration_stage_data_with_classname(
826
-                get_class($stage),
827
-                $stages_properties_arrays
828
-            );
829
-            // SO, if we found the stage data that was saved, use it. Otherwise, I guess the stage is new? (maybe added by
830
-            // an addon? Unlikely... not sure why it wouldn't exist, but if it doesn't just treat it like it was never started yet)
831
-            if ($stage_data) {
832
-                $stage->instantiate_from_array_of_properties($stage_data);
833
-            }
834
-        }
835
-    }
836
-
837
-
838
-    /**
839
-     * Gets the migration data from the array $migration_stage_data_arrays (which is an array of arrays, each of which
840
-     * is pretty well identical to EE_Data_Migration_Stage objects except all their properties are array indexes)
841
-     * for the given classname
842
-     *
843
-     * @param string $classname
844
-     * @param array  $migration_stage_data_arrays
845
-     * @return null
846
-     */
847
-    private function _find_migration_stage_data_with_classname($classname, $migration_stage_data_arrays)
848
-    {
849
-        foreach ($migration_stage_data_arrays as $migration_stage_data_array) {
850
-            if (isset($migration_stage_data_array['class']) && $migration_stage_data_array['class'] == $classname) {
851
-                return $migration_stage_data_array;
852
-            }
853
-        }
854
-        return null;
855
-    }
856
-
857
-
858
-    /**
859
-     * Returns the version that this script migrates to, based on the script's name.
860
-     * Cannot be overwritten because lots of code needs to know which version a script
861
-     * migrates to knowing only its name.
862
-     *
863
-     * @return array where the first key is the plugin's slug, the 2nd is the version of that plugin
864
-     * that will be updated to. Eg array('Core','4.1.0')
865
-     * @throws EE_Error
866
-     */
867
-    final public function migrates_to_version()
868
-    {
869
-        return EE_Data_Migration_Manager::instance()->script_migrates_to_version(get_class($this));
870
-    }
871
-
872
-
873
-    /**
874
-     * Gets this addon's slug as it would appear in the current_db_state wp option,
875
-     * and if this migration script is for an addon, it SHOULD match the addon's slug
876
-     * (and also the addon's classname, minus the 'EE_' prefix.). Eg, 'Calendar' for the EE_Calendar addon.
877
-     * Or 'Core' for core (non-addon).
878
-     *
879
-     * @return string
880
-     * @throws EE_Error
881
-     */
882
-    public function slug()
883
-    {
884
-        $migrates_to_version_info = $this->migrates_to_version();
885
-        // the slug is the first part of the array
886
-        return $migrates_to_version_info['slug'];
887
-    }
888
-
889
-
890
-    /**
891
-     * Returns the script's priority relative to DMSs from other addons. However, when
892
-     * two DMSs from the same addon/core apply, this is ignored (and instead the version that
893
-     * the script migrates to is used to determine which to run first). The default is 5, but all core DMSs
894
-     * normally have priority 10. (So if you want a DMS "A" to run before DMS "B", both of which are from addons,
895
-     * and both of which CAN run at the same time (ie, "B" doesn't depend on "A" to set
896
-     * the database up so it can run), then you can set "A" to priority 3 or something.
897
-     *
898
-     * @return int
899
-     */
900
-    public function priority()
901
-    {
902
-        return $this->_priority;
903
-    }
904
-
905
-
906
-    /**
907
-     * Sets whether this DMS is being ran as part of a migration, instead of
908
-     * just being used to setup (or verify) the current database structure matches
909
-     * what the latest DMS indicates it should be
910
-     *
911
-     * @param boolean $migrating
912
-     * @return void
913
-     */
914
-    public function set_migrating($migrating = true)
915
-    {
916
-        $this->_migrating = $migrating;
917
-    }
918
-
919
-    /**
920
-     * Marks that we think this migration class can continue to migrate
921
-     */
922
-    public function reattempt()
923
-    {
924
-        parent::reattempt();
925
-        // also, we want to reattempt any stages that were marked as borked
926
-        foreach ($this->stages() as $stage) {
927
-            if ($stage->is_broken()) {
928
-                $stage->reattempt();
929
-            }
930
-        }
931
-    }
18
+	/**
19
+	 * Set by client code to indicate this DMS is being ran as part of a proper migration,
20
+	 * instead of being used to merely setup (or verify) the database structure.
21
+	 * Defaults to TRUE, so client code that's NOT using this DMS as part of a proper migration
22
+	 * should call EE_Data_Migration_Script_Base::set_migrating( FALSE )
23
+	 *
24
+	 * @var boolean
25
+	 */
26
+	protected bool $_migrating = true;
27
+
28
+	/**
29
+	 * numerically-indexed array where each value is EE_Data_Migration_Script_Stage object
30
+	 *
31
+	 * @var EE_Data_Migration_Script_Stage[] $migration_functions
32
+	 */
33
+	protected array $_migration_stages = array();
34
+
35
+	/**
36
+	 * Indicates we've already run the schema changes that needed to happen BEFORE the data migration
37
+	 *
38
+	 * @var boolean
39
+	 */
40
+	protected ?bool $_schema_changes_before_migration_ran = null;
41
+
42
+	/**
43
+	 * Indicates we've already run the schema changes that needed to happen AFTER the data migration
44
+	 *
45
+	 * @var boolean
46
+	 */
47
+	protected ?bool $_schema_changes_after_migration_ran = null;
48
+
49
+	/**
50
+	 * String which describes what's currently happening in this migration
51
+	 *
52
+	 * @var string|null
53
+	 */
54
+	protected ?string $_feedback_message = '';
55
+
56
+	/**
57
+	 * Indicates the script's priority. Like wp's add_action and add_filter, lower numbers
58
+	 * correspond to earlier execution
59
+	 *
60
+	 * @var int
61
+	 */
62
+	protected int $_priority = 5;
63
+
64
+	/**
65
+	 * Multidimensional array that defines the mapping from OLD table Primary Keys
66
+	 * to NEW table Primary Keys.
67
+	 * Top-level array keys are OLD table names (minus the "wp_" part),
68
+	 * 2nd-level array keys are NEW table names (again, minus the "wp_" part),
69
+	 * 3rd-level array keys are the OLD table primary keys
70
+	 * and 3rd-level array values are the NEW table primary keys
71
+	 *
72
+	 * @var array
73
+	 */
74
+	protected array $_mappings = array();
75
+
76
+	/**
77
+	 * @var EE_Data_Migration_Script_Base
78
+	 */
79
+	protected EE_Data_Migration_Script_Base $previous_dms;
80
+
81
+
82
+	/**
83
+	 * Returns whether this data migration script can operate on the given version of the database.
84
+	 * Eg, if this migration script can migrate from 3.1.26 or higher (but not anything after 4.0.0), and
85
+	 * it's passed a string like '3.1.38B', it should return true.
86
+	 * If this DMS is to migrate data from an EE3 addon, you will probably want to use
87
+	 * EventEspresso\core\services\database\TableAnalysis::tableExists() to check for old EE3 tables, and
88
+	 * EE_Data_Migration_Manager::get_migration_ran() to check that core was already
89
+	 * migrated from EE3 to EE4 (ie, this DMS probably relies on some migration data generated
90
+	 * during the Core 4.1.0 DMS. If core didn't run that DMS, you probably don't want
91
+	 * to run this DMS).
92
+	 * If this DMS migrates data from a previous version of this EE4 addon, just
93
+	 * comparing $current_database_state_of[ $this->slug() ] will probably suffice.
94
+	 * If this DMS should never migrate data, because it's only used to define the initial
95
+	 * database state, just return FALSE (and core's activation process will take care
96
+	 * of calling its schema_changes_before_migration() and
97
+	 * schema_changes_after_migration() for you. )
98
+	 *
99
+	 * @param array $version_array keys are EE plugin slugs (eg 'Core', 'Calendar', 'Mailchimp', etc)
100
+	 * @return boolean
101
+	 */
102
+	abstract public function can_migrate_from_version($version_array);
103
+
104
+
105
+	/**
106
+	 * Performs database schema changes that need to occur BEFORE the data is migrated.
107
+	 * Eg, if we were going to change user passwords from plaintext to encoded versions
108
+	 * during this migration, this would probably add a new column called something like
109
+	 * "encoded_password".
110
+	 *
111
+	 * @return boolean of success
112
+	 */
113
+	abstract public function schema_changes_before_migration();
114
+
115
+
116
+	/**
117
+	 * Performs the database schema changes that need to occur AFTER the data has been migrated.
118
+	 * Usually this will mean we'll be removing old columns. Eg, if we were changing passwords
119
+	 * from plaintext to encoded versions, and we had added a column called "encoded_password",
120
+	 * this function would probably remove the old column "password" (which still holds the plaintext password)
121
+	 * and possibly rename "encoded_password" to "password"
122
+	 *
123
+	 * @return boolean of success
124
+	 */
125
+	abstract public function schema_changes_after_migration();
126
+
127
+
128
+	/**
129
+	 * All children of this must call parent::__construct()
130
+	 * at the end of their constructor or suffer the consequences!
131
+	 *
132
+	 * @param TableManager|null  $table_manager
133
+	 * @param TableAnalysis|null $table_analysis
134
+	 */
135
+	public function __construct(TableManager $table_manager = null, TableAnalysis $table_analysis = null)
136
+	{
137
+		$this->_migration_stages = (array) apply_filters(
138
+			'FHEE__' . get_class($this) . '__construct__migration_stages',
139
+			$this->_migration_stages
140
+		);
141
+		foreach ($this->_migration_stages as $migration_stage) {
142
+			if ($migration_stage instanceof EE_Data_Migration_Script_Stage) {
143
+				$migration_stage->_construct_finalize($this);
144
+			}
145
+		}
146
+		parent::__construct($table_manager, $table_analysis);
147
+	}
148
+
149
+
150
+	/**
151
+	 * Place to add hooks and filters for tweaking the migrations page, in order
152
+	 * to customize it
153
+	 */
154
+	public function migration_page_hooks()
155
+	{
156
+		// by default none are added because we normally like the default look of the migration page
157
+	}
158
+
159
+
160
+	/**
161
+	 * Sets the mapping from old table primary keys to new table primary keys.
162
+	 * This mapping is automatically persisted as a property on the migration
163
+	 *
164
+	 * @param string     $old_table with wpdb prefix (wp_). Eg: wp_events_detail
165
+	 * @param int|string $old_pk    old primary key. Eg events_detail.id's value
166
+	 * @param string     $new_table with wpdb prefix (wp_). Eg: wp_posts
167
+	 * @param array|int|string $new_pk    eg posts.ID
168
+	 * @return void
169
+	 * @throws EE_Error
170
+	 */
171
+	public function set_mapping($old_table, $old_pk, $new_table, $new_pk)
172
+	{
173
+		// make sure it has the needed keys
174
+		if (! isset($this->_mappings[ $old_table ]) || ! isset($this->_mappings[ $old_table ][ $new_table ])) {
175
+			$this->_mappings[ $old_table ][ $new_table ] = $this->_get_mapping_option($old_table, $new_table);
176
+		}
177
+		$this->_mappings[ $old_table ][ $new_table ][ $old_pk ] = $new_pk;
178
+	}
179
+
180
+
181
+	/**
182
+	 * Gets the new primary key, if provided with the OLD table and the primary key
183
+	 * of an item in the old table, and the new table
184
+	 *
185
+	 * @param string     $old_table with wpdb prefix (wp_). Eg: wp_events_detail
186
+	 * @param int|string $old_pk    old primary key. Eg events_detail.id's value
187
+	 * @param string     $new_table with wpdb prefix (wp_). Eg: wp_posts
188
+	 * @return mixed the primary key on the new table
189
+	 * @throws EE_Error
190
+	 */
191
+	public function get_mapping_new_pk($old_table, $old_pk, $new_table)
192
+	{
193
+		if (
194
+			! isset($this->_mappings[ $old_table ]) ||
195
+			! isset($this->_mappings[ $old_table ][ $new_table ])
196
+		) {
197
+			// try fetching the option
198
+			$this->_mappings[ $old_table ][ $new_table ] = $this->_get_mapping_option($old_table, $new_table);
199
+		}
200
+		return isset($this->_mappings[ $old_table ][ $new_table ][ $old_pk ])
201
+			? $this->_mappings[ $old_table ][ $new_table ][ $old_pk ] : null;
202
+	}
203
+
204
+
205
+	/**
206
+	 * Gets the old primary key, if provided with the OLD table,
207
+	 * and the new table and the primary key of an item in the new table
208
+	 *
209
+	 * @param string $old_table with wpdb prefix (wp_). Eg: wp_events_detail
210
+	 * @param string $new_table with wpdb prefix (wp_). Eg: wp_posts
211
+	 * @param mixed  $new_pk
212
+	 * @return mixed
213
+	 * @throws EE_Error
214
+	 */
215
+	public function get_mapping_old_pk($old_table, $new_table, $new_pk)
216
+	{
217
+		if (
218
+			! isset($this->_mappings[ $old_table ]) ||
219
+			! isset($this->_mappings[ $old_table ][ $new_table ])
220
+		) {
221
+			// try fetching the option
222
+			$this->_mappings[ $old_table ][ $new_table ] = $this->_get_mapping_option($old_table, $new_table);
223
+		}
224
+		if (isset($this->_mappings[ $old_table ][ $new_table ])) {
225
+			$new_pk_to_old_pk = array_flip($this->_mappings[ $old_table ][ $new_table ]);
226
+			if (isset($new_pk_to_old_pk[ $new_pk ])) {
227
+				return $new_pk_to_old_pk[ $new_pk ];
228
+			}
229
+		}
230
+		return null;
231
+	}
232
+
233
+
234
+	/**
235
+	 * Gets the mapping array option specified by the table names
236
+	 *
237
+	 * @param string $old_table_name
238
+	 * @param string $new_table_name
239
+	 * @return array
240
+	 * @throws EE_Error
241
+	 */
242
+	protected function _get_mapping_option($old_table_name, $new_table_name)
243
+	{
244
+		return get_option($this->_get_mapping_option_name($old_table_name, $new_table_name), array());
245
+	}
246
+
247
+
248
+	/**
249
+	 * Updates the mapping option specified by the table names with the array provided
250
+	 *
251
+	 * @param string $old_table_name
252
+	 * @param string $new_table_name
253
+	 * @param array  $mapping_array
254
+	 * @return boolean success of updating option
255
+	 * @throws EE_Error
256
+	 */
257
+	protected function _set_mapping_option($old_table_name, $new_table_name, $mapping_array)
258
+	{
259
+		$success = update_option($this->_get_mapping_option_name($old_table_name, $new_table_name), $mapping_array, false);
260
+		return $success;
261
+	}
262
+
263
+
264
+	/**
265
+	 * Gets the option name for this script to map from $old_table_name to $new_table_name
266
+	 *
267
+	 * @param string $old_table_name
268
+	 * @param string $new_table_name
269
+	 * @return string
270
+	 * @throws EE_Error
271
+	 */
272
+	protected function _get_mapping_option_name($old_table_name, $new_table_name)
273
+	{
274
+		global $wpdb;
275
+		$old_table_name_sans_wp = str_replace($wpdb->prefix, "", $old_table_name);
276
+		$new_table_name_sans_wp = str_replace($wpdb->prefix, "", $new_table_name);
277
+		$migrates_to = EE_Data_Migration_Manager::instance()->script_migrates_to_version(get_class($this));
278
+		return substr(
279
+			EE_Data_Migration_Manager::data_migration_script_mapping_option_prefix . $migrates_to ['slug'] . '_' . $migrates_to['version'] . '_' . $old_table_name_sans_wp . '_' . $new_table_name_sans_wp,
280
+			0,
281
+			64
282
+		);
283
+	}
284
+
285
+
286
+	/**
287
+	 * Counts all the records that will be migrated during this data migration.
288
+	 * For example, if we were changing old user passwords from plaintext to encoded versions,
289
+	 * this would be a count of all users who have passwords. If we were going to also split
290
+	 * attendee records into transactions, registrations, and attendee records, this would include
291
+	 * the count of all attendees currently in existence in the DB (ie, users + attendees).
292
+	 * If you can't determine how many records there are to migrate, just provide a guess: this
293
+	 * number will only be used in calculating the percent complete. If you estimate there to be
294
+	 * 100 records to migrate, and it turns out there's 120, we'll just show the migration as being at
295
+	 * 99% until the function "migration_step" returns EE_Data_Migration_Script_Base::status_complete.
296
+	 *
297
+	 * @return int
298
+	 */
299
+	protected function _count_records_to_migrate()
300
+	{
301
+		$count = 0;
302
+		foreach ($this->stages() as $stage) {
303
+			$count += $stage->count_records_to_migrate();
304
+		}
305
+		return $count;
306
+	}
307
+
308
+
309
+	/**
310
+	 * Returns the number of records updated so far. Usually this is easiest to do
311
+	 * by just setting a transient and updating it after each migration_step
312
+	 *
313
+	 * @return int
314
+	 */
315
+	public function count_records_migrated()
316
+	{
317
+		$count = 0;
318
+		foreach ($this->stages() as $stage) {
319
+			$count += $stage->count_records_migrated();
320
+		}
321
+		$this->_records_migrated = $count;
322
+		return $count;
323
+	}
324
+
325
+
326
+	/**
327
+	 * @param int $num_records_to_migrate_limit
328
+	 * @return int
329
+	 * @throws EE_Error
330
+	 * @throws Exception
331
+	 */
332
+	public function migration_step($num_records_to_migrate_limit)
333
+	{
334
+		// reset the feedback message
335
+		$this->_feedback_message = '';
336
+		// if we haven't yet done the 1st schema changes, do them now. buffer any output
337
+		$this->_maybe_do_schema_changes(true);
338
+
339
+		$num_records_actually_migrated = 0;
340
+		$records_migrated_per_stage = array();
341
+		// setup the 'stage' variable, which should hold the last run stage of the migration  (or none at all if nothing runs)
342
+		$stage = null;
343
+		// get the next stage that isn't complete
344
+		foreach ($this->stages() as $stage) {
345
+			if ($stage->get_status() == EE_Data_Migration_Manager::status_continue) {
346
+				try {
347
+					$records_migrated_during_stage = $stage->migration_step(
348
+						$num_records_to_migrate_limit - $num_records_actually_migrated
349
+					);
350
+					$num_records_actually_migrated += $records_migrated_during_stage;
351
+					$records_migrated_per_stage[ $stage->pretty_name() ] = $records_migrated_during_stage;
352
+				} catch (Exception $e) {
353
+					// yes if we catch an exception here, we consider that migration stage borked.
354
+					$stage->set_status(EE_Data_Migration_Manager::status_fatal_error);
355
+					$this->set_status(EE_Data_Migration_Manager::status_fatal_error);
356
+					$stage->add_error($e->getMessage() . ". Stack-trace:" . $e->getTraceAsString());
357
+					throw $e;
358
+				}
359
+				// check that the migration stage didn't mark itself as having a fatal error
360
+				if ($stage->is_broken()) {
361
+					$this->set_broken();
362
+					throw new EE_Error($stage->get_last_error());
363
+				}
364
+			}
365
+			// once we've migrated all the number we intended to (possibly from different stages), stop migrating
366
+			// or if we had a fatal error
367
+			// or if the current script stopped early- its not done, but it's done all it thinks we should do on this step
368
+			if (
369
+				$num_records_actually_migrated >= $num_records_to_migrate_limit
370
+				|| $stage->is_broken()
371
+				|| $stage->has_more_to_do()
372
+			) {
373
+				break;
374
+			}
375
+		}
376
+		// check if we're all done this data migration...
377
+		// which is indicated by being done early AND the last stage claims to be done
378
+		if ($stage == null) {
379
+			// this migration script apparently has NO stages... which is super weird, but whatever
380
+			$this->set_completed();
381
+			$this->_maybe_do_schema_changes(false);
382
+		} elseif ($num_records_actually_migrated < $num_records_to_migrate_limit && ! $stage->has_more_to_do()) {
383
+			// apparently we're done, because we couldn't migrate the number we intended to
384
+			$this->set_completed();
385
+			$this->_update_feedback_message(array_reverse($records_migrated_per_stage));
386
+			// do schema changes for after the migration now
387
+			// first double-check we haven't already done this
388
+			$this->_maybe_do_schema_changes(false);
389
+		} else {
390
+			// update feedback message, keeping in mind that we show them with the most recent at the top
391
+			$this->_update_feedback_message(array_reverse($records_migrated_per_stage));
392
+		}
393
+		return $num_records_actually_migrated;
394
+	}
395
+
396
+
397
+	/**
398
+	 * Updates the feedback message according to what was done during this migration stage.
399
+	 *
400
+	 * @param array $records_migrated_per_stage KEYS are pretty names for each stage; values are the count of records
401
+	 *                                          migrated from that stage
402
+	 * @return void
403
+	 */
404
+	private function _update_feedback_message($records_migrated_per_stage)
405
+	{
406
+		$feedback_message_array = array();
407
+		foreach ($records_migrated_per_stage as $migration_stage_name => $num_records_migrated) {
408
+			$feedback_message_array[] = sprintf(
409
+				esc_html__("Migrated %d records successfully during %s", "event_espresso"),
410
+				$num_records_migrated,
411
+				$migration_stage_name
412
+			);
413
+		}
414
+		$this->_feedback_message .= implode("<br>", $feedback_message_array);
415
+	}
416
+
417
+
418
+	/**
419
+	 * Calls either schema_changes_before_migration() (if $before==true) or schema_changes_after_migration
420
+	 * (if $before==false). Buffers their outputs and stores them on the class.
421
+	 *
422
+	 * @param boolean $before
423
+	 * @throws Exception
424
+	 * @return void
425
+	 */
426
+	private function _maybe_do_schema_changes($before = true)
427
+	{
428
+		// so this property will be either _schema_changes_after_migration_ran or _schema_changes_before_migration_ran
429
+		$property_name = '_schema_changes_' . ($before ? 'before' : 'after') . '_migration_ran';
430
+		if (! $this->{$property_name}) {
431
+			try {
432
+				ob_start();
433
+				if ($before) {
434
+					$this->schema_changes_before_migration();
435
+				} else {
436
+					$this->schema_changes_after_migration();
437
+				}
438
+				$output = ob_get_contents();
439
+				ob_end_clean();
440
+			} catch (Exception $e) {
441
+				$this->set_status(EE_Data_Migration_Manager::status_fatal_error);
442
+				throw $e;
443
+			}
444
+			// record that we've done these schema changes
445
+			$this->{$property_name} = true;
446
+			// if there were any warnings etc, record them as non-fatal errors
447
+			if ($output) {
448
+				// there were some warnings
449
+				$this->_errors[] = $output;
450
+			}
451
+		}
452
+	}
453
+
454
+
455
+	/**
456
+	 * Wrapper for EEH_Activation::create_table. However, takes into account the request type when
457
+	 * deciding what to pass for its 4th arg, $drop_pre_existing_tables. Using this function, instead
458
+	 * of _table_should_exist_previously, indicates that this table should be new to the EE version being migrated to
459
+	 * or
460
+	 * activated currently. If this is a brand new activation or a migration, and we're indicating this table should
461
+	 * not
462
+	 * previously exist, then we want to set $drop_pre_existing_tables to TRUE (ie, we shouldn't discover that this
463
+	 * table exists in the DB in EEH_Activation::create_table- if it DOES exist, something's wrong and the old table
464
+	 * should be nuked.
465
+	 *
466
+	 * Just for a bit of context, the migration script's db_schema_changes_* methods
467
+	 * are called basically in 3 cases: on brand new activation of EE4 (ie no previous version of EE existed and the
468
+	 * plugin is being activated and we want to add all the brand new tables), upon reactivation of EE4 (it was
469
+	 * deactivated and then reactivated, in which case we want to just verify the DB structure is ok) that table should
470
+	 * be dropped), and during a migration when we're moving the DB to the state of the migration script
471
+	 *
472
+	 * @param string $table_name
473
+	 * @param string $table_definition_sql
474
+	 * @param string $engine_string
475
+	 * @throws EE_Error
476
+	 * @throws ReflectionException
477
+	 */
478
+	protected function _table_is_new_in_this_version(
479
+		$table_name,
480
+		$table_definition_sql,
481
+		$engine_string = 'ENGINE=InnoDB'
482
+	) {
483
+		$this->_create_table_and_catch_errors(
484
+			$table_name,
485
+			$table_definition_sql,
486
+			$engine_string,
487
+			$this->_pre_existing_table_should_be_dropped(true)
488
+		);
489
+	}
490
+
491
+
492
+	/**
493
+	 * Like _table_is_new_in_this_version and _table_should_exist_previously, this function verifies the given table
494
+	 * exists. But we understand that this table has CHANGED in this version since the previous version. So it's not
495
+	 * completely new, but it's different. So we need to treat it like a new table in terms of verifying it's schema is
496
+	 * correct on activations, migrations, upgrades; but if it exists when it shouldn't, we need to be as lenient as
497
+	 * _table_should_exist_previously.
498
+	 * 8656]{Assumes only this plugin could have added this table (ie, if its a new activation of this plugin, the
499
+	 * table shouldn't exist).
500
+	 *
501
+	 * @param string $table_name
502
+	 * @param string $table_definition_sql
503
+	 * @param string $engine_string
504
+	 * @throws EE_Error
505
+	 * @throws ReflectionException
506
+	 */
507
+	protected function _table_is_changed_in_this_version(
508
+		$table_name,
509
+		$table_definition_sql,
510
+		$engine_string = 'ENGINE=InnoDB'
511
+	) {
512
+		$this->_create_table_and_catch_errors(
513
+			$table_name,
514
+			$table_definition_sql,
515
+			$engine_string,
516
+			$this->_pre_existing_table_should_be_dropped(false)
517
+		);
518
+	}
519
+
520
+
521
+	/**
522
+	 * _old_table_exists
523
+	 * returns TRUE if the requested table exists in the current database
524
+	 *
525
+	 * @param string $table_name
526
+	 * @return boolean
527
+	 * @throws EE_Error
528
+	 */
529
+	protected function _old_table_exists($table_name)
530
+	{
531
+		return $this->_get_table_analysis()->tableExists($table_name);
532
+	}
533
+
534
+
535
+	/**
536
+	 * _delete_table_if_empty
537
+	 * returns TRUE if the requested table was empty and successfully empty
538
+	 *
539
+	 * @param string $table_name
540
+	 * @return boolean
541
+	 * @throws EE_Error
542
+	 * @throws ReflectionException
543
+	 */
544
+	protected function _delete_table_if_empty($table_name)
545
+	{
546
+		return EEH_Activation::delete_db_table_if_empty($table_name);
547
+	}
548
+
549
+
550
+	/**
551
+	 * It is preferred to use _table_has_not_changed_since_previous or _table_is_changed_in_this_version
552
+	 * as these are significantly more efficient or explicit.
553
+	 * Please see description of _table_is_new_in_this_version. This function will only set
554
+	 * EEH_Activation::create_table's $drop_pre_existing_tables to TRUE if it's a brand
555
+	 * new activation. ie, a more accurate name for this method would be "_table_added_previously_by_this_plugin"
556
+	 * because the table will be cleared out if this is a new activation (ie, if its a new activation, it actually
557
+	 * should exist previously). Otherwise, we'll always set $drop_pre_existing_tables to FALSE because the table
558
+	 * should have existed. Note, if the table is being MODIFIED in this version being activated or migrated to, then
559
+	 * you want _table_is_changed_in_this_version NOT this one. We don't check this table's structure during migrations
560
+	 * because apparently it hasn't changed since the previous one, right?
561
+	 *
562
+	 * @param string $table_name
563
+	 * @param string $table_definition_sql
564
+	 * @param string $engine_string
565
+	 * @throws EE_Error
566
+	 * @throws ReflectionException
567
+	 */
568
+	protected function _table_should_exist_previously(
569
+		$table_name,
570
+		$table_definition_sql,
571
+		$engine_string = 'ENGINE=InnoDB'
572
+	) {
573
+		$this->_create_table_and_catch_errors(
574
+			$table_name,
575
+			$table_definition_sql,
576
+			$engine_string,
577
+			$this->_pre_existing_table_should_be_dropped(false)
578
+		);
579
+	}
580
+
581
+
582
+	/**
583
+	 * Exactly the same as _table_should_exist_previously(), except if this migration script is currently doing
584
+	 * a migration, we skip checking this table's structure in the database and just assume it's correct.
585
+	 * So this is useful only to improve efficiency when doing migrations (not a big deal for single site installs,
586
+	 * but important for multisite where migrations can take a very long time otherwise).
587
+	 * If the table is known to have changed since previous version, use _table_is_changed_in_this_version().
588
+	 * Assumes only this plugin could have added this table (ie, if its a new activation of this plugin, the table
589
+	 * shouldn't exist).
590
+	 *
591
+	 * @param string $table_name
592
+	 * @param string $table_definition_sql
593
+	 * @param string $engine_string
594
+	 * @throws EE_Error
595
+	 * @throws ReflectionException
596
+	 */
597
+	protected function _table_has_not_changed_since_previous(
598
+		$table_name,
599
+		$table_definition_sql,
600
+		$engine_string = 'ENGINE=InnoDB'
601
+	) {
602
+		if ($this->_currently_migrating()) {
603
+			// if we're doing a migration, and this table apparently already exists, then we don't need do anything right?
604
+			return;
605
+		}
606
+		$this->_create_table_and_catch_errors(
607
+			$table_name,
608
+			$table_definition_sql,
609
+			$engine_string,
610
+			$this->_pre_existing_table_should_be_dropped(false)
611
+		);
612
+	}
613
+
614
+	/**
615
+	 * Returns whether this migration script is being used as part of an actual migration
616
+	 *
617
+	 * @return boolean
618
+	 */
619
+	protected function _currently_migrating()
620
+	{
621
+		// we want to know if we are currently performing a migration. We could just believe what was set on the _migrating property, but let's double-check (ie the script should apply and we should be in MM)
622
+		return $this->_migrating
623
+			&& DbStatus::isOffline()
624
+			&& $this->can_migrate_from_version(
625
+				EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set()
626
+			);
627
+	}
628
+
629
+
630
+	/**
631
+	 * Determines if a table should be dropped, based on whether it's reported to be new in $table_is_new,
632
+	 * and the plugin's request type.
633
+	 * Assumes only this plugin could have added the table (ie, if its a new activation of this plugin, the table
634
+	 * shouldn't exist no matter what).
635
+	 *
636
+	 * @param boolean $table_is_new
637
+	 * @return boolean
638
+	 * @throws EE_Error
639
+	 */
640
+	protected function _pre_existing_table_should_be_dropped($table_is_new)
641
+	{
642
+		if ($table_is_new) {
643
+			if (
644
+				$this->_get_req_type_for_plugin_corresponding_to_this_dms() == EE_System::req_type_new_activation
645
+				|| $this->_currently_migrating()
646
+			) {
647
+				return true;
648
+			} else {
649
+				return false;
650
+			}
651
+		} else {
652
+			if (
653
+				in_array(
654
+					$this->_get_req_type_for_plugin_corresponding_to_this_dms(),
655
+					array(EE_System::req_type_new_activation)
656
+				)
657
+			) {
658
+				return true;
659
+			} else {
660
+				return false;
661
+			}
662
+		}
663
+	}
664
+
665
+
666
+	/**
667
+	 * Just wraps EEH_Activation::create_table, but catches any errors it may throw and adds them as errors on the DMS
668
+	 *
669
+	 * @param string  $table_name
670
+	 * @param string  $table_definition_sql
671
+	 * @param string  $engine_string
672
+	 * @param boolean $drop_pre_existing_tables
673
+	 * @throws ReflectionException
674
+	 */
675
+	private function _create_table_and_catch_errors(
676
+		$table_name,
677
+		$table_definition_sql,
678
+		$engine_string = 'ENGINE=InnoDB',
679
+		$drop_pre_existing_tables = false
680
+	) {
681
+		try {
682
+			EEH_Activation::create_table($table_name, $table_definition_sql, $engine_string, $drop_pre_existing_tables);
683
+		} catch (EE_Error $e) {
684
+			$message = $e->getMessage() . '<br>Stack Trace:' . $e->getTraceAsString();
685
+			$this->add_error($message);
686
+			$this->_feedback_message .= $message;
687
+		}
688
+	}
689
+
690
+
691
+	/**
692
+	 * Gets the request type for the plugin (core or addon) that corresponds to this DMS
693
+	 *
694
+	 * @return int one of EE_System::_req_type_* constants
695
+	 * @throws EE_Error
696
+	 */
697
+	private function _get_req_type_for_plugin_corresponding_to_this_dms()
698
+	{
699
+		if ($this->slug() == 'Core') {
700
+			return EE_System::instance()->detect_req_type();
701
+		} else {// it must be for an addon
702
+			$addon_name = $this->slug();
703
+			if (EE_Registry::instance()->get_addon_by_name($addon_name)) {
704
+				return EE_Registry::instance()->get_addon_by_name($addon_name)->detect_req_type();
705
+			} else {
706
+				throw new EE_Error(
707
+					sprintf(
708
+						esc_html__(
709
+							"The DMS slug '%s' should correspond to the addon's name, which should also be '%s', but no such addon was registered. These are the registered addons' names: %s",
710
+							"event_espresso"
711
+						),
712
+						$this->slug(),
713
+						$addon_name,
714
+						implode(",", array_keys(EE_Registry::instance()->get_addons_by_name()))
715
+					)
716
+				);
717
+			}
718
+		}
719
+	}
720
+
721
+
722
+	/**
723
+	 * returns an array of strings describing errors by all the script's stages
724
+	 *
725
+	 * @return array
726
+	 */
727
+	public function get_errors()
728
+	{
729
+		$all_errors = $this->_errors;
730
+		if (! is_array($all_errors)) {
731
+			$all_errors = array();
732
+		}
733
+		foreach ($this->stages() as $stage) {
734
+			$all_errors = array_merge($stage->get_errors(), $all_errors);
735
+		}
736
+		return $all_errors;
737
+	}
738
+
739
+
740
+	/**
741
+	 * Indicates whether this migration script should continue
742
+	 *
743
+	 * @return boolean
744
+	 */
745
+	public function can_continue()
746
+	{
747
+		return in_array(
748
+			$this->get_status(),
749
+			EE_Data_Migration_Manager::instance()->stati_that_indicate_to_continue_single_migration_script
750
+		);
751
+	}
752
+
753
+
754
+	/**
755
+	 * Gets all the data migration stages associated with this script. Note:
756
+	 * addons can filter this list to add their own stages, and because the list is
757
+	 * numerically-indexed, they can insert their stage wherever they like and it will
758
+	 * get ordered by the indexes
759
+	 *
760
+	 * @return EE_Data_Migration_Script_Stage[]
761
+	 */
762
+	protected function stages()
763
+	{
764
+		$stages = apply_filters('FHEE__' . get_class($this) . '__stages', $this->_migration_stages);
765
+		ksort($stages);
766
+		return $stages;
767
+	}
768
+
769
+
770
+	/**
771
+	 * Gets a string which should describe what's going on currently with this migration, which
772
+	 * can be displayed to the user
773
+	 *
774
+	 * @return string
775
+	 */
776
+	public function get_feedback_message()
777
+	{
778
+		return $this->_feedback_message;
779
+	}
780
+
781
+
782
+	/**
783
+	 * A lot like "__sleep()" magic method in purpose, this is meant for persisting this class'
784
+	 * properties to the DB. However, we don't want to use __sleep() because its quite
785
+	 * possible that this class is defined when it goes to sleep, but NOT available when it
786
+	 * awakes (eg, this class is part of an addon that is deactivated at some point).
787
+	 */
788
+	public function properties_as_array()
789
+	{
790
+		$properties = parent::properties_as_array();
791
+		$properties['_migration_stages'] = array();
792
+		foreach ($this->_migration_stages as $migration_stage_priority => $migration_stage_class) {
793
+			$properties['_migration_stages'][ $migration_stage_priority ] = $migration_stage_class->properties_as_array(
794
+			);
795
+		}
796
+		unset($properties['_mappings']);
797
+		unset($properties['previous_dms']);
798
+
799
+		foreach ($this->_mappings as $old_table_name => $mapping_to_new_table) {
800
+			foreach ($mapping_to_new_table as $new_table_name => $mapping) {
801
+				$this->_set_mapping_option($old_table_name, $new_table_name, $mapping);
802
+			}
803
+		}
804
+		return $properties;
805
+	}
806
+
807
+
808
+	/**
809
+	 * Sets all of the properties of this script stage to match what's in the array, which is assumed
810
+	 * to have been made from the properties_as_array() function.
811
+	 *
812
+	 * @param array $array_of_properties like what's produced from properties_as_array() method
813
+	 * @return void
814
+	 */
815
+	public function instantiate_from_array_of_properties($array_of_properties)
816
+	{
817
+		$stages_properties_arrays = $array_of_properties['_migration_stages'];
818
+		unset($array_of_properties['_migration_stages']);
819
+		unset($array_of_properties['class']);
820
+		foreach ($array_of_properties as $property_name => $property_value) {
821
+			$this->{$property_name} = $property_value;
822
+		}
823
+		// _migration_stages are already instantiated, but have only default data
824
+		foreach ($this->_migration_stages as $stage) {
825
+			$stage_data = $this->_find_migration_stage_data_with_classname(
826
+				get_class($stage),
827
+				$stages_properties_arrays
828
+			);
829
+			// SO, if we found the stage data that was saved, use it. Otherwise, I guess the stage is new? (maybe added by
830
+			// an addon? Unlikely... not sure why it wouldn't exist, but if it doesn't just treat it like it was never started yet)
831
+			if ($stage_data) {
832
+				$stage->instantiate_from_array_of_properties($stage_data);
833
+			}
834
+		}
835
+	}
836
+
837
+
838
+	/**
839
+	 * Gets the migration data from the array $migration_stage_data_arrays (which is an array of arrays, each of which
840
+	 * is pretty well identical to EE_Data_Migration_Stage objects except all their properties are array indexes)
841
+	 * for the given classname
842
+	 *
843
+	 * @param string $classname
844
+	 * @param array  $migration_stage_data_arrays
845
+	 * @return null
846
+	 */
847
+	private function _find_migration_stage_data_with_classname($classname, $migration_stage_data_arrays)
848
+	{
849
+		foreach ($migration_stage_data_arrays as $migration_stage_data_array) {
850
+			if (isset($migration_stage_data_array['class']) && $migration_stage_data_array['class'] == $classname) {
851
+				return $migration_stage_data_array;
852
+			}
853
+		}
854
+		return null;
855
+	}
856
+
857
+
858
+	/**
859
+	 * Returns the version that this script migrates to, based on the script's name.
860
+	 * Cannot be overwritten because lots of code needs to know which version a script
861
+	 * migrates to knowing only its name.
862
+	 *
863
+	 * @return array where the first key is the plugin's slug, the 2nd is the version of that plugin
864
+	 * that will be updated to. Eg array('Core','4.1.0')
865
+	 * @throws EE_Error
866
+	 */
867
+	final public function migrates_to_version()
868
+	{
869
+		return EE_Data_Migration_Manager::instance()->script_migrates_to_version(get_class($this));
870
+	}
871
+
872
+
873
+	/**
874
+	 * Gets this addon's slug as it would appear in the current_db_state wp option,
875
+	 * and if this migration script is for an addon, it SHOULD match the addon's slug
876
+	 * (and also the addon's classname, minus the 'EE_' prefix.). Eg, 'Calendar' for the EE_Calendar addon.
877
+	 * Or 'Core' for core (non-addon).
878
+	 *
879
+	 * @return string
880
+	 * @throws EE_Error
881
+	 */
882
+	public function slug()
883
+	{
884
+		$migrates_to_version_info = $this->migrates_to_version();
885
+		// the slug is the first part of the array
886
+		return $migrates_to_version_info['slug'];
887
+	}
888
+
889
+
890
+	/**
891
+	 * Returns the script's priority relative to DMSs from other addons. However, when
892
+	 * two DMSs from the same addon/core apply, this is ignored (and instead the version that
893
+	 * the script migrates to is used to determine which to run first). The default is 5, but all core DMSs
894
+	 * normally have priority 10. (So if you want a DMS "A" to run before DMS "B", both of which are from addons,
895
+	 * and both of which CAN run at the same time (ie, "B" doesn't depend on "A" to set
896
+	 * the database up so it can run), then you can set "A" to priority 3 or something.
897
+	 *
898
+	 * @return int
899
+	 */
900
+	public function priority()
901
+	{
902
+		return $this->_priority;
903
+	}
904
+
905
+
906
+	/**
907
+	 * Sets whether this DMS is being ran as part of a migration, instead of
908
+	 * just being used to setup (or verify) the current database structure matches
909
+	 * what the latest DMS indicates it should be
910
+	 *
911
+	 * @param boolean $migrating
912
+	 * @return void
913
+	 */
914
+	public function set_migrating($migrating = true)
915
+	{
916
+		$this->_migrating = $migrating;
917
+	}
918
+
919
+	/**
920
+	 * Marks that we think this migration class can continue to migrate
921
+	 */
922
+	public function reattempt()
923
+	{
924
+		parent::reattempt();
925
+		// also, we want to reattempt any stages that were marked as borked
926
+		foreach ($this->stages() as $stage) {
927
+			if ($stage->is_broken()) {
928
+				$stage->reattempt();
929
+			}
930
+		}
931
+	}
932 932
 }
Please login to merge, or discard this patch.
core/db_models/strategies/EE_Restriction_Generator_Public.strategy.php 2 patches
Spacing   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -19,7 +19,7 @@  discard block
 block discarded – undo
19 19
     protected function _generate_restrictions(): array
20 20
     {
21 21
         // if there are no standard caps for this model, then for allow full access
22
-        if (! $this->model()->cap_slug()) {
22
+        if ( ! $this->model()->cap_slug()) {
23 23
             return [];
24 24
         }
25 25
 
@@ -32,17 +32,17 @@  discard block
 block discarded – undo
32 32
             )
33 33
         ) {
34 34
             if ($this->model() instanceof EEM_CPT_Base) {
35
-                $restrictions[ EE_Restriction_Generator_Base::get_cap_name(
35
+                $restrictions[EE_Restriction_Generator_Base::get_cap_name(
36 36
                     $this->model(),
37 37
                     $this->action()
38
-                ) ] = new EE_Default_Where_Conditions(
38
+                )] = new EE_Default_Where_Conditions(
39 39
                     $this->addPublishedPostConditions()
40 40
                 );
41 41
             } elseif ($this->model() instanceof EEM_Soft_Delete_Base) {
42
-                $restrictions[ EE_Restriction_Generator_Base::get_cap_name(
42
+                $restrictions[EE_Restriction_Generator_Base::get_cap_name(
43 43
                     $this->model(),
44 44
                     $this->action()
45
-                ) ] = new EE_Default_Where_Conditions(
45
+                )] = new EE_Default_Where_Conditions(
46 46
                     [$this->model()->deleted_field_name() => false]
47 47
                 );
48 48
             }
@@ -52,21 +52,21 @@  discard block
 block discarded – undo
52 52
             if (
53 53
                 EE_Restriction_Generator_Base::is_cap(
54 54
                     $this->model(),
55
-                    $this->action() . '_others'
55
+                    $this->action().'_others'
56 56
                 )
57 57
             ) {// both caps exist
58 58
                 if ($this->model() instanceof EEM_CPT_Base) {
59 59
                     // then if they don't have the others cap,
60 60
                     // AT MOST show them their own and other published ones
61
-                    $restrictions[ EE_Restriction_Generator_Base::get_cap_name(
61
+                    $restrictions[EE_Restriction_Generator_Base::get_cap_name(
62 62
                         $this->model(),
63
-                        $this->action() . '_others'
64
-                    ) ] = new EE_Default_Where_Conditions(
63
+                        $this->action().'_others'
64
+                    )] = new EE_Default_Where_Conditions(
65 65
                         [
66
-                            'OR*' .
66
+                            'OR*'.
67 67
                             EE_Restriction_Generator_Base::get_cap_name(
68 68
                                 $this->model(),
69
-                                $this->action() . '_others'
69
+                                $this->action().'_others'
70 70
                             ) => $this->addPublishedPostConditions(
71 71
                                 [
72 72
                                     EE_QUERY_PLACEHOLDER_USER_FIELD_NAME => EE_QUERY_PLACEHOLDER_CURRENT_USER,
@@ -77,15 +77,15 @@  discard block
 block discarded – undo
77 77
                 } elseif ($this->model() instanceof EEM_Soft_Delete_Base) {
78 78
                     // then if they don't have the other cap,
79 79
                     // AT MOST show them their own or non deleted ones
80
-                    $restrictions[ EE_Restriction_Generator_Base::get_cap_name(
80
+                    $restrictions[EE_Restriction_Generator_Base::get_cap_name(
81 81
                         $this->model(),
82
-                        $this->action() . '_others'
83
-                    ) ] = new EE_Default_Where_Conditions(
82
+                        $this->action().'_others'
83
+                    )] = new EE_Default_Where_Conditions(
84 84
                         [
85
-                            'OR*' .
85
+                            'OR*'.
86 86
                             EE_Restriction_Generator_Base::get_cap_name(
87 87
                                 $this->model(),
88
-                                $this->action() . '_others'
88
+                                $this->action().'_others'
89 89
                             ) => [
90 90
                                 EE_QUERY_PLACEHOLDER_USER_FIELD_NAME => EE_QUERY_PLACEHOLDER_CURRENT_USER,
91 91
                                 $this->model()->deleted_field_name(
@@ -101,20 +101,20 @@  discard block
 block discarded – undo
101 101
                 if (
102 102
                     EE_Restriction_Generator_Base::is_cap(
103 103
                         $this->model(),
104
-                        $this->action() . '_private'
104
+                        $this->action().'_private'
105 105
                     ) && $this->model() instanceof EEM_CPT_Base
106 106
                 ) {
107 107
                     // if they have basic and others, but not private,
108 108
                     // restrict them to see theirs and others' that aren't private
109
-                    $restrictions[ EE_Restriction_Generator_Base::get_cap_name(
109
+                    $restrictions[EE_Restriction_Generator_Base::get_cap_name(
110 110
                         $this->model(),
111
-                        $this->action() . '_private'
112
-                    ) ] = new EE_Default_Where_Conditions(
111
+                        $this->action().'_private'
112
+                    )] = new EE_Default_Where_Conditions(
113 113
                         [
114
-                            'OR*' .
114
+                            'OR*'.
115 115
                             EE_Restriction_Generator_Base::get_cap_name(
116 116
                                 $this->model(),
117
-                                $this->action() . '_private'
117
+                                $this->action().'_private'
118 118
                             ) => $this->addPublishedPostConditions(
119 119
                                 [
120 120
                                     EE_QUERY_PLACEHOLDER_USER_FIELD_NAME => EE_QUERY_PLACEHOLDER_CURRENT_USER,
Please login to merge, or discard this patch.
Indentation   +116 added lines, -116 removed lines patch added patch discarded remove patch
@@ -11,123 +11,123 @@
 block discarded – undo
11 11
  */
12 12
 class EE_Restriction_Generator_Public extends EE_Restriction_Generator_Base
13 13
 {
14
-    /**
15
-     * @return EE_Default_Where_Conditions[]|EE_Return_None_Where_Conditions[]
16
-     * @throws EE_Error
17
-     */
18
-    protected function _generate_restrictions(): array
19
-    {
20
-        // if there are no standard caps for this model, then for allow full access
21
-        if (! $this->model()->cap_slug()) {
22
-            return [];
23
-        }
14
+	/**
15
+	 * @return EE_Default_Where_Conditions[]|EE_Return_None_Where_Conditions[]
16
+	 * @throws EE_Error
17
+	 */
18
+	protected function _generate_restrictions(): array
19
+	{
20
+		// if there are no standard caps for this model, then for allow full access
21
+		if (! $this->model()->cap_slug()) {
22
+			return [];
23
+		}
24 24
 
25
-        $restrictions = [];
26
-        // does the basic cap exist? (eg 'ee_read_registrations')
27
-        if (
28
-            EE_Restriction_Generator_Base::is_cap(
29
-                $this->model(),
30
-                $this->action()
31
-            )
32
-        ) {
33
-            if ($this->model() instanceof EEM_CPT_Base) {
34
-                $restrictions[ EE_Restriction_Generator_Base::get_cap_name(
35
-                    $this->model(),
36
-                    $this->action()
37
-                ) ] = new EE_Default_Where_Conditions(
38
-                    $this->addPublishedPostConditions()
39
-                );
40
-            } elseif ($this->model() instanceof EEM_Soft_Delete_Base) {
41
-                $restrictions[ EE_Restriction_Generator_Base::get_cap_name(
42
-                    $this->model(),
43
-                    $this->action()
44
-                ) ] = new EE_Default_Where_Conditions(
45
-                    [$this->model()->deleted_field_name() => false]
46
-                );
47
-            }
48
-            // don't impose any restrictions if they don't have the basic reading cap
25
+		$restrictions = [];
26
+		// does the basic cap exist? (eg 'ee_read_registrations')
27
+		if (
28
+			EE_Restriction_Generator_Base::is_cap(
29
+				$this->model(),
30
+				$this->action()
31
+			)
32
+		) {
33
+			if ($this->model() instanceof EEM_CPT_Base) {
34
+				$restrictions[ EE_Restriction_Generator_Base::get_cap_name(
35
+					$this->model(),
36
+					$this->action()
37
+				) ] = new EE_Default_Where_Conditions(
38
+					$this->addPublishedPostConditions()
39
+				);
40
+			} elseif ($this->model() instanceof EEM_Soft_Delete_Base) {
41
+				$restrictions[ EE_Restriction_Generator_Base::get_cap_name(
42
+					$this->model(),
43
+					$this->action()
44
+				) ] = new EE_Default_Where_Conditions(
45
+					[$this->model()->deleted_field_name() => false]
46
+				);
47
+			}
48
+			// don't impose any restrictions if they don't have the basic reading cap
49 49
 
50
-            // does the others cap exist? (eg 'ee_read_others_registrations')
51
-            if (
52
-                EE_Restriction_Generator_Base::is_cap(
53
-                    $this->model(),
54
-                    $this->action() . '_others'
55
-                )
56
-            ) {// both caps exist
57
-                if ($this->model() instanceof EEM_CPT_Base) {
58
-                    // then if they don't have the others cap,
59
-                    // AT MOST show them their own and other published ones
60
-                    $restrictions[ EE_Restriction_Generator_Base::get_cap_name(
61
-                        $this->model(),
62
-                        $this->action() . '_others'
63
-                    ) ] = new EE_Default_Where_Conditions(
64
-                        [
65
-                            'OR*' .
66
-                            EE_Restriction_Generator_Base::get_cap_name(
67
-                                $this->model(),
68
-                                $this->action() . '_others'
69
-                            ) => $this->addPublishedPostConditions(
70
-                                [
71
-                                    EE_QUERY_PLACEHOLDER_USER_FIELD_NAME => EE_QUERY_PLACEHOLDER_CURRENT_USER,
72
-                                ]
73
-                            ),
74
-                        ]
75
-                    );
76
-                } elseif ($this->model() instanceof EEM_Soft_Delete_Base) {
77
-                    // then if they don't have the other cap,
78
-                    // AT MOST show them their own or non deleted ones
79
-                    $restrictions[ EE_Restriction_Generator_Base::get_cap_name(
80
-                        $this->model(),
81
-                        $this->action() . '_others'
82
-                    ) ] = new EE_Default_Where_Conditions(
83
-                        [
84
-                            'OR*' .
85
-                            EE_Restriction_Generator_Base::get_cap_name(
86
-                                $this->model(),
87
-                                $this->action() . '_others'
88
-                            ) => [
89
-                                EE_QUERY_PLACEHOLDER_USER_FIELD_NAME => EE_QUERY_PLACEHOLDER_CURRENT_USER,
90
-                                $this->model()->deleted_field_name(
91
-                                )                                    => false,
92
-                            ],
93
-                        ]
94
-                    );
95
-                }
96
-                // again, if they don't have the others cap,
97
-                // continue showing all because there are no inherently hidden ones
50
+			// does the others cap exist? (eg 'ee_read_others_registrations')
51
+			if (
52
+				EE_Restriction_Generator_Base::is_cap(
53
+					$this->model(),
54
+					$this->action() . '_others'
55
+				)
56
+			) {// both caps exist
57
+				if ($this->model() instanceof EEM_CPT_Base) {
58
+					// then if they don't have the others cap,
59
+					// AT MOST show them their own and other published ones
60
+					$restrictions[ EE_Restriction_Generator_Base::get_cap_name(
61
+						$this->model(),
62
+						$this->action() . '_others'
63
+					) ] = new EE_Default_Where_Conditions(
64
+						[
65
+							'OR*' .
66
+							EE_Restriction_Generator_Base::get_cap_name(
67
+								$this->model(),
68
+								$this->action() . '_others'
69
+							) => $this->addPublishedPostConditions(
70
+								[
71
+									EE_QUERY_PLACEHOLDER_USER_FIELD_NAME => EE_QUERY_PLACEHOLDER_CURRENT_USER,
72
+								]
73
+							),
74
+						]
75
+					);
76
+				} elseif ($this->model() instanceof EEM_Soft_Delete_Base) {
77
+					// then if they don't have the other cap,
78
+					// AT MOST show them their own or non deleted ones
79
+					$restrictions[ EE_Restriction_Generator_Base::get_cap_name(
80
+						$this->model(),
81
+						$this->action() . '_others'
82
+					) ] = new EE_Default_Where_Conditions(
83
+						[
84
+							'OR*' .
85
+							EE_Restriction_Generator_Base::get_cap_name(
86
+								$this->model(),
87
+								$this->action() . '_others'
88
+							) => [
89
+								EE_QUERY_PLACEHOLDER_USER_FIELD_NAME => EE_QUERY_PLACEHOLDER_CURRENT_USER,
90
+								$this->model()->deleted_field_name(
91
+								)                                    => false,
92
+							],
93
+						]
94
+					);
95
+				}
96
+				// again, if they don't have the others cap,
97
+				// continue showing all because there are no inherently hidden ones
98 98
 
99
-                // does the private cap exist (eg 'ee_read_others_private_events')
100
-                if (
101
-                    EE_Restriction_Generator_Base::is_cap(
102
-                        $this->model(),
103
-                        $this->action() . '_private'
104
-                    ) && $this->model() instanceof EEM_CPT_Base
105
-                ) {
106
-                    // if they have basic and others, but not private,
107
-                    // restrict them to see theirs and others' that aren't private
108
-                    $restrictions[ EE_Restriction_Generator_Base::get_cap_name(
109
-                        $this->model(),
110
-                        $this->action() . '_private'
111
-                    ) ] = new EE_Default_Where_Conditions(
112
-                        [
113
-                            'OR*' .
114
-                            EE_Restriction_Generator_Base::get_cap_name(
115
-                                $this->model(),
116
-                                $this->action() . '_private'
117
-                            ) => $this->addPublishedPostConditions(
118
-                                [
119
-                                    EE_QUERY_PLACEHOLDER_USER_FIELD_NAME => EE_QUERY_PLACEHOLDER_CURRENT_USER,
120
-                                ],
121
-                                false
122
-                            ),
123
-                        ]
124
-                    );
125
-                }
126
-            }
127
-        } else {
128
-            // there is no basic cap. So allow full access
129
-            $restrictions = [];
130
-        }
131
-        return $restrictions;
132
-    }
99
+				// does the private cap exist (eg 'ee_read_others_private_events')
100
+				if (
101
+					EE_Restriction_Generator_Base::is_cap(
102
+						$this->model(),
103
+						$this->action() . '_private'
104
+					) && $this->model() instanceof EEM_CPT_Base
105
+				) {
106
+					// if they have basic and others, but not private,
107
+					// restrict them to see theirs and others' that aren't private
108
+					$restrictions[ EE_Restriction_Generator_Base::get_cap_name(
109
+						$this->model(),
110
+						$this->action() . '_private'
111
+					) ] = new EE_Default_Where_Conditions(
112
+						[
113
+							'OR*' .
114
+							EE_Restriction_Generator_Base::get_cap_name(
115
+								$this->model(),
116
+								$this->action() . '_private'
117
+							) => $this->addPublishedPostConditions(
118
+								[
119
+									EE_QUERY_PLACEHOLDER_USER_FIELD_NAME => EE_QUERY_PLACEHOLDER_CURRENT_USER,
120
+								],
121
+								false
122
+							),
123
+						]
124
+					);
125
+				}
126
+			}
127
+		} else {
128
+			// there is no basic cap. So allow full access
129
+			$restrictions = [];
130
+		}
131
+		return $restrictions;
132
+	}
133 133
 }
Please login to merge, or discard this patch.