@@ -29,295 +29,295 @@ |
||
29 | 29 | class CollectionLoader |
30 | 30 | { |
31 | 31 | |
32 | - /** |
|
33 | - * possible return value when adding entities to a collection. |
|
34 | - * denotes that the entity was NOT ADDED to the collection |
|
35 | - */ |
|
36 | - const ENTITY_NOT_ADDED = 'entity-not-added-to-collection'; |
|
32 | + /** |
|
33 | + * possible return value when adding entities to a collection. |
|
34 | + * denotes that the entity was NOT ADDED to the collection |
|
35 | + */ |
|
36 | + const ENTITY_NOT_ADDED = 'entity-not-added-to-collection'; |
|
37 | 37 | |
38 | - /** |
|
39 | - * possible return value when adding entities to a collection. |
|
40 | - * denotes that the entity was SUCCESSFULLY ADDED to the collection |
|
41 | - */ |
|
42 | - const ENTITY_ADDED = 'entity-added-to-collection'; |
|
38 | + /** |
|
39 | + * possible return value when adding entities to a collection. |
|
40 | + * denotes that the entity was SUCCESSFULLY ADDED to the collection |
|
41 | + */ |
|
42 | + const ENTITY_ADDED = 'entity-added-to-collection'; |
|
43 | 43 | |
44 | - /** |
|
45 | - * possible return value when adding entities to a collection. |
|
46 | - * denotes that the entity was ALREADY ADDED to the collection, |
|
47 | - * and therefore could not be added again. |
|
48 | - */ |
|
49 | - const ENTITY_EXISTS = 'entity-already-in-collection'; |
|
44 | + /** |
|
45 | + * possible return value when adding entities to a collection. |
|
46 | + * denotes that the entity was ALREADY ADDED to the collection, |
|
47 | + * and therefore could not be added again. |
|
48 | + */ |
|
49 | + const ENTITY_EXISTS = 'entity-already-in-collection'; |
|
50 | 50 | |
51 | 51 | |
52 | - /** |
|
53 | - * @var CollectionDetailsInterface $collection_details |
|
54 | - */ |
|
55 | - protected $collection_details; |
|
52 | + /** |
|
53 | + * @var CollectionDetailsInterface $collection_details |
|
54 | + */ |
|
55 | + protected $collection_details; |
|
56 | 56 | |
57 | - /** |
|
58 | - * @var CollectionInterface $collection |
|
59 | - */ |
|
60 | - protected $collection; |
|
57 | + /** |
|
58 | + * @var CollectionInterface $collection |
|
59 | + */ |
|
60 | + protected $collection; |
|
61 | 61 | |
62 | - /** |
|
63 | - * @var FactoryInterface $entity_factory |
|
64 | - */ |
|
65 | - protected $entity_factory; |
|
62 | + /** |
|
63 | + * @var FactoryInterface $entity_factory |
|
64 | + */ |
|
65 | + protected $entity_factory; |
|
66 | 66 | |
67 | - /** |
|
68 | - * @var FileLocator $file_locator |
|
69 | - */ |
|
70 | - protected $file_locator; |
|
67 | + /** |
|
68 | + * @var FileLocator $file_locator |
|
69 | + */ |
|
70 | + protected $file_locator; |
|
71 | 71 | |
72 | 72 | |
73 | - /** |
|
74 | - * CollectionLoader constructor. |
|
75 | - * |
|
76 | - * @param CollectionDetailsInterface $collection_details |
|
77 | - * @param CollectionInterface $collection |
|
78 | - * @param LocatorInterface $file_locator |
|
79 | - * @param FactoryInterface|null $entity_factory |
|
80 | - * @throws CollectionLoaderException |
|
81 | - */ |
|
82 | - public function __construct( |
|
83 | - CollectionDetailsInterface $collection_details, |
|
84 | - CollectionInterface $collection = null, |
|
85 | - LocatorInterface $file_locator = null, |
|
86 | - FactoryInterface $entity_factory = null |
|
87 | - ) { |
|
88 | - try { |
|
89 | - $this->collection_details = $collection_details; |
|
90 | - if (! $collection instanceof CollectionInterface) { |
|
91 | - $collection = new Collection($this->collection_details->getCollectionInterface()); |
|
92 | - } |
|
93 | - $this->collection = $collection; |
|
94 | - $this->file_locator = $file_locator; |
|
95 | - $this->entity_factory = $entity_factory; |
|
96 | - $this->loadAllFromFilepaths(); |
|
97 | - $this->loadFromFQCNs(); |
|
98 | - } catch (Exception $exception) { |
|
99 | - throw new CollectionLoaderException($exception); |
|
100 | - } |
|
101 | - } |
|
73 | + /** |
|
74 | + * CollectionLoader constructor. |
|
75 | + * |
|
76 | + * @param CollectionDetailsInterface $collection_details |
|
77 | + * @param CollectionInterface $collection |
|
78 | + * @param LocatorInterface $file_locator |
|
79 | + * @param FactoryInterface|null $entity_factory |
|
80 | + * @throws CollectionLoaderException |
|
81 | + */ |
|
82 | + public function __construct( |
|
83 | + CollectionDetailsInterface $collection_details, |
|
84 | + CollectionInterface $collection = null, |
|
85 | + LocatorInterface $file_locator = null, |
|
86 | + FactoryInterface $entity_factory = null |
|
87 | + ) { |
|
88 | + try { |
|
89 | + $this->collection_details = $collection_details; |
|
90 | + if (! $collection instanceof CollectionInterface) { |
|
91 | + $collection = new Collection($this->collection_details->getCollectionInterface()); |
|
92 | + } |
|
93 | + $this->collection = $collection; |
|
94 | + $this->file_locator = $file_locator; |
|
95 | + $this->entity_factory = $entity_factory; |
|
96 | + $this->loadAllFromFilepaths(); |
|
97 | + $this->loadFromFQCNs(); |
|
98 | + } catch (Exception $exception) { |
|
99 | + throw new CollectionLoaderException($exception); |
|
100 | + } |
|
101 | + } |
|
102 | 102 | |
103 | 103 | |
104 | - /** |
|
105 | - * @return CollectionInterface |
|
106 | - */ |
|
107 | - public function getCollection() |
|
108 | - { |
|
109 | - return $this->collection; |
|
110 | - } |
|
104 | + /** |
|
105 | + * @return CollectionInterface |
|
106 | + */ |
|
107 | + public function getCollection() |
|
108 | + { |
|
109 | + return $this->collection; |
|
110 | + } |
|
111 | 111 | |
112 | 112 | |
113 | - /** |
|
114 | - * @throws InvalidClassException |
|
115 | - * @throws InvalidFilePathException |
|
116 | - * @throws InvalidDataTypeException |
|
117 | - * @throws InvalidEntityException |
|
118 | - * @throws DuplicateCollectionIdentifierException |
|
119 | - */ |
|
120 | - protected function loadAllFromFilepaths() |
|
121 | - { |
|
122 | - if (! $this->file_locator instanceof FileLocator) { |
|
123 | - $this->file_locator = new FileLocator(); |
|
124 | - } |
|
125 | - $this->file_locator->setFileMask($this->collection_details->getFileMask()); |
|
126 | - // find all of the files that match the file mask in the specified folder |
|
127 | - $this->file_locator->locate($this->collection_details->getCollectionPaths()); |
|
128 | - // filter the results |
|
129 | - $filepaths = (array) apply_filters( |
|
130 | - 'FHEE__CollectionLoader__loadAllFromFilepath__filepaths', |
|
131 | - $this->file_locator->getFilePaths(), |
|
132 | - $this->collection_details->collectionName(), |
|
133 | - $this->collection_details |
|
134 | - ); |
|
135 | - if (empty($filepaths)) { |
|
136 | - return; |
|
137 | - } |
|
138 | - foreach ($filepaths as $filepath) { |
|
139 | - $this->loadClassFromFilepath($filepath); |
|
140 | - } |
|
141 | - } |
|
113 | + /** |
|
114 | + * @throws InvalidClassException |
|
115 | + * @throws InvalidFilePathException |
|
116 | + * @throws InvalidDataTypeException |
|
117 | + * @throws InvalidEntityException |
|
118 | + * @throws DuplicateCollectionIdentifierException |
|
119 | + */ |
|
120 | + protected function loadAllFromFilepaths() |
|
121 | + { |
|
122 | + if (! $this->file_locator instanceof FileLocator) { |
|
123 | + $this->file_locator = new FileLocator(); |
|
124 | + } |
|
125 | + $this->file_locator->setFileMask($this->collection_details->getFileMask()); |
|
126 | + // find all of the files that match the file mask in the specified folder |
|
127 | + $this->file_locator->locate($this->collection_details->getCollectionPaths()); |
|
128 | + // filter the results |
|
129 | + $filepaths = (array) apply_filters( |
|
130 | + 'FHEE__CollectionLoader__loadAllFromFilepath__filepaths', |
|
131 | + $this->file_locator->getFilePaths(), |
|
132 | + $this->collection_details->collectionName(), |
|
133 | + $this->collection_details |
|
134 | + ); |
|
135 | + if (empty($filepaths)) { |
|
136 | + return; |
|
137 | + } |
|
138 | + foreach ($filepaths as $filepath) { |
|
139 | + $this->loadClassFromFilepath($filepath); |
|
140 | + } |
|
141 | + } |
|
142 | 142 | |
143 | 143 | |
144 | - /** |
|
145 | - * @param string $filepath |
|
146 | - * @return string |
|
147 | - * @throws InvalidEntityException |
|
148 | - * @throws InvalidDataTypeException |
|
149 | - * @throws InvalidFilePathException |
|
150 | - * @throws InvalidClassException |
|
151 | - * @throws DuplicateCollectionIdentifierException |
|
152 | - */ |
|
153 | - protected function loadClassFromFilepath($filepath) |
|
154 | - { |
|
155 | - if (! is_string($filepath)) { |
|
156 | - throw new InvalidDataTypeException('$filepath', $filepath, 'string'); |
|
157 | - } |
|
158 | - if (! is_readable($filepath)) { |
|
159 | - throw new InvalidFilePathException($filepath); |
|
160 | - } |
|
161 | - require_once $filepath; |
|
162 | - // extract filename from path |
|
163 | - $file_name = basename($filepath); |
|
164 | - // now remove any file extensions |
|
165 | - $class_name = EEH_File::get_classname_from_filepath_with_standard_filename($file_name); |
|
166 | - if (! class_exists($class_name)) { |
|
167 | - throw new InvalidClassException($class_name); |
|
168 | - } |
|
169 | - $entity = $this->entity_factory instanceof FactoryInterface |
|
170 | - ? call_user_func(array($this->entity_factory, 'create'), $class_name) |
|
171 | - : new $class_name(); |
|
172 | - return $this->addEntityToCollection($entity, $file_name); |
|
173 | - } |
|
144 | + /** |
|
145 | + * @param string $filepath |
|
146 | + * @return string |
|
147 | + * @throws InvalidEntityException |
|
148 | + * @throws InvalidDataTypeException |
|
149 | + * @throws InvalidFilePathException |
|
150 | + * @throws InvalidClassException |
|
151 | + * @throws DuplicateCollectionIdentifierException |
|
152 | + */ |
|
153 | + protected function loadClassFromFilepath($filepath) |
|
154 | + { |
|
155 | + if (! is_string($filepath)) { |
|
156 | + throw new InvalidDataTypeException('$filepath', $filepath, 'string'); |
|
157 | + } |
|
158 | + if (! is_readable($filepath)) { |
|
159 | + throw new InvalidFilePathException($filepath); |
|
160 | + } |
|
161 | + require_once $filepath; |
|
162 | + // extract filename from path |
|
163 | + $file_name = basename($filepath); |
|
164 | + // now remove any file extensions |
|
165 | + $class_name = EEH_File::get_classname_from_filepath_with_standard_filename($file_name); |
|
166 | + if (! class_exists($class_name)) { |
|
167 | + throw new InvalidClassException($class_name); |
|
168 | + } |
|
169 | + $entity = $this->entity_factory instanceof FactoryInterface |
|
170 | + ? call_user_func(array($this->entity_factory, 'create'), $class_name) |
|
171 | + : new $class_name(); |
|
172 | + return $this->addEntityToCollection($entity, $file_name); |
|
173 | + } |
|
174 | 174 | |
175 | 175 | |
176 | - /** |
|
177 | - * @param $entity |
|
178 | - * @param mixed $identifier |
|
179 | - * @return string |
|
180 | - * @throws InvalidEntityException |
|
181 | - * @throws DuplicateCollectionIdentifierException |
|
182 | - */ |
|
183 | - protected function addEntityToCollection($entity, $identifier) |
|
184 | - { |
|
185 | - do_action( |
|
186 | - 'FHEE__CollectionLoader__addEntityToCollection__entity', |
|
187 | - $entity, |
|
188 | - $this->collection_details->collectionName(), |
|
189 | - $this->collection_details |
|
190 | - ); |
|
191 | - $identifier = $this->setIdentifier($entity, $identifier); |
|
192 | - if ($this->collection->has($identifier)) { |
|
193 | - do_action( |
|
194 | - 'FHEE__CollectionLoader__addEntityToCollection__entity_already_added', |
|
195 | - $this, |
|
196 | - $this->collection_details->collectionName(), |
|
197 | - $this->collection_details |
|
198 | - ); |
|
199 | - return CollectionLoader::ENTITY_EXISTS; |
|
200 | - } |
|
201 | - if ($this->collection->add($entity, $identifier)) { |
|
202 | - do_action( |
|
203 | - 'FHEE__CollectionLoader__addEntityToCollection__entity_added', |
|
204 | - $this, |
|
205 | - $this->collection_details->collectionName(), |
|
206 | - $this->collection_details |
|
207 | - ); |
|
208 | - return CollectionLoader::ENTITY_ADDED; |
|
209 | - } |
|
210 | - do_action( |
|
211 | - 'FHEE__CollectionLoader__addEntityToCollection__entity_not_added', |
|
212 | - $this, |
|
213 | - $this->collection_details->collectionName(), |
|
214 | - $this->collection_details |
|
215 | - ); |
|
216 | - return CollectionLoader::ENTITY_NOT_ADDED; |
|
217 | - } |
|
176 | + /** |
|
177 | + * @param $entity |
|
178 | + * @param mixed $identifier |
|
179 | + * @return string |
|
180 | + * @throws InvalidEntityException |
|
181 | + * @throws DuplicateCollectionIdentifierException |
|
182 | + */ |
|
183 | + protected function addEntityToCollection($entity, $identifier) |
|
184 | + { |
|
185 | + do_action( |
|
186 | + 'FHEE__CollectionLoader__addEntityToCollection__entity', |
|
187 | + $entity, |
|
188 | + $this->collection_details->collectionName(), |
|
189 | + $this->collection_details |
|
190 | + ); |
|
191 | + $identifier = $this->setIdentifier($entity, $identifier); |
|
192 | + if ($this->collection->has($identifier)) { |
|
193 | + do_action( |
|
194 | + 'FHEE__CollectionLoader__addEntityToCollection__entity_already_added', |
|
195 | + $this, |
|
196 | + $this->collection_details->collectionName(), |
|
197 | + $this->collection_details |
|
198 | + ); |
|
199 | + return CollectionLoader::ENTITY_EXISTS; |
|
200 | + } |
|
201 | + if ($this->collection->add($entity, $identifier)) { |
|
202 | + do_action( |
|
203 | + 'FHEE__CollectionLoader__addEntityToCollection__entity_added', |
|
204 | + $this, |
|
205 | + $this->collection_details->collectionName(), |
|
206 | + $this->collection_details |
|
207 | + ); |
|
208 | + return CollectionLoader::ENTITY_ADDED; |
|
209 | + } |
|
210 | + do_action( |
|
211 | + 'FHEE__CollectionLoader__addEntityToCollection__entity_not_added', |
|
212 | + $this, |
|
213 | + $this->collection_details->collectionName(), |
|
214 | + $this->collection_details |
|
215 | + ); |
|
216 | + return CollectionLoader::ENTITY_NOT_ADDED; |
|
217 | + } |
|
218 | 218 | |
219 | 219 | |
220 | - /** |
|
221 | - * @param $entity |
|
222 | - * @param mixed $identifier |
|
223 | - * @return string |
|
224 | - * @throws InvalidEntityException |
|
225 | - */ |
|
226 | - protected function setIdentifier($entity, $identifier) |
|
227 | - { |
|
228 | - switch ($this->collection_details->identifierType()) { |
|
229 | - // every unique object gets added to the collection, but not duplicates of the exact same object |
|
230 | - case CollectionDetails::ID_OBJECT_HASH: |
|
231 | - $identifier = spl_object_hash($entity); |
|
232 | - break; |
|
233 | - // only one entity per class can be added to collection, like a singleton |
|
234 | - case CollectionDetails::ID_CLASS_NAME: |
|
235 | - $identifier = get_class($entity); |
|
236 | - break; |
|
237 | - // objects added to the collection based on entity callback, so the entity itself decides |
|
238 | - case CollectionDetails::ID_CALLBACK_METHOD: |
|
239 | - $identifier_callback = $this->collection_details->identifierCallback(); |
|
240 | - if (! method_exists($entity, $identifier_callback)) { |
|
241 | - throw new InvalidEntityException( |
|
242 | - $entity, |
|
243 | - $this->collection_details->getCollectionInterface(), |
|
244 | - sprintf( |
|
245 | - __( |
|
246 | - 'The current collection is configured to use a method named "%1$s" when setting or retrieving objects. The supplied entity is an instance |
|
220 | + /** |
|
221 | + * @param $entity |
|
222 | + * @param mixed $identifier |
|
223 | + * @return string |
|
224 | + * @throws InvalidEntityException |
|
225 | + */ |
|
226 | + protected function setIdentifier($entity, $identifier) |
|
227 | + { |
|
228 | + switch ($this->collection_details->identifierType()) { |
|
229 | + // every unique object gets added to the collection, but not duplicates of the exact same object |
|
230 | + case CollectionDetails::ID_OBJECT_HASH: |
|
231 | + $identifier = spl_object_hash($entity); |
|
232 | + break; |
|
233 | + // only one entity per class can be added to collection, like a singleton |
|
234 | + case CollectionDetails::ID_CLASS_NAME: |
|
235 | + $identifier = get_class($entity); |
|
236 | + break; |
|
237 | + // objects added to the collection based on entity callback, so the entity itself decides |
|
238 | + case CollectionDetails::ID_CALLBACK_METHOD: |
|
239 | + $identifier_callback = $this->collection_details->identifierCallback(); |
|
240 | + if (! method_exists($entity, $identifier_callback)) { |
|
241 | + throw new InvalidEntityException( |
|
242 | + $entity, |
|
243 | + $this->collection_details->getCollectionInterface(), |
|
244 | + sprintf( |
|
245 | + __( |
|
246 | + 'The current collection is configured to use a method named "%1$s" when setting or retrieving objects. The supplied entity is an instance |
|
247 | 247 | of "%2$s", but does not contain this method.', |
248 | - 'event_espresso' |
|
249 | - ), |
|
250 | - $identifier_callback, |
|
251 | - get_class($entity) |
|
252 | - ) |
|
253 | - ); |
|
254 | - } |
|
255 | - $identifier = $entity->{$identifier_callback}(); |
|
256 | - break; |
|
257 | - } |
|
258 | - return apply_filters( |
|
259 | - 'FHEE__CollectionLoader__addEntityToCollection__identifier', |
|
260 | - $identifier, |
|
261 | - $this->collection_details->collectionName(), |
|
262 | - $this->collection_details |
|
263 | - ); |
|
264 | - } |
|
248 | + 'event_espresso' |
|
249 | + ), |
|
250 | + $identifier_callback, |
|
251 | + get_class($entity) |
|
252 | + ) |
|
253 | + ); |
|
254 | + } |
|
255 | + $identifier = $entity->{$identifier_callback}(); |
|
256 | + break; |
|
257 | + } |
|
258 | + return apply_filters( |
|
259 | + 'FHEE__CollectionLoader__addEntityToCollection__identifier', |
|
260 | + $identifier, |
|
261 | + $this->collection_details->collectionName(), |
|
262 | + $this->collection_details |
|
263 | + ); |
|
264 | + } |
|
265 | 265 | |
266 | 266 | |
267 | - /** |
|
268 | - * @throws ReflectionException |
|
269 | - * @throws InvalidArgumentException |
|
270 | - * @throws InvalidInterfaceException |
|
271 | - * @throws EE_Error |
|
272 | - * @throws InvalidClassException |
|
273 | - * @throws InvalidDataTypeException |
|
274 | - * @throws InvalidEntityException |
|
275 | - * @throws DuplicateCollectionIdentifierException |
|
276 | - */ |
|
277 | - protected function loadFromFQCNs() |
|
278 | - { |
|
279 | - $FQCNs = $this->collection_details->getCollectionFQCNs(); |
|
280 | - $FQCNs = (array) apply_filters( |
|
281 | - 'FHEE__CollectionLoader__loadAllFromFQCNs__FQCNs', |
|
282 | - $FQCNs, |
|
283 | - $this->collection_details->collectionName(), |
|
284 | - $this->collection_details |
|
285 | - ); |
|
286 | - foreach ($FQCNs as $FQCN) { |
|
287 | - $this->loadClassFromFQCN($FQCN); |
|
288 | - } |
|
289 | - } |
|
267 | + /** |
|
268 | + * @throws ReflectionException |
|
269 | + * @throws InvalidArgumentException |
|
270 | + * @throws InvalidInterfaceException |
|
271 | + * @throws EE_Error |
|
272 | + * @throws InvalidClassException |
|
273 | + * @throws InvalidDataTypeException |
|
274 | + * @throws InvalidEntityException |
|
275 | + * @throws DuplicateCollectionIdentifierException |
|
276 | + */ |
|
277 | + protected function loadFromFQCNs() |
|
278 | + { |
|
279 | + $FQCNs = $this->collection_details->getCollectionFQCNs(); |
|
280 | + $FQCNs = (array) apply_filters( |
|
281 | + 'FHEE__CollectionLoader__loadAllFromFQCNs__FQCNs', |
|
282 | + $FQCNs, |
|
283 | + $this->collection_details->collectionName(), |
|
284 | + $this->collection_details |
|
285 | + ); |
|
286 | + foreach ($FQCNs as $FQCN) { |
|
287 | + $this->loadClassFromFQCN($FQCN); |
|
288 | + } |
|
289 | + } |
|
290 | 290 | |
291 | 291 | |
292 | - /** |
|
293 | - * @param string $FQCN Fully Qualified Class Name |
|
294 | - * @return string |
|
295 | - * @throws InvalidArgumentException |
|
296 | - * @throws InvalidInterfaceException |
|
297 | - * @throws ReflectionException |
|
298 | - * @throws EE_Error |
|
299 | - * @throws InvalidEntityException |
|
300 | - * @throws InvalidDataTypeException |
|
301 | - * @throws InvalidClassException |
|
302 | - * @throws DuplicateCollectionIdentifierException |
|
303 | - */ |
|
304 | - protected function loadClassFromFQCN($FQCN) |
|
305 | - { |
|
306 | - if (! is_string($FQCN)) { |
|
307 | - throw new InvalidDataTypeException('$FQCN', $FQCN, 'string'); |
|
308 | - } |
|
309 | - if (! class_exists($FQCN)) { |
|
310 | - throw new InvalidClassException($FQCN); |
|
311 | - } |
|
312 | - do_action( |
|
313 | - 'FHEE__CollectionLoader__loadClassFromFQCN__beforeLoading', |
|
314 | - $FQCN, |
|
315 | - $this->collection_details->collectionName(), |
|
316 | - $this->collection_details |
|
317 | - ); |
|
318 | - $entity = $this->entity_factory instanceof FactoryInterface |
|
319 | - ? call_user_func(array($this->entity_factory, 'create'), $FQCN) |
|
320 | - : EE_Registry::instance()->create($FQCN); |
|
321 | - return $this->addEntityToCollection($entity, $FQCN); |
|
322 | - } |
|
292 | + /** |
|
293 | + * @param string $FQCN Fully Qualified Class Name |
|
294 | + * @return string |
|
295 | + * @throws InvalidArgumentException |
|
296 | + * @throws InvalidInterfaceException |
|
297 | + * @throws ReflectionException |
|
298 | + * @throws EE_Error |
|
299 | + * @throws InvalidEntityException |
|
300 | + * @throws InvalidDataTypeException |
|
301 | + * @throws InvalidClassException |
|
302 | + * @throws DuplicateCollectionIdentifierException |
|
303 | + */ |
|
304 | + protected function loadClassFromFQCN($FQCN) |
|
305 | + { |
|
306 | + if (! is_string($FQCN)) { |
|
307 | + throw new InvalidDataTypeException('$FQCN', $FQCN, 'string'); |
|
308 | + } |
|
309 | + if (! class_exists($FQCN)) { |
|
310 | + throw new InvalidClassException($FQCN); |
|
311 | + } |
|
312 | + do_action( |
|
313 | + 'FHEE__CollectionLoader__loadClassFromFQCN__beforeLoading', |
|
314 | + $FQCN, |
|
315 | + $this->collection_details->collectionName(), |
|
316 | + $this->collection_details |
|
317 | + ); |
|
318 | + $entity = $this->entity_factory instanceof FactoryInterface |
|
319 | + ? call_user_func(array($this->entity_factory, 'create'), $FQCN) |
|
320 | + : EE_Registry::instance()->create($FQCN); |
|
321 | + return $this->addEntityToCollection($entity, $FQCN); |
|
322 | + } |
|
323 | 323 | } |
@@ -87,7 +87,7 @@ discard block |
||
87 | 87 | ) { |
88 | 88 | try { |
89 | 89 | $this->collection_details = $collection_details; |
90 | - if (! $collection instanceof CollectionInterface) { |
|
90 | + if ( ! $collection instanceof CollectionInterface) { |
|
91 | 91 | $collection = new Collection($this->collection_details->getCollectionInterface()); |
92 | 92 | } |
93 | 93 | $this->collection = $collection; |
@@ -119,7 +119,7 @@ discard block |
||
119 | 119 | */ |
120 | 120 | protected function loadAllFromFilepaths() |
121 | 121 | { |
122 | - if (! $this->file_locator instanceof FileLocator) { |
|
122 | + if ( ! $this->file_locator instanceof FileLocator) { |
|
123 | 123 | $this->file_locator = new FileLocator(); |
124 | 124 | } |
125 | 125 | $this->file_locator->setFileMask($this->collection_details->getFileMask()); |
@@ -152,10 +152,10 @@ discard block |
||
152 | 152 | */ |
153 | 153 | protected function loadClassFromFilepath($filepath) |
154 | 154 | { |
155 | - if (! is_string($filepath)) { |
|
155 | + if ( ! is_string($filepath)) { |
|
156 | 156 | throw new InvalidDataTypeException('$filepath', $filepath, 'string'); |
157 | 157 | } |
158 | - if (! is_readable($filepath)) { |
|
158 | + if ( ! is_readable($filepath)) { |
|
159 | 159 | throw new InvalidFilePathException($filepath); |
160 | 160 | } |
161 | 161 | require_once $filepath; |
@@ -163,7 +163,7 @@ discard block |
||
163 | 163 | $file_name = basename($filepath); |
164 | 164 | // now remove any file extensions |
165 | 165 | $class_name = EEH_File::get_classname_from_filepath_with_standard_filename($file_name); |
166 | - if (! class_exists($class_name)) { |
|
166 | + if ( ! class_exists($class_name)) { |
|
167 | 167 | throw new InvalidClassException($class_name); |
168 | 168 | } |
169 | 169 | $entity = $this->entity_factory instanceof FactoryInterface |
@@ -237,7 +237,7 @@ discard block |
||
237 | 237 | // objects added to the collection based on entity callback, so the entity itself decides |
238 | 238 | case CollectionDetails::ID_CALLBACK_METHOD: |
239 | 239 | $identifier_callback = $this->collection_details->identifierCallback(); |
240 | - if (! method_exists($entity, $identifier_callback)) { |
|
240 | + if ( ! method_exists($entity, $identifier_callback)) { |
|
241 | 241 | throw new InvalidEntityException( |
242 | 242 | $entity, |
243 | 243 | $this->collection_details->getCollectionInterface(), |
@@ -303,10 +303,10 @@ discard block |
||
303 | 303 | */ |
304 | 304 | protected function loadClassFromFQCN($FQCN) |
305 | 305 | { |
306 | - if (! is_string($FQCN)) { |
|
306 | + if ( ! is_string($FQCN)) { |
|
307 | 307 | throw new InvalidDataTypeException('$FQCN', $FQCN, 'string'); |
308 | 308 | } |
309 | - if (! class_exists($FQCN)) { |
|
309 | + if ( ! class_exists($FQCN)) { |
|
310 | 310 | throw new InvalidClassException($FQCN); |
311 | 311 | } |
312 | 312 | do_action( |
@@ -16,25 +16,25 @@ |
||
16 | 16 | class CollectionLoaderException extends RuntimeException |
17 | 17 | { |
18 | 18 | |
19 | - /** |
|
20 | - * DuplicateCollectionIdentifierException constructor. |
|
21 | - * |
|
22 | - * @param Exception $previous |
|
23 | - * @param string $message |
|
24 | - * @param int $code |
|
25 | - */ |
|
26 | - public function __construct(Exception $previous, $message = '', $code = 0) |
|
27 | - { |
|
28 | - if (empty($message)) { |
|
29 | - $message = sprintf( |
|
30 | - __( |
|
31 | - 'The following error occurred during the creation and/or loading of this collection: %1$s %2$s', |
|
32 | - 'event_espresso' |
|
33 | - ), |
|
34 | - '<br />', |
|
35 | - $previous->getMessage() |
|
36 | - ); |
|
37 | - } |
|
38 | - parent::__construct($message, $code, $previous); |
|
39 | - } |
|
19 | + /** |
|
20 | + * DuplicateCollectionIdentifierException constructor. |
|
21 | + * |
|
22 | + * @param Exception $previous |
|
23 | + * @param string $message |
|
24 | + * @param int $code |
|
25 | + */ |
|
26 | + public function __construct(Exception $previous, $message = '', $code = 0) |
|
27 | + { |
|
28 | + if (empty($message)) { |
|
29 | + $message = sprintf( |
|
30 | + __( |
|
31 | + 'The following error occurred during the creation and/or loading of this collection: %1$s %2$s', |
|
32 | + 'event_espresso' |
|
33 | + ), |
|
34 | + '<br />', |
|
35 | + $previous->getMessage() |
|
36 | + ); |
|
37 | + } |
|
38 | + parent::__construct($message, $code, $previous); |
|
39 | + } |
|
40 | 40 | } |
@@ -16,25 +16,25 @@ |
||
16 | 16 | class CollectionDetailsException extends RuntimeException |
17 | 17 | { |
18 | 18 | |
19 | - /** |
|
20 | - * DuplicateCollectionIdentifierException constructor. |
|
21 | - * |
|
22 | - * @param Exception $previous |
|
23 | - * @param string $message |
|
24 | - * @param int $code |
|
25 | - */ |
|
26 | - public function __construct(Exception $previous, $message = '', $code = 0) |
|
27 | - { |
|
28 | - if (empty($message)) { |
|
29 | - $message = sprintf( |
|
30 | - __( |
|
31 | - 'The following error occurred during the collection details generation: %1$s %2$s', |
|
32 | - 'event_espresso' |
|
33 | - ), |
|
34 | - '<br />', |
|
35 | - $previous->getMessage() |
|
36 | - ); |
|
37 | - } |
|
38 | - parent::__construct($message, $code, $previous); |
|
39 | - } |
|
19 | + /** |
|
20 | + * DuplicateCollectionIdentifierException constructor. |
|
21 | + * |
|
22 | + * @param Exception $previous |
|
23 | + * @param string $message |
|
24 | + * @param int $code |
|
25 | + */ |
|
26 | + public function __construct(Exception $previous, $message = '', $code = 0) |
|
27 | + { |
|
28 | + if (empty($message)) { |
|
29 | + $message = sprintf( |
|
30 | + __( |
|
31 | + 'The following error occurred during the collection details generation: %1$s %2$s', |
|
32 | + 'event_espresso' |
|
33 | + ), |
|
34 | + '<br />', |
|
35 | + $previous->getMessage() |
|
36 | + ); |
|
37 | + } |
|
38 | + parent::__construct($message, $code, $previous); |
|
39 | + } |
|
40 | 40 | } |
@@ -99,7 +99,7 @@ discard block |
||
99 | 99 | } |
100 | 100 | // If not, then attempt to deal with any errors, |
101 | 101 | // otherwise, try to hobble along without the session |
102 | - if (! $this->handleSessionSaveHandlerErrors()) { |
|
102 | + if ( ! $this->handleSessionSaveHandlerErrors()) { |
|
103 | 103 | return; |
104 | 104 | } |
105 | 105 | // there is no record of a fatal error while trying to start the session |
@@ -249,7 +249,7 @@ discard block |
||
249 | 249 | ), |
250 | 250 | '<a href="https://wordpress.org/plugins/wp-native-php-sessions/">', |
251 | 251 | '</a>', |
252 | - '<a href="' . $retry_session_url . '">' |
|
252 | + '<a href="'.$retry_session_url.'">' |
|
253 | 253 | ), |
254 | 254 | __FILE__, |
255 | 255 | __FUNCTION__, |
@@ -27,237 +27,237 @@ |
||
27 | 27 | */ |
28 | 28 | class SessionStartHandler |
29 | 29 | { |
30 | - const OPTION_NAME_SESSION_SAVE_HANDLER_STATUS = 'ee_session_save_handler_status'; |
|
31 | - const REQUEST_PARAM_RETRY_SESSION = 'ee_retry_session'; |
|
32 | - const SESSION_SAVE_HANDLER_STATUS_FAILED = 'session_save_handler_failed'; |
|
33 | - const SESSION_SAVE_HANDLER_STATUS_SUCCESS = 'session_save_handler_success'; |
|
34 | - const SESSION_SAVE_HANDLER_STATUS_UNKNOWN = 'session_save_handler_untested'; |
|
30 | + const OPTION_NAME_SESSION_SAVE_HANDLER_STATUS = 'ee_session_save_handler_status'; |
|
31 | + const REQUEST_PARAM_RETRY_SESSION = 'ee_retry_session'; |
|
32 | + const SESSION_SAVE_HANDLER_STATUS_FAILED = 'session_save_handler_failed'; |
|
33 | + const SESSION_SAVE_HANDLER_STATUS_SUCCESS = 'session_save_handler_success'; |
|
34 | + const SESSION_SAVE_HANDLER_STATUS_UNKNOWN = 'session_save_handler_untested'; |
|
35 | 35 | |
36 | - /** |
|
37 | - * @var RequestInterface $request |
|
38 | - */ |
|
39 | - protected $request; |
|
36 | + /** |
|
37 | + * @var RequestInterface $request |
|
38 | + */ |
|
39 | + protected $request; |
|
40 | 40 | |
41 | - /** |
|
42 | - * StartSession constructor. |
|
43 | - * |
|
44 | - * @param RequestInterface $request |
|
45 | - */ |
|
46 | - public function __construct(RequestInterface $request) |
|
47 | - { |
|
48 | - $this->request = $request; |
|
49 | - } |
|
41 | + /** |
|
42 | + * StartSession constructor. |
|
43 | + * |
|
44 | + * @param RequestInterface $request |
|
45 | + */ |
|
46 | + public function __construct(RequestInterface $request) |
|
47 | + { |
|
48 | + $this->request = $request; |
|
49 | + } |
|
50 | 50 | |
51 | - /** |
|
52 | - * Check if a custom session save handler is in play |
|
53 | - * and attempt to start the PHP session |
|
54 | - * |
|
55 | - * @since 4.9.68.p |
|
56 | - */ |
|
57 | - public function startSession() |
|
58 | - { |
|
59 | - // check that session has started |
|
60 | - if (session_id() === '') { |
|
61 | - // starts a new session if one doesn't already exist, or re-initiates an existing one |
|
62 | - if ($this->hasKnownCustomSessionSaveHandler()) { |
|
63 | - $this->checkCustomSessionSaveHandler(); |
|
64 | - } else { |
|
65 | - session_start(); |
|
66 | - session_write_close(); |
|
67 | - } |
|
68 | - } |
|
69 | - } |
|
51 | + /** |
|
52 | + * Check if a custom session save handler is in play |
|
53 | + * and attempt to start the PHP session |
|
54 | + * |
|
55 | + * @since 4.9.68.p |
|
56 | + */ |
|
57 | + public function startSession() |
|
58 | + { |
|
59 | + // check that session has started |
|
60 | + if (session_id() === '') { |
|
61 | + // starts a new session if one doesn't already exist, or re-initiates an existing one |
|
62 | + if ($this->hasKnownCustomSessionSaveHandler()) { |
|
63 | + $this->checkCustomSessionSaveHandler(); |
|
64 | + } else { |
|
65 | + session_start(); |
|
66 | + session_write_close(); |
|
67 | + } |
|
68 | + } |
|
69 | + } |
|
70 | 70 | |
71 | - /** |
|
72 | - * Returns `true` if the 'session.save_handler' ini setting matches a known custom handler |
|
73 | - * |
|
74 | - * @since 4.9.68.p |
|
75 | - * @return bool |
|
76 | - */ |
|
77 | - private function hasKnownCustomSessionSaveHandler() |
|
78 | - { |
|
79 | - return in_array( |
|
80 | - ini_get('session.save_handler'), |
|
81 | - array( |
|
82 | - 'user', |
|
83 | - ), |
|
84 | - true |
|
85 | - ); |
|
86 | - } |
|
71 | + /** |
|
72 | + * Returns `true` if the 'session.save_handler' ini setting matches a known custom handler |
|
73 | + * |
|
74 | + * @since 4.9.68.p |
|
75 | + * @return bool |
|
76 | + */ |
|
77 | + private function hasKnownCustomSessionSaveHandler() |
|
78 | + { |
|
79 | + return in_array( |
|
80 | + ini_get('session.save_handler'), |
|
81 | + array( |
|
82 | + 'user', |
|
83 | + ), |
|
84 | + true |
|
85 | + ); |
|
86 | + } |
|
87 | 87 | |
88 | - /** |
|
89 | - * Attempt to start the PHP session when a custom Session Save Handler is known to be set. |
|
90 | - * |
|
91 | - * @since 4.9.68.p |
|
92 | - */ |
|
93 | - private function checkCustomSessionSaveHandler() |
|
94 | - { |
|
95 | - // If we've already successfully tested the session save handler |
|
96 | - // on a previous request then just start the session |
|
97 | - if ($this->sessionSaveHandlerIsValid()) { |
|
98 | - session_start(); |
|
99 | - session_write_close(); |
|
100 | - return; |
|
101 | - } |
|
102 | - // If not, then attempt to deal with any errors, |
|
103 | - // otherwise, try to hobble along without the session |
|
104 | - if (! $this->handleSessionSaveHandlerErrors()) { |
|
105 | - return; |
|
106 | - } |
|
107 | - // there is no record of a fatal error while trying to start the session |
|
108 | - // so let's see if there's a custom session save handler. Proceed with caution |
|
109 | - $this->initializeSessionSaveHandlerStatus(); |
|
110 | - // hold your breath, the custom session save handler might cause a fatal here... |
|
111 | - session_start(); |
|
112 | - session_write_close(); |
|
113 | - // phew! we made it! the custom session handler is a-ok |
|
114 | - $this->setSessionSaveHandlerStatusToValid(); |
|
115 | - } |
|
88 | + /** |
|
89 | + * Attempt to start the PHP session when a custom Session Save Handler is known to be set. |
|
90 | + * |
|
91 | + * @since 4.9.68.p |
|
92 | + */ |
|
93 | + private function checkCustomSessionSaveHandler() |
|
94 | + { |
|
95 | + // If we've already successfully tested the session save handler |
|
96 | + // on a previous request then just start the session |
|
97 | + if ($this->sessionSaveHandlerIsValid()) { |
|
98 | + session_start(); |
|
99 | + session_write_close(); |
|
100 | + return; |
|
101 | + } |
|
102 | + // If not, then attempt to deal with any errors, |
|
103 | + // otherwise, try to hobble along without the session |
|
104 | + if (! $this->handleSessionSaveHandlerErrors()) { |
|
105 | + return; |
|
106 | + } |
|
107 | + // there is no record of a fatal error while trying to start the session |
|
108 | + // so let's see if there's a custom session save handler. Proceed with caution |
|
109 | + $this->initializeSessionSaveHandlerStatus(); |
|
110 | + // hold your breath, the custom session save handler might cause a fatal here... |
|
111 | + session_start(); |
|
112 | + session_write_close(); |
|
113 | + // phew! we made it! the custom session handler is a-ok |
|
114 | + $this->setSessionSaveHandlerStatusToValid(); |
|
115 | + } |
|
116 | 116 | |
117 | 117 | |
118 | - /** |
|
119 | - * retrieves the value for the 'ee_session_save_handler_status' WP option. |
|
120 | - * default value = 'session_save_handler_untested' |
|
121 | - * |
|
122 | - * @since 4.9.68.p |
|
123 | - * @return string |
|
124 | - */ |
|
125 | - private function getSessionSaveHandlerStatus() |
|
126 | - { |
|
127 | - return get_option( |
|
128 | - SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
129 | - SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_UNKNOWN |
|
130 | - ); |
|
131 | - } |
|
118 | + /** |
|
119 | + * retrieves the value for the 'ee_session_save_handler_status' WP option. |
|
120 | + * default value = 'session_save_handler_untested' |
|
121 | + * |
|
122 | + * @since 4.9.68.p |
|
123 | + * @return string |
|
124 | + */ |
|
125 | + private function getSessionSaveHandlerStatus() |
|
126 | + { |
|
127 | + return get_option( |
|
128 | + SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
129 | + SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_UNKNOWN |
|
130 | + ); |
|
131 | + } |
|
132 | 132 | |
133 | - /** |
|
134 | - * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_failed' |
|
135 | - * which can then be upgraded is everything works correctly |
|
136 | - * |
|
137 | - * @since 4.9.68.p |
|
138 | - * @return bool |
|
139 | - */ |
|
140 | - private function initializeSessionSaveHandlerStatus() |
|
141 | - { |
|
142 | - return update_option( |
|
143 | - SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
144 | - SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_FAILED |
|
145 | - ); |
|
146 | - } |
|
133 | + /** |
|
134 | + * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_failed' |
|
135 | + * which can then be upgraded is everything works correctly |
|
136 | + * |
|
137 | + * @since 4.9.68.p |
|
138 | + * @return bool |
|
139 | + */ |
|
140 | + private function initializeSessionSaveHandlerStatus() |
|
141 | + { |
|
142 | + return update_option( |
|
143 | + SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
144 | + SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_FAILED |
|
145 | + ); |
|
146 | + } |
|
147 | 147 | |
148 | - /** |
|
149 | - * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_success' |
|
150 | - * |
|
151 | - * @since 4.9.68.p |
|
152 | - * @return bool |
|
153 | - */ |
|
154 | - private function setSessionSaveHandlerStatusToValid() |
|
155 | - { |
|
156 | - return update_option( |
|
157 | - SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
158 | - SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_SUCCESS |
|
159 | - ); |
|
160 | - } |
|
148 | + /** |
|
149 | + * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_success' |
|
150 | + * |
|
151 | + * @since 4.9.68.p |
|
152 | + * @return bool |
|
153 | + */ |
|
154 | + private function setSessionSaveHandlerStatusToValid() |
|
155 | + { |
|
156 | + return update_option( |
|
157 | + SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
158 | + SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_SUCCESS |
|
159 | + ); |
|
160 | + } |
|
161 | 161 | |
162 | - /** |
|
163 | - * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_untested' |
|
164 | - * |
|
165 | - * @since 4.9.68.p |
|
166 | - * @return bool |
|
167 | - */ |
|
168 | - private function resetSessionSaveHandlerStatus() |
|
169 | - { |
|
170 | - return update_option( |
|
171 | - SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
172 | - SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_UNKNOWN |
|
173 | - ); |
|
174 | - } |
|
162 | + /** |
|
163 | + * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_untested' |
|
164 | + * |
|
165 | + * @since 4.9.68.p |
|
166 | + * @return bool |
|
167 | + */ |
|
168 | + private function resetSessionSaveHandlerStatus() |
|
169 | + { |
|
170 | + return update_option( |
|
171 | + SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, |
|
172 | + SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_UNKNOWN |
|
173 | + ); |
|
174 | + } |
|
175 | 175 | |
176 | - /** |
|
177 | - * Returns `true` if the 'ee_session_save_handler_status' WP option value |
|
178 | - * is equal to 'session_save_handler_success' |
|
179 | - * |
|
180 | - * @since 4.9.68.p |
|
181 | - * @return bool |
|
182 | - */ |
|
183 | - private function sessionSaveHandlerIsValid() |
|
184 | - { |
|
185 | - return $this->getSessionSaveHandlerStatus() === SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_SUCCESS; |
|
186 | - } |
|
176 | + /** |
|
177 | + * Returns `true` if the 'ee_session_save_handler_status' WP option value |
|
178 | + * is equal to 'session_save_handler_success' |
|
179 | + * |
|
180 | + * @since 4.9.68.p |
|
181 | + * @return bool |
|
182 | + */ |
|
183 | + private function sessionSaveHandlerIsValid() |
|
184 | + { |
|
185 | + return $this->getSessionSaveHandlerStatus() === SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_SUCCESS; |
|
186 | + } |
|
187 | 187 | |
188 | - /** |
|
189 | - * Returns `true` if the 'ee_session_save_handler_status' WP option value |
|
190 | - * is equal to 'session_save_handler_failed' |
|
191 | - * |
|
192 | - * @since 4.9.68.p |
|
193 | - * @return bool |
|
194 | - */ |
|
195 | - private function sessionSaveHandlerFailed() |
|
196 | - { |
|
197 | - return $this->getSessionSaveHandlerStatus() === SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_FAILED; |
|
198 | - } |
|
188 | + /** |
|
189 | + * Returns `true` if the 'ee_session_save_handler_status' WP option value |
|
190 | + * is equal to 'session_save_handler_failed' |
|
191 | + * |
|
192 | + * @since 4.9.68.p |
|
193 | + * @return bool |
|
194 | + */ |
|
195 | + private function sessionSaveHandlerFailed() |
|
196 | + { |
|
197 | + return $this->getSessionSaveHandlerStatus() === SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_FAILED; |
|
198 | + } |
|
199 | 199 | |
200 | - /** |
|
201 | - * Returns `true` if no errors were detected with the session save handler, |
|
202 | - * otherwise attempts to work notify the appropriate authorities |
|
203 | - * with a suggestion for how to fix the issue, and returns `false`. |
|
204 | - * |
|
205 | - * |
|
206 | - * @since 4.9.68.p |
|
207 | - * @return bool |
|
208 | - */ |
|
209 | - private function handleSessionSaveHandlerErrors() |
|
210 | - { |
|
211 | - // Check if we had a fatal error last time while trying to start the session |
|
212 | - if ($this->sessionSaveHandlerFailed()) { |
|
213 | - // apparently, last time we tried using the custom session save handler there was a fatal |
|
214 | - if ($this->request->requestParamIsSet(SessionStartHandler::REQUEST_PARAM_RETRY_SESSION)) { |
|
215 | - $this->resetSessionSaveHandlerStatus(); |
|
216 | - // remove "ee_retry_session", otherwise if the problem still isn't fixed, |
|
217 | - // we'll just keep getting the fatal error over and over. |
|
218 | - // Better to remove it and redirect, and try on the next request |
|
219 | - EEH_URL::safeRedirectAndExit( |
|
220 | - remove_query_arg( |
|
221 | - array(SessionStartHandler::REQUEST_PARAM_RETRY_SESSION), |
|
222 | - EEH_URL::current_url() |
|
223 | - ) |
|
224 | - ); |
|
225 | - } |
|
226 | - // so the session is broken, don't try it again, |
|
227 | - // just show a message to users that can fix it |
|
228 | - $this->displaySessionSaveHandlerErrorNotice(); |
|
229 | - return false; |
|
230 | - } |
|
231 | - return true; |
|
232 | - } |
|
200 | + /** |
|
201 | + * Returns `true` if no errors were detected with the session save handler, |
|
202 | + * otherwise attempts to work notify the appropriate authorities |
|
203 | + * with a suggestion for how to fix the issue, and returns `false`. |
|
204 | + * |
|
205 | + * |
|
206 | + * @since 4.9.68.p |
|
207 | + * @return bool |
|
208 | + */ |
|
209 | + private function handleSessionSaveHandlerErrors() |
|
210 | + { |
|
211 | + // Check if we had a fatal error last time while trying to start the session |
|
212 | + if ($this->sessionSaveHandlerFailed()) { |
|
213 | + // apparently, last time we tried using the custom session save handler there was a fatal |
|
214 | + if ($this->request->requestParamIsSet(SessionStartHandler::REQUEST_PARAM_RETRY_SESSION)) { |
|
215 | + $this->resetSessionSaveHandlerStatus(); |
|
216 | + // remove "ee_retry_session", otherwise if the problem still isn't fixed, |
|
217 | + // we'll just keep getting the fatal error over and over. |
|
218 | + // Better to remove it and redirect, and try on the next request |
|
219 | + EEH_URL::safeRedirectAndExit( |
|
220 | + remove_query_arg( |
|
221 | + array(SessionStartHandler::REQUEST_PARAM_RETRY_SESSION), |
|
222 | + EEH_URL::current_url() |
|
223 | + ) |
|
224 | + ); |
|
225 | + } |
|
226 | + // so the session is broken, don't try it again, |
|
227 | + // just show a message to users that can fix it |
|
228 | + $this->displaySessionSaveHandlerErrorNotice(); |
|
229 | + return false; |
|
230 | + } |
|
231 | + return true; |
|
232 | + } |
|
233 | 233 | |
234 | - /** |
|
235 | - * Generates an EE_Error notice regarding the current session woes |
|
236 | - * but only if the current user is an admin with permission to 'install_plugins'. |
|
237 | - * |
|
238 | - * @since 4.9.68.p |
|
239 | - */ |
|
240 | - private function displaySessionSaveHandlerErrorNotice() |
|
241 | - { |
|
242 | - if (current_user_can('install_plugins')) { |
|
243 | - $retry_session_url = add_query_arg( |
|
244 | - array(SessionStartHandler::REQUEST_PARAM_RETRY_SESSION => true), |
|
245 | - EEH_URL::current_url() |
|
246 | - ); |
|
247 | - EE_Error::add_error( |
|
248 | - sprintf( |
|
249 | - esc_html__( |
|
250 | - 'It appears there was a fatal error while starting the session, so Event Espresso is not able to process registrations normally. Some hosting companies, like Pantheon, require an extra plugin for Event Espresso to work. Please install the %1$sWordPress Native PHP Sessions plugin%2$s, then %3$sclick here to check if the problem is resolved.%2$s', |
|
251 | - 'event_espresso' |
|
252 | - ), |
|
253 | - '<a href="https://wordpress.org/plugins/wp-native-php-sessions/">', |
|
254 | - '</a>', |
|
255 | - '<a href="' . $retry_session_url . '">' |
|
256 | - ), |
|
257 | - __FILE__, |
|
258 | - __FUNCTION__, |
|
259 | - __LINE__ |
|
260 | - ); |
|
261 | - } |
|
262 | - } |
|
234 | + /** |
|
235 | + * Generates an EE_Error notice regarding the current session woes |
|
236 | + * but only if the current user is an admin with permission to 'install_plugins'. |
|
237 | + * |
|
238 | + * @since 4.9.68.p |
|
239 | + */ |
|
240 | + private function displaySessionSaveHandlerErrorNotice() |
|
241 | + { |
|
242 | + if (current_user_can('install_plugins')) { |
|
243 | + $retry_session_url = add_query_arg( |
|
244 | + array(SessionStartHandler::REQUEST_PARAM_RETRY_SESSION => true), |
|
245 | + EEH_URL::current_url() |
|
246 | + ); |
|
247 | + EE_Error::add_error( |
|
248 | + sprintf( |
|
249 | + esc_html__( |
|
250 | + 'It appears there was a fatal error while starting the session, so Event Espresso is not able to process registrations normally. Some hosting companies, like Pantheon, require an extra plugin for Event Espresso to work. Please install the %1$sWordPress Native PHP Sessions plugin%2$s, then %3$sclick here to check if the problem is resolved.%2$s', |
|
251 | + 'event_espresso' |
|
252 | + ), |
|
253 | + '<a href="https://wordpress.org/plugins/wp-native-php-sessions/">', |
|
254 | + '</a>', |
|
255 | + '<a href="' . $retry_session_url . '">' |
|
256 | + ), |
|
257 | + __FILE__, |
|
258 | + __FUNCTION__, |
|
259 | + __LINE__ |
|
260 | + ); |
|
261 | + } |
|
262 | + } |
|
263 | 263 | } |
@@ -171,9 +171,9 @@ discard block |
||
171 | 171 | 'order_by' => $this->_get_priority_orderby(), |
172 | 172 | 'limit' => $this->_batch_count, |
173 | 173 | ); |
174 | - $messages = EEM_Message::instance()->get_all($query_args); |
|
174 | + $messages = EEM_Message::instance()->get_all($query_args); |
|
175 | 175 | |
176 | - if (! $messages) { |
|
176 | + if ( ! $messages) { |
|
177 | 177 | return false; // nothing to generate |
178 | 178 | } |
179 | 179 | |
@@ -227,7 +227,7 @@ discard block |
||
227 | 227 | |
228 | 228 | |
229 | 229 | // any to send? |
230 | - if (! $messages_to_send) { |
|
230 | + if ( ! $messages_to_send) { |
|
231 | 231 | $this->unlock_queue(EE_Messages_Queue::action_sending); |
232 | 232 | return false; |
233 | 233 | } |
@@ -283,7 +283,7 @@ discard block |
||
283 | 283 | */ |
284 | 284 | protected function _get_lock_key($type = EE_Messages_Queue::action_generating) |
285 | 285 | { |
286 | - return '_ee_lock_' . $type; |
|
286 | + return '_ee_lock_'.$type; |
|
287 | 287 | } |
288 | 288 | |
289 | 289 | |
@@ -355,7 +355,7 @@ discard block |
||
355 | 355 | */ |
356 | 356 | public function is_locked($type = EE_Messages_Queue::action_generating) |
357 | 357 | { |
358 | - if (! EE_Maintenance_Mode::instance()->models_can_query()) { |
|
358 | + if ( ! EE_Maintenance_Mode::instance()->models_can_query()) { |
|
359 | 359 | return true; |
360 | 360 | } |
361 | 361 | $lock = (int) get_option($this->_get_lock_key($type), 0); |
@@ -505,7 +505,7 @@ discard block |
||
505 | 505 | /** @type EE_Message $message */ |
506 | 506 | $message = $this->_message_repository->current(); |
507 | 507 | // only process things that are queued for sending |
508 | - if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) { |
|
508 | + if ( ! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) { |
|
509 | 509 | $this->_message_repository->next(); |
510 | 510 | continue; |
511 | 511 | } |
@@ -515,13 +515,13 @@ discard block |
||
515 | 515 | continue; |
516 | 516 | } |
517 | 517 | // error checking |
518 | - if (! $message->valid_messenger()) { |
|
518 | + if ( ! $message->valid_messenger()) { |
|
519 | 519 | $error_messages[] = sprintf( |
520 | 520 | __('The %s messenger is not active at time of sending.', 'event_espresso'), |
521 | 521 | $message->messenger() |
522 | 522 | ); |
523 | 523 | } |
524 | - if (! $message->valid_message_type()) { |
|
524 | + if ( ! $message->valid_message_type()) { |
|
525 | 525 | $error_messages[] = sprintf( |
526 | 526 | __('The %s message type is not active at the time of sending.', 'event_espresso'), |
527 | 527 | $message->message_type() |
@@ -582,9 +582,9 @@ discard block |
||
582 | 582 | // send using messenger, but double check objects |
583 | 583 | if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) { |
584 | 584 | // set hook for message type (but only if not using another messenger to send). |
585 | - if (! isset($this->_did_hook[ $message_type->name ])) { |
|
585 | + if ( ! isset($this->_did_hook[$message_type->name])) { |
|
586 | 586 | $message_type->do_messenger_hooks($messenger); |
587 | - $this->_did_hook[ $message_type->name ] = 1; |
|
587 | + $this->_did_hook[$message_type->name] = 1; |
|
588 | 588 | } |
589 | 589 | // if preview then use preview method |
590 | 590 | return $this->_message_repository->is_preview() |
@@ -635,7 +635,7 @@ discard block |
||
635 | 635 | $test_send |
636 | 636 | ) { |
637 | 637 | if ($preview = $messenger->get_preview($message, $message_type, $test_send)) { |
638 | - if (! $test_send) { |
|
638 | + if ( ! $test_send) { |
|
639 | 639 | $message->set_content($preview); |
640 | 640 | } |
641 | 641 | $message->set_STS_ID(EEM_Message::status_sent); |
@@ -700,7 +700,7 @@ discard block |
||
700 | 700 | } |
701 | 701 | if (count($error_messages) > 0) { |
702 | 702 | $msg = __('Message was not executed successfully.', 'event_espresso'); |
703 | - $msg = $msg . "\n" . implode("\n", $error_messages); |
|
703 | + $msg = $msg."\n".implode("\n", $error_messages); |
|
704 | 704 | $message->set_error_message($msg); |
705 | 705 | } |
706 | 706 | } |
@@ -15,699 +15,699 @@ |
||
15 | 15 | { |
16 | 16 | |
17 | 17 | |
18 | - /** |
|
19 | - * @type string reference for sending action |
|
20 | - */ |
|
21 | - const action_sending = 'sending'; |
|
22 | - |
|
23 | - /** |
|
24 | - * @type string reference for generation action |
|
25 | - */ |
|
26 | - const action_generating = 'generation'; |
|
27 | - |
|
28 | - |
|
29 | - /** |
|
30 | - * @type EE_Message_Repository $_message_repository |
|
31 | - */ |
|
32 | - protected $_message_repository; |
|
33 | - |
|
34 | - /** |
|
35 | - * Sets the limit of how many messages are generated per process. |
|
36 | - * |
|
37 | - * @type int |
|
38 | - */ |
|
39 | - protected $_batch_count; |
|
40 | - |
|
41 | - |
|
42 | - /** |
|
43 | - * This is an array of cached queue items being stored in this object. |
|
44 | - * The array keys will be the ID of the EE_Message in the db if saved. If the EE_Message |
|
45 | - * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.) |
|
46 | - * |
|
47 | - * @type EE_Message[] |
|
48 | - */ |
|
49 | - protected $_cached_queue_items; |
|
50 | - |
|
51 | - /** |
|
52 | - * Tracks the number of unsaved queue items. |
|
53 | - * |
|
54 | - * @type int |
|
55 | - */ |
|
56 | - protected $_unsaved_count = 0; |
|
57 | - |
|
58 | - /** |
|
59 | - * used to record if a do_messenger_hooks has already been called for a message type. This prevents multiple |
|
60 | - * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls. |
|
61 | - * |
|
62 | - * @type array |
|
63 | - */ |
|
64 | - protected $_did_hook = array(); |
|
65 | - |
|
66 | - |
|
67 | - /** |
|
68 | - * Constructor. |
|
69 | - * Setup all the initial properties and load a EE_Message_Repository. |
|
70 | - * |
|
71 | - * @param \EE_Message_Repository $message_repository |
|
72 | - */ |
|
73 | - public function __construct(EE_Message_Repository $message_repository) |
|
74 | - { |
|
75 | - $this->_batch_count = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50); |
|
76 | - $this->_message_repository = $message_repository; |
|
77 | - } |
|
78 | - |
|
79 | - |
|
80 | - /** |
|
81 | - * Add a EE_Message object to the queue |
|
82 | - * |
|
83 | - * @param EE_Message $message |
|
84 | - * @param array $data This will be an array of data to attach to the object in the repository. If the |
|
85 | - * object is persisted, this data will be saved on an extra_meta object related to |
|
86 | - * EE_Message. |
|
87 | - * @param bool $preview Whether this EE_Message represents a preview or not. |
|
88 | - * @param bool $test_send This indicates whether to do a test send instead of actual send. A test send will |
|
89 | - * use the messenger send method but typically is based on preview data. |
|
90 | - * @return bool Whether the message was successfully added to the repository or not. |
|
91 | - */ |
|
92 | - public function add(EE_Message $message, $data = array(), $preview = false, $test_send = false) |
|
93 | - { |
|
94 | - $data['preview'] = $preview; |
|
95 | - $data['test_send'] = $test_send; |
|
96 | - return $this->_message_repository->add($message, $data); |
|
97 | - } |
|
98 | - |
|
99 | - |
|
100 | - /** |
|
101 | - * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message |
|
102 | - * |
|
103 | - * @param EE_Message $message The message to detach from the queue |
|
104 | - * @param bool $persist This flag indicates whether to attempt to delete the object from the db as well. |
|
105 | - * @return bool |
|
106 | - */ |
|
107 | - public function remove(EE_Message $message, $persist = false) |
|
108 | - { |
|
109 | - if ($persist && $this->_message_repository->current() !== $message) { |
|
110 | - // get pointer on right message |
|
111 | - if ($this->_message_repository->has($message)) { |
|
112 | - $this->_message_repository->rewind(); |
|
113 | - while ($this->_message_repository->valid()) { |
|
114 | - if ($this->_message_repository->current() === $message) { |
|
115 | - break; |
|
116 | - } |
|
117 | - $this->_message_repository->next(); |
|
118 | - } |
|
119 | - } else { |
|
120 | - return false; |
|
121 | - } |
|
122 | - } |
|
123 | - return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message); |
|
124 | - } |
|
125 | - |
|
126 | - |
|
127 | - /** |
|
128 | - * Persists all queued EE_Message objects to the db. |
|
129 | - * |
|
130 | - * @param bool $do_hooks_only @see EE_Message_Repository::saveAll |
|
131 | - * @return array @see EE_Messages_Repository::saveAll() for return values. |
|
132 | - */ |
|
133 | - public function save($do_hooks_only = false) |
|
134 | - { |
|
135 | - return $this->_message_repository->saveAll($do_hooks_only); |
|
136 | - } |
|
137 | - |
|
138 | - |
|
139 | - /** |
|
140 | - * @return EE_Message_Repository |
|
141 | - */ |
|
142 | - public function get_message_repository() |
|
143 | - { |
|
144 | - return $this->_message_repository; |
|
145 | - } |
|
146 | - |
|
147 | - |
|
148 | - /** |
|
149 | - * This does the following things: |
|
150 | - * 1. Checks if there is a lock on generation (prevents race conditions). If there is a lock then exits (return |
|
151 | - * false). |
|
152 | - * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue |
|
153 | - * 3. Returns bool. True = batch ready. False = no batch ready (or nothing available for generation). |
|
154 | - * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from |
|
155 | - * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not |
|
156 | - * removed. |
|
157 | - * |
|
158 | - * @return bool true if successfully retrieved batch, false no batch ready. |
|
159 | - */ |
|
160 | - public function get_batch_to_generate() |
|
161 | - { |
|
162 | - if ($this->is_locked(EE_Messages_Queue::action_generating)) { |
|
163 | - return false; |
|
164 | - } |
|
165 | - |
|
166 | - // lock batch generation to prevent race conditions. |
|
167 | - $this->lock_queue(EE_Messages_Queue::action_generating); |
|
168 | - |
|
169 | - $query_args = array( |
|
170 | - // key 0 = where conditions |
|
171 | - 0 => array('STS_ID' => EEM_Message::status_incomplete), |
|
172 | - 'order_by' => $this->_get_priority_orderby(), |
|
173 | - 'limit' => $this->_batch_count, |
|
174 | - ); |
|
175 | - $messages = EEM_Message::instance()->get_all($query_args); |
|
176 | - |
|
177 | - if (! $messages) { |
|
178 | - return false; // nothing to generate |
|
179 | - } |
|
180 | - |
|
181 | - foreach ($messages as $message) { |
|
182 | - if ($message instanceof EE_Message) { |
|
183 | - $data = $message->all_extra_meta_array(); |
|
184 | - $this->add($message, $data); |
|
185 | - } |
|
186 | - } |
|
187 | - return true; |
|
188 | - } |
|
189 | - |
|
190 | - |
|
191 | - /** |
|
192 | - * This does the following things: |
|
193 | - * 1. Checks if there is a lock on sending (prevents race conditions). If there is a lock then exits (return |
|
194 | - * false). |
|
195 | - * 2. Grabs the allowed number of messages to send for the rate_limit. If cannot send any more messages, then |
|
196 | - * return false. |
|
197 | - * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution. |
|
198 | - * 3. On success or unsuccessful send, sets status appropriately. |
|
199 | - * 4. Saves messages via the queue |
|
200 | - * 5. Releases lock. |
|
201 | - * |
|
202 | - * @return bool true on success, false if something preventing sending (i.e. lock set). Note: true does not |
|
203 | - * necessarily mean that all messages were successfully sent. It just means that this method |
|
204 | - * successfully completed. On true, client may want to call $this->count_STS_in_queue( |
|
205 | - * EEM_Message::status_failed ) to see if any failed EE_Message objects. Each failed message object |
|
206 | - * will also have a saved error message on it to assist with notifying user. |
|
207 | - */ |
|
208 | - public function get_to_send_batch_and_send() |
|
209 | - { |
|
210 | - $rate_limit = $this->get_rate_limit(); |
|
211 | - if ( |
|
212 | - $rate_limit < 1 |
|
213 | - || $this->is_locked(EE_Messages_Queue::action_sending) |
|
214 | - ) { |
|
215 | - return false; |
|
216 | - } |
|
217 | - |
|
218 | - $this->lock_queue(EE_Messages_Queue::action_sending); |
|
219 | - |
|
220 | - $batch = $this->_batch_count < $rate_limit ? $this->_batch_count : $rate_limit; |
|
221 | - |
|
222 | - $query_args = array( |
|
223 | - // key 0 = where conditions |
|
224 | - 0 => array('STS_ID' => array('IN', EEM_Message::instance()->stati_indicating_to_send())), |
|
225 | - 'order_by' => $this->_get_priority_orderby(), |
|
226 | - 'limit' => $batch, |
|
227 | - ); |
|
228 | - |
|
229 | - $messages_to_send = EEM_Message::instance()->get_all($query_args); |
|
230 | - |
|
231 | - |
|
232 | - // any to send? |
|
233 | - if (! $messages_to_send) { |
|
234 | - $this->unlock_queue(EE_Messages_Queue::action_sending); |
|
235 | - return false; |
|
236 | - } |
|
237 | - |
|
238 | - $queue_count = 0; |
|
239 | - |
|
240 | - // add to queue. |
|
241 | - foreach ($messages_to_send as $message) { |
|
242 | - if ($message instanceof EE_Message) { |
|
243 | - $queue_count++; |
|
244 | - $this->add($message); |
|
245 | - } |
|
246 | - } |
|
247 | - |
|
248 | - // send messages (this also updates the rate limit) |
|
249 | - $this->execute(); |
|
250 | - |
|
251 | - // release lock |
|
252 | - $this->unlock_queue(EE_Messages_Queue::action_sending); |
|
253 | - // update rate limit |
|
254 | - $this->set_rate_limit($queue_count); |
|
255 | - return true; |
|
256 | - } |
|
257 | - |
|
258 | - |
|
259 | - /** |
|
260 | - * Locks the queue so that no other queues can call the "batch" methods. |
|
261 | - * |
|
262 | - * @param string $type The type of queue being locked. |
|
263 | - */ |
|
264 | - public function lock_queue($type = EE_Messages_Queue::action_generating) |
|
265 | - { |
|
266 | - update_option($this->_get_lock_key($type), $this->_get_lock_expiry($type)); |
|
267 | - } |
|
268 | - |
|
269 | - |
|
270 | - /** |
|
271 | - * Unlocks the queue so that batch methods can be used. |
|
272 | - * |
|
273 | - * @param string $type The type of queue being unlocked. |
|
274 | - */ |
|
275 | - public function unlock_queue($type = EE_Messages_Queue::action_generating) |
|
276 | - { |
|
277 | - delete_option($this->_get_lock_key($type)); |
|
278 | - } |
|
279 | - |
|
280 | - |
|
281 | - /** |
|
282 | - * Retrieve the key used for the lock transient. |
|
283 | - * |
|
284 | - * @param string $type The type of lock. |
|
285 | - * @return string |
|
286 | - */ |
|
287 | - protected function _get_lock_key($type = EE_Messages_Queue::action_generating) |
|
288 | - { |
|
289 | - return '_ee_lock_' . $type; |
|
290 | - } |
|
291 | - |
|
292 | - |
|
293 | - /** |
|
294 | - * Retrieve the expiry time for the lock transient. |
|
295 | - * |
|
296 | - * @param string $type The type of lock |
|
297 | - * @return int time to expiry in seconds. |
|
298 | - */ |
|
299 | - protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating) |
|
300 | - { |
|
301 | - return time() + (int) apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type); |
|
302 | - } |
|
303 | - |
|
304 | - |
|
305 | - /** |
|
306 | - * Returns the key used for rate limit transient. |
|
307 | - * |
|
308 | - * @return string |
|
309 | - */ |
|
310 | - protected function _get_rate_limit_key() |
|
311 | - { |
|
312 | - return '_ee_rate_limit'; |
|
313 | - } |
|
314 | - |
|
315 | - |
|
316 | - /** |
|
317 | - * Returns the rate limit expiry time. |
|
318 | - * |
|
319 | - * @return int |
|
320 | - */ |
|
321 | - protected function _get_rate_limit_expiry() |
|
322 | - { |
|
323 | - return time() + (int) apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS); |
|
324 | - } |
|
325 | - |
|
326 | - |
|
327 | - /** |
|
328 | - * Returns the default rate limit for sending messages. |
|
329 | - * |
|
330 | - * @return int |
|
331 | - */ |
|
332 | - protected function _default_rate_limit() |
|
333 | - { |
|
334 | - return (int) apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200); |
|
335 | - } |
|
336 | - |
|
337 | - |
|
338 | - /** |
|
339 | - * Return the orderby array for priority. |
|
340 | - * |
|
341 | - * @return array |
|
342 | - */ |
|
343 | - protected function _get_priority_orderby() |
|
344 | - { |
|
345 | - return array( |
|
346 | - 'MSG_priority' => 'ASC', |
|
347 | - 'MSG_modified' => 'DESC', |
|
348 | - ); |
|
349 | - } |
|
350 | - |
|
351 | - |
|
352 | - /** |
|
353 | - * Returns whether batch methods are "locked" or not, and if models an currently be used to query the database. |
|
354 | - * Return true when batch methods should not be used; returns false when they can be. |
|
355 | - * |
|
356 | - * @param string $type The type of lock being checked for. |
|
357 | - * @return bool |
|
358 | - */ |
|
359 | - public function is_locked($type = EE_Messages_Queue::action_generating) |
|
360 | - { |
|
361 | - if (! EE_Maintenance_Mode::instance()->models_can_query()) { |
|
362 | - return true; |
|
363 | - } |
|
364 | - $lock = (int) get_option($this->_get_lock_key($type), 0); |
|
365 | - /** |
|
366 | - * This filters the default is_locked behaviour. |
|
367 | - */ |
|
368 | - $is_locked = filter_var( |
|
369 | - apply_filters( |
|
370 | - 'FHEE__EE_Messages_Queue__is_locked', |
|
371 | - $lock > time(), |
|
372 | - $this |
|
373 | - ), |
|
374 | - FILTER_VALIDATE_BOOLEAN |
|
375 | - ); |
|
376 | - |
|
377 | - /** |
|
378 | - * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method. |
|
379 | - * Also implemented here because messages processed on the same request should not have any locks applied. |
|
380 | - */ |
|
381 | - if ( |
|
382 | - apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false) |
|
383 | - || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request |
|
384 | - ) { |
|
385 | - $is_locked = false; |
|
386 | - } |
|
387 | - |
|
388 | - |
|
389 | - return $is_locked; |
|
390 | - } |
|
391 | - |
|
392 | - |
|
393 | - /** |
|
394 | - * Retrieves the rate limit that may be cached as a transient. |
|
395 | - * If the rate limit is not set, then this sets the default rate limit and expiry and returns it. |
|
396 | - * |
|
397 | - * @param bool $return_expiry If true then return the expiry time not the rate_limit. |
|
398 | - * @return int |
|
399 | - */ |
|
400 | - protected function get_rate_limit($return_expiry = false) |
|
401 | - { |
|
402 | - $stored_rate_info = get_option($this->_get_rate_limit_key(), array()); |
|
403 | - $rate_limit = isset($stored_rate_info[0]) |
|
404 | - ? (int) $stored_rate_info[0] |
|
405 | - : 0; |
|
406 | - $expiry = isset($stored_rate_info[1]) |
|
407 | - ? (int) $stored_rate_info[1] |
|
408 | - : 0; |
|
409 | - // set the default for tracking? |
|
410 | - if (empty($stored_rate_info) || time() > $expiry) { |
|
411 | - $expiry = $this->_get_rate_limit_expiry(); |
|
412 | - $rate_limit = $this->_default_rate_limit(); |
|
413 | - update_option($this->_get_rate_limit_key(), array($rate_limit, $expiry)); |
|
414 | - } |
|
415 | - return $return_expiry ? $expiry : $rate_limit; |
|
416 | - } |
|
417 | - |
|
418 | - |
|
419 | - /** |
|
420 | - * This updates existing rate limit with the new limit which is the old minus the batch. |
|
421 | - * |
|
422 | - * @param int $batch_completed This sets the new rate limit based on the given batch that was completed. |
|
423 | - */ |
|
424 | - protected function set_rate_limit($batch_completed) |
|
425 | - { |
|
426 | - // first get the most up to date rate limit (in case its expired and reset) |
|
427 | - $rate_limit = $this->get_rate_limit(); |
|
428 | - $expiry = $this->get_rate_limit(true); |
|
429 | - $new_limit = $rate_limit - $batch_completed; |
|
430 | - // updating the transient option directly to avoid resetting the expiry. |
|
431 | - |
|
432 | - update_option($this->_get_rate_limit_key(), array($new_limit, $expiry)); |
|
433 | - } |
|
434 | - |
|
435 | - |
|
436 | - /** |
|
437 | - * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in. |
|
438 | - * If that exists, then we immediately initiate a non-blocking request to do the requested action type. |
|
439 | - * Note: Keep in mind that there is the possibility that the request will not execute if there is already another |
|
440 | - * request running on a queue for the given task. |
|
441 | - * |
|
442 | - * @param string $task This indicates what type of request is going to be initiated. |
|
443 | - * @param int $priority This indicates the priority that triggers initiating the request. |
|
444 | - */ |
|
445 | - public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high) |
|
446 | - { |
|
447 | - // determine what status is matched with the priority as part of the trigger conditions. |
|
448 | - $status = $task == 'generate' |
|
449 | - ? EEM_Message::status_incomplete |
|
450 | - : EEM_Message::instance()->stati_indicating_to_send(); |
|
451 | - // always make sure we save because either this will get executed immediately on a separate request |
|
452 | - // or remains in the queue for the regularly scheduled queue batch. |
|
453 | - $this->save(); |
|
454 | - /** |
|
455 | - * This filter/option allows users to override processing of messages on separate requests and instead have everything |
|
456 | - * happen on the same request. If this is utilized remember: |
|
457 | - * - message priorities don't matter |
|
458 | - * - existing unprocessed messages in the queue will not get processed unless manually triggered. |
|
459 | - * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional |
|
460 | - * processing happening on the same request. |
|
461 | - * - any race condition protection (locks) are removed because they don't apply when things are processed on |
|
462 | - * the same request. |
|
463 | - */ |
|
464 | - if ( |
|
465 | - apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false) |
|
466 | - || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request |
|
467 | - ) { |
|
468 | - $messages_processor = EE_Registry::instance()->load_lib('Messages_Processor'); |
|
469 | - if ($messages_processor instanceof EE_Messages_Processor) { |
|
470 | - return $messages_processor->process_immediately_from_queue($this); |
|
471 | - } |
|
472 | - // if we get here then that means the messages processor couldn't be loaded so messages will just remain |
|
473 | - // queued for manual triggering by end user. |
|
474 | - } |
|
475 | - |
|
476 | - if ($this->_message_repository->count_by_priority_and_status($priority, $status)) { |
|
477 | - EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task); |
|
478 | - } |
|
479 | - } |
|
480 | - |
|
481 | - |
|
482 | - /** |
|
483 | - * Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message. |
|
484 | - * |
|
485 | - * @param bool $save Used to indicate whether to save the message queue after sending |
|
486 | - * (default will save). |
|
487 | - * @param mixed $sending_messenger (optional) When the sending messenger is different than |
|
488 | - * what is on the EE_Message object in the queue. |
|
489 | - * For instance, showing the browser view of an email message, |
|
490 | - * or giving a pdf generated view of an html document. |
|
491 | - * This should be an instance of EE_messenger but if you call this |
|
492 | - * method |
|
493 | - * intending it to be a sending messenger but a valid one could not be |
|
494 | - * retrieved then send in an instance of EE_Error that contains the |
|
495 | - * related error message. |
|
496 | - * @param bool|int $by_priority When set, this indicates that only messages |
|
497 | - * matching the given priority should be executed. |
|
498 | - * @return int Number of messages sent. Note, 0 does not mean that no messages were processed. |
|
499 | - * Also, if the messenger is an request type messenger (or a preview), |
|
500 | - * its entirely possible that the messenger will exit before |
|
501 | - */ |
|
502 | - public function execute($save = true, $sending_messenger = null, $by_priority = false) |
|
503 | - { |
|
504 | - $messages_sent = 0; |
|
505 | - $this->_did_hook = array(); |
|
506 | - $this->_message_repository->rewind(); |
|
507 | - |
|
508 | - while ($this->_message_repository->valid()) { |
|
509 | - $error_messages = array(); |
|
510 | - /** @type EE_Message $message */ |
|
511 | - $message = $this->_message_repository->current(); |
|
512 | - // only process things that are queued for sending |
|
513 | - if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) { |
|
514 | - $this->_message_repository->next(); |
|
515 | - continue; |
|
516 | - } |
|
517 | - // if $by_priority is set and does not match then continue; |
|
518 | - if ($by_priority && $by_priority != $message->priority()) { |
|
519 | - $this->_message_repository->next(); |
|
520 | - continue; |
|
521 | - } |
|
522 | - // error checking |
|
523 | - if (! $message->valid_messenger()) { |
|
524 | - $error_messages[] = sprintf( |
|
525 | - __('The %s messenger is not active at time of sending.', 'event_espresso'), |
|
526 | - $message->messenger() |
|
527 | - ); |
|
528 | - } |
|
529 | - if (! $message->valid_message_type()) { |
|
530 | - $error_messages[] = sprintf( |
|
531 | - __('The %s message type is not active at the time of sending.', 'event_espresso'), |
|
532 | - $message->message_type() |
|
533 | - ); |
|
534 | - } |
|
535 | - // if there was supposed to be a sending messenger for this message, but it was invalid/inactive, |
|
536 | - // then it will instead be an EE_Error object, so let's check for that |
|
537 | - if ($sending_messenger instanceof EE_Error) { |
|
538 | - $error_messages[] = $sending_messenger->getMessage(); |
|
539 | - } |
|
540 | - // if there are no errors, then let's process the message |
|
541 | - if (empty($error_messages)) { |
|
542 | - if ($save) { |
|
543 | - $message->set_messenger_is_executing(); |
|
544 | - } |
|
545 | - if ($this->_process_message($message, $sending_messenger)) { |
|
546 | - $messages_sent++; |
|
547 | - } |
|
548 | - } |
|
549 | - $this->_set_error_message($message, $error_messages); |
|
550 | - // add modified time |
|
551 | - $message->set_modified(time()); |
|
552 | - // we save each message after its processed to make sure its status persists in case PHP times-out or runs |
|
553 | - // out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281 |
|
554 | - if ($save) { |
|
555 | - $message->save(); |
|
556 | - } |
|
557 | - |
|
558 | - $this->_message_repository->next(); |
|
559 | - } |
|
560 | - if ($save) { |
|
561 | - $this->save(true); |
|
562 | - } |
|
563 | - return $messages_sent; |
|
564 | - } |
|
565 | - |
|
566 | - |
|
567 | - /** |
|
568 | - * _process_message |
|
569 | - * |
|
570 | - * @param EE_Message $message |
|
571 | - * @param mixed $sending_messenger (optional) |
|
572 | - * @return bool |
|
573 | - */ |
|
574 | - protected function _process_message(EE_Message $message, $sending_messenger = null) |
|
575 | - { |
|
576 | - // these *should* have been validated in the execute() method above |
|
577 | - $messenger = $message->messenger_object(); |
|
578 | - $message_type = $message->message_type_object(); |
|
579 | - // do actions for sending messenger if it differs from generating messenger and swap values. |
|
580 | - if ( |
|
581 | - $sending_messenger instanceof EE_messenger |
|
582 | - && $messenger instanceof EE_messenger |
|
583 | - && $sending_messenger->name != $messenger->name |
|
584 | - ) { |
|
585 | - $messenger->do_secondary_messenger_hooks($sending_messenger->name); |
|
586 | - $messenger = $sending_messenger; |
|
587 | - } |
|
588 | - // send using messenger, but double check objects |
|
589 | - if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) { |
|
590 | - // set hook for message type (but only if not using another messenger to send). |
|
591 | - if (! isset($this->_did_hook[ $message_type->name ])) { |
|
592 | - $message_type->do_messenger_hooks($messenger); |
|
593 | - $this->_did_hook[ $message_type->name ] = 1; |
|
594 | - } |
|
595 | - // if preview then use preview method |
|
596 | - return $this->_message_repository->is_preview() |
|
597 | - ? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send()) |
|
598 | - : $this->_do_send($message, $messenger, $message_type); |
|
599 | - } |
|
600 | - return false; |
|
601 | - } |
|
602 | - |
|
603 | - |
|
604 | - /** |
|
605 | - * The intention of this method is to count how many EE_Message objects |
|
606 | - * are in the queue with a given status. |
|
607 | - * Example usage: |
|
608 | - * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed |
|
609 | - * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ). |
|
610 | - * |
|
611 | - * @param array|string $status Stati to check for in queue |
|
612 | - * @return int Count of EE_Message's matching the given status. |
|
613 | - */ |
|
614 | - public function count_STS_in_queue($status) |
|
615 | - { |
|
616 | - $count = 0; |
|
617 | - $status = is_array($status) ? $status : array($status); |
|
618 | - $this->_message_repository->rewind(); |
|
619 | - foreach ($this->_message_repository as $message) { |
|
620 | - if (in_array($message->STS_ID(), $status)) { |
|
621 | - $count++; |
|
622 | - } |
|
623 | - } |
|
624 | - return $count; |
|
625 | - } |
|
626 | - |
|
627 | - |
|
628 | - /** |
|
629 | - * Executes the get_preview method on the provided messenger. |
|
630 | - * |
|
631 | - * @param EE_Message $message |
|
632 | - * @param EE_messenger $messenger |
|
633 | - * @param EE_message_type $message_type |
|
634 | - * @param $test_send |
|
635 | - * @return bool true means all went well, false means, not so much. |
|
636 | - */ |
|
637 | - protected function _do_preview( |
|
638 | - EE_Message $message, |
|
639 | - EE_messenger $messenger, |
|
640 | - EE_message_type $message_type, |
|
641 | - $test_send |
|
642 | - ) { |
|
643 | - if ($preview = $messenger->get_preview($message, $message_type, $test_send)) { |
|
644 | - if (! $test_send) { |
|
645 | - $message->set_content($preview); |
|
646 | - } |
|
647 | - $message->set_STS_ID(EEM_Message::status_sent); |
|
648 | - return true; |
|
649 | - } else { |
|
650 | - $message->set_STS_ID(EEM_Message::status_failed); |
|
651 | - return false; |
|
652 | - } |
|
653 | - } |
|
654 | - |
|
655 | - |
|
656 | - /** |
|
657 | - * Executes the send method on the provided messenger |
|
658 | - * EE_Messengers are expected to: |
|
659 | - * - return true if the send was successful. |
|
660 | - * - return false if the send was unsuccessful but can be tried again. |
|
661 | - * - throw an Exception if the send was unsuccessful and cannot be tried again. |
|
662 | - * |
|
663 | - * @param EE_Message $message |
|
664 | - * @param EE_messenger $messenger |
|
665 | - * @param EE_message_type $message_type |
|
666 | - * @return bool true means all went well, false means, not so much. |
|
667 | - */ |
|
668 | - protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type) |
|
669 | - { |
|
670 | - try { |
|
671 | - if ($messenger->send_message($message, $message_type)) { |
|
672 | - $message->set_STS_ID(EEM_Message::status_sent); |
|
673 | - return true; |
|
674 | - } else { |
|
675 | - $message->set_STS_ID(EEM_Message::status_retry); |
|
676 | - return false; |
|
677 | - } |
|
678 | - } catch (SendMessageException $e) { |
|
679 | - $message->set_STS_ID(EEM_Message::status_failed); |
|
680 | - $message->set_error_message($e->getMessage()); |
|
681 | - return false; |
|
682 | - } |
|
683 | - } |
|
684 | - |
|
685 | - |
|
686 | - /** |
|
687 | - * This sets any necessary error messages on the message object and its status to failed. |
|
688 | - * |
|
689 | - * @param EE_Message $message |
|
690 | - * @param array $error_messages the response from the messenger. |
|
691 | - */ |
|
692 | - protected function _set_error_message(EE_Message $message, $error_messages) |
|
693 | - { |
|
694 | - $error_messages = (array) $error_messages; |
|
695 | - if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) { |
|
696 | - $notices = EE_Error::has_notices(); |
|
697 | - $error_messages[] = __( |
|
698 | - 'Messenger and Message Type were valid and active, but the messenger send method failed.', |
|
699 | - 'event_espresso' |
|
700 | - ); |
|
701 | - if ($notices === 1) { |
|
702 | - $notices = EE_Error::get_vanilla_notices(); |
|
703 | - $notices['errors'] = isset($notices['errors']) ? $notices['errors'] : array(); |
|
704 | - $error_messages[] = implode("\n", $notices['errors']); |
|
705 | - } |
|
706 | - } |
|
707 | - if (count($error_messages) > 0) { |
|
708 | - $msg = __('Message was not executed successfully.', 'event_espresso'); |
|
709 | - $msg = $msg . "\n" . implode("\n", $error_messages); |
|
710 | - $message->set_error_message($msg); |
|
711 | - } |
|
712 | - } |
|
18 | + /** |
|
19 | + * @type string reference for sending action |
|
20 | + */ |
|
21 | + const action_sending = 'sending'; |
|
22 | + |
|
23 | + /** |
|
24 | + * @type string reference for generation action |
|
25 | + */ |
|
26 | + const action_generating = 'generation'; |
|
27 | + |
|
28 | + |
|
29 | + /** |
|
30 | + * @type EE_Message_Repository $_message_repository |
|
31 | + */ |
|
32 | + protected $_message_repository; |
|
33 | + |
|
34 | + /** |
|
35 | + * Sets the limit of how many messages are generated per process. |
|
36 | + * |
|
37 | + * @type int |
|
38 | + */ |
|
39 | + protected $_batch_count; |
|
40 | + |
|
41 | + |
|
42 | + /** |
|
43 | + * This is an array of cached queue items being stored in this object. |
|
44 | + * The array keys will be the ID of the EE_Message in the db if saved. If the EE_Message |
|
45 | + * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.) |
|
46 | + * |
|
47 | + * @type EE_Message[] |
|
48 | + */ |
|
49 | + protected $_cached_queue_items; |
|
50 | + |
|
51 | + /** |
|
52 | + * Tracks the number of unsaved queue items. |
|
53 | + * |
|
54 | + * @type int |
|
55 | + */ |
|
56 | + protected $_unsaved_count = 0; |
|
57 | + |
|
58 | + /** |
|
59 | + * used to record if a do_messenger_hooks has already been called for a message type. This prevents multiple |
|
60 | + * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls. |
|
61 | + * |
|
62 | + * @type array |
|
63 | + */ |
|
64 | + protected $_did_hook = array(); |
|
65 | + |
|
66 | + |
|
67 | + /** |
|
68 | + * Constructor. |
|
69 | + * Setup all the initial properties and load a EE_Message_Repository. |
|
70 | + * |
|
71 | + * @param \EE_Message_Repository $message_repository |
|
72 | + */ |
|
73 | + public function __construct(EE_Message_Repository $message_repository) |
|
74 | + { |
|
75 | + $this->_batch_count = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50); |
|
76 | + $this->_message_repository = $message_repository; |
|
77 | + } |
|
78 | + |
|
79 | + |
|
80 | + /** |
|
81 | + * Add a EE_Message object to the queue |
|
82 | + * |
|
83 | + * @param EE_Message $message |
|
84 | + * @param array $data This will be an array of data to attach to the object in the repository. If the |
|
85 | + * object is persisted, this data will be saved on an extra_meta object related to |
|
86 | + * EE_Message. |
|
87 | + * @param bool $preview Whether this EE_Message represents a preview or not. |
|
88 | + * @param bool $test_send This indicates whether to do a test send instead of actual send. A test send will |
|
89 | + * use the messenger send method but typically is based on preview data. |
|
90 | + * @return bool Whether the message was successfully added to the repository or not. |
|
91 | + */ |
|
92 | + public function add(EE_Message $message, $data = array(), $preview = false, $test_send = false) |
|
93 | + { |
|
94 | + $data['preview'] = $preview; |
|
95 | + $data['test_send'] = $test_send; |
|
96 | + return $this->_message_repository->add($message, $data); |
|
97 | + } |
|
98 | + |
|
99 | + |
|
100 | + /** |
|
101 | + * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message |
|
102 | + * |
|
103 | + * @param EE_Message $message The message to detach from the queue |
|
104 | + * @param bool $persist This flag indicates whether to attempt to delete the object from the db as well. |
|
105 | + * @return bool |
|
106 | + */ |
|
107 | + public function remove(EE_Message $message, $persist = false) |
|
108 | + { |
|
109 | + if ($persist && $this->_message_repository->current() !== $message) { |
|
110 | + // get pointer on right message |
|
111 | + if ($this->_message_repository->has($message)) { |
|
112 | + $this->_message_repository->rewind(); |
|
113 | + while ($this->_message_repository->valid()) { |
|
114 | + if ($this->_message_repository->current() === $message) { |
|
115 | + break; |
|
116 | + } |
|
117 | + $this->_message_repository->next(); |
|
118 | + } |
|
119 | + } else { |
|
120 | + return false; |
|
121 | + } |
|
122 | + } |
|
123 | + return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message); |
|
124 | + } |
|
125 | + |
|
126 | + |
|
127 | + /** |
|
128 | + * Persists all queued EE_Message objects to the db. |
|
129 | + * |
|
130 | + * @param bool $do_hooks_only @see EE_Message_Repository::saveAll |
|
131 | + * @return array @see EE_Messages_Repository::saveAll() for return values. |
|
132 | + */ |
|
133 | + public function save($do_hooks_only = false) |
|
134 | + { |
|
135 | + return $this->_message_repository->saveAll($do_hooks_only); |
|
136 | + } |
|
137 | + |
|
138 | + |
|
139 | + /** |
|
140 | + * @return EE_Message_Repository |
|
141 | + */ |
|
142 | + public function get_message_repository() |
|
143 | + { |
|
144 | + return $this->_message_repository; |
|
145 | + } |
|
146 | + |
|
147 | + |
|
148 | + /** |
|
149 | + * This does the following things: |
|
150 | + * 1. Checks if there is a lock on generation (prevents race conditions). If there is a lock then exits (return |
|
151 | + * false). |
|
152 | + * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue |
|
153 | + * 3. Returns bool. True = batch ready. False = no batch ready (or nothing available for generation). |
|
154 | + * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from |
|
155 | + * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not |
|
156 | + * removed. |
|
157 | + * |
|
158 | + * @return bool true if successfully retrieved batch, false no batch ready. |
|
159 | + */ |
|
160 | + public function get_batch_to_generate() |
|
161 | + { |
|
162 | + if ($this->is_locked(EE_Messages_Queue::action_generating)) { |
|
163 | + return false; |
|
164 | + } |
|
165 | + |
|
166 | + // lock batch generation to prevent race conditions. |
|
167 | + $this->lock_queue(EE_Messages_Queue::action_generating); |
|
168 | + |
|
169 | + $query_args = array( |
|
170 | + // key 0 = where conditions |
|
171 | + 0 => array('STS_ID' => EEM_Message::status_incomplete), |
|
172 | + 'order_by' => $this->_get_priority_orderby(), |
|
173 | + 'limit' => $this->_batch_count, |
|
174 | + ); |
|
175 | + $messages = EEM_Message::instance()->get_all($query_args); |
|
176 | + |
|
177 | + if (! $messages) { |
|
178 | + return false; // nothing to generate |
|
179 | + } |
|
180 | + |
|
181 | + foreach ($messages as $message) { |
|
182 | + if ($message instanceof EE_Message) { |
|
183 | + $data = $message->all_extra_meta_array(); |
|
184 | + $this->add($message, $data); |
|
185 | + } |
|
186 | + } |
|
187 | + return true; |
|
188 | + } |
|
189 | + |
|
190 | + |
|
191 | + /** |
|
192 | + * This does the following things: |
|
193 | + * 1. Checks if there is a lock on sending (prevents race conditions). If there is a lock then exits (return |
|
194 | + * false). |
|
195 | + * 2. Grabs the allowed number of messages to send for the rate_limit. If cannot send any more messages, then |
|
196 | + * return false. |
|
197 | + * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution. |
|
198 | + * 3. On success or unsuccessful send, sets status appropriately. |
|
199 | + * 4. Saves messages via the queue |
|
200 | + * 5. Releases lock. |
|
201 | + * |
|
202 | + * @return bool true on success, false if something preventing sending (i.e. lock set). Note: true does not |
|
203 | + * necessarily mean that all messages were successfully sent. It just means that this method |
|
204 | + * successfully completed. On true, client may want to call $this->count_STS_in_queue( |
|
205 | + * EEM_Message::status_failed ) to see if any failed EE_Message objects. Each failed message object |
|
206 | + * will also have a saved error message on it to assist with notifying user. |
|
207 | + */ |
|
208 | + public function get_to_send_batch_and_send() |
|
209 | + { |
|
210 | + $rate_limit = $this->get_rate_limit(); |
|
211 | + if ( |
|
212 | + $rate_limit < 1 |
|
213 | + || $this->is_locked(EE_Messages_Queue::action_sending) |
|
214 | + ) { |
|
215 | + return false; |
|
216 | + } |
|
217 | + |
|
218 | + $this->lock_queue(EE_Messages_Queue::action_sending); |
|
219 | + |
|
220 | + $batch = $this->_batch_count < $rate_limit ? $this->_batch_count : $rate_limit; |
|
221 | + |
|
222 | + $query_args = array( |
|
223 | + // key 0 = where conditions |
|
224 | + 0 => array('STS_ID' => array('IN', EEM_Message::instance()->stati_indicating_to_send())), |
|
225 | + 'order_by' => $this->_get_priority_orderby(), |
|
226 | + 'limit' => $batch, |
|
227 | + ); |
|
228 | + |
|
229 | + $messages_to_send = EEM_Message::instance()->get_all($query_args); |
|
230 | + |
|
231 | + |
|
232 | + // any to send? |
|
233 | + if (! $messages_to_send) { |
|
234 | + $this->unlock_queue(EE_Messages_Queue::action_sending); |
|
235 | + return false; |
|
236 | + } |
|
237 | + |
|
238 | + $queue_count = 0; |
|
239 | + |
|
240 | + // add to queue. |
|
241 | + foreach ($messages_to_send as $message) { |
|
242 | + if ($message instanceof EE_Message) { |
|
243 | + $queue_count++; |
|
244 | + $this->add($message); |
|
245 | + } |
|
246 | + } |
|
247 | + |
|
248 | + // send messages (this also updates the rate limit) |
|
249 | + $this->execute(); |
|
250 | + |
|
251 | + // release lock |
|
252 | + $this->unlock_queue(EE_Messages_Queue::action_sending); |
|
253 | + // update rate limit |
|
254 | + $this->set_rate_limit($queue_count); |
|
255 | + return true; |
|
256 | + } |
|
257 | + |
|
258 | + |
|
259 | + /** |
|
260 | + * Locks the queue so that no other queues can call the "batch" methods. |
|
261 | + * |
|
262 | + * @param string $type The type of queue being locked. |
|
263 | + */ |
|
264 | + public function lock_queue($type = EE_Messages_Queue::action_generating) |
|
265 | + { |
|
266 | + update_option($this->_get_lock_key($type), $this->_get_lock_expiry($type)); |
|
267 | + } |
|
268 | + |
|
269 | + |
|
270 | + /** |
|
271 | + * Unlocks the queue so that batch methods can be used. |
|
272 | + * |
|
273 | + * @param string $type The type of queue being unlocked. |
|
274 | + */ |
|
275 | + public function unlock_queue($type = EE_Messages_Queue::action_generating) |
|
276 | + { |
|
277 | + delete_option($this->_get_lock_key($type)); |
|
278 | + } |
|
279 | + |
|
280 | + |
|
281 | + /** |
|
282 | + * Retrieve the key used for the lock transient. |
|
283 | + * |
|
284 | + * @param string $type The type of lock. |
|
285 | + * @return string |
|
286 | + */ |
|
287 | + protected function _get_lock_key($type = EE_Messages_Queue::action_generating) |
|
288 | + { |
|
289 | + return '_ee_lock_' . $type; |
|
290 | + } |
|
291 | + |
|
292 | + |
|
293 | + /** |
|
294 | + * Retrieve the expiry time for the lock transient. |
|
295 | + * |
|
296 | + * @param string $type The type of lock |
|
297 | + * @return int time to expiry in seconds. |
|
298 | + */ |
|
299 | + protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating) |
|
300 | + { |
|
301 | + return time() + (int) apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type); |
|
302 | + } |
|
303 | + |
|
304 | + |
|
305 | + /** |
|
306 | + * Returns the key used for rate limit transient. |
|
307 | + * |
|
308 | + * @return string |
|
309 | + */ |
|
310 | + protected function _get_rate_limit_key() |
|
311 | + { |
|
312 | + return '_ee_rate_limit'; |
|
313 | + } |
|
314 | + |
|
315 | + |
|
316 | + /** |
|
317 | + * Returns the rate limit expiry time. |
|
318 | + * |
|
319 | + * @return int |
|
320 | + */ |
|
321 | + protected function _get_rate_limit_expiry() |
|
322 | + { |
|
323 | + return time() + (int) apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS); |
|
324 | + } |
|
325 | + |
|
326 | + |
|
327 | + /** |
|
328 | + * Returns the default rate limit for sending messages. |
|
329 | + * |
|
330 | + * @return int |
|
331 | + */ |
|
332 | + protected function _default_rate_limit() |
|
333 | + { |
|
334 | + return (int) apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200); |
|
335 | + } |
|
336 | + |
|
337 | + |
|
338 | + /** |
|
339 | + * Return the orderby array for priority. |
|
340 | + * |
|
341 | + * @return array |
|
342 | + */ |
|
343 | + protected function _get_priority_orderby() |
|
344 | + { |
|
345 | + return array( |
|
346 | + 'MSG_priority' => 'ASC', |
|
347 | + 'MSG_modified' => 'DESC', |
|
348 | + ); |
|
349 | + } |
|
350 | + |
|
351 | + |
|
352 | + /** |
|
353 | + * Returns whether batch methods are "locked" or not, and if models an currently be used to query the database. |
|
354 | + * Return true when batch methods should not be used; returns false when they can be. |
|
355 | + * |
|
356 | + * @param string $type The type of lock being checked for. |
|
357 | + * @return bool |
|
358 | + */ |
|
359 | + public function is_locked($type = EE_Messages_Queue::action_generating) |
|
360 | + { |
|
361 | + if (! EE_Maintenance_Mode::instance()->models_can_query()) { |
|
362 | + return true; |
|
363 | + } |
|
364 | + $lock = (int) get_option($this->_get_lock_key($type), 0); |
|
365 | + /** |
|
366 | + * This filters the default is_locked behaviour. |
|
367 | + */ |
|
368 | + $is_locked = filter_var( |
|
369 | + apply_filters( |
|
370 | + 'FHEE__EE_Messages_Queue__is_locked', |
|
371 | + $lock > time(), |
|
372 | + $this |
|
373 | + ), |
|
374 | + FILTER_VALIDATE_BOOLEAN |
|
375 | + ); |
|
376 | + |
|
377 | + /** |
|
378 | + * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method. |
|
379 | + * Also implemented here because messages processed on the same request should not have any locks applied. |
|
380 | + */ |
|
381 | + if ( |
|
382 | + apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false) |
|
383 | + || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request |
|
384 | + ) { |
|
385 | + $is_locked = false; |
|
386 | + } |
|
387 | + |
|
388 | + |
|
389 | + return $is_locked; |
|
390 | + } |
|
391 | + |
|
392 | + |
|
393 | + /** |
|
394 | + * Retrieves the rate limit that may be cached as a transient. |
|
395 | + * If the rate limit is not set, then this sets the default rate limit and expiry and returns it. |
|
396 | + * |
|
397 | + * @param bool $return_expiry If true then return the expiry time not the rate_limit. |
|
398 | + * @return int |
|
399 | + */ |
|
400 | + protected function get_rate_limit($return_expiry = false) |
|
401 | + { |
|
402 | + $stored_rate_info = get_option($this->_get_rate_limit_key(), array()); |
|
403 | + $rate_limit = isset($stored_rate_info[0]) |
|
404 | + ? (int) $stored_rate_info[0] |
|
405 | + : 0; |
|
406 | + $expiry = isset($stored_rate_info[1]) |
|
407 | + ? (int) $stored_rate_info[1] |
|
408 | + : 0; |
|
409 | + // set the default for tracking? |
|
410 | + if (empty($stored_rate_info) || time() > $expiry) { |
|
411 | + $expiry = $this->_get_rate_limit_expiry(); |
|
412 | + $rate_limit = $this->_default_rate_limit(); |
|
413 | + update_option($this->_get_rate_limit_key(), array($rate_limit, $expiry)); |
|
414 | + } |
|
415 | + return $return_expiry ? $expiry : $rate_limit; |
|
416 | + } |
|
417 | + |
|
418 | + |
|
419 | + /** |
|
420 | + * This updates existing rate limit with the new limit which is the old minus the batch. |
|
421 | + * |
|
422 | + * @param int $batch_completed This sets the new rate limit based on the given batch that was completed. |
|
423 | + */ |
|
424 | + protected function set_rate_limit($batch_completed) |
|
425 | + { |
|
426 | + // first get the most up to date rate limit (in case its expired and reset) |
|
427 | + $rate_limit = $this->get_rate_limit(); |
|
428 | + $expiry = $this->get_rate_limit(true); |
|
429 | + $new_limit = $rate_limit - $batch_completed; |
|
430 | + // updating the transient option directly to avoid resetting the expiry. |
|
431 | + |
|
432 | + update_option($this->_get_rate_limit_key(), array($new_limit, $expiry)); |
|
433 | + } |
|
434 | + |
|
435 | + |
|
436 | + /** |
|
437 | + * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in. |
|
438 | + * If that exists, then we immediately initiate a non-blocking request to do the requested action type. |
|
439 | + * Note: Keep in mind that there is the possibility that the request will not execute if there is already another |
|
440 | + * request running on a queue for the given task. |
|
441 | + * |
|
442 | + * @param string $task This indicates what type of request is going to be initiated. |
|
443 | + * @param int $priority This indicates the priority that triggers initiating the request. |
|
444 | + */ |
|
445 | + public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high) |
|
446 | + { |
|
447 | + // determine what status is matched with the priority as part of the trigger conditions. |
|
448 | + $status = $task == 'generate' |
|
449 | + ? EEM_Message::status_incomplete |
|
450 | + : EEM_Message::instance()->stati_indicating_to_send(); |
|
451 | + // always make sure we save because either this will get executed immediately on a separate request |
|
452 | + // or remains in the queue for the regularly scheduled queue batch. |
|
453 | + $this->save(); |
|
454 | + /** |
|
455 | + * This filter/option allows users to override processing of messages on separate requests and instead have everything |
|
456 | + * happen on the same request. If this is utilized remember: |
|
457 | + * - message priorities don't matter |
|
458 | + * - existing unprocessed messages in the queue will not get processed unless manually triggered. |
|
459 | + * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional |
|
460 | + * processing happening on the same request. |
|
461 | + * - any race condition protection (locks) are removed because they don't apply when things are processed on |
|
462 | + * the same request. |
|
463 | + */ |
|
464 | + if ( |
|
465 | + apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false) |
|
466 | + || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request |
|
467 | + ) { |
|
468 | + $messages_processor = EE_Registry::instance()->load_lib('Messages_Processor'); |
|
469 | + if ($messages_processor instanceof EE_Messages_Processor) { |
|
470 | + return $messages_processor->process_immediately_from_queue($this); |
|
471 | + } |
|
472 | + // if we get here then that means the messages processor couldn't be loaded so messages will just remain |
|
473 | + // queued for manual triggering by end user. |
|
474 | + } |
|
475 | + |
|
476 | + if ($this->_message_repository->count_by_priority_and_status($priority, $status)) { |
|
477 | + EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task); |
|
478 | + } |
|
479 | + } |
|
480 | + |
|
481 | + |
|
482 | + /** |
|
483 | + * Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message. |
|
484 | + * |
|
485 | + * @param bool $save Used to indicate whether to save the message queue after sending |
|
486 | + * (default will save). |
|
487 | + * @param mixed $sending_messenger (optional) When the sending messenger is different than |
|
488 | + * what is on the EE_Message object in the queue. |
|
489 | + * For instance, showing the browser view of an email message, |
|
490 | + * or giving a pdf generated view of an html document. |
|
491 | + * This should be an instance of EE_messenger but if you call this |
|
492 | + * method |
|
493 | + * intending it to be a sending messenger but a valid one could not be |
|
494 | + * retrieved then send in an instance of EE_Error that contains the |
|
495 | + * related error message. |
|
496 | + * @param bool|int $by_priority When set, this indicates that only messages |
|
497 | + * matching the given priority should be executed. |
|
498 | + * @return int Number of messages sent. Note, 0 does not mean that no messages were processed. |
|
499 | + * Also, if the messenger is an request type messenger (or a preview), |
|
500 | + * its entirely possible that the messenger will exit before |
|
501 | + */ |
|
502 | + public function execute($save = true, $sending_messenger = null, $by_priority = false) |
|
503 | + { |
|
504 | + $messages_sent = 0; |
|
505 | + $this->_did_hook = array(); |
|
506 | + $this->_message_repository->rewind(); |
|
507 | + |
|
508 | + while ($this->_message_repository->valid()) { |
|
509 | + $error_messages = array(); |
|
510 | + /** @type EE_Message $message */ |
|
511 | + $message = $this->_message_repository->current(); |
|
512 | + // only process things that are queued for sending |
|
513 | + if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) { |
|
514 | + $this->_message_repository->next(); |
|
515 | + continue; |
|
516 | + } |
|
517 | + // if $by_priority is set and does not match then continue; |
|
518 | + if ($by_priority && $by_priority != $message->priority()) { |
|
519 | + $this->_message_repository->next(); |
|
520 | + continue; |
|
521 | + } |
|
522 | + // error checking |
|
523 | + if (! $message->valid_messenger()) { |
|
524 | + $error_messages[] = sprintf( |
|
525 | + __('The %s messenger is not active at time of sending.', 'event_espresso'), |
|
526 | + $message->messenger() |
|
527 | + ); |
|
528 | + } |
|
529 | + if (! $message->valid_message_type()) { |
|
530 | + $error_messages[] = sprintf( |
|
531 | + __('The %s message type is not active at the time of sending.', 'event_espresso'), |
|
532 | + $message->message_type() |
|
533 | + ); |
|
534 | + } |
|
535 | + // if there was supposed to be a sending messenger for this message, but it was invalid/inactive, |
|
536 | + // then it will instead be an EE_Error object, so let's check for that |
|
537 | + if ($sending_messenger instanceof EE_Error) { |
|
538 | + $error_messages[] = $sending_messenger->getMessage(); |
|
539 | + } |
|
540 | + // if there are no errors, then let's process the message |
|
541 | + if (empty($error_messages)) { |
|
542 | + if ($save) { |
|
543 | + $message->set_messenger_is_executing(); |
|
544 | + } |
|
545 | + if ($this->_process_message($message, $sending_messenger)) { |
|
546 | + $messages_sent++; |
|
547 | + } |
|
548 | + } |
|
549 | + $this->_set_error_message($message, $error_messages); |
|
550 | + // add modified time |
|
551 | + $message->set_modified(time()); |
|
552 | + // we save each message after its processed to make sure its status persists in case PHP times-out or runs |
|
553 | + // out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281 |
|
554 | + if ($save) { |
|
555 | + $message->save(); |
|
556 | + } |
|
557 | + |
|
558 | + $this->_message_repository->next(); |
|
559 | + } |
|
560 | + if ($save) { |
|
561 | + $this->save(true); |
|
562 | + } |
|
563 | + return $messages_sent; |
|
564 | + } |
|
565 | + |
|
566 | + |
|
567 | + /** |
|
568 | + * _process_message |
|
569 | + * |
|
570 | + * @param EE_Message $message |
|
571 | + * @param mixed $sending_messenger (optional) |
|
572 | + * @return bool |
|
573 | + */ |
|
574 | + protected function _process_message(EE_Message $message, $sending_messenger = null) |
|
575 | + { |
|
576 | + // these *should* have been validated in the execute() method above |
|
577 | + $messenger = $message->messenger_object(); |
|
578 | + $message_type = $message->message_type_object(); |
|
579 | + // do actions for sending messenger if it differs from generating messenger and swap values. |
|
580 | + if ( |
|
581 | + $sending_messenger instanceof EE_messenger |
|
582 | + && $messenger instanceof EE_messenger |
|
583 | + && $sending_messenger->name != $messenger->name |
|
584 | + ) { |
|
585 | + $messenger->do_secondary_messenger_hooks($sending_messenger->name); |
|
586 | + $messenger = $sending_messenger; |
|
587 | + } |
|
588 | + // send using messenger, but double check objects |
|
589 | + if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) { |
|
590 | + // set hook for message type (but only if not using another messenger to send). |
|
591 | + if (! isset($this->_did_hook[ $message_type->name ])) { |
|
592 | + $message_type->do_messenger_hooks($messenger); |
|
593 | + $this->_did_hook[ $message_type->name ] = 1; |
|
594 | + } |
|
595 | + // if preview then use preview method |
|
596 | + return $this->_message_repository->is_preview() |
|
597 | + ? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send()) |
|
598 | + : $this->_do_send($message, $messenger, $message_type); |
|
599 | + } |
|
600 | + return false; |
|
601 | + } |
|
602 | + |
|
603 | + |
|
604 | + /** |
|
605 | + * The intention of this method is to count how many EE_Message objects |
|
606 | + * are in the queue with a given status. |
|
607 | + * Example usage: |
|
608 | + * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed |
|
609 | + * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ). |
|
610 | + * |
|
611 | + * @param array|string $status Stati to check for in queue |
|
612 | + * @return int Count of EE_Message's matching the given status. |
|
613 | + */ |
|
614 | + public function count_STS_in_queue($status) |
|
615 | + { |
|
616 | + $count = 0; |
|
617 | + $status = is_array($status) ? $status : array($status); |
|
618 | + $this->_message_repository->rewind(); |
|
619 | + foreach ($this->_message_repository as $message) { |
|
620 | + if (in_array($message->STS_ID(), $status)) { |
|
621 | + $count++; |
|
622 | + } |
|
623 | + } |
|
624 | + return $count; |
|
625 | + } |
|
626 | + |
|
627 | + |
|
628 | + /** |
|
629 | + * Executes the get_preview method on the provided messenger. |
|
630 | + * |
|
631 | + * @param EE_Message $message |
|
632 | + * @param EE_messenger $messenger |
|
633 | + * @param EE_message_type $message_type |
|
634 | + * @param $test_send |
|
635 | + * @return bool true means all went well, false means, not so much. |
|
636 | + */ |
|
637 | + protected function _do_preview( |
|
638 | + EE_Message $message, |
|
639 | + EE_messenger $messenger, |
|
640 | + EE_message_type $message_type, |
|
641 | + $test_send |
|
642 | + ) { |
|
643 | + if ($preview = $messenger->get_preview($message, $message_type, $test_send)) { |
|
644 | + if (! $test_send) { |
|
645 | + $message->set_content($preview); |
|
646 | + } |
|
647 | + $message->set_STS_ID(EEM_Message::status_sent); |
|
648 | + return true; |
|
649 | + } else { |
|
650 | + $message->set_STS_ID(EEM_Message::status_failed); |
|
651 | + return false; |
|
652 | + } |
|
653 | + } |
|
654 | + |
|
655 | + |
|
656 | + /** |
|
657 | + * Executes the send method on the provided messenger |
|
658 | + * EE_Messengers are expected to: |
|
659 | + * - return true if the send was successful. |
|
660 | + * - return false if the send was unsuccessful but can be tried again. |
|
661 | + * - throw an Exception if the send was unsuccessful and cannot be tried again. |
|
662 | + * |
|
663 | + * @param EE_Message $message |
|
664 | + * @param EE_messenger $messenger |
|
665 | + * @param EE_message_type $message_type |
|
666 | + * @return bool true means all went well, false means, not so much. |
|
667 | + */ |
|
668 | + protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type) |
|
669 | + { |
|
670 | + try { |
|
671 | + if ($messenger->send_message($message, $message_type)) { |
|
672 | + $message->set_STS_ID(EEM_Message::status_sent); |
|
673 | + return true; |
|
674 | + } else { |
|
675 | + $message->set_STS_ID(EEM_Message::status_retry); |
|
676 | + return false; |
|
677 | + } |
|
678 | + } catch (SendMessageException $e) { |
|
679 | + $message->set_STS_ID(EEM_Message::status_failed); |
|
680 | + $message->set_error_message($e->getMessage()); |
|
681 | + return false; |
|
682 | + } |
|
683 | + } |
|
684 | + |
|
685 | + |
|
686 | + /** |
|
687 | + * This sets any necessary error messages on the message object and its status to failed. |
|
688 | + * |
|
689 | + * @param EE_Message $message |
|
690 | + * @param array $error_messages the response from the messenger. |
|
691 | + */ |
|
692 | + protected function _set_error_message(EE_Message $message, $error_messages) |
|
693 | + { |
|
694 | + $error_messages = (array) $error_messages; |
|
695 | + if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) { |
|
696 | + $notices = EE_Error::has_notices(); |
|
697 | + $error_messages[] = __( |
|
698 | + 'Messenger and Message Type were valid and active, but the messenger send method failed.', |
|
699 | + 'event_espresso' |
|
700 | + ); |
|
701 | + if ($notices === 1) { |
|
702 | + $notices = EE_Error::get_vanilla_notices(); |
|
703 | + $notices['errors'] = isset($notices['errors']) ? $notices['errors'] : array(); |
|
704 | + $error_messages[] = implode("\n", $notices['errors']); |
|
705 | + } |
|
706 | + } |
|
707 | + if (count($error_messages) > 0) { |
|
708 | + $msg = __('Message was not executed successfully.', 'event_espresso'); |
|
709 | + $msg = $msg . "\n" . implode("\n", $error_messages); |
|
710 | + $message->set_error_message($msg); |
|
711 | + } |
|
712 | + } |
|
713 | 713 | } |
@@ -16,27 +16,27 @@ |
||
16 | 16 | class InvalidAliasException extends DomainException |
17 | 17 | { |
18 | 18 | |
19 | - /** |
|
20 | - * InvalidClassException constructor. |
|
21 | - * |
|
22 | - * @param string $fqcn |
|
23 | - * @param string $alias |
|
24 | - * @param string $message |
|
25 | - * @param int $code |
|
26 | - * @param Exception $previous |
|
27 | - */ |
|
28 | - public function __construct($fqcn, $alias, $message = '', $code = 0, Exception $previous = null) |
|
29 | - { |
|
30 | - if (empty($message)) { |
|
31 | - $message = sprintf( |
|
32 | - __( |
|
33 | - '"%1$s" can not be used as an alias because the "%2$s" class does not extend or implement it.', |
|
34 | - 'event_espresso' |
|
35 | - ), |
|
36 | - $alias, |
|
37 | - $fqcn |
|
38 | - ); |
|
39 | - } |
|
40 | - parent::__construct($message, $code, $previous); |
|
41 | - } |
|
19 | + /** |
|
20 | + * InvalidClassException constructor. |
|
21 | + * |
|
22 | + * @param string $fqcn |
|
23 | + * @param string $alias |
|
24 | + * @param string $message |
|
25 | + * @param int $code |
|
26 | + * @param Exception $previous |
|
27 | + */ |
|
28 | + public function __construct($fqcn, $alias, $message = '', $code = 0, Exception $previous = null) |
|
29 | + { |
|
30 | + if (empty($message)) { |
|
31 | + $message = sprintf( |
|
32 | + __( |
|
33 | + '"%1$s" can not be used as an alias because the "%2$s" class does not extend or implement it.', |
|
34 | + 'event_espresso' |
|
35 | + ), |
|
36 | + $alias, |
|
37 | + $fqcn |
|
38 | + ); |
|
39 | + } |
|
40 | + parent::__construct($message, $code, $previous); |
|
41 | + } |
|
42 | 42 | } |
@@ -34,7 +34,7 @@ |
||
34 | 34 | */ |
35 | 35 | public function __construct($alias, $fqcn) |
36 | 36 | { |
37 | - if (! is_subclass_of($fqcn, $alias)) { |
|
37 | + if ( ! is_subclass_of($fqcn, $alias)) { |
|
38 | 38 | throw new InvalidAliasException($fqcn, $alias); |
39 | 39 | } |
40 | 40 | $this->alias = $alias; |
@@ -17,46 +17,46 @@ |
||
17 | 17 | class ClassAlias |
18 | 18 | { |
19 | 19 | |
20 | - /** |
|
21 | - * @var string $alias an interface or base class representing what object |
|
22 | - * can be utilized by another object and/or function |
|
23 | - */ |
|
24 | - private $alias; |
|
25 | - |
|
26 | - /** |
|
27 | - * @var string $fqcn the actual class that should be substituted for the alias above |
|
28 | - */ |
|
29 | - private $fqcn; |
|
30 | - |
|
31 | - /** |
|
32 | - * ClassAlias constructor. |
|
33 | - * |
|
34 | - * @param string $alias Interface specified by implementing class |
|
35 | - * @param string $fqcn Concrete class that satisfies interface |
|
36 | - * @throws InvalidAliasException |
|
37 | - */ |
|
38 | - public function __construct($alias, $fqcn) |
|
39 | - { |
|
40 | - if (! is_subclass_of($fqcn, $alias)) { |
|
41 | - throw new InvalidAliasException($fqcn, $alias); |
|
42 | - } |
|
43 | - $this->alias = $alias; |
|
44 | - $this->fqcn = $fqcn; |
|
45 | - } |
|
46 | - |
|
47 | - /** |
|
48 | - * @return string |
|
49 | - */ |
|
50 | - public function alias() |
|
51 | - { |
|
52 | - return $this->alias; |
|
53 | - } |
|
54 | - |
|
55 | - /** |
|
56 | - * @return string |
|
57 | - */ |
|
58 | - public function fqcn() |
|
59 | - { |
|
60 | - return $this->fqcn; |
|
61 | - } |
|
20 | + /** |
|
21 | + * @var string $alias an interface or base class representing what object |
|
22 | + * can be utilized by another object and/or function |
|
23 | + */ |
|
24 | + private $alias; |
|
25 | + |
|
26 | + /** |
|
27 | + * @var string $fqcn the actual class that should be substituted for the alias above |
|
28 | + */ |
|
29 | + private $fqcn; |
|
30 | + |
|
31 | + /** |
|
32 | + * ClassAlias constructor. |
|
33 | + * |
|
34 | + * @param string $alias Interface specified by implementing class |
|
35 | + * @param string $fqcn Concrete class that satisfies interface |
|
36 | + * @throws InvalidAliasException |
|
37 | + */ |
|
38 | + public function __construct($alias, $fqcn) |
|
39 | + { |
|
40 | + if (! is_subclass_of($fqcn, $alias)) { |
|
41 | + throw new InvalidAliasException($fqcn, $alias); |
|
42 | + } |
|
43 | + $this->alias = $alias; |
|
44 | + $this->fqcn = $fqcn; |
|
45 | + } |
|
46 | + |
|
47 | + /** |
|
48 | + * @return string |
|
49 | + */ |
|
50 | + public function alias() |
|
51 | + { |
|
52 | + return $this->alias; |
|
53 | + } |
|
54 | + |
|
55 | + /** |
|
56 | + * @return string |
|
57 | + */ |
|
58 | + public function fqcn() |
|
59 | + { |
|
60 | + return $this->fqcn; |
|
61 | + } |
|
62 | 62 | } |
@@ -18,41 +18,41 @@ |
||
18 | 18 | */ |
19 | 19 | abstract class FactoryWithDependencyResolver implements FactoryInterface |
20 | 20 | { |
21 | - /** |
|
22 | - * @var DependencyResolverInterface $dependency_resolver |
|
23 | - */ |
|
24 | - private $dependency_resolver; |
|
21 | + /** |
|
22 | + * @var DependencyResolverInterface $dependency_resolver |
|
23 | + */ |
|
24 | + private $dependency_resolver; |
|
25 | 25 | |
26 | - /** |
|
27 | - * @var LoaderInterface $loader |
|
28 | - */ |
|
29 | - private $loader; |
|
26 | + /** |
|
27 | + * @var LoaderInterface $loader |
|
28 | + */ |
|
29 | + private $loader; |
|
30 | 30 | |
31 | - /** |
|
32 | - * FactoryWithDependencyResolver constructor. |
|
33 | - * |
|
34 | - * @param DependencyResolverInterface $dependency_resolver |
|
35 | - * @param LoaderInterface $loader |
|
36 | - */ |
|
37 | - public function __construct(DependencyResolverInterface $dependency_resolver, LoaderInterface $loader) |
|
38 | - { |
|
39 | - $this->dependency_resolver = $dependency_resolver; |
|
40 | - $this->loader = $loader; |
|
41 | - } |
|
31 | + /** |
|
32 | + * FactoryWithDependencyResolver constructor. |
|
33 | + * |
|
34 | + * @param DependencyResolverInterface $dependency_resolver |
|
35 | + * @param LoaderInterface $loader |
|
36 | + */ |
|
37 | + public function __construct(DependencyResolverInterface $dependency_resolver, LoaderInterface $loader) |
|
38 | + { |
|
39 | + $this->dependency_resolver = $dependency_resolver; |
|
40 | + $this->loader = $loader; |
|
41 | + } |
|
42 | 42 | |
43 | - /** |
|
44 | - * @return DependencyResolverInterface |
|
45 | - */ |
|
46 | - public function dependencyResolver() |
|
47 | - { |
|
48 | - return $this->dependency_resolver; |
|
49 | - } |
|
43 | + /** |
|
44 | + * @return DependencyResolverInterface |
|
45 | + */ |
|
46 | + public function dependencyResolver() |
|
47 | + { |
|
48 | + return $this->dependency_resolver; |
|
49 | + } |
|
50 | 50 | |
51 | - /** |
|
52 | - * @return LoaderInterface |
|
53 | - */ |
|
54 | - public function loader() |
|
55 | - { |
|
56 | - return $this->loader; |
|
57 | - } |
|
51 | + /** |
|
52 | + * @return LoaderInterface |
|
53 | + */ |
|
54 | + public function loader() |
|
55 | + { |
|
56 | + return $this->loader; |
|
57 | + } |
|
58 | 58 | } |
@@ -11,10 +11,10 @@ |
||
11 | 11 | interface FactoryInterface |
12 | 12 | { |
13 | 13 | |
14 | - /** |
|
15 | - * @param mixed $arguments Either a Fully Qualified Class Name |
|
16 | - * or array of data required for construction |
|
17 | - * @return mixed |
|
18 | - */ |
|
19 | - public static function create($arguments); |
|
14 | + /** |
|
15 | + * @param mixed $arguments Either a Fully Qualified Class Name |
|
16 | + * or array of data required for construction |
|
17 | + * @return mixed |
|
18 | + */ |
|
19 | + public static function create($arguments); |
|
20 | 20 | } |