Completed
Branch EE5Update (bc64e6)
by
unknown
09:36 queued 05:38
created
core/services/container/CoffeeMaker.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -68,7 +68,7 @@  discard block
 block discarded – undo
68 68
     public static function validateType($type)
69 69
     {
70 70
         $types = CoffeeMaker::getTypes();
71
-        if (! in_array($type, $types, true)) {
71
+        if ( ! in_array($type, $types, true)) {
72 72
             throw new InvalidIdentifierException(
73 73
                 is_object($type) ? get_class($type) : gettype($type),
74 74
                 esc_html__(
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
     protected function resolveClassAndFilepath(RecipeInterface $recipe)
152 152
     {
153 153
         $paths = $recipe->paths();
154
-        if (! empty($paths)) {
154
+        if ( ! empty($paths)) {
155 155
             foreach ($paths as $path) {
156 156
                 if (strpos($path, '*') === false && is_readable($path)) {
157 157
                     require_once($path);
Please login to merge, or discard this patch.
Indentation   +152 added lines, -152 removed lines patch added patch discarded remove patch
@@ -17,156 +17,156 @@
 block discarded – undo
17 17
  */
18 18
 abstract class CoffeeMaker implements CoffeeMakerInterface
19 19
 {
20
-    /**
21
-     * Indicates that CoffeeMaker should construct a NEW entity instance from the provided arguments (if given)
22
-     */
23
-    const BREW_NEW = 'new';
24
-
25
-    /**
26
-     * Indicates that CoffeeMaker should always return a SHARED instance
27
-     */
28
-    const BREW_SHARED = 'shared';
29
-
30
-    /**
31
-     * Indicates that CoffeeMaker should only load the file/class/interface but NOT instantiate
32
-     */
33
-    const BREW_LOAD_ONLY = 'load_only';
34
-
35
-
36
-    /**
37
-     * @var CoffeePotInterface $coffee_pot
38
-     */
39
-    private $coffee_pot;
40
-
41
-    /**
42
-     * @var DependencyInjector $injector
43
-     */
44
-    private $injector;
45
-
46
-
47
-    /**
48
-     * @return array
49
-     */
50
-    public static function getTypes()
51
-    {
52
-        return (array) apply_filters(
53
-            'FHEE__EventEspresso\core\services\container\CoffeeMaker__getTypes',
54
-            array(
55
-                CoffeeMaker::BREW_NEW,
56
-                CoffeeMaker::BREW_SHARED,
57
-                CoffeeMaker::BREW_LOAD_ONLY,
58
-            )
59
-        );
60
-    }
61
-
62
-
63
-    /**
64
-     * @param $type
65
-     * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
66
-     */
67
-    public static function validateType($type)
68
-    {
69
-        $types = CoffeeMaker::getTypes();
70
-        if (! in_array($type, $types, true)) {
71
-            throw new InvalidIdentifierException(
72
-                is_object($type) ? get_class($type) : gettype($type),
73
-                esc_html__(
74
-                    'recipe type (one of the class constants on \EventEspresso\core\services\container\CoffeeMaker)',
75
-                    'event_espresso'
76
-                )
77
-            );
78
-        }
79
-        return $type;
80
-    }
81
-
82
-
83
-    /**
84
-     * CoffeeMaker constructor.
85
-     *
86
-     * @param CoffeePotInterface $coffee_pot
87
-     * @param InjectorInterface  $injector
88
-     */
89
-    public function __construct(CoffeePotInterface $coffee_pot, InjectorInterface $injector)
90
-    {
91
-        $this->coffee_pot = $coffee_pot;
92
-        $this->injector = $injector;
93
-    }
94
-
95
-
96
-    /**
97
-     * @return \EventEspresso\core\services\container\CoffeePotInterface
98
-     */
99
-    protected function coffeePot()
100
-    {
101
-        return $this->coffee_pot;
102
-    }
103
-
104
-
105
-    /**
106
-     * @return \EventEspresso\core\services\container\DependencyInjector
107
-     */
108
-    protected function injector()
109
-    {
110
-        return $this->injector;
111
-    }
112
-
113
-
114
-    /**
115
-     * Examines the constructor to determine which method should be used for instantiation
116
-     *
117
-     * @param \ReflectionClass $reflector
118
-     * @return mixed
119
-     * @throws InstantiationException
120
-     */
121
-    protected function resolveInstantiationMethod(\ReflectionClass $reflector)
122
-    {
123
-        if ($reflector->getConstructor() === null) {
124
-            return 'NewInstance';
125
-        }
126
-        if ($reflector->isInstantiable()) {
127
-            return 'NewInstanceArgs';
128
-        }
129
-        if (method_exists($reflector->getName(), 'instance')) {
130
-            return 'instance';
131
-        }
132
-        if (method_exists($reflector->getName(), 'new_instance')) {
133
-            return 'new_instance';
134
-        }
135
-        if (method_exists($reflector->getName(), 'new_instance_from_db')) {
136
-            return 'new_instance_from_db';
137
-        }
138
-        throw new InstantiationException($reflector->getName());
139
-    }
140
-
141
-
142
-    /**
143
-     * Ensures files for classes that are not PSR-4 compatible are loaded
144
-     * and then verifies that classes exist where applicable
145
-     *
146
-     * @param RecipeInterface $recipe
147
-     * @return bool
148
-     * @throws InvalidClassException
149
-     */
150
-    protected function resolveClassAndFilepath(RecipeInterface $recipe)
151
-    {
152
-        $paths = $recipe->paths();
153
-        if (! empty($paths)) {
154
-            foreach ($paths as $path) {
155
-                if (strpos($path, '*') === false && is_readable($path)) {
156
-                    require_once($path);
157
-                }
158
-            }
159
-        }
160
-        // re: using "false" for class_exists() second param:
161
-        // if a class name is not already known to PHP, then class_exists() will run through
162
-        // all of the registered spl_autoload functions until it either finds the class,
163
-        // or gets to the end of the registered spl_autoload functions.
164
-        // When the second parameter is true, it will also attempt to load the class file,
165
-        // but it will also trigger an error if the class can not be loaded.
166
-        // We don't want that extra error in the mix, so we have set the second param to "false"
167
-        if ($recipe->type() !== CoffeeMaker::BREW_LOAD_ONLY && ! class_exists($recipe->fqcn(), false)) {
168
-            throw new InvalidClassException($recipe->identifier());
169
-        }
170
-        return true;
171
-    }
20
+	/**
21
+	 * Indicates that CoffeeMaker should construct a NEW entity instance from the provided arguments (if given)
22
+	 */
23
+	const BREW_NEW = 'new';
24
+
25
+	/**
26
+	 * Indicates that CoffeeMaker should always return a SHARED instance
27
+	 */
28
+	const BREW_SHARED = 'shared';
29
+
30
+	/**
31
+	 * Indicates that CoffeeMaker should only load the file/class/interface but NOT instantiate
32
+	 */
33
+	const BREW_LOAD_ONLY = 'load_only';
34
+
35
+
36
+	/**
37
+	 * @var CoffeePotInterface $coffee_pot
38
+	 */
39
+	private $coffee_pot;
40
+
41
+	/**
42
+	 * @var DependencyInjector $injector
43
+	 */
44
+	private $injector;
45
+
46
+
47
+	/**
48
+	 * @return array
49
+	 */
50
+	public static function getTypes()
51
+	{
52
+		return (array) apply_filters(
53
+			'FHEE__EventEspresso\core\services\container\CoffeeMaker__getTypes',
54
+			array(
55
+				CoffeeMaker::BREW_NEW,
56
+				CoffeeMaker::BREW_SHARED,
57
+				CoffeeMaker::BREW_LOAD_ONLY,
58
+			)
59
+		);
60
+	}
61
+
62
+
63
+	/**
64
+	 * @param $type
65
+	 * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
66
+	 */
67
+	public static function validateType($type)
68
+	{
69
+		$types = CoffeeMaker::getTypes();
70
+		if (! in_array($type, $types, true)) {
71
+			throw new InvalidIdentifierException(
72
+				is_object($type) ? get_class($type) : gettype($type),
73
+				esc_html__(
74
+					'recipe type (one of the class constants on \EventEspresso\core\services\container\CoffeeMaker)',
75
+					'event_espresso'
76
+				)
77
+			);
78
+		}
79
+		return $type;
80
+	}
81
+
82
+
83
+	/**
84
+	 * CoffeeMaker constructor.
85
+	 *
86
+	 * @param CoffeePotInterface $coffee_pot
87
+	 * @param InjectorInterface  $injector
88
+	 */
89
+	public function __construct(CoffeePotInterface $coffee_pot, InjectorInterface $injector)
90
+	{
91
+		$this->coffee_pot = $coffee_pot;
92
+		$this->injector = $injector;
93
+	}
94
+
95
+
96
+	/**
97
+	 * @return \EventEspresso\core\services\container\CoffeePotInterface
98
+	 */
99
+	protected function coffeePot()
100
+	{
101
+		return $this->coffee_pot;
102
+	}
103
+
104
+
105
+	/**
106
+	 * @return \EventEspresso\core\services\container\DependencyInjector
107
+	 */
108
+	protected function injector()
109
+	{
110
+		return $this->injector;
111
+	}
112
+
113
+
114
+	/**
115
+	 * Examines the constructor to determine which method should be used for instantiation
116
+	 *
117
+	 * @param \ReflectionClass $reflector
118
+	 * @return mixed
119
+	 * @throws InstantiationException
120
+	 */
121
+	protected function resolveInstantiationMethod(\ReflectionClass $reflector)
122
+	{
123
+		if ($reflector->getConstructor() === null) {
124
+			return 'NewInstance';
125
+		}
126
+		if ($reflector->isInstantiable()) {
127
+			return 'NewInstanceArgs';
128
+		}
129
+		if (method_exists($reflector->getName(), 'instance')) {
130
+			return 'instance';
131
+		}
132
+		if (method_exists($reflector->getName(), 'new_instance')) {
133
+			return 'new_instance';
134
+		}
135
+		if (method_exists($reflector->getName(), 'new_instance_from_db')) {
136
+			return 'new_instance_from_db';
137
+		}
138
+		throw new InstantiationException($reflector->getName());
139
+	}
140
+
141
+
142
+	/**
143
+	 * Ensures files for classes that are not PSR-4 compatible are loaded
144
+	 * and then verifies that classes exist where applicable
145
+	 *
146
+	 * @param RecipeInterface $recipe
147
+	 * @return bool
148
+	 * @throws InvalidClassException
149
+	 */
150
+	protected function resolveClassAndFilepath(RecipeInterface $recipe)
151
+	{
152
+		$paths = $recipe->paths();
153
+		if (! empty($paths)) {
154
+			foreach ($paths as $path) {
155
+				if (strpos($path, '*') === false && is_readable($path)) {
156
+					require_once($path);
157
+				}
158
+			}
159
+		}
160
+		// re: using "false" for class_exists() second param:
161
+		// if a class name is not already known to PHP, then class_exists() will run through
162
+		// all of the registered spl_autoload functions until it either finds the class,
163
+		// or gets to the end of the registered spl_autoload functions.
164
+		// When the second parameter is true, it will also attempt to load the class file,
165
+		// but it will also trigger an error if the class can not be loaded.
166
+		// We don't want that extra error in the mix, so we have set the second param to "false"
167
+		if ($recipe->type() !== CoffeeMaker::BREW_LOAD_ONLY && ! class_exists($recipe->fqcn(), false)) {
168
+			throw new InvalidClassException($recipe->identifier());
169
+		}
170
+		return true;
171
+	}
172 172
 }
Please login to merge, or discard this patch.
core/services/container/Recipe.php 2 patches
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
      */
190 190
     public function setIdentifier($identifier)
191 191
     {
192
-        if (! is_string($identifier) || empty($identifier)) {
192
+        if ( ! is_string($identifier) || empty($identifier)) {
193 193
             throw new InvalidIdentifierException(
194 194
                 is_object($identifier) ? get_class($identifier) : gettype($identifier),
195 195
                 esc_html__('class identifier (typically a \Fully\Qualified\ClassName)', 'event_espresso')
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
     public function setFqcn($fqcn)
217 217
     {
218 218
         $fqcn = ! empty($fqcn) ? $fqcn : $this->identifier;
219
-        if (! is_string($fqcn)) {
219
+        if ( ! is_string($fqcn)) {
220 220
             throw new InvalidDataTypeException(
221 221
                 '$fqcn',
222 222
                 is_object($fqcn) ? get_class($fqcn) : gettype($fqcn),
@@ -247,7 +247,7 @@  discard block
 block discarded – undo
247 247
         if (empty($ingredients)) {
248 248
             return;
249 249
         }
250
-        if (! is_array($ingredients)) {
250
+        if ( ! is_array($ingredients)) {
251 251
             throw new InvalidDataTypeException(
252 252
                 '$ingredients',
253 253
                 is_object($ingredients) ? get_class($ingredients) : gettype($ingredients),
@@ -279,7 +279,7 @@  discard block
 block discarded – undo
279 279
         if (empty($filters)) {
280 280
             return;
281 281
         }
282
-        if (! is_array($filters)) {
282
+        if ( ! is_array($filters)) {
283 283
             throw new InvalidDataTypeException(
284 284
                 '$filters',
285 285
                 is_object($filters) ? get_class($filters) : gettype($filters),
@@ -306,7 +306,7 @@  discard block
 block discarded – undo
306 306
         if (empty($paths)) {
307 307
             return;
308 308
         }
309
-        if (! (is_string($paths) || is_array($paths))) {
309
+        if ( ! (is_string($paths) || is_array($paths))) {
310 310
             throw new InvalidDataTypeException(
311 311
                 '$path',
312 312
                 is_object($paths) ? get_class($paths) : gettype($paths),
Please login to merge, or discard this patch.
Indentation   +307 added lines, -307 removed lines patch added patch discarded remove patch
@@ -18,311 +18,311 @@
 block discarded – undo
18 18
  */
19 19
 class Recipe implements RecipeInterface
20 20
 {
21
-    /**
22
-     * A default Recipe to use if none is specified for a class
23
-     */
24
-    const DEFAULT_ID = '*';
25
-
26
-    /**
27
-     * Identifier for the entity class to be constructed.
28
-     * Typically a Fully Qualified Class Name
29
-     *
30
-     * @var string $identifier
31
-     */
32
-    private $identifier;
33
-
34
-    /**
35
-     * Fully Qualified Class Name
36
-     *
37
-     * @var string $fqcn
38
-     */
39
-    private $fqcn;
40
-
41
-    /**
42
-     * a dependency class map array
43
-     * If a Recipe is for a single class (or group of classes that shares the EXACT SAME constructor arguments),
44
-     * and that class type hints for an interface, then this property allows you to configure what dependencies
45
-     * get used when instantiating the class.
46
-     * For example:
47
-     *  There's a class called Coffee, and one of its constructor arguments is BeanInterface
48
-     *  There are two implementations of BeanInterface: HonduranBean, and KenyanBean
49
-     *  We want one Coffee object to use HonduranBean for its BeanInterface,
50
-     *  and the 2nd Coffee object to use KenyanBean for its BeanInterface.
51
-     *  To do this, we need to create two Recipes:
52
-     *      one with an identifier of 'HonduranCoffee' using the following ingredients :
53
-     *          array('BeanInterface' => 'HonduranBean')
54
-     *      and the other with an identifier of 'KenyanCoffee' using the following ingredients :
55
-     *          array('BeanInterface' => 'KenyanBean')
56
-     *  Then, whenever the CoffeeShop brews an instance of HonduranCoffee,
57
-     *  an instance of HonduranBean will get injected for the BeanInterface dependency,
58
-     *  and whenever the CoffeeShop brews an instance of KenyanCoffee,
59
-     *  an instance of KenyanBean will get injected for the BeanInterface dependency
60
-     *
61
-     * @var array $ingredients
62
-     */
63
-    private $ingredients = array();
64
-
65
-    /**
66
-     * one of the class constants from CoffeeShop:
67
-     *  CoffeeMaker::BREW_NEW - creates a new instance
68
-     *  CoffeeMaker::BREW_SHARED - creates a shared instance
69
-     *  CoffeeMaker::BREW_LOAD_ONLY - loads but does not instantiate
70
-     *
71
-     * @var string $type
72
-     */
73
-    private $type;
74
-
75
-    /**
76
-     * class name aliases - typically a Fully Qualified Interface that the class implements
77
-     * identifiers passed to the CoffeeShop will be run through the filters to find the correct class name
78
-     *
79
-     * @var array $filters
80
-     */
81
-    private $filters = array();
82
-
83
-    /**
84
-     * array of full server filepaths to files that may contain the class
85
-     *
86
-     * @var array $paths
87
-     */
88
-    private $paths = array();
89
-
90
-
91
-    /**
92
-     * Recipe constructor.
93
-     *
94
-     * @param string $identifier    class identifier, can be an alias, or FQCN, or whatever
95
-     * @param string $fqcn          \Fully\Qualified\ClassName, optional if $identifier is FQCN
96
-     * @param array  $ingredients   array of dependencies that can not be resolved automatically,
97
-     *                              used for resolving concrete classes for type hinted interfaces
98
-     *                              for the dependencies of THIS class
99
-     * @param string $type          recipe type: one of the class constants on
100
-     *                              \EventEspresso\core\services\container\CoffeeMaker
101
-     * @param array  $filters       array of class aliases, or class interfaces
102
-     *                              this works somewhat opposite to the $ingredients array above,
103
-     *                              in that this array specifies interfaces or aliases
104
-     *                              that this Recipe can be used for when resolving OTHER class's dependencies
105
-     * @param array  $paths         if class can not be loaded via PSR-4 autoloading,
106
-     *                              then supply a filepath, or array of filepaths, so that it can be included
107
-     * @throws InvalidIdentifierException
108
-     * @throws RuntimeException
109
-     * @throws InvalidInterfaceException
110
-     * @throws InvalidClassException
111
-     * @throws InvalidDataTypeException
112
-     */
113
-    public function __construct(
114
-        $identifier,
115
-        $fqcn = '',
116
-        array $filters = array(),
117
-        array $ingredients = array(),
118
-        $type = CoffeeMaker::BREW_NEW,
119
-        array $paths = array()
120
-    ) {
121
-        $this->setIdentifier($identifier);
122
-        $this->setFilters($filters);
123
-        $this->setIngredients($ingredients);
124
-        $this->setType($type);
125
-        $this->setPaths($paths);
126
-        $this->setFqcn($fqcn);
127
-    }
128
-
129
-
130
-    /**
131
-     * @return string
132
-     */
133
-    public function identifier()
134
-    {
135
-        return $this->identifier;
136
-    }
137
-
138
-
139
-    /**
140
-     * @return string
141
-     */
142
-    public function fqcn()
143
-    {
144
-        return $this->fqcn;
145
-    }
146
-
147
-
148
-    /**
149
-     * @return array
150
-     */
151
-    public function filters()
152
-    {
153
-        return $this->filters;
154
-    }
155
-
156
-
157
-    /**
158
-     * @return array
159
-     */
160
-    public function ingredients()
161
-    {
162
-        return $this->ingredients;
163
-    }
164
-
165
-
166
-    /**
167
-     * @return string
168
-     */
169
-    public function type()
170
-    {
171
-        return $this->type;
172
-    }
173
-
174
-
175
-    /**
176
-     * @return array
177
-     */
178
-    public function paths()
179
-    {
180
-        return $this->paths;
181
-    }
182
-
183
-
184
-    /**
185
-     * @param  string $identifier Identifier for the entity class that the Recipe applies to
186
-     *                            Typically a Fully Qualified Class Name
187
-     * @throws InvalidIdentifierException
188
-     */
189
-    public function setIdentifier($identifier)
190
-    {
191
-        if (! is_string($identifier) || empty($identifier)) {
192
-            throw new InvalidIdentifierException(
193
-                is_object($identifier) ? get_class($identifier) : gettype($identifier),
194
-                esc_html__('class identifier (typically a \Fully\Qualified\ClassName)', 'event_espresso')
195
-            );
196
-        }
197
-        $this->identifier = $identifier;
198
-    }
199
-
200
-
201
-    /**
202
-     * Ensures incoming string is a valid Fully Qualified Class Name,
203
-     * except if this is the default wildcard Recipe ( * ),
204
-     * or it's NOT an actual FQCN because the Recipe is using filepaths
205
-     * for classes that are not PSR-4 compatible
206
-     * PLZ NOTE:
207
-     *  Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not,
208
-     *  therefore you should always call Recipe::setPaths() before Recipe::setFqcn()
209
-     *
210
-     * @param string $fqcn
211
-     * @throws InvalidDataTypeException
212
-     * @throws InvalidClassException
213
-     * @throws InvalidInterfaceException
214
-     */
215
-    public function setFqcn($fqcn)
216
-    {
217
-        $fqcn = ! empty($fqcn) ? $fqcn : $this->identifier;
218
-        if (! is_string($fqcn)) {
219
-            throw new InvalidDataTypeException(
220
-                '$fqcn',
221
-                is_object($fqcn) ? get_class($fqcn) : gettype($fqcn),
222
-                esc_html__('string (Fully\Qualified\ClassName)', 'event_espresso')
223
-            );
224
-        }
225
-        $fqcn = ltrim($fqcn, '\\');
226
-        if (
227
-            $fqcn !== Recipe::DEFAULT_ID
228
-            && ! empty($fqcn)
229
-            && empty($this->paths)
230
-            && ! (class_exists($fqcn) || interface_exists($fqcn))
231
-        ) {
232
-            throw new InvalidClassException($fqcn);
233
-        }
234
-        $this->fqcn = $fqcn;
235
-    }
236
-
237
-
238
-    /**
239
-     * @param array $ingredients    an array of dependencies where keys are the aliases and values are the FQCNs
240
-     *                              example:
241
-     *                              array( 'ClassInterface' => 'Fully\Qualified\ClassName' )
242
-     * @throws InvalidDataTypeException
243
-     */
244
-    public function setIngredients(array $ingredients)
245
-    {
246
-        if (empty($ingredients)) {
247
-            return;
248
-        }
249
-        if (! is_array($ingredients)) {
250
-            throw new InvalidDataTypeException(
251
-                '$ingredients',
252
-                is_object($ingredients) ? get_class($ingredients) : gettype($ingredients),
253
-                esc_html__('array of class dependencies', 'event_espresso')
254
-            );
255
-        }
256
-        $this->ingredients = array_merge($this->ingredients, $ingredients);
257
-    }
258
-
259
-
260
-    /**
261
-     * @param string $type one of the class constants returned from CoffeeMaker::getTypes()
262
-     * @throws InvalidIdentifierException
263
-     */
264
-    public function setType($type = CoffeeMaker::BREW_NEW)
265
-    {
266
-        $this->type = CoffeeMaker::validateType($type);
267
-    }
268
-
269
-
270
-    /**
271
-     * @param array $filters    an array of filters where keys are the aliases and values are the FQCNs
272
-     *                          example:
273
-     *                          array( 'ClassInterface' => 'Fully\Qualified\ClassName' )
274
-     * @throws InvalidDataTypeException
275
-     */
276
-    public function setFilters(array $filters)
277
-    {
278
-        if (empty($filters)) {
279
-            return;
280
-        }
281
-        if (! is_array($filters)) {
282
-            throw new InvalidDataTypeException(
283
-                '$filters',
284
-                is_object($filters) ? get_class($filters) : gettype($filters),
285
-                esc_html__('array of class aliases', 'event_espresso')
286
-            );
287
-        }
288
-        $this->filters = array_merge($this->filters, $filters);
289
-    }
290
-
291
-
292
-    /**
293
-     * Ensures incoming paths is a valid filepath, or array of valid filepaths,
294
-     * and merges them in with any existing filepaths
295
-     * PLZ NOTE:
296
-     *  Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not,
297
-     *  therefore you should always call Recipe::setPaths() before Recipe::setFqcn()
298
-     *
299
-     * @param string|array $paths
300
-     * @throws RuntimeException
301
-     * @throws InvalidDataTypeException
302
-     */
303
-    public function setPaths($paths = array())
304
-    {
305
-        if (empty($paths)) {
306
-            return;
307
-        }
308
-        if (! (is_string($paths) || is_array($paths))) {
309
-            throw new InvalidDataTypeException(
310
-                '$path',
311
-                is_object($paths) ? get_class($paths) : gettype($paths),
312
-                esc_html__('string or array of strings (full server filepath(s))', 'event_espresso')
313
-            );
314
-        }
315
-        $paths = (array) $paths;
316
-        foreach ($paths as $path) {
317
-            if (strpos($path, '*') === false && ! is_readable($path)) {
318
-                throw new RuntimeException(
319
-                    sprintf(
320
-                        esc_html__('The following filepath is not readable: "%1$s"', 'event_espresso'),
321
-                        $path
322
-                    )
323
-                );
324
-            }
325
-        }
326
-        $this->paths = array_merge($this->paths, $paths);
327
-    }
21
+	/**
22
+	 * A default Recipe to use if none is specified for a class
23
+	 */
24
+	const DEFAULT_ID = '*';
25
+
26
+	/**
27
+	 * Identifier for the entity class to be constructed.
28
+	 * Typically a Fully Qualified Class Name
29
+	 *
30
+	 * @var string $identifier
31
+	 */
32
+	private $identifier;
33
+
34
+	/**
35
+	 * Fully Qualified Class Name
36
+	 *
37
+	 * @var string $fqcn
38
+	 */
39
+	private $fqcn;
40
+
41
+	/**
42
+	 * a dependency class map array
43
+	 * If a Recipe is for a single class (or group of classes that shares the EXACT SAME constructor arguments),
44
+	 * and that class type hints for an interface, then this property allows you to configure what dependencies
45
+	 * get used when instantiating the class.
46
+	 * For example:
47
+	 *  There's a class called Coffee, and one of its constructor arguments is BeanInterface
48
+	 *  There are two implementations of BeanInterface: HonduranBean, and KenyanBean
49
+	 *  We want one Coffee object to use HonduranBean for its BeanInterface,
50
+	 *  and the 2nd Coffee object to use KenyanBean for its BeanInterface.
51
+	 *  To do this, we need to create two Recipes:
52
+	 *      one with an identifier of 'HonduranCoffee' using the following ingredients :
53
+	 *          array('BeanInterface' => 'HonduranBean')
54
+	 *      and the other with an identifier of 'KenyanCoffee' using the following ingredients :
55
+	 *          array('BeanInterface' => 'KenyanBean')
56
+	 *  Then, whenever the CoffeeShop brews an instance of HonduranCoffee,
57
+	 *  an instance of HonduranBean will get injected for the BeanInterface dependency,
58
+	 *  and whenever the CoffeeShop brews an instance of KenyanCoffee,
59
+	 *  an instance of KenyanBean will get injected for the BeanInterface dependency
60
+	 *
61
+	 * @var array $ingredients
62
+	 */
63
+	private $ingredients = array();
64
+
65
+	/**
66
+	 * one of the class constants from CoffeeShop:
67
+	 *  CoffeeMaker::BREW_NEW - creates a new instance
68
+	 *  CoffeeMaker::BREW_SHARED - creates a shared instance
69
+	 *  CoffeeMaker::BREW_LOAD_ONLY - loads but does not instantiate
70
+	 *
71
+	 * @var string $type
72
+	 */
73
+	private $type;
74
+
75
+	/**
76
+	 * class name aliases - typically a Fully Qualified Interface that the class implements
77
+	 * identifiers passed to the CoffeeShop will be run through the filters to find the correct class name
78
+	 *
79
+	 * @var array $filters
80
+	 */
81
+	private $filters = array();
82
+
83
+	/**
84
+	 * array of full server filepaths to files that may contain the class
85
+	 *
86
+	 * @var array $paths
87
+	 */
88
+	private $paths = array();
89
+
90
+
91
+	/**
92
+	 * Recipe constructor.
93
+	 *
94
+	 * @param string $identifier    class identifier, can be an alias, or FQCN, or whatever
95
+	 * @param string $fqcn          \Fully\Qualified\ClassName, optional if $identifier is FQCN
96
+	 * @param array  $ingredients   array of dependencies that can not be resolved automatically,
97
+	 *                              used for resolving concrete classes for type hinted interfaces
98
+	 *                              for the dependencies of THIS class
99
+	 * @param string $type          recipe type: one of the class constants on
100
+	 *                              \EventEspresso\core\services\container\CoffeeMaker
101
+	 * @param array  $filters       array of class aliases, or class interfaces
102
+	 *                              this works somewhat opposite to the $ingredients array above,
103
+	 *                              in that this array specifies interfaces or aliases
104
+	 *                              that this Recipe can be used for when resolving OTHER class's dependencies
105
+	 * @param array  $paths         if class can not be loaded via PSR-4 autoloading,
106
+	 *                              then supply a filepath, or array of filepaths, so that it can be included
107
+	 * @throws InvalidIdentifierException
108
+	 * @throws RuntimeException
109
+	 * @throws InvalidInterfaceException
110
+	 * @throws InvalidClassException
111
+	 * @throws InvalidDataTypeException
112
+	 */
113
+	public function __construct(
114
+		$identifier,
115
+		$fqcn = '',
116
+		array $filters = array(),
117
+		array $ingredients = array(),
118
+		$type = CoffeeMaker::BREW_NEW,
119
+		array $paths = array()
120
+	) {
121
+		$this->setIdentifier($identifier);
122
+		$this->setFilters($filters);
123
+		$this->setIngredients($ingredients);
124
+		$this->setType($type);
125
+		$this->setPaths($paths);
126
+		$this->setFqcn($fqcn);
127
+	}
128
+
129
+
130
+	/**
131
+	 * @return string
132
+	 */
133
+	public function identifier()
134
+	{
135
+		return $this->identifier;
136
+	}
137
+
138
+
139
+	/**
140
+	 * @return string
141
+	 */
142
+	public function fqcn()
143
+	{
144
+		return $this->fqcn;
145
+	}
146
+
147
+
148
+	/**
149
+	 * @return array
150
+	 */
151
+	public function filters()
152
+	{
153
+		return $this->filters;
154
+	}
155
+
156
+
157
+	/**
158
+	 * @return array
159
+	 */
160
+	public function ingredients()
161
+	{
162
+		return $this->ingredients;
163
+	}
164
+
165
+
166
+	/**
167
+	 * @return string
168
+	 */
169
+	public function type()
170
+	{
171
+		return $this->type;
172
+	}
173
+
174
+
175
+	/**
176
+	 * @return array
177
+	 */
178
+	public function paths()
179
+	{
180
+		return $this->paths;
181
+	}
182
+
183
+
184
+	/**
185
+	 * @param  string $identifier Identifier for the entity class that the Recipe applies to
186
+	 *                            Typically a Fully Qualified Class Name
187
+	 * @throws InvalidIdentifierException
188
+	 */
189
+	public function setIdentifier($identifier)
190
+	{
191
+		if (! is_string($identifier) || empty($identifier)) {
192
+			throw new InvalidIdentifierException(
193
+				is_object($identifier) ? get_class($identifier) : gettype($identifier),
194
+				esc_html__('class identifier (typically a \Fully\Qualified\ClassName)', 'event_espresso')
195
+			);
196
+		}
197
+		$this->identifier = $identifier;
198
+	}
199
+
200
+
201
+	/**
202
+	 * Ensures incoming string is a valid Fully Qualified Class Name,
203
+	 * except if this is the default wildcard Recipe ( * ),
204
+	 * or it's NOT an actual FQCN because the Recipe is using filepaths
205
+	 * for classes that are not PSR-4 compatible
206
+	 * PLZ NOTE:
207
+	 *  Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not,
208
+	 *  therefore you should always call Recipe::setPaths() before Recipe::setFqcn()
209
+	 *
210
+	 * @param string $fqcn
211
+	 * @throws InvalidDataTypeException
212
+	 * @throws InvalidClassException
213
+	 * @throws InvalidInterfaceException
214
+	 */
215
+	public function setFqcn($fqcn)
216
+	{
217
+		$fqcn = ! empty($fqcn) ? $fqcn : $this->identifier;
218
+		if (! is_string($fqcn)) {
219
+			throw new InvalidDataTypeException(
220
+				'$fqcn',
221
+				is_object($fqcn) ? get_class($fqcn) : gettype($fqcn),
222
+				esc_html__('string (Fully\Qualified\ClassName)', 'event_espresso')
223
+			);
224
+		}
225
+		$fqcn = ltrim($fqcn, '\\');
226
+		if (
227
+			$fqcn !== Recipe::DEFAULT_ID
228
+			&& ! empty($fqcn)
229
+			&& empty($this->paths)
230
+			&& ! (class_exists($fqcn) || interface_exists($fqcn))
231
+		) {
232
+			throw new InvalidClassException($fqcn);
233
+		}
234
+		$this->fqcn = $fqcn;
235
+	}
236
+
237
+
238
+	/**
239
+	 * @param array $ingredients    an array of dependencies where keys are the aliases and values are the FQCNs
240
+	 *                              example:
241
+	 *                              array( 'ClassInterface' => 'Fully\Qualified\ClassName' )
242
+	 * @throws InvalidDataTypeException
243
+	 */
244
+	public function setIngredients(array $ingredients)
245
+	{
246
+		if (empty($ingredients)) {
247
+			return;
248
+		}
249
+		if (! is_array($ingredients)) {
250
+			throw new InvalidDataTypeException(
251
+				'$ingredients',
252
+				is_object($ingredients) ? get_class($ingredients) : gettype($ingredients),
253
+				esc_html__('array of class dependencies', 'event_espresso')
254
+			);
255
+		}
256
+		$this->ingredients = array_merge($this->ingredients, $ingredients);
257
+	}
258
+
259
+
260
+	/**
261
+	 * @param string $type one of the class constants returned from CoffeeMaker::getTypes()
262
+	 * @throws InvalidIdentifierException
263
+	 */
264
+	public function setType($type = CoffeeMaker::BREW_NEW)
265
+	{
266
+		$this->type = CoffeeMaker::validateType($type);
267
+	}
268
+
269
+
270
+	/**
271
+	 * @param array $filters    an array of filters where keys are the aliases and values are the FQCNs
272
+	 *                          example:
273
+	 *                          array( 'ClassInterface' => 'Fully\Qualified\ClassName' )
274
+	 * @throws InvalidDataTypeException
275
+	 */
276
+	public function setFilters(array $filters)
277
+	{
278
+		if (empty($filters)) {
279
+			return;
280
+		}
281
+		if (! is_array($filters)) {
282
+			throw new InvalidDataTypeException(
283
+				'$filters',
284
+				is_object($filters) ? get_class($filters) : gettype($filters),
285
+				esc_html__('array of class aliases', 'event_espresso')
286
+			);
287
+		}
288
+		$this->filters = array_merge($this->filters, $filters);
289
+	}
290
+
291
+
292
+	/**
293
+	 * Ensures incoming paths is a valid filepath, or array of valid filepaths,
294
+	 * and merges them in with any existing filepaths
295
+	 * PLZ NOTE:
296
+	 *  Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not,
297
+	 *  therefore you should always call Recipe::setPaths() before Recipe::setFqcn()
298
+	 *
299
+	 * @param string|array $paths
300
+	 * @throws RuntimeException
301
+	 * @throws InvalidDataTypeException
302
+	 */
303
+	public function setPaths($paths = array())
304
+	{
305
+		if (empty($paths)) {
306
+			return;
307
+		}
308
+		if (! (is_string($paths) || is_array($paths))) {
309
+			throw new InvalidDataTypeException(
310
+				'$path',
311
+				is_object($paths) ? get_class($paths) : gettype($paths),
312
+				esc_html__('string or array of strings (full server filepath(s))', 'event_espresso')
313
+			);
314
+		}
315
+		$paths = (array) $paths;
316
+		foreach ($paths as $path) {
317
+			if (strpos($path, '*') === false && ! is_readable($path)) {
318
+				throw new RuntimeException(
319
+					sprintf(
320
+						esc_html__('The following filepath is not readable: "%1$s"', 'event_espresso'),
321
+						$path
322
+					)
323
+				);
324
+			}
325
+		}
326
+		$this->paths = array_merge($this->paths, $paths);
327
+	}
328 328
 }
Please login to merge, or discard this patch.
core/services/container/CoffeeShop.php 2 patches
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
         }
160 160
         // if the reservoir doesn't have a closure already for the requested identifier,
161 161
         // then neither a shared service nor a closure for making entities has been built yet
162
-        if (! $this->reservoir->has($identifier)) {
162
+        if ( ! $this->reservoir->has($identifier)) {
163 163
             // so let's brew something up and add it to the proper collection
164 164
             $brewed = $this->makeCoffee($identifier, $arguments, $type);
165 165
         }
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
      */
285 285
     public function addClosure($identifier, $closure)
286 286
     {
287
-        if (! is_callable($closure)) {
287
+        if ( ! is_callable($closure)) {
288 288
             throw new InvalidDataTypeException('$closure', $closure, 'Closure');
289 289
         }
290 290
         $identifier = $this->processIdentifier($identifier);
@@ -393,7 +393,7 @@  discard block
 block discarded – undo
393 393
             // is the wildcard recipe prefix in the identifier ?
394 394
             if (strpos($identifier, $wildcard) !== false) {
395 395
                 // track matches and use the number of wildcard characters matched for the key
396
-                $matches[ strlen($wildcard) ] = $default_recipe;
396
+                $matches[strlen($wildcard)] = $default_recipe;
397 397
             }
398 398
         }
399 399
         if (count($matches) > 0) {
@@ -433,7 +433,7 @@  discard block
 block discarded – undo
433 433
         }
434 434
         $identifier = $this->processIdentifier($identifier);
435 435
         foreach ((array) $aliases as $alias) {
436
-            $this->filters[ $this->processIdentifier($alias) ] = $identifier;
436
+            $this->filters[$this->processIdentifier($alias)] = $identifier;
437 437
         }
438 438
     }
439 439
 
@@ -475,8 +475,8 @@  discard block
 block discarded – undo
475 475
     private function filterIdentifier($identifier)
476 476
     {
477 477
         $identifier = $this->processIdentifier($identifier);
478
-        return isset($this->filters[ $identifier ]) && ! empty($this->filters[ $identifier ])
479
-            ? $this->filters[ $identifier ]
478
+        return isset($this->filters[$identifier]) && ! empty($this->filters[$identifier])
479
+            ? $this->filters[$identifier]
480 480
             : $identifier;
481 481
     }
482 482
 
@@ -491,7 +491,7 @@  discard block
 block discarded – undo
491 491
      */
492 492
     private function processIdentifier($identifier)
493 493
     {
494
-        if (! is_string($identifier)) {
494
+        if ( ! is_string($identifier)) {
495 495
             throw new InvalidIdentifierException(
496 496
                 is_object($identifier) ? get_class($identifier) : gettype($identifier),
497 497
                 '\Fully\Qualified\ClassName'
@@ -510,7 +510,7 @@  discard block
 block discarded – undo
510 510
      */
511 511
     private function getCoffeeMaker($type)
512 512
     {
513
-        if (! $this->coffee_makers->has($type)) {
513
+        if ( ! $this->coffee_makers->has($type)) {
514 514
             throw new OutOfBoundsException(
515 515
                 esc_html__('The requested coffee maker is either missing or invalid.', 'event_espresso')
516 516
             );
@@ -537,7 +537,7 @@  discard block
 block discarded – undo
537 537
             // does this recipe use a wildcard ? (but is NOT the global default)
538 538
             if ($identifier !== Recipe::DEFAULT_ID && strpos($identifier, '*') !== false) {
539 539
                 // strip the wildcard and use identifier as key
540
-                $default_recipes[ str_replace('*', '', $identifier) ] = $this->recipes->current();
540
+                $default_recipes[str_replace('*', '', $identifier)] = $this->recipes->current();
541 541
             }
542 542
             $this->recipes->next();
543 543
         }
@@ -557,7 +557,7 @@  discard block
 block discarded – undo
557 557
     private function copyDefaultRecipe(RecipeInterface $default_recipe, $identifier, $type = '')
558 558
     {
559 559
         $recipe = clone $default_recipe;
560
-        if (! empty($type)) {
560
+        if ( ! empty($type)) {
561 561
             $recipe->setType($type);
562 562
         }
563 563
         // is this the base default recipe ?
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
      */
588 588
     private function validateService($identifier, $service)
589 589
     {
590
-        if (! is_object($service)) {
590
+        if ( ! is_object($service)) {
591 591
             throw new InvalidServiceException(
592 592
                 $identifier,
593 593
                 $service
Please login to merge, or discard this patch.
Indentation   +565 added lines, -565 removed lines patch added patch discarded remove patch
@@ -28,569 +28,569 @@
 block discarded – undo
28 28
  */
29 29
 class CoffeeShop implements CoffeePotInterface
30 30
 {
31
-    /**
32
-     * This was the best coffee related name I could think of to represent class name "aliases"
33
-     * So classes can be found via an alias identifier,
34
-     * that is revealed when it is run through... the filters... eh? get it?
35
-     *
36
-     * @var array $filters
37
-     */
38
-    private $filters;
39
-
40
-    /**
41
-     * These are the classes that will actually build the objects (to order of course)
42
-     *
43
-     * @var array $coffee_makers
44
-     */
45
-    private $coffee_makers;
46
-
47
-    /**
48
-     * where the instantiated "singleton" objects are stored
49
-     *
50
-     * @var CollectionInterface $carafe
51
-     */
52
-    private $carafe;
53
-
54
-    /**
55
-     * collection of Recipes that instruct us how to brew objects
56
-     *
57
-     * @var CollectionInterface $recipes
58
-     */
59
-    private $recipes;
60
-
61
-    /**
62
-     * collection of closures for brewing objects
63
-     *
64
-     * @var CollectionInterface $reservoir
65
-     */
66
-    private $reservoir;
67
-
68
-
69
-    /**
70
-     * CoffeeShop constructor
71
-     *
72
-     * @throws InvalidInterfaceException
73
-     */
74
-    public function __construct()
75
-    {
76
-        // array for storing class aliases
77
-        $this->filters = array();
78
-        // create collection for storing shared services
79
-        $this->carafe = new LooseCollection('');
80
-        // create collection for storing recipes that tell us how to build services and entities
81
-        $this->recipes = new Collection('EventEspresso\core\services\container\RecipeInterface');
82
-        // create collection for storing closures for constructing new entities
83
-        $this->reservoir = new Collection('Closure');
84
-        // create collection for storing the generators that build our services and entity closures
85
-        $this->coffee_makers = new Collection('EventEspresso\core\services\container\CoffeeMakerInterface');
86
-    }
87
-
88
-
89
-    /**
90
-     * Returns true if the container can return an entry for the given identifier.
91
-     * Returns false otherwise.
92
-     * `has($identifier)` returning true does not mean that `get($identifier)` will not throw an exception.
93
-     * It does however mean that `get($identifier)` will not throw a `ServiceNotFoundException`.
94
-     *
95
-     * @param string $identifier  Identifier of the entry to look for.
96
-     *                            Typically a Fully Qualified Class Name
97
-     * @return boolean
98
-     * @throws InvalidIdentifierException
99
-     */
100
-    public function has($identifier)
101
-    {
102
-        $identifier = $this->filterIdentifier($identifier);
103
-        return $this->carafe->has($identifier);
104
-    }
105
-
106
-
107
-    /**
108
-     * finds a previously brewed (SHARED) service and returns it
109
-     *
110
-     * @param  string $identifier Identifier for the entity class to be constructed.
111
-     *                            Typically a Fully Qualified Class Name
112
-     * @return mixed
113
-     * @throws InvalidIdentifierException
114
-     * @throws ServiceNotFoundException No service was found for this identifier.
115
-     */
116
-    public function get($identifier)
117
-    {
118
-        $identifier = $this->filterIdentifier($identifier);
119
-        if ($this->carafe->has($identifier)) {
120
-            return $this->carafe->get($identifier);
121
-        }
122
-        throw new ServiceNotFoundException($identifier);
123
-    }
124
-
125
-
126
-    /**
127
-     * returns an instance of the requested entity type using the supplied arguments.
128
-     * If a shared service is requested and an instance is already in the carafe, then it will be returned.
129
-     * If it is not already in the carafe, then the service will be constructed, added to the carafe, and returned
130
-     * If the request is for a new entity and a closure exists in the reservoir for creating it,
131
-     * then a new entity will be instantiated from the closure and returned.
132
-     * If a closure does not exist, then one will be built and added to the reservoir
133
-     * before instantiating the requested entity.
134
-     *
135
-     * @param  string $identifier Identifier for the entity class to be constructed.
136
-     *                            Typically a Fully Qualified Class Name
137
-     * @param array   $arguments  an array of arguments to be passed to the entity constructor
138
-     * @param string  $type
139
-     * @return mixed
140
-     * @throws OutOfBoundsException
141
-     * @throws InstantiationException
142
-     * @throws InvalidDataTypeException
143
-     * @throws InvalidClassException
144
-     * @throws InvalidIdentifierException
145
-     * @throws ServiceExistsException
146
-     * @throws ServiceNotFoundException No service was found for this identifier.
147
-     */
148
-    public function brew($identifier, $arguments = array(), $type = '')
149
-    {
150
-        // resolve any class aliases that may exist
151
-        $identifier = $this->filterIdentifier($identifier);
152
-        // is a shared service being requested and already exists in the carafe?
153
-        $brewed = $this->getShared($identifier, $type);
154
-        // then return whatever was found
155
-        if ($brewed !== false) {
156
-            return $brewed;
157
-        }
158
-        // if the reservoir doesn't have a closure already for the requested identifier,
159
-        // then neither a shared service nor a closure for making entities has been built yet
160
-        if (! $this->reservoir->has($identifier)) {
161
-            // so let's brew something up and add it to the proper collection
162
-            $brewed = $this->makeCoffee($identifier, $arguments, $type);
163
-        }
164
-        // did the requested class only require loading, and if so, was that successful?
165
-        if ($this->brewedLoadOnly($brewed, $identifier, $type) === true) {
166
-            return true;
167
-        }
168
-        // was the brewed item a callable factory function ?
169
-        if (is_callable($brewed)) {
170
-            // then instantiate a new entity from the cached closure
171
-            return $brewed($arguments);
172
-        }
173
-        if ($brewed) {
174
-            // requested object was a shared entity, so attempt to get it from the carafe again
175
-            // because if it wasn't there before, then it should have just been brewed and added,
176
-            // but if it still isn't there, then this time the thrown ServiceNotFoundException will not be caught
177
-            return $this->get($identifier);
178
-        }
179
-        // if identifier is for a non-shared entity,
180
-        // then either a cached closure already existed, or was just brewed
181
-        return $this->brewedClosure($identifier, $arguments);
182
-    }
183
-
184
-
185
-    /**
186
-     * @param string $identifier
187
-     * @param string $type
188
-     * @return bool|mixed
189
-     * @throws InvalidIdentifierException
190
-     */
191
-    protected function getShared($identifier, $type)
192
-    {
193
-        try {
194
-            if (empty($type) || $type === CoffeeMaker::BREW_SHARED) {
195
-                // if a shared service was requested and an instance is in the carafe, then return it
196
-                return $this->get($identifier);
197
-            }
198
-        } catch (ServiceNotFoundException $e) {
199
-            // if not then we'll just catch the ServiceNotFoundException but not do anything just yet,
200
-            // and instead, attempt to build whatever was requested
201
-        }
202
-        return false;
203
-    }
204
-
205
-
206
-    /**
207
-     * @param mixed  $brewed
208
-     * @param string $identifier
209
-     * @param string $type
210
-     * @return bool
211
-     * @throws InvalidClassException
212
-     * @throws InvalidDataTypeException
213
-     * @throws InvalidIdentifierException
214
-     * @throws OutOfBoundsException
215
-     * @throws ServiceExistsException
216
-     * @throws ServiceNotFoundException
217
-     */
218
-    protected function brewedLoadOnly($brewed, $identifier, $type)
219
-    {
220
-        if ($type === CoffeeMaker::BREW_LOAD_ONLY) {
221
-            if ($brewed !== true) {
222
-                throw new ServiceNotFoundException(
223
-                    sprintf(
224
-                        esc_html__(
225
-                            'The "%1$s" class could not be loaded.',
226
-                            'event_espresso'
227
-                        ),
228
-                        $identifier
229
-                    )
230
-                );
231
-            }
232
-            return true;
233
-        }
234
-        return false;
235
-    }
236
-
237
-
238
-    /**
239
-     * @param string $identifier
240
-     * @param array  $arguments
241
-     * @return mixed
242
-     * @throws InstantiationException
243
-     */
244
-    protected function brewedClosure($identifier, array $arguments)
245
-    {
246
-        $closure = $this->reservoir->get($identifier);
247
-        if (empty($closure)) {
248
-            throw new InstantiationException(
249
-                sprintf(
250
-                    esc_html__(
251
-                        'Could not brew an instance of "%1$s".',
252
-                        'event_espresso'
253
-                    ),
254
-                    $identifier
255
-                )
256
-            );
257
-        }
258
-        return $closure($arguments);
259
-    }
260
-
261
-
262
-    /**
263
-     * @param CoffeeMakerInterface $coffee_maker
264
-     * @param string               $type
265
-     * @return bool
266
-     * @throws InvalidIdentifierException
267
-     * @throws InvalidEntityException
268
-     */
269
-    public function addCoffeeMaker(CoffeeMakerInterface $coffee_maker, $type)
270
-    {
271
-        $type = CoffeeMaker::validateType($type);
272
-        return $this->coffee_makers->add($coffee_maker, $type);
273
-    }
274
-
275
-
276
-    /**
277
-     * @param string   $identifier
278
-     * @param callable $closure
279
-     * @return callable|null
280
-     * @throws InvalidIdentifierException
281
-     * @throws InvalidDataTypeException
282
-     */
283
-    public function addClosure($identifier, $closure)
284
-    {
285
-        if (! is_callable($closure)) {
286
-            throw new InvalidDataTypeException('$closure', $closure, 'Closure');
287
-        }
288
-        $identifier = $this->processIdentifier($identifier);
289
-        if ($this->reservoir->add($closure, $identifier)) {
290
-            return $closure;
291
-        }
292
-        return null;
293
-    }
294
-
295
-
296
-    /**
297
-     * @param string $identifier
298
-     * @return boolean
299
-     * @throws InvalidIdentifierException
300
-     */
301
-    public function removeClosure($identifier)
302
-    {
303
-        $identifier = $this->processIdentifier($identifier);
304
-        if ($this->reservoir->has($identifier)) {
305
-            return $this->reservoir->remove($this->reservoir->get($identifier));
306
-        }
307
-        return false;
308
-    }
309
-
310
-
311
-    /**
312
-     * @param  string $identifier Identifier for the entity class that the service applies to
313
-     *                            Typically a Fully Qualified Class Name
314
-     * @param mixed   $service
315
-     * @return bool
316
-     * @throws \EventEspresso\core\services\container\exceptions\InvalidServiceException
317
-     * @throws InvalidIdentifierException
318
-     */
319
-    public function addService($identifier, $service)
320
-    {
321
-        $identifier = $this->processIdentifier($identifier);
322
-        $service = $this->validateService($identifier, $service);
323
-        return $this->carafe->add($service, $identifier);
324
-    }
325
-
326
-
327
-    /**
328
-     * @param string $identifier
329
-     * @return boolean
330
-     * @throws InvalidIdentifierException
331
-     */
332
-    public function removeService($identifier)
333
-    {
334
-        $identifier = $this->processIdentifier($identifier);
335
-        if ($this->carafe->has($identifier)) {
336
-            return $this->carafe->remove($this->carafe->get($identifier));
337
-        }
338
-        return false;
339
-    }
340
-
341
-
342
-    /**
343
-     * Adds instructions on how to brew objects
344
-     *
345
-     * @param RecipeInterface $recipe
346
-     * @return mixed
347
-     * @throws InvalidIdentifierException
348
-     */
349
-    public function addRecipe(RecipeInterface $recipe)
350
-    {
351
-        $this->addAliases($recipe->identifier(), $recipe->filters());
352
-        $identifier = $this->processIdentifier($recipe->identifier());
353
-        return $this->recipes->add($recipe, $identifier);
354
-    }
355
-
356
-
357
-    /**
358
-     * @param string $identifier The Recipe's identifier
359
-     * @return boolean
360
-     * @throws InvalidIdentifierException
361
-     */
362
-    public function removeRecipe($identifier)
363
-    {
364
-        $identifier = $this->processIdentifier($identifier);
365
-        if ($this->recipes->has($identifier)) {
366
-            return $this->recipes->remove($this->recipes->get($identifier));
367
-        }
368
-        return false;
369
-    }
370
-
371
-
372
-    /**
373
-     * Get instructions on how to brew objects
374
-     *
375
-     * @param  string $identifier Identifier for the entity class that the recipe applies to
376
-     *                            Typically a Fully Qualified Class Name
377
-     * @param string  $type
378
-     * @return RecipeInterface
379
-     * @throws OutOfBoundsException
380
-     * @throws InvalidIdentifierException
381
-     */
382
-    public function getRecipe($identifier, $type = '')
383
-    {
384
-        $identifier = $this->processIdentifier($identifier);
385
-        if ($this->recipes->has($identifier)) {
386
-            return $this->recipes->get($identifier);
387
-        }
388
-        $default_recipes = $this->getDefaultRecipes();
389
-        $matches = array();
390
-        foreach ($default_recipes as $wildcard => $default_recipe) {
391
-            // is the wildcard recipe prefix in the identifier ?
392
-            if (strpos($identifier, $wildcard) !== false) {
393
-                // track matches and use the number of wildcard characters matched for the key
394
-                $matches[ strlen($wildcard) ] = $default_recipe;
395
-            }
396
-        }
397
-        if (count($matches) > 0) {
398
-            // sort our recipes by the number of wildcard characters matched
399
-            ksort($matches);
400
-            // then grab the last recipe form the list, since it had the most matching characters
401
-            $match = array_pop($matches);
402
-            // since we are using a default recipe, we need to set it's identifier and fqcn
403
-            return $this->copyDefaultRecipe($match, $identifier, $type);
404
-        }
405
-        if ($this->recipes->has(Recipe::DEFAULT_ID)) {
406
-            // since we are using a default recipe, we need to set it's identifier and fqcn
407
-            return $this->copyDefaultRecipe($this->recipes->get(Recipe::DEFAULT_ID), $identifier, $type);
408
-        }
409
-        throw new OutOfBoundsException(
410
-            sprintf(
411
-                esc_html__('Could not brew coffee because no recipes were found for class "%1$s".', 'event_espresso'),
412
-                $identifier
413
-            )
414
-        );
415
-    }
416
-
417
-
418
-    /**
419
-     * adds class name aliases to list of filters
420
-     *
421
-     * @param  string       $identifier Identifier for the entity class that the alias applies to
422
-     *                                  Typically a Fully Qualified Class Name
423
-     * @param  array|string $aliases
424
-     * @return void
425
-     * @throws InvalidIdentifierException
426
-     */
427
-    public function addAliases($identifier, $aliases)
428
-    {
429
-        if (empty($aliases)) {
430
-            return;
431
-        }
432
-        $identifier = $this->processIdentifier($identifier);
433
-        foreach ((array) $aliases as $alias) {
434
-            $this->filters[ $this->processIdentifier($alias) ] = $identifier;
435
-        }
436
-    }
437
-
438
-
439
-    /**
440
-     * Adds a service to one of the internal collections
441
-     *
442
-     * @param        $identifier
443
-     * @param array  $arguments
444
-     * @param string $type
445
-     * @return mixed
446
-     * @throws InvalidDataTypeException
447
-     * @throws InvalidClassException
448
-     * @throws OutOfBoundsException
449
-     * @throws InvalidIdentifierException
450
-     * @throws ServiceExistsException
451
-     */
452
-    private function makeCoffee($identifier, $arguments = array(), $type = '')
453
-    {
454
-        if ((empty($type) || $type === CoffeeMaker::BREW_SHARED) && $this->has($identifier)) {
455
-            throw new ServiceExistsException($identifier);
456
-        }
457
-        $identifier = $this->filterIdentifier($identifier);
458
-        $recipe = $this->getRecipe($identifier, $type);
459
-        $type = ! empty($type) ? $type : $recipe->type();
460
-        $coffee_maker = $this->getCoffeeMaker($type);
461
-        return $coffee_maker->brew($recipe, $arguments);
462
-    }
463
-
464
-
465
-    /**
466
-     * filters alias identifiers to find the real class name
467
-     *
468
-     * @param  string $identifier Identifier for the entity class that the filter applies to
469
-     *                            Typically a Fully Qualified Class Name
470
-     * @return string
471
-     * @throws InvalidIdentifierException
472
-     */
473
-    private function filterIdentifier($identifier)
474
-    {
475
-        $identifier = $this->processIdentifier($identifier);
476
-        return isset($this->filters[ $identifier ]) && ! empty($this->filters[ $identifier ])
477
-            ? $this->filters[ $identifier ]
478
-            : $identifier;
479
-    }
480
-
481
-
482
-    /**
483
-     * verifies and standardizes identifiers
484
-     *
485
-     * @param  string $identifier Identifier for the entity class
486
-     *                            Typically a Fully Qualified Class Name
487
-     * @return string
488
-     * @throws InvalidIdentifierException
489
-     */
490
-    private function processIdentifier($identifier)
491
-    {
492
-        if (! is_string($identifier)) {
493
-            throw new InvalidIdentifierException(
494
-                is_object($identifier) ? get_class($identifier) : gettype($identifier),
495
-                '\Fully\Qualified\ClassName'
496
-            );
497
-        }
498
-        return ltrim($identifier, '\\');
499
-    }
500
-
501
-
502
-    /**
503
-     * @param string $type
504
-     * @return CoffeeMakerInterface
505
-     * @throws OutOfBoundsException
506
-     * @throws InvalidDataTypeException
507
-     * @throws InvalidClassException
508
-     */
509
-    private function getCoffeeMaker($type)
510
-    {
511
-        if (! $this->coffee_makers->has($type)) {
512
-            throw new OutOfBoundsException(
513
-                esc_html__('The requested coffee maker is either missing or invalid.', 'event_espresso')
514
-            );
515
-        }
516
-        return $this->coffee_makers->get($type);
517
-    }
518
-
519
-
520
-    /**
521
-     * Retrieves all recipes that use a wildcard "*" in their identifier
522
-     * This allows recipes to be set up for handling
523
-     * legacy classes that do not support PSR-4 autoloading.
524
-     * for example:
525
-     * using "EEM_*" for a recipe identifier would target all legacy models like EEM_Attendee
526
-     *
527
-     * @return array
528
-     */
529
-    private function getDefaultRecipes()
530
-    {
531
-        $default_recipes = array();
532
-        $this->recipes->rewind();
533
-        while ($this->recipes->valid()) {
534
-            $identifier = $this->recipes->getInfo();
535
-            // does this recipe use a wildcard ? (but is NOT the global default)
536
-            if ($identifier !== Recipe::DEFAULT_ID && strpos($identifier, '*') !== false) {
537
-                // strip the wildcard and use identifier as key
538
-                $default_recipes[ str_replace('*', '', $identifier) ] = $this->recipes->current();
539
-            }
540
-            $this->recipes->next();
541
-        }
542
-        return $default_recipes;
543
-    }
544
-
545
-
546
-    /**
547
-     * clones a default recipe and then copies details
548
-     * from the incoming request to it so that it can be used
549
-     *
550
-     * @param RecipeInterface $default_recipe
551
-     * @param string          $identifier
552
-     * @param string          $type
553
-     * @return RecipeInterface
554
-     */
555
-    private function copyDefaultRecipe(RecipeInterface $default_recipe, $identifier, $type = '')
556
-    {
557
-        $recipe = clone $default_recipe;
558
-        if (! empty($type)) {
559
-            $recipe->setType($type);
560
-        }
561
-        // is this the base default recipe ?
562
-        if ($default_recipe->identifier() === Recipe::DEFAULT_ID) {
563
-            $recipe->setIdentifier($identifier);
564
-            $recipe->setFqcn($identifier);
565
-            return $recipe;
566
-        }
567
-        $recipe->setIdentifier($identifier);
568
-        foreach ($default_recipe->paths() as $path) {
569
-            $path = str_replace('*', $identifier, $path);
570
-            if (is_readable($path)) {
571
-                $recipe->setPaths($path);
572
-            }
573
-        }
574
-        $recipe->setFqcn($identifier);
575
-        return $recipe;
576
-    }
577
-
578
-
579
-    /**
580
-     * @param  string $identifier Identifier for the entity class that the service applies to
581
-     *                            Typically a Fully Qualified Class Name
582
-     * @param mixed   $service
583
-     * @return mixed
584
-     * @throws InvalidServiceException
585
-     */
586
-    private function validateService($identifier, $service)
587
-    {
588
-        if (! is_object($service)) {
589
-            throw new InvalidServiceException(
590
-                $identifier,
591
-                $service
592
-            );
593
-        }
594
-        return $service;
595
-    }
31
+	/**
32
+	 * This was the best coffee related name I could think of to represent class name "aliases"
33
+	 * So classes can be found via an alias identifier,
34
+	 * that is revealed when it is run through... the filters... eh? get it?
35
+	 *
36
+	 * @var array $filters
37
+	 */
38
+	private $filters;
39
+
40
+	/**
41
+	 * These are the classes that will actually build the objects (to order of course)
42
+	 *
43
+	 * @var array $coffee_makers
44
+	 */
45
+	private $coffee_makers;
46
+
47
+	/**
48
+	 * where the instantiated "singleton" objects are stored
49
+	 *
50
+	 * @var CollectionInterface $carafe
51
+	 */
52
+	private $carafe;
53
+
54
+	/**
55
+	 * collection of Recipes that instruct us how to brew objects
56
+	 *
57
+	 * @var CollectionInterface $recipes
58
+	 */
59
+	private $recipes;
60
+
61
+	/**
62
+	 * collection of closures for brewing objects
63
+	 *
64
+	 * @var CollectionInterface $reservoir
65
+	 */
66
+	private $reservoir;
67
+
68
+
69
+	/**
70
+	 * CoffeeShop constructor
71
+	 *
72
+	 * @throws InvalidInterfaceException
73
+	 */
74
+	public function __construct()
75
+	{
76
+		// array for storing class aliases
77
+		$this->filters = array();
78
+		// create collection for storing shared services
79
+		$this->carafe = new LooseCollection('');
80
+		// create collection for storing recipes that tell us how to build services and entities
81
+		$this->recipes = new Collection('EventEspresso\core\services\container\RecipeInterface');
82
+		// create collection for storing closures for constructing new entities
83
+		$this->reservoir = new Collection('Closure');
84
+		// create collection for storing the generators that build our services and entity closures
85
+		$this->coffee_makers = new Collection('EventEspresso\core\services\container\CoffeeMakerInterface');
86
+	}
87
+
88
+
89
+	/**
90
+	 * Returns true if the container can return an entry for the given identifier.
91
+	 * Returns false otherwise.
92
+	 * `has($identifier)` returning true does not mean that `get($identifier)` will not throw an exception.
93
+	 * It does however mean that `get($identifier)` will not throw a `ServiceNotFoundException`.
94
+	 *
95
+	 * @param string $identifier  Identifier of the entry to look for.
96
+	 *                            Typically a Fully Qualified Class Name
97
+	 * @return boolean
98
+	 * @throws InvalidIdentifierException
99
+	 */
100
+	public function has($identifier)
101
+	{
102
+		$identifier = $this->filterIdentifier($identifier);
103
+		return $this->carafe->has($identifier);
104
+	}
105
+
106
+
107
+	/**
108
+	 * finds a previously brewed (SHARED) service and returns it
109
+	 *
110
+	 * @param  string $identifier Identifier for the entity class to be constructed.
111
+	 *                            Typically a Fully Qualified Class Name
112
+	 * @return mixed
113
+	 * @throws InvalidIdentifierException
114
+	 * @throws ServiceNotFoundException No service was found for this identifier.
115
+	 */
116
+	public function get($identifier)
117
+	{
118
+		$identifier = $this->filterIdentifier($identifier);
119
+		if ($this->carafe->has($identifier)) {
120
+			return $this->carafe->get($identifier);
121
+		}
122
+		throw new ServiceNotFoundException($identifier);
123
+	}
124
+
125
+
126
+	/**
127
+	 * returns an instance of the requested entity type using the supplied arguments.
128
+	 * If a shared service is requested and an instance is already in the carafe, then it will be returned.
129
+	 * If it is not already in the carafe, then the service will be constructed, added to the carafe, and returned
130
+	 * If the request is for a new entity and a closure exists in the reservoir for creating it,
131
+	 * then a new entity will be instantiated from the closure and returned.
132
+	 * If a closure does not exist, then one will be built and added to the reservoir
133
+	 * before instantiating the requested entity.
134
+	 *
135
+	 * @param  string $identifier Identifier for the entity class to be constructed.
136
+	 *                            Typically a Fully Qualified Class Name
137
+	 * @param array   $arguments  an array of arguments to be passed to the entity constructor
138
+	 * @param string  $type
139
+	 * @return mixed
140
+	 * @throws OutOfBoundsException
141
+	 * @throws InstantiationException
142
+	 * @throws InvalidDataTypeException
143
+	 * @throws InvalidClassException
144
+	 * @throws InvalidIdentifierException
145
+	 * @throws ServiceExistsException
146
+	 * @throws ServiceNotFoundException No service was found for this identifier.
147
+	 */
148
+	public function brew($identifier, $arguments = array(), $type = '')
149
+	{
150
+		// resolve any class aliases that may exist
151
+		$identifier = $this->filterIdentifier($identifier);
152
+		// is a shared service being requested and already exists in the carafe?
153
+		$brewed = $this->getShared($identifier, $type);
154
+		// then return whatever was found
155
+		if ($brewed !== false) {
156
+			return $brewed;
157
+		}
158
+		// if the reservoir doesn't have a closure already for the requested identifier,
159
+		// then neither a shared service nor a closure for making entities has been built yet
160
+		if (! $this->reservoir->has($identifier)) {
161
+			// so let's brew something up and add it to the proper collection
162
+			$brewed = $this->makeCoffee($identifier, $arguments, $type);
163
+		}
164
+		// did the requested class only require loading, and if so, was that successful?
165
+		if ($this->brewedLoadOnly($brewed, $identifier, $type) === true) {
166
+			return true;
167
+		}
168
+		// was the brewed item a callable factory function ?
169
+		if (is_callable($brewed)) {
170
+			// then instantiate a new entity from the cached closure
171
+			return $brewed($arguments);
172
+		}
173
+		if ($brewed) {
174
+			// requested object was a shared entity, so attempt to get it from the carafe again
175
+			// because if it wasn't there before, then it should have just been brewed and added,
176
+			// but if it still isn't there, then this time the thrown ServiceNotFoundException will not be caught
177
+			return $this->get($identifier);
178
+		}
179
+		// if identifier is for a non-shared entity,
180
+		// then either a cached closure already existed, or was just brewed
181
+		return $this->brewedClosure($identifier, $arguments);
182
+	}
183
+
184
+
185
+	/**
186
+	 * @param string $identifier
187
+	 * @param string $type
188
+	 * @return bool|mixed
189
+	 * @throws InvalidIdentifierException
190
+	 */
191
+	protected function getShared($identifier, $type)
192
+	{
193
+		try {
194
+			if (empty($type) || $type === CoffeeMaker::BREW_SHARED) {
195
+				// if a shared service was requested and an instance is in the carafe, then return it
196
+				return $this->get($identifier);
197
+			}
198
+		} catch (ServiceNotFoundException $e) {
199
+			// if not then we'll just catch the ServiceNotFoundException but not do anything just yet,
200
+			// and instead, attempt to build whatever was requested
201
+		}
202
+		return false;
203
+	}
204
+
205
+
206
+	/**
207
+	 * @param mixed  $brewed
208
+	 * @param string $identifier
209
+	 * @param string $type
210
+	 * @return bool
211
+	 * @throws InvalidClassException
212
+	 * @throws InvalidDataTypeException
213
+	 * @throws InvalidIdentifierException
214
+	 * @throws OutOfBoundsException
215
+	 * @throws ServiceExistsException
216
+	 * @throws ServiceNotFoundException
217
+	 */
218
+	protected function brewedLoadOnly($brewed, $identifier, $type)
219
+	{
220
+		if ($type === CoffeeMaker::BREW_LOAD_ONLY) {
221
+			if ($brewed !== true) {
222
+				throw new ServiceNotFoundException(
223
+					sprintf(
224
+						esc_html__(
225
+							'The "%1$s" class could not be loaded.',
226
+							'event_espresso'
227
+						),
228
+						$identifier
229
+					)
230
+				);
231
+			}
232
+			return true;
233
+		}
234
+		return false;
235
+	}
236
+
237
+
238
+	/**
239
+	 * @param string $identifier
240
+	 * @param array  $arguments
241
+	 * @return mixed
242
+	 * @throws InstantiationException
243
+	 */
244
+	protected function brewedClosure($identifier, array $arguments)
245
+	{
246
+		$closure = $this->reservoir->get($identifier);
247
+		if (empty($closure)) {
248
+			throw new InstantiationException(
249
+				sprintf(
250
+					esc_html__(
251
+						'Could not brew an instance of "%1$s".',
252
+						'event_espresso'
253
+					),
254
+					$identifier
255
+				)
256
+			);
257
+		}
258
+		return $closure($arguments);
259
+	}
260
+
261
+
262
+	/**
263
+	 * @param CoffeeMakerInterface $coffee_maker
264
+	 * @param string               $type
265
+	 * @return bool
266
+	 * @throws InvalidIdentifierException
267
+	 * @throws InvalidEntityException
268
+	 */
269
+	public function addCoffeeMaker(CoffeeMakerInterface $coffee_maker, $type)
270
+	{
271
+		$type = CoffeeMaker::validateType($type);
272
+		return $this->coffee_makers->add($coffee_maker, $type);
273
+	}
274
+
275
+
276
+	/**
277
+	 * @param string   $identifier
278
+	 * @param callable $closure
279
+	 * @return callable|null
280
+	 * @throws InvalidIdentifierException
281
+	 * @throws InvalidDataTypeException
282
+	 */
283
+	public function addClosure($identifier, $closure)
284
+	{
285
+		if (! is_callable($closure)) {
286
+			throw new InvalidDataTypeException('$closure', $closure, 'Closure');
287
+		}
288
+		$identifier = $this->processIdentifier($identifier);
289
+		if ($this->reservoir->add($closure, $identifier)) {
290
+			return $closure;
291
+		}
292
+		return null;
293
+	}
294
+
295
+
296
+	/**
297
+	 * @param string $identifier
298
+	 * @return boolean
299
+	 * @throws InvalidIdentifierException
300
+	 */
301
+	public function removeClosure($identifier)
302
+	{
303
+		$identifier = $this->processIdentifier($identifier);
304
+		if ($this->reservoir->has($identifier)) {
305
+			return $this->reservoir->remove($this->reservoir->get($identifier));
306
+		}
307
+		return false;
308
+	}
309
+
310
+
311
+	/**
312
+	 * @param  string $identifier Identifier for the entity class that the service applies to
313
+	 *                            Typically a Fully Qualified Class Name
314
+	 * @param mixed   $service
315
+	 * @return bool
316
+	 * @throws \EventEspresso\core\services\container\exceptions\InvalidServiceException
317
+	 * @throws InvalidIdentifierException
318
+	 */
319
+	public function addService($identifier, $service)
320
+	{
321
+		$identifier = $this->processIdentifier($identifier);
322
+		$service = $this->validateService($identifier, $service);
323
+		return $this->carafe->add($service, $identifier);
324
+	}
325
+
326
+
327
+	/**
328
+	 * @param string $identifier
329
+	 * @return boolean
330
+	 * @throws InvalidIdentifierException
331
+	 */
332
+	public function removeService($identifier)
333
+	{
334
+		$identifier = $this->processIdentifier($identifier);
335
+		if ($this->carafe->has($identifier)) {
336
+			return $this->carafe->remove($this->carafe->get($identifier));
337
+		}
338
+		return false;
339
+	}
340
+
341
+
342
+	/**
343
+	 * Adds instructions on how to brew objects
344
+	 *
345
+	 * @param RecipeInterface $recipe
346
+	 * @return mixed
347
+	 * @throws InvalidIdentifierException
348
+	 */
349
+	public function addRecipe(RecipeInterface $recipe)
350
+	{
351
+		$this->addAliases($recipe->identifier(), $recipe->filters());
352
+		$identifier = $this->processIdentifier($recipe->identifier());
353
+		return $this->recipes->add($recipe, $identifier);
354
+	}
355
+
356
+
357
+	/**
358
+	 * @param string $identifier The Recipe's identifier
359
+	 * @return boolean
360
+	 * @throws InvalidIdentifierException
361
+	 */
362
+	public function removeRecipe($identifier)
363
+	{
364
+		$identifier = $this->processIdentifier($identifier);
365
+		if ($this->recipes->has($identifier)) {
366
+			return $this->recipes->remove($this->recipes->get($identifier));
367
+		}
368
+		return false;
369
+	}
370
+
371
+
372
+	/**
373
+	 * Get instructions on how to brew objects
374
+	 *
375
+	 * @param  string $identifier Identifier for the entity class that the recipe applies to
376
+	 *                            Typically a Fully Qualified Class Name
377
+	 * @param string  $type
378
+	 * @return RecipeInterface
379
+	 * @throws OutOfBoundsException
380
+	 * @throws InvalidIdentifierException
381
+	 */
382
+	public function getRecipe($identifier, $type = '')
383
+	{
384
+		$identifier = $this->processIdentifier($identifier);
385
+		if ($this->recipes->has($identifier)) {
386
+			return $this->recipes->get($identifier);
387
+		}
388
+		$default_recipes = $this->getDefaultRecipes();
389
+		$matches = array();
390
+		foreach ($default_recipes as $wildcard => $default_recipe) {
391
+			// is the wildcard recipe prefix in the identifier ?
392
+			if (strpos($identifier, $wildcard) !== false) {
393
+				// track matches and use the number of wildcard characters matched for the key
394
+				$matches[ strlen($wildcard) ] = $default_recipe;
395
+			}
396
+		}
397
+		if (count($matches) > 0) {
398
+			// sort our recipes by the number of wildcard characters matched
399
+			ksort($matches);
400
+			// then grab the last recipe form the list, since it had the most matching characters
401
+			$match = array_pop($matches);
402
+			// since we are using a default recipe, we need to set it's identifier and fqcn
403
+			return $this->copyDefaultRecipe($match, $identifier, $type);
404
+		}
405
+		if ($this->recipes->has(Recipe::DEFAULT_ID)) {
406
+			// since we are using a default recipe, we need to set it's identifier and fqcn
407
+			return $this->copyDefaultRecipe($this->recipes->get(Recipe::DEFAULT_ID), $identifier, $type);
408
+		}
409
+		throw new OutOfBoundsException(
410
+			sprintf(
411
+				esc_html__('Could not brew coffee because no recipes were found for class "%1$s".', 'event_espresso'),
412
+				$identifier
413
+			)
414
+		);
415
+	}
416
+
417
+
418
+	/**
419
+	 * adds class name aliases to list of filters
420
+	 *
421
+	 * @param  string       $identifier Identifier for the entity class that the alias applies to
422
+	 *                                  Typically a Fully Qualified Class Name
423
+	 * @param  array|string $aliases
424
+	 * @return void
425
+	 * @throws InvalidIdentifierException
426
+	 */
427
+	public function addAliases($identifier, $aliases)
428
+	{
429
+		if (empty($aliases)) {
430
+			return;
431
+		}
432
+		$identifier = $this->processIdentifier($identifier);
433
+		foreach ((array) $aliases as $alias) {
434
+			$this->filters[ $this->processIdentifier($alias) ] = $identifier;
435
+		}
436
+	}
437
+
438
+
439
+	/**
440
+	 * Adds a service to one of the internal collections
441
+	 *
442
+	 * @param        $identifier
443
+	 * @param array  $arguments
444
+	 * @param string $type
445
+	 * @return mixed
446
+	 * @throws InvalidDataTypeException
447
+	 * @throws InvalidClassException
448
+	 * @throws OutOfBoundsException
449
+	 * @throws InvalidIdentifierException
450
+	 * @throws ServiceExistsException
451
+	 */
452
+	private function makeCoffee($identifier, $arguments = array(), $type = '')
453
+	{
454
+		if ((empty($type) || $type === CoffeeMaker::BREW_SHARED) && $this->has($identifier)) {
455
+			throw new ServiceExistsException($identifier);
456
+		}
457
+		$identifier = $this->filterIdentifier($identifier);
458
+		$recipe = $this->getRecipe($identifier, $type);
459
+		$type = ! empty($type) ? $type : $recipe->type();
460
+		$coffee_maker = $this->getCoffeeMaker($type);
461
+		return $coffee_maker->brew($recipe, $arguments);
462
+	}
463
+
464
+
465
+	/**
466
+	 * filters alias identifiers to find the real class name
467
+	 *
468
+	 * @param  string $identifier Identifier for the entity class that the filter applies to
469
+	 *                            Typically a Fully Qualified Class Name
470
+	 * @return string
471
+	 * @throws InvalidIdentifierException
472
+	 */
473
+	private function filterIdentifier($identifier)
474
+	{
475
+		$identifier = $this->processIdentifier($identifier);
476
+		return isset($this->filters[ $identifier ]) && ! empty($this->filters[ $identifier ])
477
+			? $this->filters[ $identifier ]
478
+			: $identifier;
479
+	}
480
+
481
+
482
+	/**
483
+	 * verifies and standardizes identifiers
484
+	 *
485
+	 * @param  string $identifier Identifier for the entity class
486
+	 *                            Typically a Fully Qualified Class Name
487
+	 * @return string
488
+	 * @throws InvalidIdentifierException
489
+	 */
490
+	private function processIdentifier($identifier)
491
+	{
492
+		if (! is_string($identifier)) {
493
+			throw new InvalidIdentifierException(
494
+				is_object($identifier) ? get_class($identifier) : gettype($identifier),
495
+				'\Fully\Qualified\ClassName'
496
+			);
497
+		}
498
+		return ltrim($identifier, '\\');
499
+	}
500
+
501
+
502
+	/**
503
+	 * @param string $type
504
+	 * @return CoffeeMakerInterface
505
+	 * @throws OutOfBoundsException
506
+	 * @throws InvalidDataTypeException
507
+	 * @throws InvalidClassException
508
+	 */
509
+	private function getCoffeeMaker($type)
510
+	{
511
+		if (! $this->coffee_makers->has($type)) {
512
+			throw new OutOfBoundsException(
513
+				esc_html__('The requested coffee maker is either missing or invalid.', 'event_espresso')
514
+			);
515
+		}
516
+		return $this->coffee_makers->get($type);
517
+	}
518
+
519
+
520
+	/**
521
+	 * Retrieves all recipes that use a wildcard "*" in their identifier
522
+	 * This allows recipes to be set up for handling
523
+	 * legacy classes that do not support PSR-4 autoloading.
524
+	 * for example:
525
+	 * using "EEM_*" for a recipe identifier would target all legacy models like EEM_Attendee
526
+	 *
527
+	 * @return array
528
+	 */
529
+	private function getDefaultRecipes()
530
+	{
531
+		$default_recipes = array();
532
+		$this->recipes->rewind();
533
+		while ($this->recipes->valid()) {
534
+			$identifier = $this->recipes->getInfo();
535
+			// does this recipe use a wildcard ? (but is NOT the global default)
536
+			if ($identifier !== Recipe::DEFAULT_ID && strpos($identifier, '*') !== false) {
537
+				// strip the wildcard and use identifier as key
538
+				$default_recipes[ str_replace('*', '', $identifier) ] = $this->recipes->current();
539
+			}
540
+			$this->recipes->next();
541
+		}
542
+		return $default_recipes;
543
+	}
544
+
545
+
546
+	/**
547
+	 * clones a default recipe and then copies details
548
+	 * from the incoming request to it so that it can be used
549
+	 *
550
+	 * @param RecipeInterface $default_recipe
551
+	 * @param string          $identifier
552
+	 * @param string          $type
553
+	 * @return RecipeInterface
554
+	 */
555
+	private function copyDefaultRecipe(RecipeInterface $default_recipe, $identifier, $type = '')
556
+	{
557
+		$recipe = clone $default_recipe;
558
+		if (! empty($type)) {
559
+			$recipe->setType($type);
560
+		}
561
+		// is this the base default recipe ?
562
+		if ($default_recipe->identifier() === Recipe::DEFAULT_ID) {
563
+			$recipe->setIdentifier($identifier);
564
+			$recipe->setFqcn($identifier);
565
+			return $recipe;
566
+		}
567
+		$recipe->setIdentifier($identifier);
568
+		foreach ($default_recipe->paths() as $path) {
569
+			$path = str_replace('*', $identifier, $path);
570
+			if (is_readable($path)) {
571
+				$recipe->setPaths($path);
572
+			}
573
+		}
574
+		$recipe->setFqcn($identifier);
575
+		return $recipe;
576
+	}
577
+
578
+
579
+	/**
580
+	 * @param  string $identifier Identifier for the entity class that the service applies to
581
+	 *                            Typically a Fully Qualified Class Name
582
+	 * @param mixed   $service
583
+	 * @return mixed
584
+	 * @throws InvalidServiceException
585
+	 */
586
+	private function validateService($identifier, $service)
587
+	{
588
+		if (! is_object($service)) {
589
+			throw new InvalidServiceException(
590
+				$identifier,
591
+				$service
592
+			);
593
+		}
594
+		return $service;
595
+	}
596 596
 }
Please login to merge, or discard this patch.
core/CPTs/CptQueryModifier.php 2 patches
Indentation   +578 added lines, -578 removed lines patch added patch discarded remove patch
@@ -30,582 +30,582 @@
 block discarded – undo
30 30
  */
31 31
 class CptQueryModifier
32 32
 {
33
-    /**
34
-     * @var CurrentPage $current_page
35
-     */
36
-    protected $current_page;
37
-
38
-    /**
39
-     * @var string $post_type
40
-     */
41
-    protected $post_type = '';
42
-
43
-    /**
44
-     * CPT details from CustomPostTypeDefinitions for specific post type
45
-     *
46
-     * @var array $cpt_details
47
-     */
48
-    protected $cpt_details = array();
49
-
50
-    /**
51
-     * @var EE_Table_Base[] $model_tables
52
-     */
53
-    protected $model_tables = array();
54
-
55
-    /**
56
-     * @var array $taxonomies
57
-     */
58
-    protected $taxonomies = array();
59
-
60
-    /**
61
-     * meta table for the related CPT
62
-     *
63
-     * @var EE_Secondary_Table $meta_table
64
-     */
65
-    protected $meta_table;
66
-
67
-    /**
68
-     * EEM_CPT_Base model for the related CPT
69
-     *
70
-     * @var EEM_CPT_Base $model
71
-     */
72
-    protected $model;
73
-
74
-    /**
75
-     * @var EE_Request_Handler $request_handler
76
-     */
77
-    protected $request_handler;
78
-
79
-    /**
80
-     * @var WP_Query $wp_query
81
-     */
82
-    protected $wp_query;
83
-
84
-    /**
85
-     * @var LoaderInterface $loader
86
-     */
87
-    protected $loader;
88
-
89
-    /**
90
-     * @var RequestInterface $request
91
-     */
92
-    protected $request;
93
-
94
-
95
-    /**
96
-     * CptQueryModifier constructor
97
-     *
98
-     * @param string             $post_type
99
-     * @param array              $cpt_details
100
-     * @param WP_Query           $WP_Query
101
-     * @param CurrentPage $current_page
102
-     * @param RequestInterface   $request
103
-     * @param LoaderInterface    $loader
104
-     * @throws EE_Error
105
-     */
106
-    public function __construct(
107
-        $post_type,
108
-        array $cpt_details,
109
-        WP_Query $WP_Query,
110
-        CurrentPage $current_page,
111
-        RequestInterface $request,
112
-        LoaderInterface $loader
113
-    ) {
114
-        $this->loader = $loader;
115
-        $this->request = $request;
116
-        $this->current_page = $current_page;
117
-        $this->setWpQuery($WP_Query);
118
-        $this->setPostType($post_type);
119
-        $this->setCptDetails($cpt_details);
120
-        $this->init();
121
-    }
122
-
123
-
124
-    /**
125
-     * @return string
126
-     */
127
-    public function postType()
128
-    {
129
-        return $this->post_type;
130
-    }
131
-
132
-
133
-    /**
134
-     * @param string $post_type
135
-     */
136
-    protected function setPostType($post_type)
137
-    {
138
-        $this->post_type = $post_type;
139
-    }
140
-
141
-
142
-    /**
143
-     * @return array
144
-     */
145
-    public function cptDetails()
146
-    {
147
-        return $this->cpt_details;
148
-    }
149
-
150
-
151
-    /**
152
-     * @param array $cpt_details
153
-     */
154
-    protected function setCptDetails($cpt_details)
155
-    {
156
-        $this->cpt_details = $cpt_details;
157
-    }
158
-
159
-
160
-    /**
161
-     * @return EE_Table_Base[]
162
-     */
163
-    public function modelTables()
164
-    {
165
-        return $this->model_tables;
166
-    }
167
-
168
-
169
-    /**
170
-     * @param EE_Table_Base[] $model_tables
171
-     */
172
-    protected function setModelTables($model_tables)
173
-    {
174
-        $this->model_tables = $model_tables;
175
-    }
176
-
177
-
178
-    /**
179
-     * @return array
180
-     * @throws InvalidArgumentException
181
-     * @throws InvalidDataTypeException
182
-     * @throws InvalidInterfaceException
183
-     */
184
-    public function taxonomies()
185
-    {
186
-        if (empty($this->taxonomies)) {
187
-            $this->initializeTaxonomies();
188
-        }
189
-        return $this->taxonomies;
190
-    }
191
-
192
-
193
-    /**
194
-     * @param array $taxonomies
195
-     */
196
-    protected function setTaxonomies(array $taxonomies)
197
-    {
198
-        $this->taxonomies = $taxonomies;
199
-    }
200
-
201
-
202
-    /**
203
-     * @return EE_Secondary_Table
204
-     */
205
-    public function metaTable()
206
-    {
207
-        return $this->meta_table;
208
-    }
209
-
210
-
211
-    /**
212
-     * @param EE_Secondary_Table $meta_table
213
-     */
214
-    public function setMetaTable(EE_Secondary_Table $meta_table)
215
-    {
216
-        $this->meta_table = $meta_table;
217
-    }
218
-
219
-
220
-    /**
221
-     * @return EEM_Base
222
-     */
223
-    public function model()
224
-    {
225
-        return $this->model;
226
-    }
227
-
228
-
229
-    /**
230
-     * @param EEM_Base $CPT_model
231
-     */
232
-    protected function setModel(EEM_Base $CPT_model)
233
-    {
234
-        $this->model = $CPT_model;
235
-    }
236
-
237
-
238
-    /**
239
-     * @deprecated 4.9.63.p
240
-     * @return EE_Request_Handler
241
-     */
242
-    public function request()
243
-    {
244
-        if (! $this->request_handler instanceof EE_Request_Handler) {
245
-            $this->request_handler = LoaderFactory::getLoader()->getShared('EE_Request_Handler');
246
-        }
247
-        return $this->request_handler;
248
-    }
249
-
250
-
251
-
252
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
253
-
254
-
255
-    /**
256
-     * @return WP_Query
257
-     */
258
-    public function WpQuery()
259
-    {
260
-        return $this->wp_query;
261
-    }
262
-    // phpcs:enable
263
-
264
-
265
-    /**
266
-     * @param WP_Query $wp_query
267
-     */
268
-    public function setWpQuery(WP_Query $wp_query)
269
-    {
270
-        $this->wp_query = $wp_query;
271
-    }
272
-
273
-
274
-    /**
275
-     * @return void
276
-     * @throws InvalidDataTypeException
277
-     * @throws InvalidInterfaceException
278
-     * @throws InvalidArgumentException
279
-     */
280
-    protected function initializeTaxonomies()
281
-    {
282
-        // check if taxonomies have already been set and that this CPT has taxonomies registered for it
283
-        if (
284
-            empty($this->taxonomies)
285
-            && isset($this->cpt_details['args']['taxonomies'])
286
-        ) {
287
-            // if so then grab them, but we want the taxonomy name as the key
288
-            $taxonomies = array_flip($this->cpt_details['args']['taxonomies']);
289
-            // then grab the list of ALL taxonomies
290
-            /** @var CustomTaxonomyDefinitions
291
-             * $taxonomy_definitions
292
-             */
293
-            $taxonomy_definitions = $this->loader->getShared(
294
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions'
295
-            );
296
-            $all_taxonomies = $taxonomy_definitions->getCustomTaxonomyDefinitions();
297
-            foreach ($taxonomies as $taxonomy => &$details) {
298
-                // add details to our taxonomies if they exist
299
-                $details = isset($all_taxonomies[ $taxonomy ])
300
-                    ? $all_taxonomies[ $taxonomy ]
301
-                    : array();
302
-            }
303
-            // ALWAYS unset() variables that were passed by reference
304
-            unset($details);
305
-            $this->setTaxonomies($taxonomies);
306
-        }
307
-    }
308
-
309
-
310
-    /**
311
-     * @since 4.9.63.p
312
-     * @throws EE_Error
313
-     */
314
-    protected function init()
315
-    {
316
-        $this->setAdditionalCptDetails();
317
-        $this->setRequestVarsIfCpt();
318
-        // convert post_type to model name
319
-        $model_name = str_replace('EE_', '', $this->cpt_details['class_name']);
320
-        // load all tables related to CPT
321
-        $this->setupModelsAndTables($model_name);
322
-        // load and instantiate CPT_*_Strategy
323
-        $CPT_Strategy = $this->cptStrategyClass($model_name);
324
-        // !!!!!!!!!!  IMPORTANT !!!!!!!!!!!!
325
-        // here's the list of available filters in the WP_Query object
326
-        // 'posts_where_paged'
327
-        // 'posts_groupby'
328
-        // 'posts_join_paged'
329
-        // 'posts_orderby'
330
-        // 'posts_distinct'
331
-        // 'post_limits'
332
-        // 'posts_fields'
333
-        // 'posts_join'
334
-        add_filter('posts_fields', array($this, 'postsFields'));
335
-        add_filter('posts_join', array($this, 'postsJoin'));
336
-        add_filter(
337
-            'get_' . $this->post_type . '_metadata',
338
-            array($CPT_Strategy, 'get_EE_post_type_metadata'),
339
-            1,
340
-            4
341
-        );
342
-        add_filter('the_posts', array($this, 'thePosts'), 1, 1);
343
-        if ($this->wp_query->is_main_query()) {
344
-            add_filter('get_edit_post_link', array($this, 'getEditPostLink'), 10, 2);
345
-            $this->addTemplateFilters();
346
-        }
347
-    }
348
-
349
-
350
-    /**
351
-     * sets some basic query vars that pertain to the CPT
352
-     *
353
-     * @access protected
354
-     * @return void
355
-     */
356
-    protected function setAdditionalCptDetails()
357
-    {
358
-        // the post or category or term that is triggering EE
359
-        $this->cpt_details['espresso_page'] = $this->current_page->isEspressoPage();
360
-        // requested post name
361
-        $this->cpt_details['post_name'] = $this->request->getRequestParam('post_name');
362
-        // add support for viewing 'private', 'draft', or 'pending' posts
363
-        if (
364
-            isset($this->wp_query->query_vars['p'])
365
-            && $this->wp_query->query_vars['p'] !== 0
366
-            && is_user_logged_in()
367
-            && current_user_can('edit_post', $this->wp_query->query_vars['p'])
368
-        ) {
369
-            // we can just inject directly into the WP_Query object
370
-            $this->wp_query->query['post_status'] = array('publish', 'private', 'draft', 'pending');
371
-            // now set the main 'ee' request var so that the appropriate module can load the appropriate template(s)
372
-            $this->request->setRequestParam('ee', $this->cpt_details['singular_slug']);
373
-        }
374
-    }
375
-
376
-
377
-    /**
378
-     * Checks if we're on a EE-CPT archive-or-single page, and if we've never set the EE request var.
379
-     * If so, sets the 'ee' request variable
380
-     * so other parts of EE can know what CPT is getting queried.
381
-     * To Mike's knowledge, this must be called from during or after the pre_get_posts hook
382
-     * in order for is_archive() and is_single() methods to work properly.
383
-     *
384
-     * @return void
385
-     */
386
-    public function setRequestVarsIfCpt()
387
-    {
388
-        // check if ee action var has been set
389
-        if (! $this->request->requestParamIsSet('ee')) {
390
-            // check that route exists for CPT archive slug
391
-            if (is_archive() && EE_Config::get_route($this->cpt_details['plural_slug'])) {
392
-                // ie: set "ee" to "events"
393
-                $this->request->setRequestParam('ee', $this->cpt_details['plural_slug']);
394
-                // or does it match a single page CPT like /event/
395
-            } elseif (is_single() && EE_Config::get_route($this->cpt_details['singular_slug'])) {
396
-                // ie: set "ee" to "event"
397
-                $this->request->setRequestParam('ee', $this->cpt_details['singular_slug']);
398
-            }
399
-        }
400
-    }
401
-
402
-
403
-    /**
404
-     * setupModelsAndTables
405
-     *
406
-     * @access protected
407
-     * @param string $model_name
408
-     * @throws EE_Error
409
-     */
410
-    protected function setupModelsAndTables($model_name)
411
-    {
412
-        // get CPT table data via CPT Model
413
-        $full_model_name = strpos($model_name, 'EEM_') !== 0
414
-            ? 'EEM_' . $model_name
415
-            : $model_name;
416
-        $model = $this->loader->getShared($full_model_name);
417
-        if (! $model instanceof EEM_Base) {
418
-            throw new EE_Error(
419
-                sprintf(
420
-                    esc_html__(
421
-                        'The "%1$s" model could not be loaded.',
422
-                        'event_espresso'
423
-                    ),
424
-                    $full_model_name
425
-                )
426
-            );
427
-        }
428
-        $this->setModel($model);
429
-        $this->setModelTables($this->model->get_tables());
430
-        $meta_model = $model_name . '_Meta';
431
-        // is there a Meta Table for this CPT?
432
-        if (
433
-            isset($this->cpt_details['tables'][ $meta_model ])
434
-            && $this->cpt_details['tables'][ $meta_model ] instanceof EE_Secondary_Table
435
-        ) {
436
-            $this->setMetaTable($this->cpt_details['tables'][ $meta_model ]);
437
-        }
438
-    }
439
-
440
-
441
-    /**
442
-     * cptStrategyClass
443
-     *
444
-     * @access protected
445
-     * @param  string $model_name
446
-     * @return string
447
-     */
448
-    protected function cptStrategyClass($model_name)
449
-    {
450
-        // creates classname like:  CPT_Event_Strategy
451
-        $CPT_Strategy_class_name = 'EE_CPT_' . $model_name . '_Strategy';
452
-        // load and instantiate
453
-        $CPT_Strategy = $this->loader->getShared(
454
-            $CPT_Strategy_class_name,
455
-            array('WP_Query' => $this->wp_query, 'CPT' => $this->cpt_details)
456
-        );
457
-        if ($CPT_Strategy === null) {
458
-            $CPT_Strategy = $this->loader->getShared(
459
-                'EE_CPT_Default_Strategy',
460
-                array('WP_Query' => $this->wp_query, 'CPT' => $this->cpt_details)
461
-            );
462
-        }
463
-        return $CPT_Strategy;
464
-    }
465
-
466
-
467
-    /**
468
-     * postsFields
469
-     *
470
-     * @access public
471
-     * @param  $SQL
472
-     * @return string
473
-     */
474
-    public function postsFields($SQL)
475
-    {
476
-        // does this CPT have a meta table ?
477
-        if ($this->meta_table instanceof EE_Secondary_Table) {
478
-            // adds something like ", wp_esp_event_meta.* " to WP Query SELECT statement
479
-            $SQL .= ', ' . $this->meta_table->get_table_name() . '.* ';
480
-        }
481
-        remove_filter('posts_fields', array($this, 'postsFields'));
482
-        return $SQL;
483
-    }
484
-
485
-
486
-    /**
487
-     * postsJoin
488
-     *
489
-     * @access public
490
-     * @param  $SQL
491
-     * @return string
492
-     */
493
-    public function postsJoin($SQL)
494
-    {
495
-        // does this CPT have a meta table ?
496
-        if ($this->meta_table instanceof EE_Secondary_Table) {
497
-            global $wpdb;
498
-            // adds something like " LEFT JOIN wp_esp_event_meta ON ( wp_esp_event_meta.EVT_ID = wp_posts.ID ) " to WP Query JOIN statement
499
-            $SQL .= ' LEFT JOIN '
500
-                    . $this->meta_table->get_table_name()
501
-                    . ' ON ( '
502
-                    . $this->meta_table->get_table_name()
503
-                    . '.'
504
-                    . $this->meta_table->get_fk_on_table()
505
-                    . ' = '
506
-                    . $wpdb->posts
507
-                    . '.ID ) ';
508
-        }
509
-        remove_filter('posts_join', array($this, 'postsJoin'));
510
-        return $SQL;
511
-    }
512
-
513
-
514
-    /**
515
-     * thePosts
516
-     *
517
-     * @access public
518
-     * @param  WP_Post[] $posts
519
-     * @return WP_Post[]
520
-     */
521
-    public function thePosts($posts)
522
-    {
523
-        $CPT_class = $this->cpt_details['class_name'];
524
-        // loop thru posts
525
-        if (is_array($posts) && $this->model instanceof EEM_CPT_Base) {
526
-            foreach ($posts as $post) {
527
-                if ($post->post_type === $this->post_type) {
528
-                    $post->{$CPT_class} = $this->model->instantiate_class_from_post_object($post);
529
-                }
530
-            }
531
-        }
532
-        remove_filter('the_posts', array($this, 'thePosts'), 1);
533
-        return $posts;
534
-    }
535
-
536
-
537
-    /**
538
-     * @param $url
539
-     * @param $ID
540
-     * @return string
541
-     */
542
-    public function getEditPostLink($url, $ID)
543
-    {
544
-        // need to make sure we only edit links if our cpt
545
-        global $post;
546
-        // notice if the cpt is registered with `show_ee_ui` set to false, we take that to mean that the WordPress core ui
547
-        // for interacting with the CPT is desired and there is no EE UI for interacting with the CPT in the admin.
548
-        if (
549
-            ! $post instanceof WP_Post
550
-            || $post->post_type !== $this->post_type
551
-            || (
552
-                isset($this->cpt_details['args']['show_ee_ui'])
553
-                && ! $this->cpt_details['args']['show_ee_ui']
554
-            )
555
-        ) {
556
-            return $url;
557
-        }
558
-        // k made it here so all is good.
559
-        return wp_nonce_url(
560
-            add_query_arg(
561
-                array('page' => $this->post_type, 'post' => $ID, 'action' => 'edit'),
562
-                admin_url('admin.php')
563
-            ),
564
-            'edit',
565
-            'edit_nonce'
566
-        );
567
-    }
568
-
569
-
570
-    /**
571
-     * Execute any template filters.
572
-     * This method is only called if in main query.
573
-     *
574
-     * @return void
575
-     */
576
-    public function addTemplateFilters()
577
-    {
578
-        // if requested cpt supports page_templates and it's the main query
579
-        if (! empty($this->cpt_details['args']['page_templates']) && $this->wp_query->is_main_query()) {
580
-            // then let's hook into the appropriate query_template hook
581
-            add_filter('single_template', array($this, 'singleCptTemplate'));
582
-        }
583
-    }
584
-
585
-
586
-    /**
587
-     * Callback for single_template wp filter.
588
-     * This is used to load the set page_template for a single ee cpt if its set.  If "default" then we load the normal
589
-     * hierarchy.
590
-     *
591
-     * @access public
592
-     * @param string $current_template Existing default template path derived for this page call.
593
-     * @return string the path to the full template file.
594
-     */
595
-    public function singleCptTemplate($current_template)
596
-    {
597
-        $object = get_queried_object();
598
-        // does this called object HAVE a page template set that is something other than the default.
599
-        $template = get_post_meta($object->ID, '_wp_page_template', true);
600
-        // exit early if default or not set or invalid path (accounts for theme changes)
601
-        if (
602
-            $template === 'default'
603
-            || empty($template)
604
-            || ! is_readable(get_stylesheet_directory() . '/' . $template)
605
-        ) {
606
-            return $current_template;
607
-        }
608
-        // made it here so we SHOULD be able to just locate the template and then return it.
609
-        return locate_template(array($template));
610
-    }
33
+	/**
34
+	 * @var CurrentPage $current_page
35
+	 */
36
+	protected $current_page;
37
+
38
+	/**
39
+	 * @var string $post_type
40
+	 */
41
+	protected $post_type = '';
42
+
43
+	/**
44
+	 * CPT details from CustomPostTypeDefinitions for specific post type
45
+	 *
46
+	 * @var array $cpt_details
47
+	 */
48
+	protected $cpt_details = array();
49
+
50
+	/**
51
+	 * @var EE_Table_Base[] $model_tables
52
+	 */
53
+	protected $model_tables = array();
54
+
55
+	/**
56
+	 * @var array $taxonomies
57
+	 */
58
+	protected $taxonomies = array();
59
+
60
+	/**
61
+	 * meta table for the related CPT
62
+	 *
63
+	 * @var EE_Secondary_Table $meta_table
64
+	 */
65
+	protected $meta_table;
66
+
67
+	/**
68
+	 * EEM_CPT_Base model for the related CPT
69
+	 *
70
+	 * @var EEM_CPT_Base $model
71
+	 */
72
+	protected $model;
73
+
74
+	/**
75
+	 * @var EE_Request_Handler $request_handler
76
+	 */
77
+	protected $request_handler;
78
+
79
+	/**
80
+	 * @var WP_Query $wp_query
81
+	 */
82
+	protected $wp_query;
83
+
84
+	/**
85
+	 * @var LoaderInterface $loader
86
+	 */
87
+	protected $loader;
88
+
89
+	/**
90
+	 * @var RequestInterface $request
91
+	 */
92
+	protected $request;
93
+
94
+
95
+	/**
96
+	 * CptQueryModifier constructor
97
+	 *
98
+	 * @param string             $post_type
99
+	 * @param array              $cpt_details
100
+	 * @param WP_Query           $WP_Query
101
+	 * @param CurrentPage $current_page
102
+	 * @param RequestInterface   $request
103
+	 * @param LoaderInterface    $loader
104
+	 * @throws EE_Error
105
+	 */
106
+	public function __construct(
107
+		$post_type,
108
+		array $cpt_details,
109
+		WP_Query $WP_Query,
110
+		CurrentPage $current_page,
111
+		RequestInterface $request,
112
+		LoaderInterface $loader
113
+	) {
114
+		$this->loader = $loader;
115
+		$this->request = $request;
116
+		$this->current_page = $current_page;
117
+		$this->setWpQuery($WP_Query);
118
+		$this->setPostType($post_type);
119
+		$this->setCptDetails($cpt_details);
120
+		$this->init();
121
+	}
122
+
123
+
124
+	/**
125
+	 * @return string
126
+	 */
127
+	public function postType()
128
+	{
129
+		return $this->post_type;
130
+	}
131
+
132
+
133
+	/**
134
+	 * @param string $post_type
135
+	 */
136
+	protected function setPostType($post_type)
137
+	{
138
+		$this->post_type = $post_type;
139
+	}
140
+
141
+
142
+	/**
143
+	 * @return array
144
+	 */
145
+	public function cptDetails()
146
+	{
147
+		return $this->cpt_details;
148
+	}
149
+
150
+
151
+	/**
152
+	 * @param array $cpt_details
153
+	 */
154
+	protected function setCptDetails($cpt_details)
155
+	{
156
+		$this->cpt_details = $cpt_details;
157
+	}
158
+
159
+
160
+	/**
161
+	 * @return EE_Table_Base[]
162
+	 */
163
+	public function modelTables()
164
+	{
165
+		return $this->model_tables;
166
+	}
167
+
168
+
169
+	/**
170
+	 * @param EE_Table_Base[] $model_tables
171
+	 */
172
+	protected function setModelTables($model_tables)
173
+	{
174
+		$this->model_tables = $model_tables;
175
+	}
176
+
177
+
178
+	/**
179
+	 * @return array
180
+	 * @throws InvalidArgumentException
181
+	 * @throws InvalidDataTypeException
182
+	 * @throws InvalidInterfaceException
183
+	 */
184
+	public function taxonomies()
185
+	{
186
+		if (empty($this->taxonomies)) {
187
+			$this->initializeTaxonomies();
188
+		}
189
+		return $this->taxonomies;
190
+	}
191
+
192
+
193
+	/**
194
+	 * @param array $taxonomies
195
+	 */
196
+	protected function setTaxonomies(array $taxonomies)
197
+	{
198
+		$this->taxonomies = $taxonomies;
199
+	}
200
+
201
+
202
+	/**
203
+	 * @return EE_Secondary_Table
204
+	 */
205
+	public function metaTable()
206
+	{
207
+		return $this->meta_table;
208
+	}
209
+
210
+
211
+	/**
212
+	 * @param EE_Secondary_Table $meta_table
213
+	 */
214
+	public function setMetaTable(EE_Secondary_Table $meta_table)
215
+	{
216
+		$this->meta_table = $meta_table;
217
+	}
218
+
219
+
220
+	/**
221
+	 * @return EEM_Base
222
+	 */
223
+	public function model()
224
+	{
225
+		return $this->model;
226
+	}
227
+
228
+
229
+	/**
230
+	 * @param EEM_Base $CPT_model
231
+	 */
232
+	protected function setModel(EEM_Base $CPT_model)
233
+	{
234
+		$this->model = $CPT_model;
235
+	}
236
+
237
+
238
+	/**
239
+	 * @deprecated 4.9.63.p
240
+	 * @return EE_Request_Handler
241
+	 */
242
+	public function request()
243
+	{
244
+		if (! $this->request_handler instanceof EE_Request_Handler) {
245
+			$this->request_handler = LoaderFactory::getLoader()->getShared('EE_Request_Handler');
246
+		}
247
+		return $this->request_handler;
248
+	}
249
+
250
+
251
+
252
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
253
+
254
+
255
+	/**
256
+	 * @return WP_Query
257
+	 */
258
+	public function WpQuery()
259
+	{
260
+		return $this->wp_query;
261
+	}
262
+	// phpcs:enable
263
+
264
+
265
+	/**
266
+	 * @param WP_Query $wp_query
267
+	 */
268
+	public function setWpQuery(WP_Query $wp_query)
269
+	{
270
+		$this->wp_query = $wp_query;
271
+	}
272
+
273
+
274
+	/**
275
+	 * @return void
276
+	 * @throws InvalidDataTypeException
277
+	 * @throws InvalidInterfaceException
278
+	 * @throws InvalidArgumentException
279
+	 */
280
+	protected function initializeTaxonomies()
281
+	{
282
+		// check if taxonomies have already been set and that this CPT has taxonomies registered for it
283
+		if (
284
+			empty($this->taxonomies)
285
+			&& isset($this->cpt_details['args']['taxonomies'])
286
+		) {
287
+			// if so then grab them, but we want the taxonomy name as the key
288
+			$taxonomies = array_flip($this->cpt_details['args']['taxonomies']);
289
+			// then grab the list of ALL taxonomies
290
+			/** @var CustomTaxonomyDefinitions
291
+			 * $taxonomy_definitions
292
+			 */
293
+			$taxonomy_definitions = $this->loader->getShared(
294
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions'
295
+			);
296
+			$all_taxonomies = $taxonomy_definitions->getCustomTaxonomyDefinitions();
297
+			foreach ($taxonomies as $taxonomy => &$details) {
298
+				// add details to our taxonomies if they exist
299
+				$details = isset($all_taxonomies[ $taxonomy ])
300
+					? $all_taxonomies[ $taxonomy ]
301
+					: array();
302
+			}
303
+			// ALWAYS unset() variables that were passed by reference
304
+			unset($details);
305
+			$this->setTaxonomies($taxonomies);
306
+		}
307
+	}
308
+
309
+
310
+	/**
311
+	 * @since 4.9.63.p
312
+	 * @throws EE_Error
313
+	 */
314
+	protected function init()
315
+	{
316
+		$this->setAdditionalCptDetails();
317
+		$this->setRequestVarsIfCpt();
318
+		// convert post_type to model name
319
+		$model_name = str_replace('EE_', '', $this->cpt_details['class_name']);
320
+		// load all tables related to CPT
321
+		$this->setupModelsAndTables($model_name);
322
+		// load and instantiate CPT_*_Strategy
323
+		$CPT_Strategy = $this->cptStrategyClass($model_name);
324
+		// !!!!!!!!!!  IMPORTANT !!!!!!!!!!!!
325
+		// here's the list of available filters in the WP_Query object
326
+		// 'posts_where_paged'
327
+		// 'posts_groupby'
328
+		// 'posts_join_paged'
329
+		// 'posts_orderby'
330
+		// 'posts_distinct'
331
+		// 'post_limits'
332
+		// 'posts_fields'
333
+		// 'posts_join'
334
+		add_filter('posts_fields', array($this, 'postsFields'));
335
+		add_filter('posts_join', array($this, 'postsJoin'));
336
+		add_filter(
337
+			'get_' . $this->post_type . '_metadata',
338
+			array($CPT_Strategy, 'get_EE_post_type_metadata'),
339
+			1,
340
+			4
341
+		);
342
+		add_filter('the_posts', array($this, 'thePosts'), 1, 1);
343
+		if ($this->wp_query->is_main_query()) {
344
+			add_filter('get_edit_post_link', array($this, 'getEditPostLink'), 10, 2);
345
+			$this->addTemplateFilters();
346
+		}
347
+	}
348
+
349
+
350
+	/**
351
+	 * sets some basic query vars that pertain to the CPT
352
+	 *
353
+	 * @access protected
354
+	 * @return void
355
+	 */
356
+	protected function setAdditionalCptDetails()
357
+	{
358
+		// the post or category or term that is triggering EE
359
+		$this->cpt_details['espresso_page'] = $this->current_page->isEspressoPage();
360
+		// requested post name
361
+		$this->cpt_details['post_name'] = $this->request->getRequestParam('post_name');
362
+		// add support for viewing 'private', 'draft', or 'pending' posts
363
+		if (
364
+			isset($this->wp_query->query_vars['p'])
365
+			&& $this->wp_query->query_vars['p'] !== 0
366
+			&& is_user_logged_in()
367
+			&& current_user_can('edit_post', $this->wp_query->query_vars['p'])
368
+		) {
369
+			// we can just inject directly into the WP_Query object
370
+			$this->wp_query->query['post_status'] = array('publish', 'private', 'draft', 'pending');
371
+			// now set the main 'ee' request var so that the appropriate module can load the appropriate template(s)
372
+			$this->request->setRequestParam('ee', $this->cpt_details['singular_slug']);
373
+		}
374
+	}
375
+
376
+
377
+	/**
378
+	 * Checks if we're on a EE-CPT archive-or-single page, and if we've never set the EE request var.
379
+	 * If so, sets the 'ee' request variable
380
+	 * so other parts of EE can know what CPT is getting queried.
381
+	 * To Mike's knowledge, this must be called from during or after the pre_get_posts hook
382
+	 * in order for is_archive() and is_single() methods to work properly.
383
+	 *
384
+	 * @return void
385
+	 */
386
+	public function setRequestVarsIfCpt()
387
+	{
388
+		// check if ee action var has been set
389
+		if (! $this->request->requestParamIsSet('ee')) {
390
+			// check that route exists for CPT archive slug
391
+			if (is_archive() && EE_Config::get_route($this->cpt_details['plural_slug'])) {
392
+				// ie: set "ee" to "events"
393
+				$this->request->setRequestParam('ee', $this->cpt_details['plural_slug']);
394
+				// or does it match a single page CPT like /event/
395
+			} elseif (is_single() && EE_Config::get_route($this->cpt_details['singular_slug'])) {
396
+				// ie: set "ee" to "event"
397
+				$this->request->setRequestParam('ee', $this->cpt_details['singular_slug']);
398
+			}
399
+		}
400
+	}
401
+
402
+
403
+	/**
404
+	 * setupModelsAndTables
405
+	 *
406
+	 * @access protected
407
+	 * @param string $model_name
408
+	 * @throws EE_Error
409
+	 */
410
+	protected function setupModelsAndTables($model_name)
411
+	{
412
+		// get CPT table data via CPT Model
413
+		$full_model_name = strpos($model_name, 'EEM_') !== 0
414
+			? 'EEM_' . $model_name
415
+			: $model_name;
416
+		$model = $this->loader->getShared($full_model_name);
417
+		if (! $model instanceof EEM_Base) {
418
+			throw new EE_Error(
419
+				sprintf(
420
+					esc_html__(
421
+						'The "%1$s" model could not be loaded.',
422
+						'event_espresso'
423
+					),
424
+					$full_model_name
425
+				)
426
+			);
427
+		}
428
+		$this->setModel($model);
429
+		$this->setModelTables($this->model->get_tables());
430
+		$meta_model = $model_name . '_Meta';
431
+		// is there a Meta Table for this CPT?
432
+		if (
433
+			isset($this->cpt_details['tables'][ $meta_model ])
434
+			&& $this->cpt_details['tables'][ $meta_model ] instanceof EE_Secondary_Table
435
+		) {
436
+			$this->setMetaTable($this->cpt_details['tables'][ $meta_model ]);
437
+		}
438
+	}
439
+
440
+
441
+	/**
442
+	 * cptStrategyClass
443
+	 *
444
+	 * @access protected
445
+	 * @param  string $model_name
446
+	 * @return string
447
+	 */
448
+	protected function cptStrategyClass($model_name)
449
+	{
450
+		// creates classname like:  CPT_Event_Strategy
451
+		$CPT_Strategy_class_name = 'EE_CPT_' . $model_name . '_Strategy';
452
+		// load and instantiate
453
+		$CPT_Strategy = $this->loader->getShared(
454
+			$CPT_Strategy_class_name,
455
+			array('WP_Query' => $this->wp_query, 'CPT' => $this->cpt_details)
456
+		);
457
+		if ($CPT_Strategy === null) {
458
+			$CPT_Strategy = $this->loader->getShared(
459
+				'EE_CPT_Default_Strategy',
460
+				array('WP_Query' => $this->wp_query, 'CPT' => $this->cpt_details)
461
+			);
462
+		}
463
+		return $CPT_Strategy;
464
+	}
465
+
466
+
467
+	/**
468
+	 * postsFields
469
+	 *
470
+	 * @access public
471
+	 * @param  $SQL
472
+	 * @return string
473
+	 */
474
+	public function postsFields($SQL)
475
+	{
476
+		// does this CPT have a meta table ?
477
+		if ($this->meta_table instanceof EE_Secondary_Table) {
478
+			// adds something like ", wp_esp_event_meta.* " to WP Query SELECT statement
479
+			$SQL .= ', ' . $this->meta_table->get_table_name() . '.* ';
480
+		}
481
+		remove_filter('posts_fields', array($this, 'postsFields'));
482
+		return $SQL;
483
+	}
484
+
485
+
486
+	/**
487
+	 * postsJoin
488
+	 *
489
+	 * @access public
490
+	 * @param  $SQL
491
+	 * @return string
492
+	 */
493
+	public function postsJoin($SQL)
494
+	{
495
+		// does this CPT have a meta table ?
496
+		if ($this->meta_table instanceof EE_Secondary_Table) {
497
+			global $wpdb;
498
+			// adds something like " LEFT JOIN wp_esp_event_meta ON ( wp_esp_event_meta.EVT_ID = wp_posts.ID ) " to WP Query JOIN statement
499
+			$SQL .= ' LEFT JOIN '
500
+					. $this->meta_table->get_table_name()
501
+					. ' ON ( '
502
+					. $this->meta_table->get_table_name()
503
+					. '.'
504
+					. $this->meta_table->get_fk_on_table()
505
+					. ' = '
506
+					. $wpdb->posts
507
+					. '.ID ) ';
508
+		}
509
+		remove_filter('posts_join', array($this, 'postsJoin'));
510
+		return $SQL;
511
+	}
512
+
513
+
514
+	/**
515
+	 * thePosts
516
+	 *
517
+	 * @access public
518
+	 * @param  WP_Post[] $posts
519
+	 * @return WP_Post[]
520
+	 */
521
+	public function thePosts($posts)
522
+	{
523
+		$CPT_class = $this->cpt_details['class_name'];
524
+		// loop thru posts
525
+		if (is_array($posts) && $this->model instanceof EEM_CPT_Base) {
526
+			foreach ($posts as $post) {
527
+				if ($post->post_type === $this->post_type) {
528
+					$post->{$CPT_class} = $this->model->instantiate_class_from_post_object($post);
529
+				}
530
+			}
531
+		}
532
+		remove_filter('the_posts', array($this, 'thePosts'), 1);
533
+		return $posts;
534
+	}
535
+
536
+
537
+	/**
538
+	 * @param $url
539
+	 * @param $ID
540
+	 * @return string
541
+	 */
542
+	public function getEditPostLink($url, $ID)
543
+	{
544
+		// need to make sure we only edit links if our cpt
545
+		global $post;
546
+		// notice if the cpt is registered with `show_ee_ui` set to false, we take that to mean that the WordPress core ui
547
+		// for interacting with the CPT is desired and there is no EE UI for interacting with the CPT in the admin.
548
+		if (
549
+			! $post instanceof WP_Post
550
+			|| $post->post_type !== $this->post_type
551
+			|| (
552
+				isset($this->cpt_details['args']['show_ee_ui'])
553
+				&& ! $this->cpt_details['args']['show_ee_ui']
554
+			)
555
+		) {
556
+			return $url;
557
+		}
558
+		// k made it here so all is good.
559
+		return wp_nonce_url(
560
+			add_query_arg(
561
+				array('page' => $this->post_type, 'post' => $ID, 'action' => 'edit'),
562
+				admin_url('admin.php')
563
+			),
564
+			'edit',
565
+			'edit_nonce'
566
+		);
567
+	}
568
+
569
+
570
+	/**
571
+	 * Execute any template filters.
572
+	 * This method is only called if in main query.
573
+	 *
574
+	 * @return void
575
+	 */
576
+	public function addTemplateFilters()
577
+	{
578
+		// if requested cpt supports page_templates and it's the main query
579
+		if (! empty($this->cpt_details['args']['page_templates']) && $this->wp_query->is_main_query()) {
580
+			// then let's hook into the appropriate query_template hook
581
+			add_filter('single_template', array($this, 'singleCptTemplate'));
582
+		}
583
+	}
584
+
585
+
586
+	/**
587
+	 * Callback for single_template wp filter.
588
+	 * This is used to load the set page_template for a single ee cpt if its set.  If "default" then we load the normal
589
+	 * hierarchy.
590
+	 *
591
+	 * @access public
592
+	 * @param string $current_template Existing default template path derived for this page call.
593
+	 * @return string the path to the full template file.
594
+	 */
595
+	public function singleCptTemplate($current_template)
596
+	{
597
+		$object = get_queried_object();
598
+		// does this called object HAVE a page template set that is something other than the default.
599
+		$template = get_post_meta($object->ID, '_wp_page_template', true);
600
+		// exit early if default or not set or invalid path (accounts for theme changes)
601
+		if (
602
+			$template === 'default'
603
+			|| empty($template)
604
+			|| ! is_readable(get_stylesheet_directory() . '/' . $template)
605
+		) {
606
+			return $current_template;
607
+		}
608
+		// made it here so we SHOULD be able to just locate the template and then return it.
609
+		return locate_template(array($template));
610
+	}
611 611
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -241,7 +241,7 @@  discard block
 block discarded – undo
241 241
      */
242 242
     public function request()
243 243
     {
244
-        if (! $this->request_handler instanceof EE_Request_Handler) {
244
+        if ( ! $this->request_handler instanceof EE_Request_Handler) {
245 245
             $this->request_handler = LoaderFactory::getLoader()->getShared('EE_Request_Handler');
246 246
         }
247 247
         return $this->request_handler;
@@ -296,8 +296,8 @@  discard block
 block discarded – undo
296 296
             $all_taxonomies = $taxonomy_definitions->getCustomTaxonomyDefinitions();
297 297
             foreach ($taxonomies as $taxonomy => &$details) {
298 298
                 // add details to our taxonomies if they exist
299
-                $details = isset($all_taxonomies[ $taxonomy ])
300
-                    ? $all_taxonomies[ $taxonomy ]
299
+                $details = isset($all_taxonomies[$taxonomy])
300
+                    ? $all_taxonomies[$taxonomy]
301 301
                     : array();
302 302
             }
303 303
             // ALWAYS unset() variables that were passed by reference
@@ -334,7 +334,7 @@  discard block
 block discarded – undo
334 334
         add_filter('posts_fields', array($this, 'postsFields'));
335 335
         add_filter('posts_join', array($this, 'postsJoin'));
336 336
         add_filter(
337
-            'get_' . $this->post_type . '_metadata',
337
+            'get_'.$this->post_type.'_metadata',
338 338
             array($CPT_Strategy, 'get_EE_post_type_metadata'),
339 339
             1,
340 340
             4
@@ -386,7 +386,7 @@  discard block
 block discarded – undo
386 386
     public function setRequestVarsIfCpt()
387 387
     {
388 388
         // check if ee action var has been set
389
-        if (! $this->request->requestParamIsSet('ee')) {
389
+        if ( ! $this->request->requestParamIsSet('ee')) {
390 390
             // check that route exists for CPT archive slug
391 391
             if (is_archive() && EE_Config::get_route($this->cpt_details['plural_slug'])) {
392 392
                 // ie: set "ee" to "events"
@@ -411,10 +411,10 @@  discard block
 block discarded – undo
411 411
     {
412 412
         // get CPT table data via CPT Model
413 413
         $full_model_name = strpos($model_name, 'EEM_') !== 0
414
-            ? 'EEM_' . $model_name
414
+            ? 'EEM_'.$model_name
415 415
             : $model_name;
416 416
         $model = $this->loader->getShared($full_model_name);
417
-        if (! $model instanceof EEM_Base) {
417
+        if ( ! $model instanceof EEM_Base) {
418 418
             throw new EE_Error(
419 419
                 sprintf(
420 420
                     esc_html__(
@@ -427,13 +427,13 @@  discard block
 block discarded – undo
427 427
         }
428 428
         $this->setModel($model);
429 429
         $this->setModelTables($this->model->get_tables());
430
-        $meta_model = $model_name . '_Meta';
430
+        $meta_model = $model_name.'_Meta';
431 431
         // is there a Meta Table for this CPT?
432 432
         if (
433
-            isset($this->cpt_details['tables'][ $meta_model ])
434
-            && $this->cpt_details['tables'][ $meta_model ] instanceof EE_Secondary_Table
433
+            isset($this->cpt_details['tables'][$meta_model])
434
+            && $this->cpt_details['tables'][$meta_model] instanceof EE_Secondary_Table
435 435
         ) {
436
-            $this->setMetaTable($this->cpt_details['tables'][ $meta_model ]);
436
+            $this->setMetaTable($this->cpt_details['tables'][$meta_model]);
437 437
         }
438 438
     }
439 439
 
@@ -448,7 +448,7 @@  discard block
 block discarded – undo
448 448
     protected function cptStrategyClass($model_name)
449 449
     {
450 450
         // creates classname like:  CPT_Event_Strategy
451
-        $CPT_Strategy_class_name = 'EE_CPT_' . $model_name . '_Strategy';
451
+        $CPT_Strategy_class_name = 'EE_CPT_'.$model_name.'_Strategy';
452 452
         // load and instantiate
453 453
         $CPT_Strategy = $this->loader->getShared(
454 454
             $CPT_Strategy_class_name,
@@ -476,7 +476,7 @@  discard block
 block discarded – undo
476 476
         // does this CPT have a meta table ?
477 477
         if ($this->meta_table instanceof EE_Secondary_Table) {
478 478
             // adds something like ", wp_esp_event_meta.* " to WP Query SELECT statement
479
-            $SQL .= ', ' . $this->meta_table->get_table_name() . '.* ';
479
+            $SQL .= ', '.$this->meta_table->get_table_name().'.* ';
480 480
         }
481 481
         remove_filter('posts_fields', array($this, 'postsFields'));
482 482
         return $SQL;
@@ -576,7 +576,7 @@  discard block
 block discarded – undo
576 576
     public function addTemplateFilters()
577 577
     {
578 578
         // if requested cpt supports page_templates and it's the main query
579
-        if (! empty($this->cpt_details['args']['page_templates']) && $this->wp_query->is_main_query()) {
579
+        if ( ! empty($this->cpt_details['args']['page_templates']) && $this->wp_query->is_main_query()) {
580 580
             // then let's hook into the appropriate query_template hook
581 581
             add_filter('single_template', array($this, 'singleCptTemplate'));
582 582
         }
@@ -601,7 +601,7 @@  discard block
 block discarded – undo
601 601
         if (
602 602
             $template === 'default'
603 603
             || empty($template)
604
-            || ! is_readable(get_stylesheet_directory() . '/' . $template)
604
+            || ! is_readable(get_stylesheet_directory().'/'.$template)
605 605
         ) {
606 606
             return $current_template;
607 607
         }
Please login to merge, or discard this patch.
core/EE_Cron_Tasks.core.php 2 patches
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -38,7 +38,7 @@  discard block
 block discarded – undo
38 38
      */
39 39
     public static function instance()
40 40
     {
41
-        if (! self::$_instance instanceof EE_Cron_Tasks) {
41
+        if ( ! self::$_instance instanceof EE_Cron_Tasks) {
42 42
             self::$_instance = new self();
43 43
         }
44 44
         return self::$_instance;
@@ -72,7 +72,7 @@  discard block
 block discarded – undo
72 72
              */
73 73
             add_action(
74 74
                 'AHEE__EE_System__load_core_configuration__complete',
75
-                function () {
75
+                function() {
76 76
                     EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
77 77
                     EE_Registry::instance()->NET_CFG->update_config(true, false);
78 78
                     add_option('ee_disabled_wp_cron_check', 1, '', false);
@@ -124,16 +124,16 @@  discard block
 block discarded – undo
124 124
             'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
125 125
         );
126 126
         $crons = (array) get_option('cron');
127
-        if (! is_array($crons)) {
127
+        if ( ! is_array($crons)) {
128 128
             return;
129 129
         }
130 130
         foreach ($crons as $timestamp => $cron) {
131 131
             /** @var array[] $cron */
132 132
             foreach ($ee_crons as $ee_cron) {
133
-                if (isset($cron[ $ee_cron ]) && is_array($cron[ $ee_cron ])) {
133
+                if (isset($cron[$ee_cron]) && is_array($cron[$ee_cron])) {
134 134
                     do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
135
-                    foreach ($cron[ $ee_cron ] as $ee_cron_details) {
136
-                        if (! empty($ee_cron_details['args'])) {
135
+                    foreach ($cron[$ee_cron] as $ee_cron_details) {
136
+                        if ( ! empty($ee_cron_details['args'])) {
137 137
                             do_action(
138 138
                                 'AHEE_log',
139 139
                                 __CLASS__,
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
      */
161 161
     public static function reschedule_cron_for_transactions_if_maintenance_mode($cron_task, array $TXN_IDs)
162 162
     {
163
-        if (! method_exists('EE_Cron_Tasks', $cron_task)) {
163
+        if ( ! method_exists('EE_Cron_Tasks', $cron_task)) {
164 164
             throw new DomainException(
165 165
                 sprintf(
166 166
                     esc_html__('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
@@ -169,7 +169,7 @@  discard block
 block discarded – undo
169 169
             );
170 170
         }
171 171
         // reschedule the cron if we can't hit the db right now
172
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
172
+        if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
173 173
             foreach ($TXN_IDs as $TXN_ID => $additional_vars) {
174 174
                 // ensure $additional_vars is an array
175 175
                 $additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars);
@@ -250,7 +250,7 @@  discard block
 block discarded – undo
250 250
     {
251 251
         do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
252 252
         if (absint($TXN_ID)) {
253
-            self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID;
253
+            self::$_update_transactions_with_payment[$TXN_ID] = $PAY_ID;
254 254
             add_action(
255 255
                 'shutdown',
256 256
                 array('EE_Cron_Tasks', 'update_transaction_with_payment'),
@@ -297,7 +297,7 @@  discard block
 block discarded – undo
297 297
         EE_Registry::instance()->load_model('Transaction');
298 298
         foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) {
299 299
             // reschedule the cron if we can't hit the db right now
300
-            if (! EE_Maintenance_Mode::instance()->models_can_query()) {
300
+            if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
301 301
                 // reset cron job for updating the TXN
302 302
                 EE_Cron_Tasks::schedule_update_transaction_with_payment(
303 303
                     time() + EE_Cron_Tasks::reschedule_timeout,
@@ -313,7 +313,7 @@  discard block
 block discarded – undo
313 313
                 // now try to update the TXN with any payments
314 314
                 $payment_processor->update_txn_based_on_payment($transaction, $payment, true, true);
315 315
             }
316
-            unset(self::$_update_transactions_with_payment[ $TXN_ID ]);
316
+            unset(self::$_update_transactions_with_payment[$TXN_ID]);
317 317
         }
318 318
     }
319 319
 
@@ -374,7 +374,7 @@  discard block
 block discarded – undo
374 374
     public static function expired_transaction_check($TXN_ID = 0)
375 375
     {
376 376
         if (absint($TXN_ID)) {
377
-            self::$_expired_transactions[ $TXN_ID ] = $TXN_ID;
377
+            self::$_expired_transactions[$TXN_ID] = $TXN_ID;
378 378
             add_action(
379 379
                 'shutdown',
380 380
                 array('EE_Cron_Tasks', 'process_expired_transactions'),
@@ -502,7 +502,7 @@  discard block
 block discarded – undo
502 502
                         break;
503 503
                 }
504 504
             }
505
-            unset(self::$_expired_transactions[ $TXN_ID ]);
505
+            unset(self::$_expired_transactions[$TXN_ID]);
506 506
         }
507 507
     }
508 508
 
@@ -549,7 +549,7 @@  discard block
 block discarded – undo
549 549
             $reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
550 550
             $time_diff_for_comparison = apply_filters(
551 551
                 'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison',
552
-                '-' . $reg_config->gateway_log_lifespan
552
+                '-'.$reg_config->gateway_log_lifespan
553 553
             );
554 554
             EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison));
555 555
         }
Please login to merge, or discard this patch.
Indentation   +600 added lines, -600 removed lines patch added patch discarded remove patch
@@ -14,607 +14,607 @@
 block discarded – undo
14 14
  */
15 15
 class EE_Cron_Tasks extends EE_Base
16 16
 {
17
-    /**
18
-     * WordPress doesn't allow duplicate crons within 10 minutes of the original,
19
-     * so we'll set our retry time for just over 10 minutes to avoid that
20
-     */
21
-    const reschedule_timeout = 605;
22
-
23
-
24
-    /**
25
-     * @var EE_Cron_Tasks
26
-     */
27
-    private static $_instance;
28
-
29
-
30
-    /**
31
-     * @return EE_Cron_Tasks
32
-     * @throws ReflectionException
33
-     * @throws EE_Error
34
-     * @throws InvalidArgumentException
35
-     * @throws InvalidInterfaceException
36
-     * @throws InvalidDataTypeException
37
-     */
38
-    public static function instance()
39
-    {
40
-        if (! self::$_instance instanceof EE_Cron_Tasks) {
41
-            self::$_instance = new self();
42
-        }
43
-        return self::$_instance;
44
-    }
45
-
46
-
47
-    /**
48
-     * @access private
49
-     * @throws InvalidDataTypeException
50
-     * @throws InvalidInterfaceException
51
-     * @throws InvalidArgumentException
52
-     * @throws EE_Error
53
-     * @throws ReflectionException
54
-     */
55
-    private function __construct()
56
-    {
57
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
58
-        // verify that WP Cron is enabled
59
-        if (
60
-            defined('DISABLE_WP_CRON')
61
-            && DISABLE_WP_CRON
62
-            && is_admin()
63
-            && ! get_option('ee_disabled_wp_cron_check')
64
-        ) {
65
-            /**
66
-             * This needs to be delayed until after the config is loaded because EE_Cron_Tasks is constructed before
67
-             * config is loaded.
68
-             * This is intentionally using a anonymous function so that its not easily de-registered.  Client code
69
-             * wanting to not have this functionality can just register its own action at a priority after this one to
70
-             * reverse any changes.
71
-             */
72
-            add_action(
73
-                'AHEE__EE_System__load_core_configuration__complete',
74
-                function () {
75
-                    EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
76
-                    EE_Registry::instance()->NET_CFG->update_config(true, false);
77
-                    add_option('ee_disabled_wp_cron_check', 1, '', false);
78
-                }
79
-            );
80
-        }
81
-        // UPDATE TRANSACTION WITH PAYMENT
82
-        add_action(
83
-            'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
84
-            array('EE_Cron_Tasks', 'setup_update_for_transaction_with_payment'),
85
-            10,
86
-            2
87
-        );
88
-        // ABANDONED / EXPIRED TRANSACTION CHECK
89
-        add_action(
90
-            'AHEE__EE_Cron_Tasks__expired_transaction_check',
91
-            array('EE_Cron_Tasks', 'expired_transaction_check'),
92
-            10,
93
-            1
94
-        );
95
-        // CLEAN OUT JUNK TRANSACTIONS AND RELATED DATA
96
-        add_action(
97
-            'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
98
-            array('EE_Cron_Tasks', 'clean_out_junk_transactions')
99
-        );
100
-        // logging
101
-        add_action(
102
-            'AHEE__EE_System__load_core_configuration__complete',
103
-            array('EE_Cron_Tasks', 'log_scheduled_ee_crons')
104
-        );
105
-        EE_Registry::instance()->load_lib('Messages_Scheduler');
106
-        // clean out old gateway logs
107
-        add_action(
108
-            'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs',
109
-            array('EE_Cron_Tasks', 'clean_out_old_gateway_logs')
110
-        );
111
-    }
112
-
113
-
114
-    /**
115
-     * @access protected
116
-     * @return void
117
-     */
118
-    public static function log_scheduled_ee_crons()
119
-    {
120
-        $ee_crons = array(
121
-            'AHEE__EE_Cron_Tasks__update_transaction_with_payment',
122
-            'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
123
-            'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
124
-        );
125
-        $crons = (array) get_option('cron');
126
-        if (! is_array($crons)) {
127
-            return;
128
-        }
129
-        foreach ($crons as $timestamp => $cron) {
130
-            /** @var array[] $cron */
131
-            foreach ($ee_crons as $ee_cron) {
132
-                if (isset($cron[ $ee_cron ]) && is_array($cron[ $ee_cron ])) {
133
-                    do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
134
-                    foreach ($cron[ $ee_cron ] as $ee_cron_details) {
135
-                        if (! empty($ee_cron_details['args'])) {
136
-                            do_action(
137
-                                'AHEE_log',
138
-                                __CLASS__,
139
-                                __FUNCTION__,
140
-                                print_r($ee_cron_details['args'], true),
141
-                                "{$ee_cron} args"
142
-                            );
143
-                        }
144
-                    }
145
-                }
146
-            }
147
-        }
148
-    }
149
-
150
-
151
-    /**
152
-     * reschedule_cron_for_transactions_if_maintenance_mode
153
-     * if Maintenance Mode is active, this will reschedule a cron to run again in 10 minutes
154
-     *
155
-     * @param string $cron_task
156
-     * @param array  $TXN_IDs
157
-     * @return bool
158
-     * @throws DomainException
159
-     */
160
-    public static function reschedule_cron_for_transactions_if_maintenance_mode($cron_task, array $TXN_IDs)
161
-    {
162
-        if (! method_exists('EE_Cron_Tasks', $cron_task)) {
163
-            throw new DomainException(
164
-                sprintf(
165
-                    esc_html__('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
166
-                    $cron_task
167
-                )
168
-            );
169
-        }
170
-        // reschedule the cron if we can't hit the db right now
171
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
172
-            foreach ($TXN_IDs as $TXN_ID => $additional_vars) {
173
-                // ensure $additional_vars is an array
174
-                $additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars);
175
-                // reset cron job for the TXN
176
-                call_user_func_array(
177
-                    array('EE_Cron_Tasks', $cron_task),
178
-                    array_merge(
179
-                        array(
180
-                            time() + (10 * MINUTE_IN_SECONDS),
181
-                            $TXN_ID,
182
-                        ),
183
-                        $additional_vars
184
-                    )
185
-                );
186
-            }
187
-            return true;
188
-        }
189
-        return false;
190
-    }
191
-
192
-
193
-
194
-
195
-    /****************  UPDATE TRANSACTION WITH PAYMENT ****************/
196
-
197
-
198
-    /**
199
-     * array of TXN IDs and the payment
200
-     *
201
-     * @var array
202
-     */
203
-    protected static $_update_transactions_with_payment = array();
204
-
205
-
206
-    /**
207
-     * schedule_update_transaction_with_payment
208
-     * sets a wp_schedule_single_event() for updating any TXNs that may
209
-     * require updating due to recently received payments
210
-     *
211
-     * @param int $timestamp
212
-     * @param int $TXN_ID
213
-     * @param int $PAY_ID
214
-     */
215
-    public static function schedule_update_transaction_with_payment(
216
-        $timestamp,
217
-        $TXN_ID,
218
-        $PAY_ID
219
-    ) {
220
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
221
-        // validate $TXN_ID and $timestamp
222
-        $TXN_ID = absint($TXN_ID);
223
-        $timestamp = absint($timestamp);
224
-        if ($TXN_ID && $timestamp) {
225
-            wp_schedule_single_event(
226
-                $timestamp,
227
-                'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
228
-                array($TXN_ID, $PAY_ID)
229
-            );
230
-        }
231
-    }
232
-
233
-
234
-    /**
235
-     * setup_update_for_transaction_with_payment
236
-     * this is the callback for the action hook:
237
-     * 'AHEE__EE_Cron_Tasks__update_transaction_with_payment'
238
-     * which is setup by EE_Cron_Tasks::schedule_update_transaction_with_payment().
239
-     * The passed TXN_ID and associated payment gets added to an array, and then
240
-     * the EE_Cron_Tasks::update_transaction_with_payment() function is hooked into
241
-     * 'shutdown' which will actually handle the processing of any
242
-     * transactions requiring updating, because doing so now would be too early
243
-     * and the required resources may not be available
244
-     *
245
-     * @param int $TXN_ID
246
-     * @param int $PAY_ID
247
-     */
248
-    public static function setup_update_for_transaction_with_payment($TXN_ID = 0, $PAY_ID = 0)
249
-    {
250
-        do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
251
-        if (absint($TXN_ID)) {
252
-            self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID;
253
-            add_action(
254
-                'shutdown',
255
-                array('EE_Cron_Tasks', 'update_transaction_with_payment'),
256
-                5
257
-            );
258
-        }
259
-    }
260
-
261
-
262
-    /**
263
-     * update_transaction_with_payment
264
-     * loops through the self::$_abandoned_transactions array
265
-     * and attempts to finalize any TXNs that have not been completed
266
-     * but have had their sessions expired, most likely due to a user not
267
-     * returning from an off-site payment gateway
268
-     *
269
-     * @throws EE_Error
270
-     * @throws DomainException
271
-     * @throws InvalidDataTypeException
272
-     * @throws InvalidInterfaceException
273
-     * @throws InvalidArgumentException
274
-     * @throws ReflectionException
275
-     * @throws RuntimeException
276
-     */
277
-    public static function update_transaction_with_payment()
278
-    {
279
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
280
-        if (
17
+	/**
18
+	 * WordPress doesn't allow duplicate crons within 10 minutes of the original,
19
+	 * so we'll set our retry time for just over 10 minutes to avoid that
20
+	 */
21
+	const reschedule_timeout = 605;
22
+
23
+
24
+	/**
25
+	 * @var EE_Cron_Tasks
26
+	 */
27
+	private static $_instance;
28
+
29
+
30
+	/**
31
+	 * @return EE_Cron_Tasks
32
+	 * @throws ReflectionException
33
+	 * @throws EE_Error
34
+	 * @throws InvalidArgumentException
35
+	 * @throws InvalidInterfaceException
36
+	 * @throws InvalidDataTypeException
37
+	 */
38
+	public static function instance()
39
+	{
40
+		if (! self::$_instance instanceof EE_Cron_Tasks) {
41
+			self::$_instance = new self();
42
+		}
43
+		return self::$_instance;
44
+	}
45
+
46
+
47
+	/**
48
+	 * @access private
49
+	 * @throws InvalidDataTypeException
50
+	 * @throws InvalidInterfaceException
51
+	 * @throws InvalidArgumentException
52
+	 * @throws EE_Error
53
+	 * @throws ReflectionException
54
+	 */
55
+	private function __construct()
56
+	{
57
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
58
+		// verify that WP Cron is enabled
59
+		if (
60
+			defined('DISABLE_WP_CRON')
61
+			&& DISABLE_WP_CRON
62
+			&& is_admin()
63
+			&& ! get_option('ee_disabled_wp_cron_check')
64
+		) {
65
+			/**
66
+			 * This needs to be delayed until after the config is loaded because EE_Cron_Tasks is constructed before
67
+			 * config is loaded.
68
+			 * This is intentionally using a anonymous function so that its not easily de-registered.  Client code
69
+			 * wanting to not have this functionality can just register its own action at a priority after this one to
70
+			 * reverse any changes.
71
+			 */
72
+			add_action(
73
+				'AHEE__EE_System__load_core_configuration__complete',
74
+				function () {
75
+					EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
76
+					EE_Registry::instance()->NET_CFG->update_config(true, false);
77
+					add_option('ee_disabled_wp_cron_check', 1, '', false);
78
+				}
79
+			);
80
+		}
81
+		// UPDATE TRANSACTION WITH PAYMENT
82
+		add_action(
83
+			'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
84
+			array('EE_Cron_Tasks', 'setup_update_for_transaction_with_payment'),
85
+			10,
86
+			2
87
+		);
88
+		// ABANDONED / EXPIRED TRANSACTION CHECK
89
+		add_action(
90
+			'AHEE__EE_Cron_Tasks__expired_transaction_check',
91
+			array('EE_Cron_Tasks', 'expired_transaction_check'),
92
+			10,
93
+			1
94
+		);
95
+		// CLEAN OUT JUNK TRANSACTIONS AND RELATED DATA
96
+		add_action(
97
+			'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
98
+			array('EE_Cron_Tasks', 'clean_out_junk_transactions')
99
+		);
100
+		// logging
101
+		add_action(
102
+			'AHEE__EE_System__load_core_configuration__complete',
103
+			array('EE_Cron_Tasks', 'log_scheduled_ee_crons')
104
+		);
105
+		EE_Registry::instance()->load_lib('Messages_Scheduler');
106
+		// clean out old gateway logs
107
+		add_action(
108
+			'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs',
109
+			array('EE_Cron_Tasks', 'clean_out_old_gateway_logs')
110
+		);
111
+	}
112
+
113
+
114
+	/**
115
+	 * @access protected
116
+	 * @return void
117
+	 */
118
+	public static function log_scheduled_ee_crons()
119
+	{
120
+		$ee_crons = array(
121
+			'AHEE__EE_Cron_Tasks__update_transaction_with_payment',
122
+			'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
123
+			'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
124
+		);
125
+		$crons = (array) get_option('cron');
126
+		if (! is_array($crons)) {
127
+			return;
128
+		}
129
+		foreach ($crons as $timestamp => $cron) {
130
+			/** @var array[] $cron */
131
+			foreach ($ee_crons as $ee_cron) {
132
+				if (isset($cron[ $ee_cron ]) && is_array($cron[ $ee_cron ])) {
133
+					do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
134
+					foreach ($cron[ $ee_cron ] as $ee_cron_details) {
135
+						if (! empty($ee_cron_details['args'])) {
136
+							do_action(
137
+								'AHEE_log',
138
+								__CLASS__,
139
+								__FUNCTION__,
140
+								print_r($ee_cron_details['args'], true),
141
+								"{$ee_cron} args"
142
+							);
143
+						}
144
+					}
145
+				}
146
+			}
147
+		}
148
+	}
149
+
150
+
151
+	/**
152
+	 * reschedule_cron_for_transactions_if_maintenance_mode
153
+	 * if Maintenance Mode is active, this will reschedule a cron to run again in 10 minutes
154
+	 *
155
+	 * @param string $cron_task
156
+	 * @param array  $TXN_IDs
157
+	 * @return bool
158
+	 * @throws DomainException
159
+	 */
160
+	public static function reschedule_cron_for_transactions_if_maintenance_mode($cron_task, array $TXN_IDs)
161
+	{
162
+		if (! method_exists('EE_Cron_Tasks', $cron_task)) {
163
+			throw new DomainException(
164
+				sprintf(
165
+					esc_html__('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
166
+					$cron_task
167
+				)
168
+			);
169
+		}
170
+		// reschedule the cron if we can't hit the db right now
171
+		if (! EE_Maintenance_Mode::instance()->models_can_query()) {
172
+			foreach ($TXN_IDs as $TXN_ID => $additional_vars) {
173
+				// ensure $additional_vars is an array
174
+				$additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars);
175
+				// reset cron job for the TXN
176
+				call_user_func_array(
177
+					array('EE_Cron_Tasks', $cron_task),
178
+					array_merge(
179
+						array(
180
+							time() + (10 * MINUTE_IN_SECONDS),
181
+							$TXN_ID,
182
+						),
183
+						$additional_vars
184
+					)
185
+				);
186
+			}
187
+			return true;
188
+		}
189
+		return false;
190
+	}
191
+
192
+
193
+
194
+
195
+	/****************  UPDATE TRANSACTION WITH PAYMENT ****************/
196
+
197
+
198
+	/**
199
+	 * array of TXN IDs and the payment
200
+	 *
201
+	 * @var array
202
+	 */
203
+	protected static $_update_transactions_with_payment = array();
204
+
205
+
206
+	/**
207
+	 * schedule_update_transaction_with_payment
208
+	 * sets a wp_schedule_single_event() for updating any TXNs that may
209
+	 * require updating due to recently received payments
210
+	 *
211
+	 * @param int $timestamp
212
+	 * @param int $TXN_ID
213
+	 * @param int $PAY_ID
214
+	 */
215
+	public static function schedule_update_transaction_with_payment(
216
+		$timestamp,
217
+		$TXN_ID,
218
+		$PAY_ID
219
+	) {
220
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
221
+		// validate $TXN_ID and $timestamp
222
+		$TXN_ID = absint($TXN_ID);
223
+		$timestamp = absint($timestamp);
224
+		if ($TXN_ID && $timestamp) {
225
+			wp_schedule_single_event(
226
+				$timestamp,
227
+				'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
228
+				array($TXN_ID, $PAY_ID)
229
+			);
230
+		}
231
+	}
232
+
233
+
234
+	/**
235
+	 * setup_update_for_transaction_with_payment
236
+	 * this is the callback for the action hook:
237
+	 * 'AHEE__EE_Cron_Tasks__update_transaction_with_payment'
238
+	 * which is setup by EE_Cron_Tasks::schedule_update_transaction_with_payment().
239
+	 * The passed TXN_ID and associated payment gets added to an array, and then
240
+	 * the EE_Cron_Tasks::update_transaction_with_payment() function is hooked into
241
+	 * 'shutdown' which will actually handle the processing of any
242
+	 * transactions requiring updating, because doing so now would be too early
243
+	 * and the required resources may not be available
244
+	 *
245
+	 * @param int $TXN_ID
246
+	 * @param int $PAY_ID
247
+	 */
248
+	public static function setup_update_for_transaction_with_payment($TXN_ID = 0, $PAY_ID = 0)
249
+	{
250
+		do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
251
+		if (absint($TXN_ID)) {
252
+			self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID;
253
+			add_action(
254
+				'shutdown',
255
+				array('EE_Cron_Tasks', 'update_transaction_with_payment'),
256
+				5
257
+			);
258
+		}
259
+	}
260
+
261
+
262
+	/**
263
+	 * update_transaction_with_payment
264
+	 * loops through the self::$_abandoned_transactions array
265
+	 * and attempts to finalize any TXNs that have not been completed
266
+	 * but have had their sessions expired, most likely due to a user not
267
+	 * returning from an off-site payment gateway
268
+	 *
269
+	 * @throws EE_Error
270
+	 * @throws DomainException
271
+	 * @throws InvalidDataTypeException
272
+	 * @throws InvalidInterfaceException
273
+	 * @throws InvalidArgumentException
274
+	 * @throws ReflectionException
275
+	 * @throws RuntimeException
276
+	 */
277
+	public static function update_transaction_with_payment()
278
+	{
279
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
280
+		if (
281 281
 // are there any TXNs that need cleaning up ?
282
-            empty(self::$_update_transactions_with_payment)
283
-            // reschedule the cron if we can't hit the db right now
284
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
285
-                'schedule_update_transaction_with_payment',
286
-                self::$_update_transactions_with_payment
287
-            )
288
-        ) {
289
-            return;
290
-        }
291
-        /** @type EE_Payment_Processor $payment_processor */
292
-        $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
293
-        // set revisit flag for payment processor
294
-        $payment_processor->set_revisit();
295
-        // load EEM_Transaction
296
-        EE_Registry::instance()->load_model('Transaction');
297
-        foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) {
298
-            // reschedule the cron if we can't hit the db right now
299
-            if (! EE_Maintenance_Mode::instance()->models_can_query()) {
300
-                // reset cron job for updating the TXN
301
-                EE_Cron_Tasks::schedule_update_transaction_with_payment(
302
-                    time() + EE_Cron_Tasks::reschedule_timeout,
303
-                    $TXN_ID,
304
-                    $PAY_ID
305
-                );
306
-                continue;
307
-            }
308
-            $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
309
-            $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
310
-            // verify transaction
311
-            if ($transaction instanceof EE_Transaction && $payment instanceof EE_Payment) {
312
-                // now try to update the TXN with any payments
313
-                $payment_processor->update_txn_based_on_payment($transaction, $payment, true, true);
314
-            }
315
-            unset(self::$_update_transactions_with_payment[ $TXN_ID ]);
316
-        }
317
-    }
318
-
319
-
320
-
321
-    /************  END OF UPDATE TRANSACTION WITH PAYMENT  ************/
322
-
323
-
324
-    /*****************  EXPIRED TRANSACTION CHECK *****************/
325
-
326
-
327
-    /**
328
-     * array of TXN IDs
329
-     *
330
-     * @var array
331
-     */
332
-    protected static $_expired_transactions = array();
333
-
334
-
335
-    /**
336
-     * schedule_expired_transaction_check
337
-     * sets a wp_schedule_single_event() for following up on TXNs after their session has expired
338
-     *
339
-     * @param int $timestamp
340
-     * @param int $TXN_ID
341
-     */
342
-    public static function schedule_expired_transaction_check(
343
-        $timestamp,
344
-        $TXN_ID
345
-    ) {
346
-        // validate $TXN_ID and $timestamp
347
-        $TXN_ID = absint($TXN_ID);
348
-        $timestamp = absint($timestamp);
349
-        if ($TXN_ID && $timestamp) {
350
-            wp_schedule_single_event(
351
-                $timestamp,
352
-                'AHEE__EE_Cron_Tasks__expired_transaction_check',
353
-                array($TXN_ID)
354
-            );
355
-        }
356
-    }
357
-
358
-
359
-    /**
360
-     * expired_transaction_check
361
-     * this is the callback for the action hook:
362
-     * 'AHEE__EE_Cron_Tasks__transaction_session_expiration_check'
363
-     * which is utilized by wp_schedule_single_event()
364
-     * in \EED_Single_Page_Checkout::_initialize_transaction().
365
-     * The passed TXN_ID gets added to an array, and then the
366
-     * process_expired_transactions() function is hooked into
367
-     * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the
368
-     * processing of any failed transactions, because doing so now would be
369
-     * too early and the required resources may not be available
370
-     *
371
-     * @param int $TXN_ID
372
-     */
373
-    public static function expired_transaction_check($TXN_ID = 0)
374
-    {
375
-        if (absint($TXN_ID)) {
376
-            self::$_expired_transactions[ $TXN_ID ] = $TXN_ID;
377
-            add_action(
378
-                'shutdown',
379
-                array('EE_Cron_Tasks', 'process_expired_transactions'),
380
-                5
381
-            );
382
-        }
383
-    }
384
-
385
-
386
-    /**
387
-     * process_expired_transactions
388
-     * loops through the self::$_expired_transactions array and processes any failed TXNs
389
-     *
390
-     * @throws EE_Error
391
-     * @throws InvalidDataTypeException
392
-     * @throws InvalidInterfaceException
393
-     * @throws InvalidArgumentException
394
-     * @throws ReflectionException
395
-     * @throws DomainException
396
-     * @throws RuntimeException
397
-     */
398
-    public static function process_expired_transactions()
399
-    {
400
-        if (
282
+			empty(self::$_update_transactions_with_payment)
283
+			// reschedule the cron if we can't hit the db right now
284
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
285
+				'schedule_update_transaction_with_payment',
286
+				self::$_update_transactions_with_payment
287
+			)
288
+		) {
289
+			return;
290
+		}
291
+		/** @type EE_Payment_Processor $payment_processor */
292
+		$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
293
+		// set revisit flag for payment processor
294
+		$payment_processor->set_revisit();
295
+		// load EEM_Transaction
296
+		EE_Registry::instance()->load_model('Transaction');
297
+		foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) {
298
+			// reschedule the cron if we can't hit the db right now
299
+			if (! EE_Maintenance_Mode::instance()->models_can_query()) {
300
+				// reset cron job for updating the TXN
301
+				EE_Cron_Tasks::schedule_update_transaction_with_payment(
302
+					time() + EE_Cron_Tasks::reschedule_timeout,
303
+					$TXN_ID,
304
+					$PAY_ID
305
+				);
306
+				continue;
307
+			}
308
+			$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
309
+			$payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
310
+			// verify transaction
311
+			if ($transaction instanceof EE_Transaction && $payment instanceof EE_Payment) {
312
+				// now try to update the TXN with any payments
313
+				$payment_processor->update_txn_based_on_payment($transaction, $payment, true, true);
314
+			}
315
+			unset(self::$_update_transactions_with_payment[ $TXN_ID ]);
316
+		}
317
+	}
318
+
319
+
320
+
321
+	/************  END OF UPDATE TRANSACTION WITH PAYMENT  ************/
322
+
323
+
324
+	/*****************  EXPIRED TRANSACTION CHECK *****************/
325
+
326
+
327
+	/**
328
+	 * array of TXN IDs
329
+	 *
330
+	 * @var array
331
+	 */
332
+	protected static $_expired_transactions = array();
333
+
334
+
335
+	/**
336
+	 * schedule_expired_transaction_check
337
+	 * sets a wp_schedule_single_event() for following up on TXNs after their session has expired
338
+	 *
339
+	 * @param int $timestamp
340
+	 * @param int $TXN_ID
341
+	 */
342
+	public static function schedule_expired_transaction_check(
343
+		$timestamp,
344
+		$TXN_ID
345
+	) {
346
+		// validate $TXN_ID and $timestamp
347
+		$TXN_ID = absint($TXN_ID);
348
+		$timestamp = absint($timestamp);
349
+		if ($TXN_ID && $timestamp) {
350
+			wp_schedule_single_event(
351
+				$timestamp,
352
+				'AHEE__EE_Cron_Tasks__expired_transaction_check',
353
+				array($TXN_ID)
354
+			);
355
+		}
356
+	}
357
+
358
+
359
+	/**
360
+	 * expired_transaction_check
361
+	 * this is the callback for the action hook:
362
+	 * 'AHEE__EE_Cron_Tasks__transaction_session_expiration_check'
363
+	 * which is utilized by wp_schedule_single_event()
364
+	 * in \EED_Single_Page_Checkout::_initialize_transaction().
365
+	 * The passed TXN_ID gets added to an array, and then the
366
+	 * process_expired_transactions() function is hooked into
367
+	 * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the
368
+	 * processing of any failed transactions, because doing so now would be
369
+	 * too early and the required resources may not be available
370
+	 *
371
+	 * @param int $TXN_ID
372
+	 */
373
+	public static function expired_transaction_check($TXN_ID = 0)
374
+	{
375
+		if (absint($TXN_ID)) {
376
+			self::$_expired_transactions[ $TXN_ID ] = $TXN_ID;
377
+			add_action(
378
+				'shutdown',
379
+				array('EE_Cron_Tasks', 'process_expired_transactions'),
380
+				5
381
+			);
382
+		}
383
+	}
384
+
385
+
386
+	/**
387
+	 * process_expired_transactions
388
+	 * loops through the self::$_expired_transactions array and processes any failed TXNs
389
+	 *
390
+	 * @throws EE_Error
391
+	 * @throws InvalidDataTypeException
392
+	 * @throws InvalidInterfaceException
393
+	 * @throws InvalidArgumentException
394
+	 * @throws ReflectionException
395
+	 * @throws DomainException
396
+	 * @throws RuntimeException
397
+	 */
398
+	public static function process_expired_transactions()
399
+	{
400
+		if (
401 401
 // are there any TXNs that need cleaning up ?
402
-            empty(self::$_expired_transactions)
403
-            // reschedule the cron if we can't hit the db right now
404
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
405
-                'schedule_expired_transaction_check',
406
-                self::$_expired_transactions
407
-            )
408
-        ) {
409
-            return;
410
-        }
411
-        /** @type EE_Transaction_Processor $transaction_processor */
412
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
413
-        // set revisit flag for txn processor
414
-        $transaction_processor->set_revisit();
415
-        // load EEM_Transaction
416
-        EE_Registry::instance()->load_model('Transaction');
417
-        foreach (self::$_expired_transactions as $TXN_ID) {
418
-            $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
419
-            // verify transaction and whether it is failed or not
420
-            if ($transaction instanceof EE_Transaction) {
421
-                switch ($transaction->status_ID()) {
422
-                    // Completed TXNs
423
-                    case EEM_Transaction::complete_status_code:
424
-                        // Don't update the transaction/registrations if the Primary Registration is Not Approved.
425
-                        $primary_registration = $transaction->primary_registration();
426
-                        if (
427
-                            $primary_registration instanceof EE_Registration
428
-                            && $primary_registration->status_ID() !== EEM_Registration::status_id_not_approved
429
-                        ) {
430
-                            /** @type EE_Transaction_Processor $transaction_processor */
431
-                            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
432
-                            $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
433
-                                $transaction,
434
-                                $transaction->last_payment()
435
-                            );
436
-                            do_action(
437
-                                'AHEE__EE_Cron_Tasks__process_expired_transactions__completed_transaction',
438
-                                $transaction
439
-                            );
440
-                        }
441
-                        break;
442
-                    // Overpaid TXNs
443
-                    case EEM_Transaction::overpaid_status_code:
444
-                        do_action(
445
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__overpaid_transaction',
446
-                            $transaction
447
-                        );
448
-                        break;
449
-                    // Incomplete TXNs
450
-                    case EEM_Transaction::incomplete_status_code:
451
-                        do_action(
452
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
453
-                            $transaction
454
-                        );
455
-                        // todo : move business logic into EE_Transaction_Processor for finalizing abandoned transactions
456
-                        break;
457
-                    // Abandoned TXNs
458
-                    case EEM_Transaction::abandoned_status_code:
459
-                        // run hook before updating transaction, primarily so
460
-                        // EED_Ticket_Sales_Monitor::process_abandoned_transactions() can release reserved tickets
461
-                        do_action(
462
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
463
-                            $transaction
464
-                        );
465
-                        // don't finalize the TXN if it has already been completed
466
-                        if ($transaction->all_reg_steps_completed() !== true) {
467
-                            /** @type EE_Payment_Processor $payment_processor */
468
-                            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
469
-                            // let's simulate an IPN here which will trigger any notifications that need to go out
470
-                            $payment_processor->update_txn_based_on_payment(
471
-                                $transaction,
472
-                                $transaction->last_payment(),
473
-                                true,
474
-                                true
475
-                            );
476
-                        }
477
-                        break;
478
-                    // Failed TXNs
479
-                    case EEM_Transaction::failed_status_code:
480
-                        do_action(
481
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
482
-                            $transaction
483
-                        );
484
-                        // todo :
485
-                        // perform garbage collection here and remove clean_out_junk_transactions()
486
-                        // $registrations = $transaction->registrations();
487
-                        // if (! empty($registrations)) {
488
-                        //     foreach ($registrations as $registration) {
489
-                        //         if ($registration instanceof EE_Registration) {
490
-                        //             $delete_registration = true;
491
-                        //             if ($registration->attendee() instanceof EE_Attendee) {
492
-                        //                 $delete_registration = false;
493
-                        //             }
494
-                        //             if ($delete_registration) {
495
-                        //                 $registration->delete_permanently();
496
-                        //                 $registration->delete_related_permanently();
497
-                        //             }
498
-                        //         }
499
-                        //     }
500
-                        // }
501
-                        break;
502
-                }
503
-            }
504
-            unset(self::$_expired_transactions[ $TXN_ID ]);
505
-        }
506
-    }
507
-
508
-
509
-
510
-    /*************  END OF EXPIRED TRANSACTION CHECK  *************/
511
-
512
-
513
-    /************* START CLEAN UP BOT TRANSACTIONS **********************/
514
-
515
-
516
-    /**
517
-     * callback for 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'
518
-     * which is setup during activation to run on an hourly cron
519
-     *
520
-     * @throws EE_Error
521
-     * @throws InvalidArgumentException
522
-     * @throws InvalidDataTypeException
523
-     * @throws InvalidInterfaceException
524
-     * @throws DomainException
525
-     */
526
-    public static function clean_out_junk_transactions()
527
-    {
528
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
529
-            EED_Ticket_Sales_Monitor::reset_reservation_counts();
530
-            EEM_Transaction::instance('')->delete_junk_transactions();
531
-            EEM_Registration::instance('')->delete_registrations_with_no_transaction();
532
-            EEM_Line_Item::instance('')->delete_line_items_with_no_transaction();
533
-        }
534
-    }
535
-
536
-
537
-    /**
538
-     * Deletes old gateway logs. After about a week we usually don't need them for debugging. But folks can filter that.
539
-     *
540
-     * @throws EE_Error
541
-     * @throws InvalidDataTypeException
542
-     * @throws InvalidInterfaceException
543
-     * @throws InvalidArgumentException
544
-     */
545
-    public static function clean_out_old_gateway_logs()
546
-    {
547
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
548
-            $reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
549
-            $time_diff_for_comparison = apply_filters(
550
-                'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison',
551
-                '-' . $reg_config->gateway_log_lifespan
552
-            );
553
-            EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison));
554
-        }
555
-    }
556
-
557
-
558
-    /*****************  FINALIZE ABANDONED TRANSACTIONS *****************/
559
-
560
-
561
-    /**
562
-     * @var array
563
-     */
564
-    protected static $_abandoned_transactions = array();
565
-
566
-
567
-    /**
568
-     * @deprecated
569
-     * @param int $timestamp
570
-     * @param int $TXN_ID
571
-     */
572
-    public static function schedule_finalize_abandoned_transactions_check($timestamp, $TXN_ID)
573
-    {
574
-        EE_Cron_Tasks::schedule_expired_transaction_check($timestamp, $TXN_ID);
575
-    }
576
-
577
-
578
-    /**
579
-     * @deprecated
580
-     * @param int $TXN_ID
581
-     */
582
-    public static function check_for_abandoned_transactions($TXN_ID = 0)
583
-    {
584
-        EE_Cron_Tasks::expired_transaction_check($TXN_ID);
585
-    }
586
-
587
-
588
-    /**
589
-     * @deprecated
590
-     * @throws EE_Error
591
-     * @throws DomainException
592
-     * @throws InvalidDataTypeException
593
-     * @throws InvalidInterfaceException
594
-     * @throws InvalidArgumentException
595
-     * @throws ReflectionException
596
-     * @throws RuntimeException
597
-     */
598
-    public static function finalize_abandoned_transactions()
599
-    {
600
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
601
-        if (
402
+			empty(self::$_expired_transactions)
403
+			// reschedule the cron if we can't hit the db right now
404
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
405
+				'schedule_expired_transaction_check',
406
+				self::$_expired_transactions
407
+			)
408
+		) {
409
+			return;
410
+		}
411
+		/** @type EE_Transaction_Processor $transaction_processor */
412
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
413
+		// set revisit flag for txn processor
414
+		$transaction_processor->set_revisit();
415
+		// load EEM_Transaction
416
+		EE_Registry::instance()->load_model('Transaction');
417
+		foreach (self::$_expired_transactions as $TXN_ID) {
418
+			$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
419
+			// verify transaction and whether it is failed or not
420
+			if ($transaction instanceof EE_Transaction) {
421
+				switch ($transaction->status_ID()) {
422
+					// Completed TXNs
423
+					case EEM_Transaction::complete_status_code:
424
+						// Don't update the transaction/registrations if the Primary Registration is Not Approved.
425
+						$primary_registration = $transaction->primary_registration();
426
+						if (
427
+							$primary_registration instanceof EE_Registration
428
+							&& $primary_registration->status_ID() !== EEM_Registration::status_id_not_approved
429
+						) {
430
+							/** @type EE_Transaction_Processor $transaction_processor */
431
+							$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
432
+							$transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
433
+								$transaction,
434
+								$transaction->last_payment()
435
+							);
436
+							do_action(
437
+								'AHEE__EE_Cron_Tasks__process_expired_transactions__completed_transaction',
438
+								$transaction
439
+							);
440
+						}
441
+						break;
442
+					// Overpaid TXNs
443
+					case EEM_Transaction::overpaid_status_code:
444
+						do_action(
445
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__overpaid_transaction',
446
+							$transaction
447
+						);
448
+						break;
449
+					// Incomplete TXNs
450
+					case EEM_Transaction::incomplete_status_code:
451
+						do_action(
452
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
453
+							$transaction
454
+						);
455
+						// todo : move business logic into EE_Transaction_Processor for finalizing abandoned transactions
456
+						break;
457
+					// Abandoned TXNs
458
+					case EEM_Transaction::abandoned_status_code:
459
+						// run hook before updating transaction, primarily so
460
+						// EED_Ticket_Sales_Monitor::process_abandoned_transactions() can release reserved tickets
461
+						do_action(
462
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
463
+							$transaction
464
+						);
465
+						// don't finalize the TXN if it has already been completed
466
+						if ($transaction->all_reg_steps_completed() !== true) {
467
+							/** @type EE_Payment_Processor $payment_processor */
468
+							$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
469
+							// let's simulate an IPN here which will trigger any notifications that need to go out
470
+							$payment_processor->update_txn_based_on_payment(
471
+								$transaction,
472
+								$transaction->last_payment(),
473
+								true,
474
+								true
475
+							);
476
+						}
477
+						break;
478
+					// Failed TXNs
479
+					case EEM_Transaction::failed_status_code:
480
+						do_action(
481
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
482
+							$transaction
483
+						);
484
+						// todo :
485
+						// perform garbage collection here and remove clean_out_junk_transactions()
486
+						// $registrations = $transaction->registrations();
487
+						// if (! empty($registrations)) {
488
+						//     foreach ($registrations as $registration) {
489
+						//         if ($registration instanceof EE_Registration) {
490
+						//             $delete_registration = true;
491
+						//             if ($registration->attendee() instanceof EE_Attendee) {
492
+						//                 $delete_registration = false;
493
+						//             }
494
+						//             if ($delete_registration) {
495
+						//                 $registration->delete_permanently();
496
+						//                 $registration->delete_related_permanently();
497
+						//             }
498
+						//         }
499
+						//     }
500
+						// }
501
+						break;
502
+				}
503
+			}
504
+			unset(self::$_expired_transactions[ $TXN_ID ]);
505
+		}
506
+	}
507
+
508
+
509
+
510
+	/*************  END OF EXPIRED TRANSACTION CHECK  *************/
511
+
512
+
513
+	/************* START CLEAN UP BOT TRANSACTIONS **********************/
514
+
515
+
516
+	/**
517
+	 * callback for 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'
518
+	 * which is setup during activation to run on an hourly cron
519
+	 *
520
+	 * @throws EE_Error
521
+	 * @throws InvalidArgumentException
522
+	 * @throws InvalidDataTypeException
523
+	 * @throws InvalidInterfaceException
524
+	 * @throws DomainException
525
+	 */
526
+	public static function clean_out_junk_transactions()
527
+	{
528
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
529
+			EED_Ticket_Sales_Monitor::reset_reservation_counts();
530
+			EEM_Transaction::instance('')->delete_junk_transactions();
531
+			EEM_Registration::instance('')->delete_registrations_with_no_transaction();
532
+			EEM_Line_Item::instance('')->delete_line_items_with_no_transaction();
533
+		}
534
+	}
535
+
536
+
537
+	/**
538
+	 * Deletes old gateway logs. After about a week we usually don't need them for debugging. But folks can filter that.
539
+	 *
540
+	 * @throws EE_Error
541
+	 * @throws InvalidDataTypeException
542
+	 * @throws InvalidInterfaceException
543
+	 * @throws InvalidArgumentException
544
+	 */
545
+	public static function clean_out_old_gateway_logs()
546
+	{
547
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
548
+			$reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
549
+			$time_diff_for_comparison = apply_filters(
550
+				'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison',
551
+				'-' . $reg_config->gateway_log_lifespan
552
+			);
553
+			EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison));
554
+		}
555
+	}
556
+
557
+
558
+	/*****************  FINALIZE ABANDONED TRANSACTIONS *****************/
559
+
560
+
561
+	/**
562
+	 * @var array
563
+	 */
564
+	protected static $_abandoned_transactions = array();
565
+
566
+
567
+	/**
568
+	 * @deprecated
569
+	 * @param int $timestamp
570
+	 * @param int $TXN_ID
571
+	 */
572
+	public static function schedule_finalize_abandoned_transactions_check($timestamp, $TXN_ID)
573
+	{
574
+		EE_Cron_Tasks::schedule_expired_transaction_check($timestamp, $TXN_ID);
575
+	}
576
+
577
+
578
+	/**
579
+	 * @deprecated
580
+	 * @param int $TXN_ID
581
+	 */
582
+	public static function check_for_abandoned_transactions($TXN_ID = 0)
583
+	{
584
+		EE_Cron_Tasks::expired_transaction_check($TXN_ID);
585
+	}
586
+
587
+
588
+	/**
589
+	 * @deprecated
590
+	 * @throws EE_Error
591
+	 * @throws DomainException
592
+	 * @throws InvalidDataTypeException
593
+	 * @throws InvalidInterfaceException
594
+	 * @throws InvalidArgumentException
595
+	 * @throws ReflectionException
596
+	 * @throws RuntimeException
597
+	 */
598
+	public static function finalize_abandoned_transactions()
599
+	{
600
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
601
+		if (
602 602
 // are there any TXNs that need cleaning up ?
603
-            empty(self::$_abandoned_transactions)
604
-            // reschedule the cron if we can't hit the db right now
605
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
606
-                'schedule_expired_transaction_check',
607
-                self::$_abandoned_transactions
608
-            )
609
-        ) {
610
-            return;
611
-        }
612
-        // combine our arrays of transaction IDs
613
-        self::$_expired_transactions = self::$_abandoned_transactions + self::$_expired_transactions;
614
-        // and deal with abandoned transactions here now...
615
-        EE_Cron_Tasks::process_expired_transactions();
616
-    }
617
-
618
-
619
-    /*************  END OF FINALIZE ABANDONED TRANSACTIONS  *************/
603
+			empty(self::$_abandoned_transactions)
604
+			// reschedule the cron if we can't hit the db right now
605
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
606
+				'schedule_expired_transaction_check',
607
+				self::$_abandoned_transactions
608
+			)
609
+		) {
610
+			return;
611
+		}
612
+		// combine our arrays of transaction IDs
613
+		self::$_expired_transactions = self::$_abandoned_transactions + self::$_expired_transactions;
614
+		// and deal with abandoned transactions here now...
615
+		EE_Cron_Tasks::process_expired_transactions();
616
+	}
617
+
618
+
619
+	/*************  END OF FINALIZE ABANDONED TRANSACTIONS  *************/
620 620
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Template_Validator.helper.php 2 patches
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -40,10 +40,10 @@  discard block
 block discarded – undo
40 40
      */
41 41
     public static function verify_is_array_of($variable_to_test, $name_of_variable, $class_name, $allow_null = 'allow_null')
42 42
     {
43
-        if (!WP_DEBUG) {
43
+        if ( ! WP_DEBUG) {
44 44
             return;
45 45
         }
46
-        self::verify_argument_is_one_of($allow_null, 'allow_null', array('allow_null','do_not_allow_null'));
46
+        self::verify_argument_is_one_of($allow_null, 'allow_null', array('allow_null', 'do_not_allow_null'));
47 47
         if ('allow_null' == $allow_null && is_null($variable_to_test)) {
48 48
             return;
49 49
         }
@@ -66,7 +66,7 @@  discard block
 block discarded – undo
66 66
      */
67 67
     public static function verify_isnt_null($variable_to_test, $name_of_variable)
68 68
     {
69
-        if (!WP_DEBUG) {
69
+        if ( ! WP_DEBUG) {
70 70
             return;
71 71
         }
72 72
         if ($variable_to_test == null && $variable_to_test != 0 && $variable_to_test != false) {
@@ -86,10 +86,10 @@  discard block
 block discarded – undo
86 86
      */
87 87
     public static function verify_is_true($expression_to_test, $expression_string_representation)
88 88
     {
89
-        if (!WP_DEBUG) {
89
+        if ( ! WP_DEBUG) {
90 90
             return;
91 91
         }
92
-        if (!$expression_to_test) {
92
+        if ( ! $expression_to_test) {
93 93
             $error[] = esc_html__('Template error.', 'event_espresso');
94 94
             $error[] = esc_html__("%s evaluated to false, but it must be true!", 'event_espresso');
95 95
             throw new EE_Error(sprintf(implode(",", $error), $expression_string_representation));
@@ -110,14 +110,14 @@  discard block
 block discarded – undo
110 110
      */
111 111
     public static function verify_instanceof($variable_to_test, $name_of_variable, $class_name, $allow_null = 'do_not_allow_null')
112 112
     {
113
-        if (!WP_DEBUG) {
113
+        if ( ! WP_DEBUG) {
114 114
             return;
115 115
         }
116
-        self::verify_argument_is_one_of($allow_null, 'allow_null', array('allow_null','do_not_allow_null'));
116
+        self::verify_argument_is_one_of($allow_null, 'allow_null', array('allow_null', 'do_not_allow_null'));
117 117
         if ($allow_null == 'allow_null' && is_null($variable_to_test)) {
118 118
             return;
119 119
         }
120
-        if ($variable_to_test == null ||  ! ( $variable_to_test instanceof $class_name )) {
120
+        if ($variable_to_test == null || ! ($variable_to_test instanceof $class_name)) {
121 121
             $msg[] = esc_html__('Variable %s is not of the correct type.', 'event_espresso');
122 122
             $msg[] = esc_html__("It should be of type %s", 'event_espresso');
123 123
             throw new EE_Error(sprintf(implode(",", $msg), $name_of_variable, $name_of_variable, $class_name));
@@ -138,14 +138,14 @@  discard block
 block discarded – undo
138 138
      */
139 139
     public static function verify_is_array($variable_to_test, $variable_name, $allow_empty = 'allow_empty')
140 140
     {
141
-        if (!WP_DEBUG) {
141
+        if ( ! WP_DEBUG) {
142 142
             return;
143 143
         }
144
-        self::verify_argument_is_one_of($allow_empty, $variable_name, array('allow_empty','do_not_allow_empty'));
144
+        self::verify_argument_is_one_of($allow_empty, $variable_name, array('allow_empty', 'do_not_allow_empty'));
145 145
         if (empty($variable_to_test) && 'allow_empty' == $allow_empty) {
146 146
             return;
147 147
         }
148
-        if (!is_array($variable_to_test)) {
148
+        if ( ! is_array($variable_to_test)) {
149 149
             $error[] = esc_html__('Variable %s should be an array, but it is not.', 'event_espresso');
150 150
             $error[] = esc_html__("Its value is, instead '%s'", 'event_espresso');
151 151
             throw new EE_Error(sprintf(implode(",", $error), $variable_name, $variable_name, $variable_to_test));
@@ -168,10 +168,10 @@  discard block
 block discarded – undo
168 168
      */
169 169
     public static function verify_argument_is_one_of($variable_to_test, $variable_name, $string_options)
170 170
     {
171
-        if (!WP_DEBUG) {
171
+        if ( ! WP_DEBUG) {
172 172
             return;
173 173
         }
174
-        if (!in_array($variable_to_test, $string_options)) {
174
+        if ( ! in_array($variable_to_test, $string_options)) {
175 175
             $msg[0] = esc_html__('Malconfigured template.', 'event_espresso');
176 176
             $msg[1] = esc_html__("Variable named '%s' was set to '%s'. It can only be one of '%s'", 'event_espresso');
177 177
             throw new EE_Error(sprintf(implode("||", $msg), $variable_name, $variable_to_test, implode("', '", $string_options)));
Please login to merge, or discard this patch.
Indentation   +148 added lines, -148 removed lines patch added patch discarded remove patch
@@ -24,152 +24,152 @@
 block discarded – undo
24 24
  */
25 25
 class EEH_Template_Validator
26 26
 {
27
-    /**
28
-     * Throws an EE_Error if $variabel_to_test isn't an array of objects of class $class_name
29
-     * @param mixed $variable_to_test
30
-     * @param string $name_of_variable helpful in throwing intelligent errors
31
-     * @param string $class_name eg EE_Answer, EE_Transaction, etc.
32
-     * @param string $allow_null one of 'allow_null', or 'do_not_allow_null'
33
-     * @return void
34
-     * @throws EE_Error (indirectly)
35
-     */
36
-    public static function verify_is_array_of($variable_to_test, $name_of_variable, $class_name, $allow_null = 'allow_null')
37
-    {
38
-        if (!WP_DEBUG) {
39
-            return;
40
-        }
41
-        self::verify_argument_is_one_of($allow_null, 'allow_null', array('allow_null','do_not_allow_null'));
42
-        if ('allow_null' == $allow_null && is_null($variable_to_test)) {
43
-            return;
44
-        }
45
-        self::verify_is_array($variable_to_test, $name_of_variable);
46
-        foreach ($variable_to_test as $key => $array_element) {
47
-            self::verify_instanceof($array_element, $key, $class_name);
48
-        }
49
-    }
50
-
51
-
52
-
53
-
54
-
55
-    /**
56
-     * throws an EE_Error if $variable_to_test is null
57
-     * @param mixed $variable_to_test
58
-     * @param string $name_of_variable helpful for throwing intelligent errors
59
-     * @return void
60
-     * @throws EE_Error
61
-     */
62
-    public static function verify_isnt_null($variable_to_test, $name_of_variable)
63
-    {
64
-        if (!WP_DEBUG) {
65
-            return;
66
-        }
67
-        if ($variable_to_test == null && $variable_to_test != 0 && $variable_to_test != false) {
68
-            $error[] = esc_html__('Variable named %s is null.', 'event_espresso');
69
-            $error[] = esc_html__("Consider looking at the stack trace to see why it wasn't set.", 'event_espresso');
70
-            throw new EE_Error(sprintf(implode(",", $error), $name_of_variable, $name_of_variable));
71
-        }
72
-    }
73
-
74
-    /**
75
-     * When WP_DEBUG is activted, throws an error if $expression_to_test is false.
76
-     * @param boolean $expression_to_test
77
-     * @param string $expression_string_representation a string representation of your expression
78
-     * for example, if your expression were $var1==23, then this should be '$var1==23'
79
-     * @return void
80
-     * @throws EE_Error
81
-     */
82
-    public static function verify_is_true($expression_to_test, $expression_string_representation)
83
-    {
84
-        if (!WP_DEBUG) {
85
-            return;
86
-        }
87
-        if (!$expression_to_test) {
88
-            $error[] = esc_html__('Template error.', 'event_espresso');
89
-            $error[] = esc_html__("%s evaluated to false, but it must be true!", 'event_espresso');
90
-            throw new EE_Error(sprintf(implode(",", $error), $expression_string_representation));
91
-        }
92
-    }
93
-
94
-
95
-
96
-
97
-
98
-    /**
99
-     * For verifying that a variable is indeed an object of class $class_name
100
-     * @param mixed $variable_to_test
101
-     * @param string $name_of_variable helpful when throwing errors
102
-     * @param string $class_name eg, EE_Answer,
103
-     * @return void
104
-     * @throws EE_Error
105
-     */
106
-    public static function verify_instanceof($variable_to_test, $name_of_variable, $class_name, $allow_null = 'do_not_allow_null')
107
-    {
108
-        if (!WP_DEBUG) {
109
-            return;
110
-        }
111
-        self::verify_argument_is_one_of($allow_null, 'allow_null', array('allow_null','do_not_allow_null'));
112
-        if ($allow_null == 'allow_null' && is_null($variable_to_test)) {
113
-            return;
114
-        }
115
-        if ($variable_to_test == null ||  ! ( $variable_to_test instanceof $class_name )) {
116
-            $msg[] = esc_html__('Variable %s is not of the correct type.', 'event_espresso');
117
-            $msg[] = esc_html__("It should be of type %s", 'event_espresso');
118
-            throw new EE_Error(sprintf(implode(",", $msg), $name_of_variable, $name_of_variable, $class_name));
119
-        }
120
-    }
121
-
122
-
123
-
124
-
125
-
126
-    /**
127
-     * For verifying that a variable is indeed an array, else throw an EE_Error
128
-     * @param type $variable_to_test
129
-     * @param type $variable_name
130
-     * @param type $allow_empty one of 'allow_empty' or 'do_not_allow_empty'
131
-     * @return void
132
-     * @throws EE_Error
133
-     */
134
-    public static function verify_is_array($variable_to_test, $variable_name, $allow_empty = 'allow_empty')
135
-    {
136
-        if (!WP_DEBUG) {
137
-            return;
138
-        }
139
-        self::verify_argument_is_one_of($allow_empty, $variable_name, array('allow_empty','do_not_allow_empty'));
140
-        if (empty($variable_to_test) && 'allow_empty' == $allow_empty) {
141
-            return;
142
-        }
143
-        if (!is_array($variable_to_test)) {
144
-            $error[] = esc_html__('Variable %s should be an array, but it is not.', 'event_espresso');
145
-            $error[] = esc_html__("Its value is, instead '%s'", 'event_espresso');
146
-            throw new EE_Error(sprintf(implode(",", $error), $variable_name, $variable_name, $variable_to_test));
147
-        }
148
-    }
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-    /**
157
-     * for verifying that a variable is one of the string optiosn supplied
158
-     * @param mixed $variable_to_test
159
-     * @param mixed $variable_name the name you've given the variable. Eg, '$foo'. THis helps in producing better error messages
160
-     * @param array $string_options an array of acceptable values
161
-     * @return void
162
-     * @throws EE_Error
163
-     */
164
-    public static function verify_argument_is_one_of($variable_to_test, $variable_name, $string_options)
165
-    {
166
-        if (!WP_DEBUG) {
167
-            return;
168
-        }
169
-        if (!in_array($variable_to_test, $string_options)) {
170
-            $msg[0] = esc_html__('Malconfigured template.', 'event_espresso');
171
-            $msg[1] = esc_html__("Variable named '%s' was set to '%s'. It can only be one of '%s'", 'event_espresso');
172
-            throw new EE_Error(sprintf(implode("||", $msg), $variable_name, $variable_to_test, implode("', '", $string_options)));
173
-        }
174
-    }
27
+	/**
28
+	 * Throws an EE_Error if $variabel_to_test isn't an array of objects of class $class_name
29
+	 * @param mixed $variable_to_test
30
+	 * @param string $name_of_variable helpful in throwing intelligent errors
31
+	 * @param string $class_name eg EE_Answer, EE_Transaction, etc.
32
+	 * @param string $allow_null one of 'allow_null', or 'do_not_allow_null'
33
+	 * @return void
34
+	 * @throws EE_Error (indirectly)
35
+	 */
36
+	public static function verify_is_array_of($variable_to_test, $name_of_variable, $class_name, $allow_null = 'allow_null')
37
+	{
38
+		if (!WP_DEBUG) {
39
+			return;
40
+		}
41
+		self::verify_argument_is_one_of($allow_null, 'allow_null', array('allow_null','do_not_allow_null'));
42
+		if ('allow_null' == $allow_null && is_null($variable_to_test)) {
43
+			return;
44
+		}
45
+		self::verify_is_array($variable_to_test, $name_of_variable);
46
+		foreach ($variable_to_test as $key => $array_element) {
47
+			self::verify_instanceof($array_element, $key, $class_name);
48
+		}
49
+	}
50
+
51
+
52
+
53
+
54
+
55
+	/**
56
+	 * throws an EE_Error if $variable_to_test is null
57
+	 * @param mixed $variable_to_test
58
+	 * @param string $name_of_variable helpful for throwing intelligent errors
59
+	 * @return void
60
+	 * @throws EE_Error
61
+	 */
62
+	public static function verify_isnt_null($variable_to_test, $name_of_variable)
63
+	{
64
+		if (!WP_DEBUG) {
65
+			return;
66
+		}
67
+		if ($variable_to_test == null && $variable_to_test != 0 && $variable_to_test != false) {
68
+			$error[] = esc_html__('Variable named %s is null.', 'event_espresso');
69
+			$error[] = esc_html__("Consider looking at the stack trace to see why it wasn't set.", 'event_espresso');
70
+			throw new EE_Error(sprintf(implode(",", $error), $name_of_variable, $name_of_variable));
71
+		}
72
+	}
73
+
74
+	/**
75
+	 * When WP_DEBUG is activted, throws an error if $expression_to_test is false.
76
+	 * @param boolean $expression_to_test
77
+	 * @param string $expression_string_representation a string representation of your expression
78
+	 * for example, if your expression were $var1==23, then this should be '$var1==23'
79
+	 * @return void
80
+	 * @throws EE_Error
81
+	 */
82
+	public static function verify_is_true($expression_to_test, $expression_string_representation)
83
+	{
84
+		if (!WP_DEBUG) {
85
+			return;
86
+		}
87
+		if (!$expression_to_test) {
88
+			$error[] = esc_html__('Template error.', 'event_espresso');
89
+			$error[] = esc_html__("%s evaluated to false, but it must be true!", 'event_espresso');
90
+			throw new EE_Error(sprintf(implode(",", $error), $expression_string_representation));
91
+		}
92
+	}
93
+
94
+
95
+
96
+
97
+
98
+	/**
99
+	 * For verifying that a variable is indeed an object of class $class_name
100
+	 * @param mixed $variable_to_test
101
+	 * @param string $name_of_variable helpful when throwing errors
102
+	 * @param string $class_name eg, EE_Answer,
103
+	 * @return void
104
+	 * @throws EE_Error
105
+	 */
106
+	public static function verify_instanceof($variable_to_test, $name_of_variable, $class_name, $allow_null = 'do_not_allow_null')
107
+	{
108
+		if (!WP_DEBUG) {
109
+			return;
110
+		}
111
+		self::verify_argument_is_one_of($allow_null, 'allow_null', array('allow_null','do_not_allow_null'));
112
+		if ($allow_null == 'allow_null' && is_null($variable_to_test)) {
113
+			return;
114
+		}
115
+		if ($variable_to_test == null ||  ! ( $variable_to_test instanceof $class_name )) {
116
+			$msg[] = esc_html__('Variable %s is not of the correct type.', 'event_espresso');
117
+			$msg[] = esc_html__("It should be of type %s", 'event_espresso');
118
+			throw new EE_Error(sprintf(implode(",", $msg), $name_of_variable, $name_of_variable, $class_name));
119
+		}
120
+	}
121
+
122
+
123
+
124
+
125
+
126
+	/**
127
+	 * For verifying that a variable is indeed an array, else throw an EE_Error
128
+	 * @param type $variable_to_test
129
+	 * @param type $variable_name
130
+	 * @param type $allow_empty one of 'allow_empty' or 'do_not_allow_empty'
131
+	 * @return void
132
+	 * @throws EE_Error
133
+	 */
134
+	public static function verify_is_array($variable_to_test, $variable_name, $allow_empty = 'allow_empty')
135
+	{
136
+		if (!WP_DEBUG) {
137
+			return;
138
+		}
139
+		self::verify_argument_is_one_of($allow_empty, $variable_name, array('allow_empty','do_not_allow_empty'));
140
+		if (empty($variable_to_test) && 'allow_empty' == $allow_empty) {
141
+			return;
142
+		}
143
+		if (!is_array($variable_to_test)) {
144
+			$error[] = esc_html__('Variable %s should be an array, but it is not.', 'event_espresso');
145
+			$error[] = esc_html__("Its value is, instead '%s'", 'event_espresso');
146
+			throw new EE_Error(sprintf(implode(",", $error), $variable_name, $variable_name, $variable_to_test));
147
+		}
148
+	}
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+	/**
157
+	 * for verifying that a variable is one of the string optiosn supplied
158
+	 * @param mixed $variable_to_test
159
+	 * @param mixed $variable_name the name you've given the variable. Eg, '$foo'. THis helps in producing better error messages
160
+	 * @param array $string_options an array of acceptable values
161
+	 * @return void
162
+	 * @throws EE_Error
163
+	 */
164
+	public static function verify_argument_is_one_of($variable_to_test, $variable_name, $string_options)
165
+	{
166
+		if (!WP_DEBUG) {
167
+			return;
168
+		}
169
+		if (!in_array($variable_to_test, $string_options)) {
170
+			$msg[0] = esc_html__('Malconfigured template.', 'event_espresso');
171
+			$msg[1] = esc_html__("Variable named '%s' was set to '%s'. It can only be one of '%s'", 'event_espresso');
172
+			throw new EE_Error(sprintf(implode("||", $msg), $variable_name, $variable_to_test, implode("', '", $string_options)));
173
+		}
174
+	}
175 175
 }
Please login to merge, or discard this patch.
core/exceptions/InvalidStatusException.php 1 patch
Indentation   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -7,26 +7,26 @@
 block discarded – undo
7 7
 
8 8
 class InvalidStatusException extends InvalidArgumentException
9 9
 {
10
-    /**
11
-     * InvalidStatusException constructor.
12
-     * @param string $status the invalid status id that was supplied
13
-     * @param string $domain the name of the domain, model, or class that the status belongs to
14
-     * @param string $message custom message
15
-     * @param int $code
16
-     * @param Exception|null $previous
17
-     */
18
-    public function __construct($status, $domain, $message = '', $code = 0, Exception $previous = null)
19
-    {
20
-        if (empty($message)) {
21
-            $message = sprintf(
22
-                esc_html__(
23
-                    '"%1$s" is not a valid %2$s status',
24
-                    'event_espresso'
25
-                ),
26
-                $status,
27
-                $domain
28
-            );
29
-        }
30
-        parent::__construct($message, $code, $previous);
31
-    }
10
+	/**
11
+	 * InvalidStatusException constructor.
12
+	 * @param string $status the invalid status id that was supplied
13
+	 * @param string $domain the name of the domain, model, or class that the status belongs to
14
+	 * @param string $message custom message
15
+	 * @param int $code
16
+	 * @param Exception|null $previous
17
+	 */
18
+	public function __construct($status, $domain, $message = '', $code = 0, Exception $previous = null)
19
+	{
20
+		if (empty($message)) {
21
+			$message = sprintf(
22
+				esc_html__(
23
+					'"%1$s" is not a valid %2$s status',
24
+					'event_espresso'
25
+				),
26
+				$status,
27
+				$domain
28
+			);
29
+		}
30
+		parent::__construct($message, $code, $previous);
31
+	}
32 32
 }
Please login to merge, or discard this patch.
core/exceptions/InvalidDataTypeException.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -31,7 +31,7 @@  discard block
 block discarded – undo
31 31
     {
32 32
         if (empty($message)) {
33 33
             $expected = strpos(' was expected.', $expected) === false
34
-                ? $this->addIndefiniteArticle($expected) . ' was expected.'
34
+                ? $this->addIndefiniteArticle($expected).' was expected.'
35 35
                 : $expected;
36 36
             $message = sprintf(
37 37
                 esc_html__(
@@ -56,6 +56,6 @@  discard block
 block discarded – undo
56 56
         if (strtolower($string) === 'null') {
57 57
             return $string;
58 58
         }
59
-        return (stripos('aeiou', $string[0]) !== false ? 'an ' : 'a ') . $string;
59
+        return (stripos('aeiou', $string[0]) !== false ? 'an ' : 'a ').$string;
60 60
     }
61 61
 }
Please login to merge, or discard this patch.
Indentation   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -15,46 +15,46 @@
 block discarded – undo
15 15
  */
16 16
 class InvalidDataTypeException extends InvalidArgumentException
17 17
 {
18
-    /**
19
-     * InvalidDataTypeException constructor
20
-     *
21
-     * @param string    $var_name  name of the variable that was of the wrong type ie: "$my_var"
22
-     * @param mixed     $variable  the actual variable that was of the wrong data type, ie: $my_var
23
-     * @param string    $expected  data type we wanted ie: "integer", "string", "array", etc.
24
-     *                             or an entire rewrite of: "{something something} was expected."
25
-     * @param string    $message
26
-     * @param int       $code
27
-     * @param Exception $previous
28
-     */
29
-    public function __construct($var_name, $variable, $expected, $message = '', $code = 0, Exception $previous = null)
30
-    {
31
-        if (empty($message)) {
32
-            $expected = strpos(' was expected.', $expected) === false
33
-                ? $this->addIndefiniteArticle($expected) . ' was expected.'
34
-                : $expected;
35
-            $message = sprintf(
36
-                esc_html__(
37
-                    'The supplied data for "%1$s" was %2$s, but %3$s',
38
-                    'event_espresso'
39
-                ),
40
-                $var_name,
41
-                $this->addIndefiniteArticle(gettype($variable)),
42
-                $expected
43
-            );
44
-        }
45
-        parent::__construct($message, $code, $previous);
46
-    }
18
+	/**
19
+	 * InvalidDataTypeException constructor
20
+	 *
21
+	 * @param string    $var_name  name of the variable that was of the wrong type ie: "$my_var"
22
+	 * @param mixed     $variable  the actual variable that was of the wrong data type, ie: $my_var
23
+	 * @param string    $expected  data type we wanted ie: "integer", "string", "array", etc.
24
+	 *                             or an entire rewrite of: "{something something} was expected."
25
+	 * @param string    $message
26
+	 * @param int       $code
27
+	 * @param Exception $previous
28
+	 */
29
+	public function __construct($var_name, $variable, $expected, $message = '', $code = 0, Exception $previous = null)
30
+	{
31
+		if (empty($message)) {
32
+			$expected = strpos(' was expected.', $expected) === false
33
+				? $this->addIndefiniteArticle($expected) . ' was expected.'
34
+				: $expected;
35
+			$message = sprintf(
36
+				esc_html__(
37
+					'The supplied data for "%1$s" was %2$s, but %3$s',
38
+					'event_espresso'
39
+				),
40
+				$var_name,
41
+				$this->addIndefiniteArticle(gettype($variable)),
42
+				$expected
43
+			);
44
+		}
45
+		parent::__construct($message, $code, $previous);
46
+	}
47 47
 
48 48
 
49
-    /**
50
-     * @param $string
51
-     * @return string
52
-     */
53
-    protected function addIndefiniteArticle($string)
54
-    {
55
-        if (strtolower($string) === 'null') {
56
-            return $string;
57
-        }
58
-        return (stripos('aeiou', $string[0]) !== false ? 'an ' : 'a ') . $string;
59
-    }
49
+	/**
50
+	 * @param $string
51
+	 * @return string
52
+	 */
53
+	protected function addIndefiniteArticle($string)
54
+	{
55
+		if (strtolower($string) === 'null') {
56
+			return $string;
57
+		}
58
+		return (stripos('aeiou', $string[0]) !== false ? 'an ' : 'a ') . $string;
59
+	}
60 60
 }
Please login to merge, or discard this patch.
payment_methods/Paypal_Express/templates/paypal_express_intro.template.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -1,10 +1,10 @@
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 printf(
4
-    esc_html__(
5
-        'PayPal Express (Express Checkout) is an off-site payment method for accepting payments via PayPal and is available to event organizers in many countries. A PayPal premier or business account is needed to accept payments. Need a PayPal account? Call 1-855-456-1338 or %1$sclick here to sign up for a merchant account%2$s.',
6
-        'event_espresso'
7
-    ),
8
-    '<a href="https://eventespresso.com/go/paypalexpress/" target="_blank">',
9
-    '</a>'
4
+	esc_html__(
5
+		'PayPal Express (Express Checkout) is an off-site payment method for accepting payments via PayPal and is available to event organizers in many countries. A PayPal premier or business account is needed to accept payments. Need a PayPal account? Call 1-855-456-1338 or %1$sclick here to sign up for a merchant account%2$s.',
6
+		'event_espresso'
7
+	),
8
+	'<a href="https://eventespresso.com/go/paypalexpress/" target="_blank">',
9
+	'</a>'
10 10
 );
Please login to merge, or discard this patch.