Completed
Branch master (89fa75)
by
unknown
05:04
created
core/services/orm/tree_traversal/RelationNode.php 2 patches
Indentation   +296 added lines, -296 removed lines patch added patch discarded remove patch
@@ -24,302 +24,302 @@
 block discarded – undo
24 24
  */
25 25
 class RelationNode extends BaseNode
26 26
 {
27
-    protected ?int $count = null;
28
-
29
-    /**
30
-     * @var string|int
31
-     */
32
-    protected $id;
33
-
34
-    protected EEM_Base $main_model;
35
-
36
-    /**
37
-     * @var ModelObjNode[]
38
-     */
39
-    protected array $nodes;
40
-
41
-    protected EEM_Base $related_model;
42
-
43
-    public ?string $main_model_name = null;
44
-    public ?string $related_model_name = null;
45
-
46
-
47
-    /**
48
-     * RelationNode constructor.
49
-     *
50
-     * @param          $main_model_obj_id
51
-     * @param EEM_Base $main_model
52
-     * @param EEM_Base $related_model
53
-     * @param array    $dont_traverse_models array of model names we DON'T want to traverse
54
-     */
55
-    public function __construct(
56
-        $main_model_obj_id,
57
-        EEM_Base $main_model,
58
-        EEM_Base $related_model,
59
-        array $dont_traverse_models = []
60
-    ) {
61
-        $this->id                   = $main_model_obj_id;
62
-        $this->main_model           = $main_model;
63
-        $this->related_model        = $related_model;
64
-        $this->nodes                = [];
65
-        $this->dont_traverse_models = $dont_traverse_models;
66
-    }
67
-
68
-
69
-    /**
70
-     * Here is where most of the work happens. We've counted how many related model objects exist, here we identify
71
-     * them (ie, learn their IDs). But its recursive, so we'll also find their related dependent model objects etc.
72
-     *
73
-     * @param int $model_objects_to_identify
74
-     * @return int
75
-     * @throws EE_Error
76
-     * @throws InvalidArgumentException
77
-     * @throws InvalidDataTypeException
78
-     * @throws InvalidInterfaceException
79
-     * @throws ReflectionException
80
-     */
81
-    protected function work($model_objects_to_identify)
82
-    {
83
-        $num_identified = $this->visitAlreadyDiscoveredNodes($this->nodes, $model_objects_to_identify);
84
-        if ($num_identified < $model_objects_to_identify) {
85
-            $related_model_objs = $this->related_model->get_all(
86
-                [
87
-                    $this->whereQueryParams(),
88
-                    'limit' => [
89
-                        count($this->nodes),
90
-                        $model_objects_to_identify - $num_identified,
91
-                    ],
92
-                ]
93
-            );
94
-            $new_item_nodes     = [];
95
-
96
-            // Add entity nodes for each of the model objects we fetched.
97
-            foreach ($related_model_objs as $related_model_obj) {
98
-                $entity_node                                = new ModelObjNode(
99
-                    $related_model_obj->ID(),
100
-                    $related_model_obj->get_model(),
101
-                    $this->dont_traverse_models
102
-                );
103
-                $this->nodes[ $related_model_obj->ID() ]    = $entity_node;
104
-                $new_item_nodes[ $related_model_obj->ID() ] = $entity_node;
105
-            }
106
-            $num_identified += count($new_item_nodes);
107
-            if ($num_identified < $model_objects_to_identify) {
108
-                // And lastly do the work.
109
-                $num_identified += $this->visitAlreadyDiscoveredNodes(
110
-                    $new_item_nodes,
111
-                    $model_objects_to_identify - $num_identified
112
-                );
113
-            }
114
-        }
115
-
116
-        if (count($this->nodes) >= $this->count && $this->allChildrenComplete()) {
117
-            $this->complete = true;
118
-        }
119
-        return $num_identified;
120
-    }
121
-
122
-
123
-    /**
124
-     * Checks if all the identified child nodes are complete or not.
125
-     *
126
-     * @return bool
127
-     */
128
-    protected function allChildrenComplete()
129
-    {
130
-        foreach ($this->nodes as $model_obj_node) {
131
-            if (! $model_obj_node->isComplete()) {
132
-                return false;
133
-            }
134
-        }
135
-        return true;
136
-    }
137
-
138
-
139
-    /**
140
-     * Visits the provided nodes and keeps track of how much work was done, making sure to not go over budget.
141
-     *
142
-     * @param ModelObjNode[] $model_obj_nodes
143
-     * @param                $work_budget
144
-     * @return int
145
-     */
146
-    protected function visitAlreadyDiscoveredNodes($model_obj_nodes, $work_budget)
147
-    {
148
-        $work_done = 0;
149
-        if (! $model_obj_nodes) {
150
-            return 0;
151
-        }
152
-        foreach ($model_obj_nodes as $model_obj_node) {
153
-            if ($work_done >= $work_budget) {
154
-                break;
155
-            }
156
-            $work_done += $model_obj_node->visit($work_budget - $work_done);
157
-        }
158
-        return $work_done;
159
-    }
160
-
161
-
162
-    /**
163
-     * Whether this item has already been initialized
164
-     */
165
-    protected function isDiscovered()
166
-    {
167
-        return $this->count !== null;
168
-    }
169
-
170
-
171
-    /**
172
-     * @return boolean
173
-     */
174
-    public function isComplete()
175
-    {
176
-        if ($this->complete === null) {
177
-            if (count($this->nodes) === $this->count) {
178
-                $this->complete = true;
179
-            } else {
180
-                $this->complete = false;
181
-            }
182
-        }
183
-        return $this->complete;
184
-    }
185
-
186
-
187
-    /**
188
-     * Discovers how many related model objects exist.
189
-     *
190
-     * @return void
191
-     * @throws EE_Error
192
-     * @throws InvalidArgumentException
193
-     * @throws InvalidDataTypeException
194
-     * @throws InvalidInterfaceException
195
-     */
196
-    protected function discover()
197
-    {
198
-        $this->count = $this->related_model->count([$this->whereQueryParams()]);
199
-    }
200
-
201
-
202
-    /**
203
-     * @return array
204
-     * @throws EE_Error
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     * @throws InvalidArgumentException
208
-     */
209
-    protected function whereQueryParams()
210
-    {
211
-        $where_params = [
212
-            $this->related_model->get_foreign_key_to(
213
-                $this->main_model->get_this_model_name()
214
-            )->get_name() => $this->id,
215
-        ];
216
-        try {
217
-            $relation_settings = $this->main_model->related_settings_for($this->related_model->get_this_model_name());
218
-        } catch (EE_Error $e) {
219
-            // This will happen for has-and-belongs-to-many relations, when this node's related model is that join table
220
-            // which hasn't been explicitly declared in the main model object's model's relations.
221
-            $relation_settings = null;
222
-        }
223
-        if ($relation_settings instanceof EE_Has_Many_Any_Relation) {
224
-            $where_params[ $this->related_model->get_field_containing_related_model_name()->get_name() ] =
225
-                $this->main_model->get_this_model_name();
226
-        }
227
-        return $where_params;
228
-    }
229
-
230
-
231
-    /**
232
-     * @return array
233
-     * @throws EE_Error
234
-     * @throws ReflectionException
235
-     */
236
-    public function toArray()
237
-    {
238
-        $tree = [
239
-            'count'    => $this->count,
240
-            'complete' => $this->isComplete(),
241
-            'objs'     => [],
242
-        ];
243
-        foreach ($this->nodes as $id => $model_obj_node) {
244
-            $tree['objs'][ $id ] = $model_obj_node->toArray();
245
-        }
246
-        return $tree;
247
-    }
248
-
249
-
250
-    /**
251
-     * Gets the IDs of all the model objects to delete; indexed first by model object name.
252
-     *
253
-     * @return array
254
-     * @throws EE_Error
255
-     * @throws ReflectionException
256
-     */
257
-    public function getIds()
258
-    {
259
-        if (empty($this->nodes)) {
260
-            return [];
261
-        }
262
-        $ids = [
263
-            $this->related_model->get_this_model_name() => array_combine(
264
-                array_keys($this->nodes),
265
-                array_keys($this->nodes)
266
-            ),
267
-        ];
268
-        foreach ($this->nodes as $model_obj_node) {
269
-            $ids = array_replace_recursive($ids, $model_obj_node->getIds());
270
-        }
271
-        return $ids;
272
-    }
273
-
274
-
275
-    /**
276
-     * Returns the number of sub-nodes found (ie, related model objects across this relation.)
277
-     *
278
-     * @return int
279
-     */
280
-    public function countSubNodes()
281
-    {
282
-        return count($this->nodes);
283
-    }
284
-
285
-
286
-    /**
287
-     * Don't serialize the models. Just record their names on some dynamic properties.
288
-     *
289
-     * @return array
290
-     */
291
-    public function __sleep()
292
-    {
293
-        $this->main_model_name  = $this->main_model->get_this_model_name();
294
-        $this->related_model_name = $this->related_model->get_this_model_name();
295
-        return array_merge(
296
-            [
297
-                'main_model_name',
298
-                'related_model_name',
299
-                'id',
300
-                'count',
301
-                'nodes',
302
-            ],
303
-            parent::__sleep()
304
-        );
305
-    }
306
-
307
-
308
-    /**
309
-     * Use the dynamic properties to instantiate the models we use.
310
-     *
311
-     * @throws EE_Error
312
-     * @throws InvalidArgumentException
313
-     * @throws InvalidDataTypeException
314
-     * @throws InvalidInterfaceException
315
-     * @throws ReflectionException
316
-     */
317
-    public function __wakeup()
318
-    {
319
-        $this->main_model    = EE_Registry::instance()->load_model($this->main_model_name);
320
-        $this->related_model = EE_Registry::instance()->load_model($this->related_model_name);
321
-        parent::__wakeup();
322
-    }
27
+	protected ?int $count = null;
28
+
29
+	/**
30
+	 * @var string|int
31
+	 */
32
+	protected $id;
33
+
34
+	protected EEM_Base $main_model;
35
+
36
+	/**
37
+	 * @var ModelObjNode[]
38
+	 */
39
+	protected array $nodes;
40
+
41
+	protected EEM_Base $related_model;
42
+
43
+	public ?string $main_model_name = null;
44
+	public ?string $related_model_name = null;
45
+
46
+
47
+	/**
48
+	 * RelationNode constructor.
49
+	 *
50
+	 * @param          $main_model_obj_id
51
+	 * @param EEM_Base $main_model
52
+	 * @param EEM_Base $related_model
53
+	 * @param array    $dont_traverse_models array of model names we DON'T want to traverse
54
+	 */
55
+	public function __construct(
56
+		$main_model_obj_id,
57
+		EEM_Base $main_model,
58
+		EEM_Base $related_model,
59
+		array $dont_traverse_models = []
60
+	) {
61
+		$this->id                   = $main_model_obj_id;
62
+		$this->main_model           = $main_model;
63
+		$this->related_model        = $related_model;
64
+		$this->nodes                = [];
65
+		$this->dont_traverse_models = $dont_traverse_models;
66
+	}
67
+
68
+
69
+	/**
70
+	 * Here is where most of the work happens. We've counted how many related model objects exist, here we identify
71
+	 * them (ie, learn their IDs). But its recursive, so we'll also find their related dependent model objects etc.
72
+	 *
73
+	 * @param int $model_objects_to_identify
74
+	 * @return int
75
+	 * @throws EE_Error
76
+	 * @throws InvalidArgumentException
77
+	 * @throws InvalidDataTypeException
78
+	 * @throws InvalidInterfaceException
79
+	 * @throws ReflectionException
80
+	 */
81
+	protected function work($model_objects_to_identify)
82
+	{
83
+		$num_identified = $this->visitAlreadyDiscoveredNodes($this->nodes, $model_objects_to_identify);
84
+		if ($num_identified < $model_objects_to_identify) {
85
+			$related_model_objs = $this->related_model->get_all(
86
+				[
87
+					$this->whereQueryParams(),
88
+					'limit' => [
89
+						count($this->nodes),
90
+						$model_objects_to_identify - $num_identified,
91
+					],
92
+				]
93
+			);
94
+			$new_item_nodes     = [];
95
+
96
+			// Add entity nodes for each of the model objects we fetched.
97
+			foreach ($related_model_objs as $related_model_obj) {
98
+				$entity_node                                = new ModelObjNode(
99
+					$related_model_obj->ID(),
100
+					$related_model_obj->get_model(),
101
+					$this->dont_traverse_models
102
+				);
103
+				$this->nodes[ $related_model_obj->ID() ]    = $entity_node;
104
+				$new_item_nodes[ $related_model_obj->ID() ] = $entity_node;
105
+			}
106
+			$num_identified += count($new_item_nodes);
107
+			if ($num_identified < $model_objects_to_identify) {
108
+				// And lastly do the work.
109
+				$num_identified += $this->visitAlreadyDiscoveredNodes(
110
+					$new_item_nodes,
111
+					$model_objects_to_identify - $num_identified
112
+				);
113
+			}
114
+		}
115
+
116
+		if (count($this->nodes) >= $this->count && $this->allChildrenComplete()) {
117
+			$this->complete = true;
118
+		}
119
+		return $num_identified;
120
+	}
121
+
122
+
123
+	/**
124
+	 * Checks if all the identified child nodes are complete or not.
125
+	 *
126
+	 * @return bool
127
+	 */
128
+	protected function allChildrenComplete()
129
+	{
130
+		foreach ($this->nodes as $model_obj_node) {
131
+			if (! $model_obj_node->isComplete()) {
132
+				return false;
133
+			}
134
+		}
135
+		return true;
136
+	}
137
+
138
+
139
+	/**
140
+	 * Visits the provided nodes and keeps track of how much work was done, making sure to not go over budget.
141
+	 *
142
+	 * @param ModelObjNode[] $model_obj_nodes
143
+	 * @param                $work_budget
144
+	 * @return int
145
+	 */
146
+	protected function visitAlreadyDiscoveredNodes($model_obj_nodes, $work_budget)
147
+	{
148
+		$work_done = 0;
149
+		if (! $model_obj_nodes) {
150
+			return 0;
151
+		}
152
+		foreach ($model_obj_nodes as $model_obj_node) {
153
+			if ($work_done >= $work_budget) {
154
+				break;
155
+			}
156
+			$work_done += $model_obj_node->visit($work_budget - $work_done);
157
+		}
158
+		return $work_done;
159
+	}
160
+
161
+
162
+	/**
163
+	 * Whether this item has already been initialized
164
+	 */
165
+	protected function isDiscovered()
166
+	{
167
+		return $this->count !== null;
168
+	}
169
+
170
+
171
+	/**
172
+	 * @return boolean
173
+	 */
174
+	public function isComplete()
175
+	{
176
+		if ($this->complete === null) {
177
+			if (count($this->nodes) === $this->count) {
178
+				$this->complete = true;
179
+			} else {
180
+				$this->complete = false;
181
+			}
182
+		}
183
+		return $this->complete;
184
+	}
185
+
186
+
187
+	/**
188
+	 * Discovers how many related model objects exist.
189
+	 *
190
+	 * @return void
191
+	 * @throws EE_Error
192
+	 * @throws InvalidArgumentException
193
+	 * @throws InvalidDataTypeException
194
+	 * @throws InvalidInterfaceException
195
+	 */
196
+	protected function discover()
197
+	{
198
+		$this->count = $this->related_model->count([$this->whereQueryParams()]);
199
+	}
200
+
201
+
202
+	/**
203
+	 * @return array
204
+	 * @throws EE_Error
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 * @throws InvalidArgumentException
208
+	 */
209
+	protected function whereQueryParams()
210
+	{
211
+		$where_params = [
212
+			$this->related_model->get_foreign_key_to(
213
+				$this->main_model->get_this_model_name()
214
+			)->get_name() => $this->id,
215
+		];
216
+		try {
217
+			$relation_settings = $this->main_model->related_settings_for($this->related_model->get_this_model_name());
218
+		} catch (EE_Error $e) {
219
+			// This will happen for has-and-belongs-to-many relations, when this node's related model is that join table
220
+			// which hasn't been explicitly declared in the main model object's model's relations.
221
+			$relation_settings = null;
222
+		}
223
+		if ($relation_settings instanceof EE_Has_Many_Any_Relation) {
224
+			$where_params[ $this->related_model->get_field_containing_related_model_name()->get_name() ] =
225
+				$this->main_model->get_this_model_name();
226
+		}
227
+		return $where_params;
228
+	}
229
+
230
+
231
+	/**
232
+	 * @return array
233
+	 * @throws EE_Error
234
+	 * @throws ReflectionException
235
+	 */
236
+	public function toArray()
237
+	{
238
+		$tree = [
239
+			'count'    => $this->count,
240
+			'complete' => $this->isComplete(),
241
+			'objs'     => [],
242
+		];
243
+		foreach ($this->nodes as $id => $model_obj_node) {
244
+			$tree['objs'][ $id ] = $model_obj_node->toArray();
245
+		}
246
+		return $tree;
247
+	}
248
+
249
+
250
+	/**
251
+	 * Gets the IDs of all the model objects to delete; indexed first by model object name.
252
+	 *
253
+	 * @return array
254
+	 * @throws EE_Error
255
+	 * @throws ReflectionException
256
+	 */
257
+	public function getIds()
258
+	{
259
+		if (empty($this->nodes)) {
260
+			return [];
261
+		}
262
+		$ids = [
263
+			$this->related_model->get_this_model_name() => array_combine(
264
+				array_keys($this->nodes),
265
+				array_keys($this->nodes)
266
+			),
267
+		];
268
+		foreach ($this->nodes as $model_obj_node) {
269
+			$ids = array_replace_recursive($ids, $model_obj_node->getIds());
270
+		}
271
+		return $ids;
272
+	}
273
+
274
+
275
+	/**
276
+	 * Returns the number of sub-nodes found (ie, related model objects across this relation.)
277
+	 *
278
+	 * @return int
279
+	 */
280
+	public function countSubNodes()
281
+	{
282
+		return count($this->nodes);
283
+	}
284
+
285
+
286
+	/**
287
+	 * Don't serialize the models. Just record their names on some dynamic properties.
288
+	 *
289
+	 * @return array
290
+	 */
291
+	public function __sleep()
292
+	{
293
+		$this->main_model_name  = $this->main_model->get_this_model_name();
294
+		$this->related_model_name = $this->related_model->get_this_model_name();
295
+		return array_merge(
296
+			[
297
+				'main_model_name',
298
+				'related_model_name',
299
+				'id',
300
+				'count',
301
+				'nodes',
302
+			],
303
+			parent::__sleep()
304
+		);
305
+	}
306
+
307
+
308
+	/**
309
+	 * Use the dynamic properties to instantiate the models we use.
310
+	 *
311
+	 * @throws EE_Error
312
+	 * @throws InvalidArgumentException
313
+	 * @throws InvalidDataTypeException
314
+	 * @throws InvalidInterfaceException
315
+	 * @throws ReflectionException
316
+	 */
317
+	public function __wakeup()
318
+	{
319
+		$this->main_model    = EE_Registry::instance()->load_model($this->main_model_name);
320
+		$this->related_model = EE_Registry::instance()->load_model($this->related_model_name);
321
+		parent::__wakeup();
322
+	}
323 323
 }
324 324
 // End of file RelationNode.php
325 325
 // Location: EventEspresso\core\services\orm\tree_traversal/RelationNode.php
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -91,17 +91,17 @@  discard block
 block discarded – undo
91 91
                     ],
92 92
                 ]
93 93
             );
94
-            $new_item_nodes     = [];
94
+            $new_item_nodes = [];
95 95
 
96 96
             // Add entity nodes for each of the model objects we fetched.
97 97
             foreach ($related_model_objs as $related_model_obj) {
98
-                $entity_node                                = new ModelObjNode(
98
+                $entity_node = new ModelObjNode(
99 99
                     $related_model_obj->ID(),
100 100
                     $related_model_obj->get_model(),
101 101
                     $this->dont_traverse_models
102 102
                 );
103
-                $this->nodes[ $related_model_obj->ID() ]    = $entity_node;
104
-                $new_item_nodes[ $related_model_obj->ID() ] = $entity_node;
103
+                $this->nodes[$related_model_obj->ID()]    = $entity_node;
104
+                $new_item_nodes[$related_model_obj->ID()] = $entity_node;
105 105
             }
106 106
             $num_identified += count($new_item_nodes);
107 107
             if ($num_identified < $model_objects_to_identify) {
@@ -128,7 +128,7 @@  discard block
 block discarded – undo
128 128
     protected function allChildrenComplete()
129 129
     {
130 130
         foreach ($this->nodes as $model_obj_node) {
131
-            if (! $model_obj_node->isComplete()) {
131
+            if ( ! $model_obj_node->isComplete()) {
132 132
                 return false;
133 133
             }
134 134
         }
@@ -146,7 +146,7 @@  discard block
 block discarded – undo
146 146
     protected function visitAlreadyDiscoveredNodes($model_obj_nodes, $work_budget)
147 147
     {
148 148
         $work_done = 0;
149
-        if (! $model_obj_nodes) {
149
+        if ( ! $model_obj_nodes) {
150 150
             return 0;
151 151
         }
152 152
         foreach ($model_obj_nodes as $model_obj_node) {
@@ -221,7 +221,7 @@  discard block
 block discarded – undo
221 221
             $relation_settings = null;
222 222
         }
223 223
         if ($relation_settings instanceof EE_Has_Many_Any_Relation) {
224
-            $where_params[ $this->related_model->get_field_containing_related_model_name()->get_name() ] =
224
+            $where_params[$this->related_model->get_field_containing_related_model_name()->get_name()] =
225 225
                 $this->main_model->get_this_model_name();
226 226
         }
227 227
         return $where_params;
@@ -241,7 +241,7 @@  discard block
 block discarded – undo
241 241
             'objs'     => [],
242 242
         ];
243 243
         foreach ($this->nodes as $id => $model_obj_node) {
244
-            $tree['objs'][ $id ] = $model_obj_node->toArray();
244
+            $tree['objs'][$id] = $model_obj_node->toArray();
245 245
         }
246 246
         return $tree;
247 247
     }
@@ -290,7 +290,7 @@  discard block
 block discarded – undo
290 290
      */
291 291
     public function __sleep()
292 292
     {
293
-        $this->main_model_name  = $this->main_model->get_this_model_name();
293
+        $this->main_model_name = $this->main_model->get_this_model_name();
294 294
         $this->related_model_name = $this->related_model->get_this_model_name();
295 295
         return array_merge(
296 296
             [
Please login to merge, or discard this patch.
core/services/orm/tree_traversal/BaseNode.php 1 patch
Indentation   +87 added lines, -87 removed lines patch added patch discarded remove patch
@@ -31,106 +31,106 @@
 block discarded – undo
31 31
  */
32 32
 abstract class BaseNode
33 33
 {
34
-    protected ?bool $complete = null;
34
+	protected ?bool $complete = null;
35 35
 
36
-    /**
37
-     * @var array of model names we don't want to traverse
38
-     */
39
-    protected array $dont_traverse_models = [];
36
+	/**
37
+	 * @var array of model names we don't want to traverse
38
+	 */
39
+	protected array $dont_traverse_models = [];
40 40
 
41 41
 
42
-    public ?bool $sleep_complete = null;
43
-    public ?array $sleep_dtm = null;
42
+	public ?bool $sleep_complete = null;
43
+	public ?array $sleep_dtm = null;
44 44
 
45 45
 
46
-    /**
47
-     * Whether this item has already been initialized
48
-     */
49
-    abstract protected function isDiscovered();
46
+	/**
47
+	 * Whether this item has already been initialized
48
+	 */
49
+	abstract protected function isDiscovered();
50 50
 
51
-    /**
52
-     * Determines if the work is done yet or not. Requires you to have first discovered what work exists by calling
53
-     * discover().
54
-     * @since 4.10.12.p
55
-     * @return boolean
56
-     */
57
-    abstract public function isComplete();
51
+	/**
52
+	 * Determines if the work is done yet or not. Requires you to have first discovered what work exists by calling
53
+	 * discover().
54
+	 * @since 4.10.12.p
55
+	 * @return boolean
56
+	 */
57
+	abstract public function isComplete();
58 58
 
59
-    /**
60
-     * Discovers what work needs to be done to complete traversing this node and its children.
61
-     * Note that this is separate from the constructor, so we can create child nodes without
62
-     * discovering them immediately.
63
-     * @since 4.10.12.p
64
-     * @return mixed
65
-     */
66
-    abstract protected function discover();
59
+	/**
60
+	 * Discovers what work needs to be done to complete traversing this node and its children.
61
+	 * Note that this is separate from the constructor, so we can create child nodes without
62
+	 * discovering them immediately.
63
+	 * @since 4.10.12.p
64
+	 * @return mixed
65
+	 */
66
+	abstract protected function discover();
67 67
 
68
-    /**
69
-     * Identifies model objects, up to the limit $model_objects_to_identify.
70
-     * @since 4.10.12.p
71
-     * @param int $model_objects_to_identify
72
-     * @return int units of work done
73
-     */
74
-    abstract protected function work($model_objects_to_identify);
68
+	/**
69
+	 * Identifies model objects, up to the limit $model_objects_to_identify.
70
+	 * @since 4.10.12.p
71
+	 * @param int $model_objects_to_identify
72
+	 * @return int units of work done
73
+	 */
74
+	abstract protected function work($model_objects_to_identify);
75 75
 
76
-    /**
77
-     * Shows the entity/relation node as an array.
78
-     * @since 4.10.12.p
79
-     * @return array
80
-     */
81
-    abstract public function toArray();
76
+	/**
77
+	 * Shows the entity/relation node as an array.
78
+	 * @since 4.10.12.p
79
+	 * @return array
80
+	 */
81
+	abstract public function toArray();
82 82
 
83
-    /**
84
-     * Discovers how much work there is to do, double-checks the work isn't already finished, and then does the work.
85
-     * Note: do not call when site is in maintenance mode level 2.
86
-     *
87
-     * @since 4.10.12.p
88
-     * @param $model_objects_to_identify
89
-     * @return int number of model objects we want to identify during this call. On subsequent calls we'll continue
90
-     * where we left off.
91
-     */
92
-    public function visit($model_objects_to_identify)
93
-    {
94
-        if (! $this->isDiscovered()) {
95
-            $this->discover();
96
-        }
97
-        if ($this->isComplete()) {
98
-            return 0;
99
-        }
100
-        return $this->work($model_objects_to_identify);
101
-    }
83
+	/**
84
+	 * Discovers how much work there is to do, double-checks the work isn't already finished, and then does the work.
85
+	 * Note: do not call when site is in maintenance mode level 2.
86
+	 *
87
+	 * @since 4.10.12.p
88
+	 * @param $model_objects_to_identify
89
+	 * @return int number of model objects we want to identify during this call. On subsequent calls we'll continue
90
+	 * where we left off.
91
+	 */
92
+	public function visit($model_objects_to_identify)
93
+	{
94
+		if (! $this->isDiscovered()) {
95
+			$this->discover();
96
+		}
97
+		if ($this->isComplete()) {
98
+			return 0;
99
+		}
100
+		return $this->work($model_objects_to_identify);
101
+	}
102 102
 
103
-    /**
104
-     * Gets the IDs of completely identified model objects that can be deleted.
105
-     * @since 4.10.12.p
106
-     * @return mixed
107
-     */
108
-    abstract public function getIds();
103
+	/**
104
+	 * Gets the IDs of completely identified model objects that can be deleted.
105
+	 * @since 4.10.12.p
106
+	 * @return mixed
107
+	 */
108
+	abstract public function getIds();
109 109
 
110
-    /**
111
-     * Make sure we encode whether its complete or not, but don't use such a long name.
112
-     * @since 4.10.12.p
113
-     * @return array
114
-     */
115
-    public function __sleep()
116
-    {
117
-        $this->sleep_complete = $this->complete;
118
-        $this->sleep_dtm = $this->dont_traverse_models;
119
-        return [
120
-            'sleep_complete',
121
-            'sleep_dtm'
122
-        ];
123
-    }
110
+	/**
111
+	 * Make sure we encode whether its complete or not, but don't use such a long name.
112
+	 * @since 4.10.12.p
113
+	 * @return array
114
+	 */
115
+	public function __sleep()
116
+	{
117
+		$this->sleep_complete = $this->complete;
118
+		$this->sleep_dtm = $this->dont_traverse_models;
119
+		return [
120
+			'sleep_complete',
121
+			'sleep_dtm'
122
+		];
123
+	}
124 124
 
125
-    /**
126
-     * Use the dynamic property to set the "complete" property.
127
-     * @since 4.10.12.p
128
-     */
129
-    public function __wakeup()
130
-    {
131
-        $this->complete = $this->sleep_complete;
132
-        $this->dont_traverse_models = $this->sleep_dtm;
133
-    }
125
+	/**
126
+	 * Use the dynamic property to set the "complete" property.
127
+	 * @since 4.10.12.p
128
+	 */
129
+	public function __wakeup()
130
+	{
131
+		$this->complete = $this->sleep_complete;
132
+		$this->dont_traverse_models = $this->sleep_dtm;
133
+	}
134 134
 }
135 135
 // End of file BaseNode.php
136 136
 // Location: EventEspresso\core\services\orm\tree_traversal/BaseNode.php
Please login to merge, or discard this patch.
core/services/orm/tree_traversal/ModelObjNode.php 1 patch
Indentation   +214 added lines, -214 removed lines patch added patch discarded remove patch
@@ -23,220 +23,220 @@
 block discarded – undo
23 23
  */
24 24
 class ModelObjNode extends BaseNode
25 25
 {
26
-    /**
27
-     * @var int|string
28
-     */
29
-    protected $id;
30
-
31
-    /**
32
-     * @var EEM_Base
33
-     */
34
-    protected EEM_Base $model;
35
-
36
-    /**
37
-     * @var RelationNode[]|null
38
-     */
39
-    protected ?array $nodes = null;
40
-
41
-    public ?string $model_name = null;
42
-
43
-
44
-    /**
45
-     * We don't pass the model objects because this needs to serialize to something tiny for effiency.
46
-     *
47
-     * @param int|string $model_obj_id
48
-     * @param EEM_Base   $model
49
-     * @param array      $dont_traverse_models array of model names we DON'T want to traverse.
50
-     */
51
-    public function __construct($model_obj_id, EEM_Base $model, array $dont_traverse_models = [])
52
-    {
53
-        $this->id                   = $model_obj_id;
54
-        $this->model                = $model;
55
-        $this->dont_traverse_models = $dont_traverse_models;
56
-    }
57
-
58
-
59
-    /**
60
-     * Creates a relation node for each relation of this model's relations.
61
-     * Does NOT call `discover` on them yet though.
62
-     *
63
-     * @throws EE_Error
64
-     * @throws InvalidDataTypeException
65
-     * @throws InvalidInterfaceException
66
-     * @throws InvalidArgumentException
67
-     * @throws ReflectionException
68
-     * @since 4.10.12.p
69
-     */
70
-    protected function discover()
71
-    {
72
-        $this->nodes = [];
73
-        foreach ($this->model->relation_settings() as $relationName => $relation) {
74
-            // Make sure this isn't one of the models we were told to not traverse into.
75
-            if (in_array($relationName, $this->dont_traverse_models)) {
76
-                continue;
77
-            }
78
-            if ($relation instanceof EE_Has_Many_Relation) {
79
-                $this->nodes[ $relationName ] = new RelationNode(
80
-                    $this->id,
81
-                    $this->model,
82
-                    $relation->get_other_model(),
83
-                    $this->dont_traverse_models
84
-                );
85
-            } elseif (
86
-                $relation instanceof EE_HABTM_Relation &&
87
-                ! in_array(
88
-                    $relation->get_join_model()->get_this_model_name(),
89
-                    $this->dont_traverse_models
90
-                )
91
-            ) {
92
-                $this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode(
93
-                    $this->id,
94
-                    $this->model,
95
-                    $relation->get_join_model(),
96
-                    $this->dont_traverse_models
97
-                );
98
-            }
99
-        }
100
-        ksort($this->nodes);
101
-    }
102
-
103
-
104
-    /**
105
-     * Whether this item has already been initialized
106
-     */
107
-    protected function isDiscovered()
108
-    {
109
-        return is_array($this->nodes);
110
-    }
111
-
112
-    /**
113
-     * @since 4.10.12.p
114
-     * @return boolean
115
-     */
116
-    public function isComplete()
117
-    {
118
-        if ($this->complete === null) {
119
-            $this->complete = false;
120
-        }
121
-        return $this->complete;
122
-    }
123
-
124
-
125
-    /**
126
-     * Triggers working on each child relation node that has work to do.
127
-     *
128
-     * @param $model_objects_to_identify
129
-     * @return int units of work done
130
-     * @since 4.10.12.p
131
-     */
132
-    protected function work($model_objects_to_identify)
133
-    {
134
-        $num_identified = 0;
135
-        // Begin assuming we'll finish all the work on this node and its children...
136
-        $this->complete = true;
137
-        foreach ($this->nodes as $model_name => $relation_node) {
138
-            $num_identified += $relation_node->visit($model_objects_to_identify - $num_identified);
139
-            // To save on space when serializing, only bother keeping a record of relation nodes that actually found
140
-            // related model objects.
141
-            if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) {
142
-                unset($this->nodes[ $model_name ]);
143
-            }
144
-            if ($num_identified >= $model_objects_to_identify) {
145
-                // ...but admit we're wrong if the work exceeded the budget.
146
-                $this->complete = false;
147
-                break;
148
-            }
149
-        }
150
-        return $num_identified;
151
-    }
152
-
153
-
154
-    /**
155
-     * @return array
156
-     * @throws EE_Error
157
-     * @throws InvalidDataTypeException
158
-     * @throws InvalidInterfaceException
159
-     * @throws InvalidArgumentException
160
-     * @throws ReflectionException
161
-     * @since 4.10.12.p
162
-     */
163
-    public function toArray()
164
-    {
165
-        $tree = [
166
-            'id'       => $this->id,
167
-            'complete' => $this->isComplete(),
168
-            'rels'     => [],
169
-        ];
170
-        if ($this->nodes === null) {
171
-            $tree['rels'] = null;
172
-        } else {
173
-            foreach ($this->nodes as $relation_name => $relation_node) {
174
-                $tree['rels'][ $relation_name ] = $relation_node->toArray();
175
-            }
176
-        }
177
-        return $tree;
178
-    }
179
-
180
-
181
-    /**
182
-     * @return array|mixed
183
-     * @throws InvalidArgumentException
184
-     * @throws InvalidDataTypeException
185
-     * @throws InvalidInterfaceException
186
-     * @throws ReflectionException
187
-     * @throws EE_Error
188
-     * @since 4.10.12.p
189
-     */
190
-    public function getIds()
191
-    {
192
-        $ids = [
193
-            $this->model->get_this_model_name() => [
194
-                $this->id => $this->id,
195
-            ],
196
-        ];
197
-        if ($this->nodes && is_array($this->nodes)) {
198
-            foreach ($this->nodes as $relation_node) {
199
-                $ids = array_replace_recursive($ids, $relation_node->getIds());
200
-            }
201
-        }
202
-        return $ids;
203
-    }
204
-
205
-
206
-    /**
207
-     * Don't serialize the models. Just record their names on some dynamic properties.
208
-     *
209
-     * @since 4.10.12.p
210
-     */
211
-    public function __sleep()
212
-    {
213
-        $this->model_name = $this->model->get_this_model_name();
214
-        return array_merge(
215
-            [
216
-                'model_name',
217
-                'id',
218
-                'nodes',
219
-            ],
220
-            parent::__sleep()
221
-        );
222
-    }
223
-
224
-
225
-    /**
226
-     * Use the dynamic properties to instantiate the models we use.
227
-     *
228
-     * @throws EE_Error
229
-     * @throws InvalidArgumentException
230
-     * @throws InvalidDataTypeException
231
-     * @throws InvalidInterfaceException
232
-     * @throws ReflectionException
233
-     * @since 4.10.12.p
234
-     */
235
-    public function __wakeup()
236
-    {
237
-        $this->model = EE_Registry::instance()->load_model($this->model_name);
238
-        parent::__wakeup();
239
-    }
26
+	/**
27
+	 * @var int|string
28
+	 */
29
+	protected $id;
30
+
31
+	/**
32
+	 * @var EEM_Base
33
+	 */
34
+	protected EEM_Base $model;
35
+
36
+	/**
37
+	 * @var RelationNode[]|null
38
+	 */
39
+	protected ?array $nodes = null;
40
+
41
+	public ?string $model_name = null;
42
+
43
+
44
+	/**
45
+	 * We don't pass the model objects because this needs to serialize to something tiny for effiency.
46
+	 *
47
+	 * @param int|string $model_obj_id
48
+	 * @param EEM_Base   $model
49
+	 * @param array      $dont_traverse_models array of model names we DON'T want to traverse.
50
+	 */
51
+	public function __construct($model_obj_id, EEM_Base $model, array $dont_traverse_models = [])
52
+	{
53
+		$this->id                   = $model_obj_id;
54
+		$this->model                = $model;
55
+		$this->dont_traverse_models = $dont_traverse_models;
56
+	}
57
+
58
+
59
+	/**
60
+	 * Creates a relation node for each relation of this model's relations.
61
+	 * Does NOT call `discover` on them yet though.
62
+	 *
63
+	 * @throws EE_Error
64
+	 * @throws InvalidDataTypeException
65
+	 * @throws InvalidInterfaceException
66
+	 * @throws InvalidArgumentException
67
+	 * @throws ReflectionException
68
+	 * @since 4.10.12.p
69
+	 */
70
+	protected function discover()
71
+	{
72
+		$this->nodes = [];
73
+		foreach ($this->model->relation_settings() as $relationName => $relation) {
74
+			// Make sure this isn't one of the models we were told to not traverse into.
75
+			if (in_array($relationName, $this->dont_traverse_models)) {
76
+				continue;
77
+			}
78
+			if ($relation instanceof EE_Has_Many_Relation) {
79
+				$this->nodes[ $relationName ] = new RelationNode(
80
+					$this->id,
81
+					$this->model,
82
+					$relation->get_other_model(),
83
+					$this->dont_traverse_models
84
+				);
85
+			} elseif (
86
+				$relation instanceof EE_HABTM_Relation &&
87
+				! in_array(
88
+					$relation->get_join_model()->get_this_model_name(),
89
+					$this->dont_traverse_models
90
+				)
91
+			) {
92
+				$this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode(
93
+					$this->id,
94
+					$this->model,
95
+					$relation->get_join_model(),
96
+					$this->dont_traverse_models
97
+				);
98
+			}
99
+		}
100
+		ksort($this->nodes);
101
+	}
102
+
103
+
104
+	/**
105
+	 * Whether this item has already been initialized
106
+	 */
107
+	protected function isDiscovered()
108
+	{
109
+		return is_array($this->nodes);
110
+	}
111
+
112
+	/**
113
+	 * @since 4.10.12.p
114
+	 * @return boolean
115
+	 */
116
+	public function isComplete()
117
+	{
118
+		if ($this->complete === null) {
119
+			$this->complete = false;
120
+		}
121
+		return $this->complete;
122
+	}
123
+
124
+
125
+	/**
126
+	 * Triggers working on each child relation node that has work to do.
127
+	 *
128
+	 * @param $model_objects_to_identify
129
+	 * @return int units of work done
130
+	 * @since 4.10.12.p
131
+	 */
132
+	protected function work($model_objects_to_identify)
133
+	{
134
+		$num_identified = 0;
135
+		// Begin assuming we'll finish all the work on this node and its children...
136
+		$this->complete = true;
137
+		foreach ($this->nodes as $model_name => $relation_node) {
138
+			$num_identified += $relation_node->visit($model_objects_to_identify - $num_identified);
139
+			// To save on space when serializing, only bother keeping a record of relation nodes that actually found
140
+			// related model objects.
141
+			if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) {
142
+				unset($this->nodes[ $model_name ]);
143
+			}
144
+			if ($num_identified >= $model_objects_to_identify) {
145
+				// ...but admit we're wrong if the work exceeded the budget.
146
+				$this->complete = false;
147
+				break;
148
+			}
149
+		}
150
+		return $num_identified;
151
+	}
152
+
153
+
154
+	/**
155
+	 * @return array
156
+	 * @throws EE_Error
157
+	 * @throws InvalidDataTypeException
158
+	 * @throws InvalidInterfaceException
159
+	 * @throws InvalidArgumentException
160
+	 * @throws ReflectionException
161
+	 * @since 4.10.12.p
162
+	 */
163
+	public function toArray()
164
+	{
165
+		$tree = [
166
+			'id'       => $this->id,
167
+			'complete' => $this->isComplete(),
168
+			'rels'     => [],
169
+		];
170
+		if ($this->nodes === null) {
171
+			$tree['rels'] = null;
172
+		} else {
173
+			foreach ($this->nodes as $relation_name => $relation_node) {
174
+				$tree['rels'][ $relation_name ] = $relation_node->toArray();
175
+			}
176
+		}
177
+		return $tree;
178
+	}
179
+
180
+
181
+	/**
182
+	 * @return array|mixed
183
+	 * @throws InvalidArgumentException
184
+	 * @throws InvalidDataTypeException
185
+	 * @throws InvalidInterfaceException
186
+	 * @throws ReflectionException
187
+	 * @throws EE_Error
188
+	 * @since 4.10.12.p
189
+	 */
190
+	public function getIds()
191
+	{
192
+		$ids = [
193
+			$this->model->get_this_model_name() => [
194
+				$this->id => $this->id,
195
+			],
196
+		];
197
+		if ($this->nodes && is_array($this->nodes)) {
198
+			foreach ($this->nodes as $relation_node) {
199
+				$ids = array_replace_recursive($ids, $relation_node->getIds());
200
+			}
201
+		}
202
+		return $ids;
203
+	}
204
+
205
+
206
+	/**
207
+	 * Don't serialize the models. Just record their names on some dynamic properties.
208
+	 *
209
+	 * @since 4.10.12.p
210
+	 */
211
+	public function __sleep()
212
+	{
213
+		$this->model_name = $this->model->get_this_model_name();
214
+		return array_merge(
215
+			[
216
+				'model_name',
217
+				'id',
218
+				'nodes',
219
+			],
220
+			parent::__sleep()
221
+		);
222
+	}
223
+
224
+
225
+	/**
226
+	 * Use the dynamic properties to instantiate the models we use.
227
+	 *
228
+	 * @throws EE_Error
229
+	 * @throws InvalidArgumentException
230
+	 * @throws InvalidDataTypeException
231
+	 * @throws InvalidInterfaceException
232
+	 * @throws ReflectionException
233
+	 * @since 4.10.12.p
234
+	 */
235
+	public function __wakeup()
236
+	{
237
+		$this->model = EE_Registry::instance()->load_model($this->model_name);
238
+		parent::__wakeup();
239
+	}
240 240
 }
241 241
 // End of file Visitor.php
242 242
 // Location: EventEspresso\core\services\orm\tree_traversal/Visitor.php
Please login to merge, or discard this patch.
core/services/orm/model_field/SchemaType.php 1 patch
Indentation   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -11,61 +11,61 @@
 block discarded – undo
11 11
  */
12 12
 class SchemaType
13 13
 {
14
-    const ARRAY   = 'array';
14
+	const ARRAY   = 'array';
15 15
 
16
-    const BOOLEAN = 'boolean';
16
+	const BOOLEAN = 'boolean';
17 17
 
18
-    const DB_FIELD = 'db_field';
18
+	const DB_FIELD = 'db_field';
19 19
 
20
-    const FLOAT = 'number';
20
+	const FLOAT = 'number';
21 21
 
22
-    const INTEGER = 'integer';
22
+	const INTEGER = 'integer';
23 23
 
24
-    const NULL    = 'null';
24
+	const NULL    = 'null';
25 25
 
26
-    const NUMBER  = 'number';
26
+	const NUMBER  = 'number';
27 27
 
28
-    const OBJECT  = 'object';
28
+	const OBJECT  = 'object';
29 29
 
30
-    const STRING  = 'string';
30
+	const STRING  = 'string';
31 31
 
32 32
 
33
-    /**
34
-     * @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
35
-     * @var array|string[]
36
-     */
37
-    private static array $allowable_types = [
38
-        SchemaType::ARRAY,
39
-        SchemaType::BOOLEAN,
40
-        SchemaType::FLOAT,
41
-        SchemaType::INTEGER,
42
-        SchemaType::NULL,
43
-        SchemaType::NUMBER,
44
-        SchemaType::OBJECT,
45
-        SchemaType::STRING,
46
-    ];
33
+	/**
34
+	 * @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
35
+	 * @var array|string[]
36
+	 */
37
+	private static array $allowable_types = [
38
+		SchemaType::ARRAY,
39
+		SchemaType::BOOLEAN,
40
+		SchemaType::FLOAT,
41
+		SchemaType::INTEGER,
42
+		SchemaType::NULL,
43
+		SchemaType::NUMBER,
44
+		SchemaType::OBJECT,
45
+		SchemaType::STRING,
46
+	];
47 47
 
48 48
 
49
-    /**
50
-     * Validates the incoming string|array to ensure its an allowable type.
51
-     *
52
-     * @param string $schema_type
53
-     * @throws InvalidArgumentException
54
-     */
55
-    public static function validateSchemaType(string $schema_type)
56
-    {
57
-        if (in_array($schema_type, SchemaType::$allowable_types, true)) {
58
-            return;
59
-        }
60
-        throw new InvalidArgumentException(
61
-            sprintf(
62
-                esc_html__(
63
-                    'The incoming argument (%1$s) must be one of the allowable types: %2$s',
64
-                    'event_espresso'
65
-                ),
66
-                $schema_type,
67
-                implode(',', SchemaType::$allowable_types)
68
-            )
69
-        );
70
-    }
49
+	/**
50
+	 * Validates the incoming string|array to ensure its an allowable type.
51
+	 *
52
+	 * @param string $schema_type
53
+	 * @throws InvalidArgumentException
54
+	 */
55
+	public static function validateSchemaType(string $schema_type)
56
+	{
57
+		if (in_array($schema_type, SchemaType::$allowable_types, true)) {
58
+			return;
59
+		}
60
+		throw new InvalidArgumentException(
61
+			sprintf(
62
+				esc_html__(
63
+					'The incoming argument (%1$s) must be one of the allowable types: %2$s',
64
+					'event_espresso'
65
+				),
66
+				$schema_type,
67
+				implode(',', SchemaType::$allowable_types)
68
+			)
69
+		);
70
+	}
71 71
 }
Please login to merge, or discard this patch.
core/services/orm/model_field/SchemaFormat.php 1 patch
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -9,56 +9,56 @@
 block discarded – undo
9 9
  */
10 10
 class SchemaFormat
11 11
 {
12
-    const DATETIME = 'date-time';
12
+	const DATETIME = 'date-time';
13 13
 
14
-    const EMAIL    = 'email';
14
+	const EMAIL    = 'email';
15 15
 
16
-    const HOSTNAME = 'hostname';
16
+	const HOSTNAME = 'hostname';
17 17
 
18
-    const IPV4     = 'ipv4';
18
+	const IPV4     = 'ipv4';
19 19
 
20
-    const IPV6     = 'ipv6';
20
+	const IPV6     = 'ipv6';
21 21
 
22
-    const URI      = 'uri';
22
+	const URI      = 'uri';
23 23
 
24
-    const URIREF   = 'uriref';
24
+	const URIREF   = 'uriref';
25 25
 
26 26
 
27
-    /**
28
-     * @var array|string[]
29
-     * @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
30
-     */
31
-    private static array $allowable_formats = [
32
-        SchemaFormat::DATETIME,
33
-        SchemaFormat::EMAIL,
34
-        SchemaFormat::HOSTNAME,
35
-        SchemaFormat::IPV4,
36
-        SchemaFormat::IPV6,
37
-        SchemaFormat::URI,
38
-        SchemaFormat::URIREF,
39
-    ];
27
+	/**
28
+	 * @var array|string[]
29
+	 * @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
30
+	 */
31
+	private static array $allowable_formats = [
32
+		SchemaFormat::DATETIME,
33
+		SchemaFormat::EMAIL,
34
+		SchemaFormat::HOSTNAME,
35
+		SchemaFormat::IPV4,
36
+		SchemaFormat::IPV6,
37
+		SchemaFormat::URI,
38
+		SchemaFormat::URIREF,
39
+	];
40 40
 
41 41
 
42
-    /**
43
-     * Validates that the incoming format is an allowable string to use for the _schema_format property
44
-     *
45
-     * @param string $schema_format
46
-     * @throws InvalidArgumentException
47
-     */
48
-    public static function validateSchemaFormat(string $schema_format)
49
-    {
50
-        if (in_array($schema_format, SchemaFormat::$allowable_formats, true)) {
51
-            return;
52
-        }
53
-        throw new InvalidArgumentException(
54
-            sprintf(
55
-                esc_html__(
56
-                    'The incoming argument (%1$s) must be one of the allowable formats: %2$s',
57
-                    'event_espresso'
58
-                ),
59
-                $schema_format,
60
-                implode(',', SchemaFormat::$allowable_formats)
61
-            )
62
-        );
63
-    }
42
+	/**
43
+	 * Validates that the incoming format is an allowable string to use for the _schema_format property
44
+	 *
45
+	 * @param string $schema_format
46
+	 * @throws InvalidArgumentException
47
+	 */
48
+	public static function validateSchemaFormat(string $schema_format)
49
+	{
50
+		if (in_array($schema_format, SchemaFormat::$allowable_formats, true)) {
51
+			return;
52
+		}
53
+		throw new InvalidArgumentException(
54
+			sprintf(
55
+				esc_html__(
56
+					'The incoming argument (%1$s) must be one of the allowable formats: %2$s',
57
+					'event_espresso'
58
+				),
59
+				$schema_format,
60
+				implode(',', SchemaFormat::$allowable_formats)
61
+			)
62
+		);
63
+	}
64 64
 }
Please login to merge, or discard this patch.
core/services/calculators/LineItemCalculator.php 2 patches
Indentation   +934 added lines, -934 removed lines patch added patch discarded remove patch
@@ -21,938 +21,938 @@
 block discarded – undo
21 21
  */
22 22
 class LineItemCalculator
23 23
 {
24
-    use DebugDisplay;
25
-
26
-    protected DecimalValues $decimal_values;
27
-
28
-    protected array $default_query_params = [];
29
-
30
-
31
-    /**
32
-     * @param DecimalValues $decimal_values
33
-     */
34
-    public function __construct(DecimalValues $decimal_values)
35
-    {
36
-        $this->decimal_values = $decimal_values;
37
-        $this->initializeDebugDisplay();
38
-    }
39
-
40
-
41
-    /**
42
-     * Gets the final total on this item, taking taxes into account.
43
-     * Has the side effect of setting the sub-total as it was just calculated.
44
-     * If this is used on a grand-total line item, also updates the transaction's
45
-     * TXN_total (provided this line item is allowed to persist, otherwise we don't
46
-     * want to change a persistable transaction with info from a non-persistent line item)
47
-     *
48
-     * @param EE_Line_Item $line_item
49
-     * @param bool         $update_txn_status
50
-     * @return float
51
-     * @throws EE_Error
52
-     * @throws ReflectionException
53
-     */
54
-    public function recalculateTotalIncludingTaxes(EE_Line_Item $line_item, bool $update_txn_status = false): float
55
-    {
56
-        $this->debugLog('', 2);
57
-        $this->debugLog(__METHOD__);
58
-        $this->debugLog(str_repeat('*', strlen(__METHOD__)), 2);
59
-        $this->debugLog(">>> TXN : " . $line_item->TXN_ID(), 2);
60
-        $this->validateLineItemAndType($line_item, EEM_Line_Item::type_total);
61
-        $ticket_line_items = EEH_Line_Item::get_ticket_line_items($line_item);
62
-        if (empty($ticket_line_items)) {
63
-            // no tickets? ensure totals are zero
64
-            $this->updatePreTaxTotal($line_item, 0);
65
-            $this->updateTotal($line_item, 0);
66
-            $this->updateTransaction($line_item, 0, $update_txn_status);
67
-            return 0;
68
-        }
69
-        [, $pretax_total] = $this->recalculateLineItemTotals($line_item);
70
-        // EEH_Line_Item::visualize($line_item);
71
-        $total_tax = $this->recalculateTaxesAndTaxTotal($line_item);
72
-        // no negative totals plz
73
-        $grand_total = max($pretax_total + $total_tax, 0);
74
-        $this->updatePreTaxTotal($line_item, $pretax_total, true);
75
-        $grand_total = $this->updateTotal($line_item, $grand_total, true);
76
-        $this->updateTransaction($line_item, $grand_total, $update_txn_status);
77
-        return $grand_total;
78
-    }
79
-
80
-
81
-    /**
82
-     * Recursively goes through all the children and recalculates sub-totals EXCEPT for
83
-     * tax-sub-totals (they're an odd beast). Updates the 'total' on each line item according to either its
84
-     * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and
85
-     * when this is called on the grand total
86
-     *
87
-     * @param EE_Line_Item $line_item
88
-     * @param float        $total
89
-     * @param float        $pretax_total
90
-     * @param bool         $is_taxable
91
-     * @return array
92
-     * @throws EE_Error
93
-     * @throws ReflectionException
94
-     */
95
-    public function recalculateLineItemTotals(
96
-        EE_Line_Item $line_item,
97
-        float $total = 0,
98
-        float $pretax_total = 0,
99
-        bool $is_taxable = false
100
-    ): array {
101
-        $this->debugLog(__FUNCTION__);
102
-        $OBJ = $line_item->OBJ_type();
103
-        $OBJ .= $OBJ ? ': ' : '';
104
-        $this->debugLog(
105
-            ' * ' . $OBJ . $line_item->name() . ' - ' . $line_item->type() . ' (' . $line_item->code() . ')',
106
-            2
107
-        );
108
-        $this->debugLog(" * total: $total", 3);
109
-        $this->debugLog(" * pretax: $pretax_total", 3);
110
-        switch ($line_item->type()) {
111
-            case EEM_Line_Item::type_total:
112
-            case EEM_Line_Item::type_sub_total:
113
-                [$total, $pretax_total] = $this->recalculateSubTotal($line_item);
114
-                break;
115
-
116
-            case EEM_Line_Item::type_line_item:
117
-                [$total, $pretax_total] = $this->recalculateLineItem($line_item, $total, $pretax_total);
118
-                break;
119
-
120
-            case EEM_Line_Item::type_sub_line_item:
121
-            case EEM_Line_Item::type_cancellation:
122
-                // sub-line-items operate on the total and update both the total AND the pre-tax total
123
-                [$total, $pretax_total] = $this->recalculateSubLineItem($line_item, $total, $pretax_total, $is_taxable);
124
-                break;
125
-
126
-            case EEM_Line_Item::type_sub_tax:
127
-                // sub-line-items taxes ONLY operate on the pre-tax total and ONLY update the total
128
-                [$total, $pretax_total] = $this->recalculateSubTax($line_item, $pretax_total);
129
-                break;
130
-
131
-            case EEM_Line_Item::type_tax_sub_total:
132
-            case EEM_Line_Item::type_tax:
133
-                // completely ignore tax totals, tax sub-totals, and cancelled line items
134
-                // when calculating the pre-tax-total
135
-                $total = $pretax_total = 0;
136
-                break;
137
-        }
138
-        return [$total, $pretax_total];
139
-    }
140
-
141
-
142
-    /**
143
-     * @param EE_Line_Item $line_item
144
-     * @return array
145
-     * @throws EE_Error
146
-     * @throws ReflectionException
147
-     */
148
-    private function recalculateSubTotal(EE_Line_Item $line_item): array
149
-    {
150
-        $this->debugLog(__FUNCTION__);
151
-        // reset the total and pretax total to zero since we are recalculating them
152
-        $total = $pretax_total = 0;
153
-        if ($line_item->is_total()) {
154
-            // if this is the grand total line item
155
-            // then first update ALL the line item quantities (if need be)
156
-            $this->updateLineItemQuantities($line_item);
157
-        }
158
-        // recursively loop through children and recalculate their totals
159
-        $children = $line_item->children($this->default_query_params);
160
-        if (empty($children)) {
161
-            $this->debugLog(' - ' . __FUNCTION__, 3);
162
-            $this->debugLog(" - - total : $total ", 3);
163
-            $this->debugLog(" - - pretax: $pretax_total ", 3);
164
-            return [$total, $pretax_total];
165
-        }
166
-        foreach ($children as $child_line_item) {
167
-            [$child_total, $child_pretax_total] = $this->recalculateLineItemTotals(
168
-                $child_line_item,
169
-                $total,
170
-                $pretax_total
171
-            );
172
-            $total        += $child_total;
173
-            $pretax_total += $child_pretax_total;
174
-        }
175
-        // update the unit price and pretax total
176
-        $this->updateUnitPrice($line_item, $pretax_total, false);
177
-        $pretax_total = $this->updatePreTaxTotal($line_item, $pretax_total, true, false);
178
-        $this->debugLog(' - ' . __FUNCTION__, 3);
179
-        $this->debugLog(" - - line_item->name() : " . $line_item->name(), 3);
180
-        $this->debugLog(" - - line_item->code() : " . $line_item->code(), 3);
181
-        // for the actual pre-tax sub-total line item, we want to save the pretax value for everything
182
-        if ($line_item->is_sub_total() && $line_item->code() === 'pre-tax-subtotal') {
183
-            $this->updateTotal($line_item, $pretax_total, true);
184
-        } elseif (! $line_item->is_total()) {
185
-            // we don't update the total for the total line item, because that will need to include taxes
186
-            $total = $this->updateTotal($line_item, $total, true);
187
-        }
188
-        $this->debugLog(' - ' . __FUNCTION__, 3);
189
-        $this->debugLog(" - - total : $total ", 3);
190
-        $this->debugLog(" - - pretax: $pretax_total ", 3);
191
-        return [$total, $pretax_total];
192
-    }
193
-
194
-
195
-    /**
196
-     * @param EE_Line_Item $line_item
197
-     * @param float        $total
198
-     * @param float        $pretax_total
199
-     * @return array
200
-     * @throws EE_Error
201
-     * @throws ReflectionException
202
-     */
203
-    private function recalculateLineItem(
204
-        EE_Line_Item $line_item,
205
-        float $total = 0,
206
-        float $pretax_total = 0
207
-    ): array {
208
-        $this->debugLog(__FUNCTION__);
209
-        $this->reorderSubLineItems($line_item);
210
-        [$total, $pretax_total] = $line_item->is_percent()
211
-            ? $this->recalculatePercentageLineItem($line_item, $total, $pretax_total)
212
-            : $this->recalculateNonPercentageLineItem($line_item);
213
-
214
-        $total        = $this->updateTotal($line_item, $total, true);
215
-        $pretax_total = $this->updatePreTaxTotal($line_item, $pretax_total, true);
216
-
217
-        // need to also adjust unit price too if the pretax total or quantity has been updated
218
-        $this->updateUnitPrice($line_item, $pretax_total);
219
-        $this->debugLog(' - ' . __FUNCTION__, 3);
220
-        $this->debugLog(" - - total : $total", 3);
221
-        $this->debugLog(" - - pretax: $pretax_total", 3);
222
-        return [$total, $pretax_total];
223
-    }
224
-
225
-
226
-    /**
227
-     * @param EE_Line_Item $line_item
228
-     * @param float        $total
229
-     * @param float        $pretax_total
230
-     * @return float[]
231
-     * @throws EE_Error
232
-     * @throws ReflectionException
233
-     * @since 5.0.12.p
234
-     */
235
-    private function recalculatePercentageLineItem(
236
-        EE_Line_Item $line_item,
237
-        float $total = 0,
238
-        float $pretax_total = 0
239
-    ): array {
240
-        $this->debugLog(' % ' . __FUNCTION__, 2);
241
-        $pretax_total = $this->calculatePercentage($pretax_total, $line_item->percent());
242
-        // if the line item is taxable, then we need to calculate the total,
243
-        // otherwise we can just use the pretax total
244
-        $total = $line_item->is_taxable()
245
-            ? $this->calculatePercentage($total, $line_item->percent())
246
-            : $pretax_total;
247
-        $this->debugLog(' % ' . __FUNCTION__, 3);
248
-        $this->debugLog(" % % total : $total ", 3);
249
-        $this->debugLog(" % % pretax: $pretax_total ", 3);
250
-        return [$total, $pretax_total];
251
-    }
252
-
253
-
254
-    /**
255
-     * @param EE_Line_Item $line_item
256
-     * @return float[]
257
-     * @throws EE_Error
258
-     * @throws ReflectionException
259
-     * @since 5.0.12.p
260
-     */
261
-    private function recalculateNonPercentageLineItem(
262
-        EE_Line_Item $line_item
263
-    ): array {
264
-        $this->debugLog(' $ ' . __FUNCTION__, 2);
265
-        // recursively loop through children and recalculate their totals
266
-        $children = $line_item->children($this->default_query_params);
267
-        if (! empty($children)) {
268
-            // reset the total and pretax total to zero since we are recalculating them
269
-            $total = $pretax_total = 0;
270
-            foreach ($children as $child_line_item) {
271
-                [$child_total, $child_pretax_total] = $this->recalculateLineItemTotals(
272
-                    $child_line_item,
273
-                    $total,
274
-                    $pretax_total,
275
-                    $line_item->is_taxable()
276
-                );
277
-                $this->debugLog(' $ $ ' . __FUNCTION__, 3);
278
-                $this->debugLog(
279
-                    ' $ $ $ ' . $child_line_item->name() . ' '
280
-                    . $child_line_item->type() . ' ' . $child_line_item->code(),
281
-                    3
282
-                );
283
-                $this->debugLog(" $ $ $ $ child total: $child_total", 3);
284
-                $this->debugLog(" $ $ $ $ child pretax: $child_pretax_total", 3);
285
-                $total        += $child_total;
286
-                $pretax_total += $child_pretax_total;
287
-            }
288
-        } else {
289
-            // no child line items, so recalculate the total from the unit price and quantity
290
-            // and set the pretax total to match since there are obviously no sub-taxes
291
-            $pretax_total = $total = $this->calculateTotalForQuantity($line_item);
292
-        }
293
-        $this->debugLog(' $ ' . __FUNCTION__, 3);
294
-        $this->debugLog(' $ $ ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
295
-        $this->debugLog(" $ $ $ total: $total", 3);
296
-        $this->debugLog(" $ $ $ pretax: $pretax_total", 3);
297
-        return [$total, $pretax_total];
298
-    }
299
-
300
-
301
-    /**
302
-     * @param EE_Line_Item $sub_line_item
303
-     * @param float|int    $total
304
-     * @param float|int    $pretax_total
305
-     * @param bool         $is_taxable
306
-     * @return float[]
307
-     * @throws EE_Error
308
-     * @throws ReflectionException
309
-     */
310
-    private function recalculateSubLineItem(
311
-        EE_Line_Item $sub_line_item,
312
-        float $total = 0,
313
-        float $pretax_total = 0,
314
-        bool $is_taxable = false
315
-    ): array {
316
-        $this->debugLog(__FUNCTION__);
317
-        $total = $is_taxable ? $total : $pretax_total;
318
-        if ($sub_line_item->is_percent()) {
319
-            $new_total        = $this->calculatePercentage($total, $sub_line_item->percent());
320
-            $new_pretax_total = $this->calculatePercentage($pretax_total, $sub_line_item->percent());
321
-        } else {
322
-            $new_total = $new_pretax_total = $this->calculateTotalForQuantity($sub_line_item);
323
-        }
324
-        $total        = $this->updateTotal($sub_line_item, $new_total, false, false);
325
-        $pretax_total = $this->updatePreTaxTotal($sub_line_item, $new_pretax_total, false, false);
326
-        // need to also adjust unit price too if the pretax total or quantity has been updated
327
-        $this->updateUnitPrice($sub_line_item, $pretax_total);
328
-        $this->debugLog(" - - total : $total ", 3);
329
-        $this->debugLog(" - - pretax: $pretax_total ", 3);
330
-        return [$total, $pretax_total];
331
-    }
332
-
333
-
334
-    /**
335
-     * @param EE_Line_Item $sub_line_item
336
-     * @param float|int    $pretax_total
337
-     * @return float[]
338
-     * @throws EE_Error
339
-     * @throws ReflectionException
340
-     */
341
-    private function recalculateSubTax(EE_Line_Item $sub_line_item, float $pretax_total = 0): array
342
-    {
343
-        $this->debugLog(__FUNCTION__);
344
-        $total_tax = $this->calculatePercentage($pretax_total, $sub_line_item->percent());
345
-        $total_tax = $this->updateTotal($sub_line_item, $total_tax);
346
-        $this->debugLog(" - total_tax : $total_tax ", 3);
347
-        return [$total_tax, 0];
348
-    }
349
-
350
-
351
-    /**
352
-     * recursively loops through the entire line item tree updating line item quantities accordingly.
353
-     * this needs to be done prior to running any other calculations for reasons that are hopefully obvious :p
354
-     *
355
-     * @param EE_Line_Item $line_item
356
-     * @param int          $quantity
357
-     * @return int
358
-     * @throws EE_Error
359
-     * @throws ReflectionException
360
-     */
361
-    private function updateLineItemQuantities(EE_Line_Item $line_item, int $quantity = 1): int
362
-    {
363
-        switch ($line_item->type()) {
364
-            case EEM_Line_Item::type_total:
365
-            case EEM_Line_Item::type_sub_total:
366
-            case EEM_Line_Item::type_tax_sub_total:
367
-                // first, loop through children and set their quantities
368
-                $count    = 0;
369
-                $children = $line_item->children($this->default_query_params);
370
-                foreach ($children as $child_line_item) {
371
-                    $count += $this->updateLineItemQuantities($child_line_item);
372
-                }
373
-                // totals and subtotals should have a quantity of 1
374
-                // unless their children have all been removed, in which case we can set them to 0
375
-                $quantity = $count > 0 ? 1 : 0;
376
-                $this->updateQuantity($line_item, $quantity);
377
-                return $quantity;
378
-
379
-            case EEM_Line_Item::type_line_item:
380
-                // line items should ALREADY have accurate quantities set, if not, then somebody done goofed!
381
-                // but if this is a percentage based line item, then ensure its quantity is 1
382
-                if ($line_item->is_percent()) {
383
-                    $this->updateQuantity($line_item, 1);
384
-                }
385
-                // and we also need to loop through all the sub items and ensure those quantities match this parent.
386
-                $children = $line_item->children($this->default_query_params);
387
-                $quantity = $line_item->quantity();
388
-                foreach ($children as $child_line_item) {
389
-                    $this->updateLineItemQuantities($child_line_item, $quantity);
390
-                }
391
-                // percentage line items should not increment their parent's count, so they return 0
392
-                return ! $line_item->is_percent() ? $quantity : 0;
393
-
394
-            case EEM_Line_Item::type_sub_line_item:
395
-                // percentage based items need their quantity set to 1,
396
-                // all others use the incoming value from the parent line item
397
-                $quantity = $line_item->is_percent() ? 1 : $quantity;
398
-                $this->updateQuantity($line_item, $quantity);
399
-                // percentage line items should not increment their parent's count, so they return 0
400
-                return ! $line_item->is_percent() ? $quantity : 0;
401
-
402
-            case EEM_Line_Item::type_tax:
403
-            case EEM_Line_Item::type_sub_tax:
404
-                // taxes should have a quantity of 1
405
-                $this->updateQuantity($line_item, 1);
406
-                return 1;
407
-
408
-            case EEM_Line_Item::type_cancellation:
409
-                // cancellations will be ignored for all calculations
410
-                // because their parent quantities should have already been adjusted when they were added
411
-                // so assume that things are already set correctly
412
-                return 0;
413
-        }
414
-        return 0;
415
-    }
416
-
417
-
418
-    /**
419
-     * @param float $total
420
-     * @param float $percent
421
-     * @param bool  $round
422
-     * @return float
423
-     */
424
-    private function calculatePercentage(float $total, float $percent, bool $round = false): float
425
-    {
426
-        $amount = $total * $percent / 100;
427
-        $amount = $this->decimal_values->roundDecimalValue($amount, $round);
428
-        $this->debugLog(' % ' . __FUNCTION__, 2);
429
-        $this->debugLog(" % % total: $total", 3);
430
-        $this->debugLog(" % % percent: $percent", 3);
431
-        $this->debugLog(" % % amount: $amount", 3);
432
-        return $amount;
433
-    }
434
-
435
-
436
-    /**
437
-     * @param EE_Line_Item $line_item
438
-     * @return float
439
-     * @throws EE_Error
440
-     * @throws ReflectionException
441
-     */
442
-    private function calculateTotalForQuantity(EE_Line_Item $line_item): float
443
-    {
444
-        $this->debugLog(' # ' . __FUNCTION__, 2);
445
-        $this->debugLog(' # # ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
446
-        $this->debugLog(" # # # unit_price: " . $line_item->unit_price(), 3);
447
-        $this->debugLog(" # # # quantity: " . $line_item->quantity(), 3);
448
-        $total = $line_item->unit_price() * $line_item->quantity();
449
-        return $this->decimal_values->roundDecimalValue($total);
450
-    }
451
-
452
-
453
-    /**
454
-     * @param EE_Line_Item $line_item
455
-     * @param float        $percent
456
-     * @throws EE_Error
457
-     * @throws ReflectionException
458
-     */
459
-    private function updatePercent(EE_Line_Item $line_item, float $percent)
460
-    {
461
-        // update and save new percent only if incoming value does not match existing value
462
-        if ($line_item->percent() !== $percent) {
463
-            $line_item->set_percent($percent);
464
-            $line_item->maybe_save();
465
-        }
466
-    }
467
-
468
-
469
-    /**
470
-     * @param EE_Line_Item $line_item
471
-     * @param float        $pretax_total
472
-     * @param bool         $round
473
-     * @param bool         $save
474
-     * @return float
475
-     * @throws EE_Error
476
-     * @throws ReflectionException
477
-     */
478
-    private function updatePreTaxTotal(
479
-        EE_Line_Item $line_item,
480
-        float $pretax_total,
481
-        bool $round = false,
482
-        bool $save = true
483
-    ): float {
484
-        $pretax_total = $this->decimal_values->roundDecimalValue($pretax_total, $round);
485
-        $sign = $line_item->type() === EEM_Line_Item::type_cancellation ? -1 : 1;
486
-        $pretax_total = $sign * $pretax_total;
487
-        $this->debugLog(' ? ' . __FUNCTION__, 2);
488
-        $this->debugLog(' ??? ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
489
-        $this->debugLog(" ????? SIGN: $sign  &&  pretax_total: $pretax_total", 3);
490
-        // update and save new total only if incoming value does not match existing value
491
-        if ($line_item->preTaxTotal() !== $pretax_total) {
492
-            $line_item->setPreTaxTotal($pretax_total);
493
-            if ($save) {
494
-                $line_item->maybe_save();
495
-            }
496
-        }
497
-        return $pretax_total;
498
-    }
499
-
500
-
501
-    /**
502
-     * @param EE_Line_Item $line_item
503
-     * @param int          $quantity
504
-     * @throws EE_Error
505
-     * @throws ReflectionException
506
-     */
507
-    private function updateQuantity(EE_Line_Item $line_item, int $quantity)
508
-    {
509
-        // update and save new quantity only if incoming value does not match existing value
510
-        if ($line_item->quantity() !== $quantity) {
511
-            $line_item->set_quantity($quantity);
512
-            $line_item->maybe_save();
513
-        }
514
-    }
515
-
516
-
517
-    /**
518
-     * @param EE_Line_Item $line_item
519
-     * @param float        $total
520
-     * @param bool         $round
521
-     * @param bool         $save
522
-     * @return float
523
-     * @throws EE_Error
524
-     * @throws ReflectionException
525
-     */
526
-    private function updateTotal(EE_Line_Item $line_item, float $total, bool $round = false, bool $save = true): float
527
-    {
528
-        $total = $this->decimal_values->roundDecimalValue($total, $round);
529
-        $sign = $line_item->type() === EEM_Line_Item::type_cancellation ? -1 : 1;
530
-        $total = $sign * $total;
531
-        $this->debugLog(' ? ' . __FUNCTION__, 2);
532
-        $this->debugLog(' ??? ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
533
-        $this->debugLog(" ????? SIGN: $sign  &&  total: $total", 3);
534
-        // update and save new total only if incoming value does not match existing value
535
-        if ($line_item->total() !== $total) {
536
-            $line_item->set_total($total);
537
-            if ($save) {
538
-                $line_item->maybe_save();
539
-            }
540
-        }
541
-        return (float) $total;
542
-    }
543
-
544
-
545
-    /**
546
-     * @param EE_Line_Item $line_item
547
-     * @param float        $total
548
-     * @param bool         $update_status
549
-     * @return void
550
-     * @throws EE_Error
551
-     * @throws ReflectionException
552
-     */
553
-    private function updateTransaction(EE_Line_Item $line_item, float $total, bool $update_status)
554
-    {
555
-        // only update the related transaction's total
556
-        // if we intend to save this line item and it's a grand total
557
-        if ($line_item->allow_persist()) {
558
-            $transaction = $line_item->transaction();
559
-            if ($transaction instanceof EE_Transaction) {
560
-                $transaction->set_total($total);
561
-                if ($update_status) {
562
-                    // don't save the TXN because that will be done below
563
-                    // and the following method only saves if the status changes
564
-                    $transaction->update_status_based_on_total_paid(false);
565
-                }
566
-                if ($transaction->ID()) {
567
-                    $transaction->save();
568
-                }
569
-            }
570
-        }
571
-    }
572
-
573
-
574
-    /**
575
-     * @param EE_Line_Item $line_item
576
-     * @param float        $pretax_total
577
-     * @param bool         $save
578
-     * @return void
579
-     * @throws EE_Error
580
-     * @throws ReflectionException
581
-     */
582
-    private function updateUnitPrice(EE_Line_Item $line_item, float $pretax_total, bool $save = true)
583
-    {
584
-        $quantity = $line_item->quantity();
585
-        // don't divide by zero else you'll create a singularity and implode the interweb
586
-        // we also don't set unit prices for percentage based line items
587
-        if ($quantity === 0 || $line_item->is_percent()) {
588
-            return;
589
-        }
590
-        $new_unit_price = $pretax_total / $quantity;
591
-        $new_unit_price = $this->decimal_values->roundDecimalValue($new_unit_price);
592
-        $sign = $line_item->type() === EEM_Line_Item::type_cancellation ? -1 : 1;
593
-        $new_unit_price = $sign * $new_unit_price;
594
-        $this->debugLog(' ? ' . __FUNCTION__, 2);
595
-        $this->debugLog(' ??? ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
596
-        $this->debugLog(" ????? SIGN: $sign  &&  new_unit_price: $new_unit_price", 3);
597
-        // update and save new total only if incoming value does not match existing value
598
-        if ($line_item->unit_price() !== $new_unit_price) {
599
-            $this->debugLog(' @ ' . __FUNCTION__, 3);
600
-            $this->debugLog(' @ @ ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
601
-            $this->debugLog(" @ @ @ pretax: $pretax_total", 3);
602
-            $this->debugLog(" @ @ @ quantity: $quantity", 3);
603
-            $this->debugLog(" @ @ @ old unit price: " . $line_item->unit_price(), 3);
604
-            $this->debugLog(" @ @ @ new unit price: $new_unit_price", 3);
605
-            $line_item->set_unit_price($new_unit_price);
606
-            if ($save) {
607
-                $line_item->maybe_save();
608
-            }
609
-        }
610
-    }
611
-
612
-
613
-    /**
614
-     * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets
615
-     * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items
616
-     * and tax sub-total if already in the DB
617
-     *
618
-     * @param EE_Line_Item $total_line_item
619
-     * @return float
620
-     * @throws EE_Error
621
-     * @throws ReflectionException
622
-     */
623
-    public function recalculateTaxesAndTaxTotal(EE_Line_Item $total_line_item): float
624
-    {
625
-        $this->debugLog(__FUNCTION__, 3);
626
-        $this->validateLineItemAndType($total_line_item, EEM_Line_Item::type_total);
627
-        // calculate the total taxable amount for globally applied taxes
628
-        $taxable_total    = $this->taxableAmountForGlobalTaxes($total_line_item);
629
-        [$total_tax, $global_taxes ]    = $this->applyGlobalTaxes($total_line_item, $taxable_total);
630
-        $non_global_taxes = $this->calculateNonGlobalTaxes($total_line_item);
631
-        $all_tax_total    = $this->applyNonGlobalTaxes($total_line_item, $total_tax, $global_taxes, $non_global_taxes);
632
-        $this->recalculateTaxSubTotal($total_line_item);
633
-        $this->debugLog(" - taxable_total : $taxable_total", 4);
634
-        $this->debugLog(" - total_tax : $total_tax", 4);
635
-        $this->debugLog(" - all_tax_total : $all_tax_total", 4);
636
-        return $all_tax_total;
637
-    }
638
-
639
-
640
-    /**
641
-     * @param EE_Line_Item $total_line_item
642
-     * @param float        $taxable_total
643
-     * @return array
644
-     * @throws EE_Error
645
-     * @throws ReflectionException
646
-     */
647
-    private function applyGlobalTaxes(EE_Line_Item $total_line_item, float $taxable_total): array
648
-    {
649
-        $this->debugLog(__FUNCTION__, 4);
650
-        $this->validateLineItemAndType($total_line_item, EEM_Line_Item::type_total);
651
-        $total_tax = 0;
652
-        if ($taxable_total === 0.0) {
653
-            return [0, []];
654
-        }
655
-        // loop through all global taxes all taxes
656
-        $global_taxes = $total_line_item->tax_descendants();
657
-        foreach ($global_taxes as $tax) {
658
-            $tax_total = $this->calculatePercentage($taxable_total, $tax->percent());
659
-            if ($tax_total === 0.0) {
660
-                $tax->delete();
661
-                continue;
662
-            }
663
-            $tax_total = $this->updateTotal($tax, $tax_total, true);
664
-            $total_tax += $tax_total;
665
-        }
666
-        return [$this->decimal_values->roundDecimalValue($total_tax, true), $global_taxes];
667
-    }
668
-
669
-
670
-    /**
671
-     * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated
672
-     *
673
-     * @param EE_Line_Item $line_item
674
-     * @return void
675
-     * @throws EE_Error
676
-     * @throws ReflectionException
677
-     */
678
-    private function recalculateTaxSubTotal(EE_Line_Item $line_item)
679
-    {
680
-        $this->debugLog(__FUNCTION__, 4);
681
-        $this->validateLineItemAndType($line_item, EEM_Line_Item::type_total);
682
-        foreach ($line_item->children() as $maybe_tax_subtotal) {
683
-            if (
684
-                $this->validateLineItemAndType($maybe_tax_subtotal)
685
-                && $maybe_tax_subtotal->is_tax_sub_total()
686
-            ) {
687
-                $total         = 0;
688
-                $total_percent = 0;
689
-                // simply loop through all its children (which should be taxes) and sum their total
690
-                foreach ($maybe_tax_subtotal->children() as $child_tax) {
691
-                    if ($this->validateLineItemAndType($child_tax) && $child_tax->isGlobalTax()) {
692
-                        $total         += $child_tax->total();
693
-                        $total_percent += $child_tax->percent();
694
-                    }
695
-                }
696
-                $this->updateTotal($maybe_tax_subtotal, $total, true);
697
-                $this->updatePercent($maybe_tax_subtotal, $total_percent);
698
-            }
699
-        }
700
-    }
701
-
702
-
703
-    /**
704
-     * returns an array of tax details like:
705
-     *  [
706
-     *      'GST_7' => [
707
-     *          'name'  => 'GST',
708
-     *          'rate'  => float(7),
709
-     *          'total' => float(4.9),
710
-     *      ]
711
-     *  ]
712
-     *
713
-     * @param EE_Line_Item $total_line_item
714
-     * @param array        $non_global_taxes
715
-     * @param float        $line_item_total
716
-     * @return array
717
-     * @throws EE_Error
718
-     * @throws ReflectionException
719
-     */
720
-    private function calculateNonGlobalTaxes(
721
-        EE_Line_Item $total_line_item,
722
-        array $non_global_taxes = [],
723
-        float $line_item_total = 0
724
-    ): array {
725
-        $this->debugLog(__FUNCTION__, 4);
726
-        foreach ($total_line_item->children() as $line_item) {
727
-            if ($this->validateLineItemAndType($line_item)) {
728
-                if ($line_item->is_sub_total()) {
729
-                    $non_global_taxes = $this->calculateNonGlobalTaxes($line_item, $non_global_taxes);
730
-                } elseif ($line_item->is_line_item()) {
731
-                    $non_global_taxes = $this->calculateNonGlobalTaxes(
732
-                        $line_item,
733
-                        $non_global_taxes,
734
-                        $line_item->pretaxTotal()
735
-                    );
736
-                } elseif ($line_item->isSubTax()) {
737
-                    $tax_ID = $line_item->name() . '_' . $line_item->percent();
738
-                    if (! isset($non_global_taxes[ $tax_ID ])) {
739
-                        $non_global_taxes[ $tax_ID ] = [
740
-                            'name'  => $line_item->name(),
741
-                            'rate'  => $line_item->percent(),
742
-                            'total' => 0,
743
-                            'obj'   => $line_item->OBJ_type(),
744
-                            'objID' => $line_item->OBJ_ID(),
745
-                        ];
746
-                    }
747
-                    $tax = $this->calculatePercentage($line_item_total, $line_item->percent());
748
-
749
-                    $non_global_taxes[ $tax_ID ]['total'] += $tax;
750
-                }
751
-            }
752
-        }
753
-        return $non_global_taxes;
754
-    }
755
-
756
-
757
-    /**
758
-     * @param EE_Line_Item   $total_line_item
759
-     * @param float          $tax_total
760
-     * @param EE_Line_Item[] $global_taxes array of tax line items returned from applyGlobalTaxes()
761
-     * @param array          $non_global_taxes array of tax details generated by calculateNonGlobalTaxes()
762
-     * @return float
763
-     * @throws EE_Error
764
-     * @throws ReflectionException
765
-     */
766
-    private function applyNonGlobalTaxes(
767
-        EE_Line_Item $total_line_item,
768
-        float $tax_total,
769
-        array $global_taxes,
770
-        array $non_global_taxes
771
-    ): float {
772
-        $this->debugLog(__FUNCTION__, 4);
773
-        $taxes_subtotal = EEH_Line_Item::get_taxes_subtotal($total_line_item);
774
-        foreach ($non_global_taxes as $non_global_tax) {
775
-            $found = false;
776
-            foreach ($global_taxes as $global_tax) {
777
-                if (
778
-                    $this->validateLineItemAndType($global_tax)
779
-                    && $non_global_tax['obj'] === $global_tax->OBJ_type()
780
-                    && $non_global_tax['objID'] === $global_tax->OBJ_ID()
781
-                ) {
782
-                    $found     = true;
783
-                    $new_total = $global_tax->total() + $non_global_tax['total'];
784
-                    // add non-global tax to matching global tax AND the tax total
785
-                    $global_tax->set_total($new_total);
786
-                    $global_tax->maybe_save();
787
-                    $tax_total += $non_global_tax['total'];
788
-                }
789
-            }
790
-            if (! $found) {
791
-                // add a new line item for this non-global tax
792
-                $taxes_subtotal->add_child_line_item(
793
-                    EE_Line_Item::new_instance(
794
-                        [
795
-                            'LIN_name'       => $non_global_tax['name'],
796
-                            'LIN_percent'    => $non_global_tax['rate'],
797
-                            'LIN_is_taxable' => false,
798
-                            'LIN_total'      => $non_global_tax['total'],
799
-                            'LIN_type'       => EEM_Line_Item::type_tax,
800
-                            'OBJ_type'       => $non_global_tax['obj'],
801
-                            'OBJ_ID'         => $non_global_tax['objID'],
802
-                        ]
803
-                    )
804
-                );
805
-                $tax_total += $non_global_tax['total'];
806
-            }
807
-        }
808
-        return $this->decimal_values->roundDecimalValue($tax_total, true);
809
-    }
810
-
811
-
812
-    /**
813
-     * Gets the total tax on this line item. Assumes taxes have already been calculated using
814
-     * recalculate_taxes_and_total
815
-     *
816
-     * @param EE_Line_Item $line_item
817
-     * @return float
818
-     * @throws EE_Error
819
-     * @throws ReflectionException
820
-     */
821
-    public function getTotalTax(EE_Line_Item $line_item): float
822
-    {
823
-        $this->validateLineItemAndType($line_item, EEM_Line_Item::type_total);
824
-        $this->recalculateTaxSubTotal($line_item);
825
-        $total = 0;
826
-        foreach ($line_item->tax_descendants() as $tax_line_item) {
827
-            if ($this->validateLineItemAndType($tax_line_item)) {
828
-                $total += $tax_line_item->total();
829
-            }
830
-        }
831
-        return $this->decimal_values->roundDecimalValue($total, true);
832
-    }
833
-
834
-
835
-    /**
836
-     * Returns the amount taxable among this line item's children (or if it has no children,
837
-     * how much of it is taxable). Does not recalculate totals or subtotals.
838
-     * If the taxable total is negative, (eg, if none of the tickets were taxable,
839
-     * but there is a "Taxable" discount), returns 0.
840
-     *
841
-     * @param EE_Line_Item|null $line_item
842
-     * @return float
843
-     * @throws EE_Error
844
-     * @throws ReflectionException
845
-     */
846
-    public function taxableAmountForGlobalTaxes(?EE_Line_Item $line_item): float
847
-    {
848
-        $this->debugLog(__FUNCTION__, 4);
849
-        $total            = 0;
850
-        $child_line_items = $line_item->children($this->default_query_params);
851
-        foreach ($child_line_items as $child_line_item) {
852
-            $this->validateLineItemAndType($child_line_item);
853
-            if ($child_line_item->is_sub_total()) {
854
-                $total += $this->taxableAmountForGlobalTaxes($child_line_item);
855
-            } elseif ($child_line_item->is_line_item() && $child_line_item->is_taxable()) {
856
-                // if it's a percent item, only take into account
857
-                // the percentage that's taxable (the taxable total so far)
858
-                if ($child_line_item->is_percent()) {
859
-                    $total += $this->calculatePercentage($total, $child_line_item->percent(), true);
860
-                } else {
861
-                    // pretax total will be equal to the total for line items with globally applied taxes
862
-                    $pretax_total = $this->calculateTotalForQuantity($child_line_item);
863
-                    $total        += $this->updatePreTaxTotal($child_line_item, $pretax_total);
864
-                }
865
-            }
866
-        }
867
-        return max($total, 0);
868
-    }
869
-
870
-
871
-    /**
872
-     * @param EE_Line_Item|null $line_item
873
-     * @param string|null       $type
874
-     * @return bool
875
-     * @throws EE_Error
876
-     * @throws ReflectionException
877
-     */
878
-    private function validateLineItemAndType(?EE_Line_Item $line_item, ?string $type = null): bool
879
-    {
880
-        if (! $line_item instanceof EE_Line_Item) {
881
-            throw new DomainException(
882
-                esc_html__('Invalid or missing Line Item supplied .', 'event_espresso')
883
-            );
884
-        }
885
-        if ($type && $line_item->type() !== $type) {
886
-            throw new DomainException(
887
-                sprintf(
888
-                    esc_html__(
889
-                        'Invalid Line Item type supplied. Received "%1$s" but expected "%2$s".',
890
-                        'event_espresso'
891
-                    ),
892
-                    $line_item->type(),
893
-                    $type
894
-                )
895
-            );
896
-        }
897
-        return true;
898
-    }
899
-
900
-
901
-    /**
902
-     * loops through all sub-line-items for the supplied line item and reorders them as follows:
903
-     * 1. sub items
904
-     * 2. other??? (not a sub-item or sub-tax)
905
-     * 3. sub taxes
906
-     *
907
-     * @param EE_Line_Item $line_item
908
-     * @return void
909
-     * @throws EE_Error
910
-     * @throws ReflectionException
911
-     * @since 5.0.12.p
912
-     */
913
-    public function reorderSubLineItems(EE_Line_Item $line_item)
914
-    {
915
-        if ($line_item->type() !== EEM_Line_Item::type_line_item) {
916
-            return;
917
-        }
918
-        $this->debugLog(' + LineItemCalculator::reorderSubLineItems', 3);
919
-        $this->debugLog(
920
-            ' + + ' . $line_item->OBJ_type() . ' ' . $line_item->name()
921
-            . ' - ' . $line_item->type() . ' (' . $line_item->code() . ')',
922
-            3
923
-        );
924
-        $sub_line_items = $line_item->children();
925
-        $items          = [];
926
-        $other          = [];
927
-        $taxes          = [];
928
-        foreach ($sub_line_items as $sub_line_item) {
929
-            switch ($sub_line_item->type()) {
930
-                case EEM_Line_Item::type_sub_line_item:
931
-                    $items[ $sub_line_item->ID() ] = $sub_line_item;
932
-                    break;
933
-                case EEM_Line_Item::type_sub_tax:
934
-                    $taxes[ $sub_line_item->ID() ] = $sub_line_item;
935
-                    break;
936
-                default:
937
-                    $other[ $sub_line_item->ID() ] = $sub_line_item;
938
-            }
939
-        }
940
-        $order      = 0;
941
-        $line_items = apply_filters(
942
-            'FHEE__EventEspresso_core_services_calculators_LineItemCalculator__reorderSubLineItems__line_items',
943
-            ['items' => $items, 'other' => $other, 'taxes' => $taxes]
944
-        );
945
-        foreach ($line_items as $sub_items) {
946
-            foreach ($sub_items as $sub_item) {
947
-                $order++;
948
-                $sub_item->set_order($order);
949
-                $sub_item->save();
950
-                $this->debugLog(
951
-                    ' + + + ' . $order . '. ' . $sub_item->OBJ_type() . ' ' . $sub_item->name()
952
-                    . ' - ' . $sub_item->type() . ' (' . $sub_item->code() . ')',
953
-                    3
954
-                );
955
-            }
956
-        }
957
-    }
24
+	use DebugDisplay;
25
+
26
+	protected DecimalValues $decimal_values;
27
+
28
+	protected array $default_query_params = [];
29
+
30
+
31
+	/**
32
+	 * @param DecimalValues $decimal_values
33
+	 */
34
+	public function __construct(DecimalValues $decimal_values)
35
+	{
36
+		$this->decimal_values = $decimal_values;
37
+		$this->initializeDebugDisplay();
38
+	}
39
+
40
+
41
+	/**
42
+	 * Gets the final total on this item, taking taxes into account.
43
+	 * Has the side effect of setting the sub-total as it was just calculated.
44
+	 * If this is used on a grand-total line item, also updates the transaction's
45
+	 * TXN_total (provided this line item is allowed to persist, otherwise we don't
46
+	 * want to change a persistable transaction with info from a non-persistent line item)
47
+	 *
48
+	 * @param EE_Line_Item $line_item
49
+	 * @param bool         $update_txn_status
50
+	 * @return float
51
+	 * @throws EE_Error
52
+	 * @throws ReflectionException
53
+	 */
54
+	public function recalculateTotalIncludingTaxes(EE_Line_Item $line_item, bool $update_txn_status = false): float
55
+	{
56
+		$this->debugLog('', 2);
57
+		$this->debugLog(__METHOD__);
58
+		$this->debugLog(str_repeat('*', strlen(__METHOD__)), 2);
59
+		$this->debugLog(">>> TXN : " . $line_item->TXN_ID(), 2);
60
+		$this->validateLineItemAndType($line_item, EEM_Line_Item::type_total);
61
+		$ticket_line_items = EEH_Line_Item::get_ticket_line_items($line_item);
62
+		if (empty($ticket_line_items)) {
63
+			// no tickets? ensure totals are zero
64
+			$this->updatePreTaxTotal($line_item, 0);
65
+			$this->updateTotal($line_item, 0);
66
+			$this->updateTransaction($line_item, 0, $update_txn_status);
67
+			return 0;
68
+		}
69
+		[, $pretax_total] = $this->recalculateLineItemTotals($line_item);
70
+		// EEH_Line_Item::visualize($line_item);
71
+		$total_tax = $this->recalculateTaxesAndTaxTotal($line_item);
72
+		// no negative totals plz
73
+		$grand_total = max($pretax_total + $total_tax, 0);
74
+		$this->updatePreTaxTotal($line_item, $pretax_total, true);
75
+		$grand_total = $this->updateTotal($line_item, $grand_total, true);
76
+		$this->updateTransaction($line_item, $grand_total, $update_txn_status);
77
+		return $grand_total;
78
+	}
79
+
80
+
81
+	/**
82
+	 * Recursively goes through all the children and recalculates sub-totals EXCEPT for
83
+	 * tax-sub-totals (they're an odd beast). Updates the 'total' on each line item according to either its
84
+	 * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and
85
+	 * when this is called on the grand total
86
+	 *
87
+	 * @param EE_Line_Item $line_item
88
+	 * @param float        $total
89
+	 * @param float        $pretax_total
90
+	 * @param bool         $is_taxable
91
+	 * @return array
92
+	 * @throws EE_Error
93
+	 * @throws ReflectionException
94
+	 */
95
+	public function recalculateLineItemTotals(
96
+		EE_Line_Item $line_item,
97
+		float $total = 0,
98
+		float $pretax_total = 0,
99
+		bool $is_taxable = false
100
+	): array {
101
+		$this->debugLog(__FUNCTION__);
102
+		$OBJ = $line_item->OBJ_type();
103
+		$OBJ .= $OBJ ? ': ' : '';
104
+		$this->debugLog(
105
+			' * ' . $OBJ . $line_item->name() . ' - ' . $line_item->type() . ' (' . $line_item->code() . ')',
106
+			2
107
+		);
108
+		$this->debugLog(" * total: $total", 3);
109
+		$this->debugLog(" * pretax: $pretax_total", 3);
110
+		switch ($line_item->type()) {
111
+			case EEM_Line_Item::type_total:
112
+			case EEM_Line_Item::type_sub_total:
113
+				[$total, $pretax_total] = $this->recalculateSubTotal($line_item);
114
+				break;
115
+
116
+			case EEM_Line_Item::type_line_item:
117
+				[$total, $pretax_total] = $this->recalculateLineItem($line_item, $total, $pretax_total);
118
+				break;
119
+
120
+			case EEM_Line_Item::type_sub_line_item:
121
+			case EEM_Line_Item::type_cancellation:
122
+				// sub-line-items operate on the total and update both the total AND the pre-tax total
123
+				[$total, $pretax_total] = $this->recalculateSubLineItem($line_item, $total, $pretax_total, $is_taxable);
124
+				break;
125
+
126
+			case EEM_Line_Item::type_sub_tax:
127
+				// sub-line-items taxes ONLY operate on the pre-tax total and ONLY update the total
128
+				[$total, $pretax_total] = $this->recalculateSubTax($line_item, $pretax_total);
129
+				break;
130
+
131
+			case EEM_Line_Item::type_tax_sub_total:
132
+			case EEM_Line_Item::type_tax:
133
+				// completely ignore tax totals, tax sub-totals, and cancelled line items
134
+				// when calculating the pre-tax-total
135
+				$total = $pretax_total = 0;
136
+				break;
137
+		}
138
+		return [$total, $pretax_total];
139
+	}
140
+
141
+
142
+	/**
143
+	 * @param EE_Line_Item $line_item
144
+	 * @return array
145
+	 * @throws EE_Error
146
+	 * @throws ReflectionException
147
+	 */
148
+	private function recalculateSubTotal(EE_Line_Item $line_item): array
149
+	{
150
+		$this->debugLog(__FUNCTION__);
151
+		// reset the total and pretax total to zero since we are recalculating them
152
+		$total = $pretax_total = 0;
153
+		if ($line_item->is_total()) {
154
+			// if this is the grand total line item
155
+			// then first update ALL the line item quantities (if need be)
156
+			$this->updateLineItemQuantities($line_item);
157
+		}
158
+		// recursively loop through children and recalculate their totals
159
+		$children = $line_item->children($this->default_query_params);
160
+		if (empty($children)) {
161
+			$this->debugLog(' - ' . __FUNCTION__, 3);
162
+			$this->debugLog(" - - total : $total ", 3);
163
+			$this->debugLog(" - - pretax: $pretax_total ", 3);
164
+			return [$total, $pretax_total];
165
+		}
166
+		foreach ($children as $child_line_item) {
167
+			[$child_total, $child_pretax_total] = $this->recalculateLineItemTotals(
168
+				$child_line_item,
169
+				$total,
170
+				$pretax_total
171
+			);
172
+			$total        += $child_total;
173
+			$pretax_total += $child_pretax_total;
174
+		}
175
+		// update the unit price and pretax total
176
+		$this->updateUnitPrice($line_item, $pretax_total, false);
177
+		$pretax_total = $this->updatePreTaxTotal($line_item, $pretax_total, true, false);
178
+		$this->debugLog(' - ' . __FUNCTION__, 3);
179
+		$this->debugLog(" - - line_item->name() : " . $line_item->name(), 3);
180
+		$this->debugLog(" - - line_item->code() : " . $line_item->code(), 3);
181
+		// for the actual pre-tax sub-total line item, we want to save the pretax value for everything
182
+		if ($line_item->is_sub_total() && $line_item->code() === 'pre-tax-subtotal') {
183
+			$this->updateTotal($line_item, $pretax_total, true);
184
+		} elseif (! $line_item->is_total()) {
185
+			// we don't update the total for the total line item, because that will need to include taxes
186
+			$total = $this->updateTotal($line_item, $total, true);
187
+		}
188
+		$this->debugLog(' - ' . __FUNCTION__, 3);
189
+		$this->debugLog(" - - total : $total ", 3);
190
+		$this->debugLog(" - - pretax: $pretax_total ", 3);
191
+		return [$total, $pretax_total];
192
+	}
193
+
194
+
195
+	/**
196
+	 * @param EE_Line_Item $line_item
197
+	 * @param float        $total
198
+	 * @param float        $pretax_total
199
+	 * @return array
200
+	 * @throws EE_Error
201
+	 * @throws ReflectionException
202
+	 */
203
+	private function recalculateLineItem(
204
+		EE_Line_Item $line_item,
205
+		float $total = 0,
206
+		float $pretax_total = 0
207
+	): array {
208
+		$this->debugLog(__FUNCTION__);
209
+		$this->reorderSubLineItems($line_item);
210
+		[$total, $pretax_total] = $line_item->is_percent()
211
+			? $this->recalculatePercentageLineItem($line_item, $total, $pretax_total)
212
+			: $this->recalculateNonPercentageLineItem($line_item);
213
+
214
+		$total        = $this->updateTotal($line_item, $total, true);
215
+		$pretax_total = $this->updatePreTaxTotal($line_item, $pretax_total, true);
216
+
217
+		// need to also adjust unit price too if the pretax total or quantity has been updated
218
+		$this->updateUnitPrice($line_item, $pretax_total);
219
+		$this->debugLog(' - ' . __FUNCTION__, 3);
220
+		$this->debugLog(" - - total : $total", 3);
221
+		$this->debugLog(" - - pretax: $pretax_total", 3);
222
+		return [$total, $pretax_total];
223
+	}
224
+
225
+
226
+	/**
227
+	 * @param EE_Line_Item $line_item
228
+	 * @param float        $total
229
+	 * @param float        $pretax_total
230
+	 * @return float[]
231
+	 * @throws EE_Error
232
+	 * @throws ReflectionException
233
+	 * @since 5.0.12.p
234
+	 */
235
+	private function recalculatePercentageLineItem(
236
+		EE_Line_Item $line_item,
237
+		float $total = 0,
238
+		float $pretax_total = 0
239
+	): array {
240
+		$this->debugLog(' % ' . __FUNCTION__, 2);
241
+		$pretax_total = $this->calculatePercentage($pretax_total, $line_item->percent());
242
+		// if the line item is taxable, then we need to calculate the total,
243
+		// otherwise we can just use the pretax total
244
+		$total = $line_item->is_taxable()
245
+			? $this->calculatePercentage($total, $line_item->percent())
246
+			: $pretax_total;
247
+		$this->debugLog(' % ' . __FUNCTION__, 3);
248
+		$this->debugLog(" % % total : $total ", 3);
249
+		$this->debugLog(" % % pretax: $pretax_total ", 3);
250
+		return [$total, $pretax_total];
251
+	}
252
+
253
+
254
+	/**
255
+	 * @param EE_Line_Item $line_item
256
+	 * @return float[]
257
+	 * @throws EE_Error
258
+	 * @throws ReflectionException
259
+	 * @since 5.0.12.p
260
+	 */
261
+	private function recalculateNonPercentageLineItem(
262
+		EE_Line_Item $line_item
263
+	): array {
264
+		$this->debugLog(' $ ' . __FUNCTION__, 2);
265
+		// recursively loop through children and recalculate their totals
266
+		$children = $line_item->children($this->default_query_params);
267
+		if (! empty($children)) {
268
+			// reset the total and pretax total to zero since we are recalculating them
269
+			$total = $pretax_total = 0;
270
+			foreach ($children as $child_line_item) {
271
+				[$child_total, $child_pretax_total] = $this->recalculateLineItemTotals(
272
+					$child_line_item,
273
+					$total,
274
+					$pretax_total,
275
+					$line_item->is_taxable()
276
+				);
277
+				$this->debugLog(' $ $ ' . __FUNCTION__, 3);
278
+				$this->debugLog(
279
+					' $ $ $ ' . $child_line_item->name() . ' '
280
+					. $child_line_item->type() . ' ' . $child_line_item->code(),
281
+					3
282
+				);
283
+				$this->debugLog(" $ $ $ $ child total: $child_total", 3);
284
+				$this->debugLog(" $ $ $ $ child pretax: $child_pretax_total", 3);
285
+				$total        += $child_total;
286
+				$pretax_total += $child_pretax_total;
287
+			}
288
+		} else {
289
+			// no child line items, so recalculate the total from the unit price and quantity
290
+			// and set the pretax total to match since there are obviously no sub-taxes
291
+			$pretax_total = $total = $this->calculateTotalForQuantity($line_item);
292
+		}
293
+		$this->debugLog(' $ ' . __FUNCTION__, 3);
294
+		$this->debugLog(' $ $ ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
295
+		$this->debugLog(" $ $ $ total: $total", 3);
296
+		$this->debugLog(" $ $ $ pretax: $pretax_total", 3);
297
+		return [$total, $pretax_total];
298
+	}
299
+
300
+
301
+	/**
302
+	 * @param EE_Line_Item $sub_line_item
303
+	 * @param float|int    $total
304
+	 * @param float|int    $pretax_total
305
+	 * @param bool         $is_taxable
306
+	 * @return float[]
307
+	 * @throws EE_Error
308
+	 * @throws ReflectionException
309
+	 */
310
+	private function recalculateSubLineItem(
311
+		EE_Line_Item $sub_line_item,
312
+		float $total = 0,
313
+		float $pretax_total = 0,
314
+		bool $is_taxable = false
315
+	): array {
316
+		$this->debugLog(__FUNCTION__);
317
+		$total = $is_taxable ? $total : $pretax_total;
318
+		if ($sub_line_item->is_percent()) {
319
+			$new_total        = $this->calculatePercentage($total, $sub_line_item->percent());
320
+			$new_pretax_total = $this->calculatePercentage($pretax_total, $sub_line_item->percent());
321
+		} else {
322
+			$new_total = $new_pretax_total = $this->calculateTotalForQuantity($sub_line_item);
323
+		}
324
+		$total        = $this->updateTotal($sub_line_item, $new_total, false, false);
325
+		$pretax_total = $this->updatePreTaxTotal($sub_line_item, $new_pretax_total, false, false);
326
+		// need to also adjust unit price too if the pretax total or quantity has been updated
327
+		$this->updateUnitPrice($sub_line_item, $pretax_total);
328
+		$this->debugLog(" - - total : $total ", 3);
329
+		$this->debugLog(" - - pretax: $pretax_total ", 3);
330
+		return [$total, $pretax_total];
331
+	}
332
+
333
+
334
+	/**
335
+	 * @param EE_Line_Item $sub_line_item
336
+	 * @param float|int    $pretax_total
337
+	 * @return float[]
338
+	 * @throws EE_Error
339
+	 * @throws ReflectionException
340
+	 */
341
+	private function recalculateSubTax(EE_Line_Item $sub_line_item, float $pretax_total = 0): array
342
+	{
343
+		$this->debugLog(__FUNCTION__);
344
+		$total_tax = $this->calculatePercentage($pretax_total, $sub_line_item->percent());
345
+		$total_tax = $this->updateTotal($sub_line_item, $total_tax);
346
+		$this->debugLog(" - total_tax : $total_tax ", 3);
347
+		return [$total_tax, 0];
348
+	}
349
+
350
+
351
+	/**
352
+	 * recursively loops through the entire line item tree updating line item quantities accordingly.
353
+	 * this needs to be done prior to running any other calculations for reasons that are hopefully obvious :p
354
+	 *
355
+	 * @param EE_Line_Item $line_item
356
+	 * @param int          $quantity
357
+	 * @return int
358
+	 * @throws EE_Error
359
+	 * @throws ReflectionException
360
+	 */
361
+	private function updateLineItemQuantities(EE_Line_Item $line_item, int $quantity = 1): int
362
+	{
363
+		switch ($line_item->type()) {
364
+			case EEM_Line_Item::type_total:
365
+			case EEM_Line_Item::type_sub_total:
366
+			case EEM_Line_Item::type_tax_sub_total:
367
+				// first, loop through children and set their quantities
368
+				$count    = 0;
369
+				$children = $line_item->children($this->default_query_params);
370
+				foreach ($children as $child_line_item) {
371
+					$count += $this->updateLineItemQuantities($child_line_item);
372
+				}
373
+				// totals and subtotals should have a quantity of 1
374
+				// unless their children have all been removed, in which case we can set them to 0
375
+				$quantity = $count > 0 ? 1 : 0;
376
+				$this->updateQuantity($line_item, $quantity);
377
+				return $quantity;
378
+
379
+			case EEM_Line_Item::type_line_item:
380
+				// line items should ALREADY have accurate quantities set, if not, then somebody done goofed!
381
+				// but if this is a percentage based line item, then ensure its quantity is 1
382
+				if ($line_item->is_percent()) {
383
+					$this->updateQuantity($line_item, 1);
384
+				}
385
+				// and we also need to loop through all the sub items and ensure those quantities match this parent.
386
+				$children = $line_item->children($this->default_query_params);
387
+				$quantity = $line_item->quantity();
388
+				foreach ($children as $child_line_item) {
389
+					$this->updateLineItemQuantities($child_line_item, $quantity);
390
+				}
391
+				// percentage line items should not increment their parent's count, so they return 0
392
+				return ! $line_item->is_percent() ? $quantity : 0;
393
+
394
+			case EEM_Line_Item::type_sub_line_item:
395
+				// percentage based items need their quantity set to 1,
396
+				// all others use the incoming value from the parent line item
397
+				$quantity = $line_item->is_percent() ? 1 : $quantity;
398
+				$this->updateQuantity($line_item, $quantity);
399
+				// percentage line items should not increment their parent's count, so they return 0
400
+				return ! $line_item->is_percent() ? $quantity : 0;
401
+
402
+			case EEM_Line_Item::type_tax:
403
+			case EEM_Line_Item::type_sub_tax:
404
+				// taxes should have a quantity of 1
405
+				$this->updateQuantity($line_item, 1);
406
+				return 1;
407
+
408
+			case EEM_Line_Item::type_cancellation:
409
+				// cancellations will be ignored for all calculations
410
+				// because their parent quantities should have already been adjusted when they were added
411
+				// so assume that things are already set correctly
412
+				return 0;
413
+		}
414
+		return 0;
415
+	}
416
+
417
+
418
+	/**
419
+	 * @param float $total
420
+	 * @param float $percent
421
+	 * @param bool  $round
422
+	 * @return float
423
+	 */
424
+	private function calculatePercentage(float $total, float $percent, bool $round = false): float
425
+	{
426
+		$amount = $total * $percent / 100;
427
+		$amount = $this->decimal_values->roundDecimalValue($amount, $round);
428
+		$this->debugLog(' % ' . __FUNCTION__, 2);
429
+		$this->debugLog(" % % total: $total", 3);
430
+		$this->debugLog(" % % percent: $percent", 3);
431
+		$this->debugLog(" % % amount: $amount", 3);
432
+		return $amount;
433
+	}
434
+
435
+
436
+	/**
437
+	 * @param EE_Line_Item $line_item
438
+	 * @return float
439
+	 * @throws EE_Error
440
+	 * @throws ReflectionException
441
+	 */
442
+	private function calculateTotalForQuantity(EE_Line_Item $line_item): float
443
+	{
444
+		$this->debugLog(' # ' . __FUNCTION__, 2);
445
+		$this->debugLog(' # # ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
446
+		$this->debugLog(" # # # unit_price: " . $line_item->unit_price(), 3);
447
+		$this->debugLog(" # # # quantity: " . $line_item->quantity(), 3);
448
+		$total = $line_item->unit_price() * $line_item->quantity();
449
+		return $this->decimal_values->roundDecimalValue($total);
450
+	}
451
+
452
+
453
+	/**
454
+	 * @param EE_Line_Item $line_item
455
+	 * @param float        $percent
456
+	 * @throws EE_Error
457
+	 * @throws ReflectionException
458
+	 */
459
+	private function updatePercent(EE_Line_Item $line_item, float $percent)
460
+	{
461
+		// update and save new percent only if incoming value does not match existing value
462
+		if ($line_item->percent() !== $percent) {
463
+			$line_item->set_percent($percent);
464
+			$line_item->maybe_save();
465
+		}
466
+	}
467
+
468
+
469
+	/**
470
+	 * @param EE_Line_Item $line_item
471
+	 * @param float        $pretax_total
472
+	 * @param bool         $round
473
+	 * @param bool         $save
474
+	 * @return float
475
+	 * @throws EE_Error
476
+	 * @throws ReflectionException
477
+	 */
478
+	private function updatePreTaxTotal(
479
+		EE_Line_Item $line_item,
480
+		float $pretax_total,
481
+		bool $round = false,
482
+		bool $save = true
483
+	): float {
484
+		$pretax_total = $this->decimal_values->roundDecimalValue($pretax_total, $round);
485
+		$sign = $line_item->type() === EEM_Line_Item::type_cancellation ? -1 : 1;
486
+		$pretax_total = $sign * $pretax_total;
487
+		$this->debugLog(' ? ' . __FUNCTION__, 2);
488
+		$this->debugLog(' ??? ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
489
+		$this->debugLog(" ????? SIGN: $sign  &&  pretax_total: $pretax_total", 3);
490
+		// update and save new total only if incoming value does not match existing value
491
+		if ($line_item->preTaxTotal() !== $pretax_total) {
492
+			$line_item->setPreTaxTotal($pretax_total);
493
+			if ($save) {
494
+				$line_item->maybe_save();
495
+			}
496
+		}
497
+		return $pretax_total;
498
+	}
499
+
500
+
501
+	/**
502
+	 * @param EE_Line_Item $line_item
503
+	 * @param int          $quantity
504
+	 * @throws EE_Error
505
+	 * @throws ReflectionException
506
+	 */
507
+	private function updateQuantity(EE_Line_Item $line_item, int $quantity)
508
+	{
509
+		// update and save new quantity only if incoming value does not match existing value
510
+		if ($line_item->quantity() !== $quantity) {
511
+			$line_item->set_quantity($quantity);
512
+			$line_item->maybe_save();
513
+		}
514
+	}
515
+
516
+
517
+	/**
518
+	 * @param EE_Line_Item $line_item
519
+	 * @param float        $total
520
+	 * @param bool         $round
521
+	 * @param bool         $save
522
+	 * @return float
523
+	 * @throws EE_Error
524
+	 * @throws ReflectionException
525
+	 */
526
+	private function updateTotal(EE_Line_Item $line_item, float $total, bool $round = false, bool $save = true): float
527
+	{
528
+		$total = $this->decimal_values->roundDecimalValue($total, $round);
529
+		$sign = $line_item->type() === EEM_Line_Item::type_cancellation ? -1 : 1;
530
+		$total = $sign * $total;
531
+		$this->debugLog(' ? ' . __FUNCTION__, 2);
532
+		$this->debugLog(' ??? ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
533
+		$this->debugLog(" ????? SIGN: $sign  &&  total: $total", 3);
534
+		// update and save new total only if incoming value does not match existing value
535
+		if ($line_item->total() !== $total) {
536
+			$line_item->set_total($total);
537
+			if ($save) {
538
+				$line_item->maybe_save();
539
+			}
540
+		}
541
+		return (float) $total;
542
+	}
543
+
544
+
545
+	/**
546
+	 * @param EE_Line_Item $line_item
547
+	 * @param float        $total
548
+	 * @param bool         $update_status
549
+	 * @return void
550
+	 * @throws EE_Error
551
+	 * @throws ReflectionException
552
+	 */
553
+	private function updateTransaction(EE_Line_Item $line_item, float $total, bool $update_status)
554
+	{
555
+		// only update the related transaction's total
556
+		// if we intend to save this line item and it's a grand total
557
+		if ($line_item->allow_persist()) {
558
+			$transaction = $line_item->transaction();
559
+			if ($transaction instanceof EE_Transaction) {
560
+				$transaction->set_total($total);
561
+				if ($update_status) {
562
+					// don't save the TXN because that will be done below
563
+					// and the following method only saves if the status changes
564
+					$transaction->update_status_based_on_total_paid(false);
565
+				}
566
+				if ($transaction->ID()) {
567
+					$transaction->save();
568
+				}
569
+			}
570
+		}
571
+	}
572
+
573
+
574
+	/**
575
+	 * @param EE_Line_Item $line_item
576
+	 * @param float        $pretax_total
577
+	 * @param bool         $save
578
+	 * @return void
579
+	 * @throws EE_Error
580
+	 * @throws ReflectionException
581
+	 */
582
+	private function updateUnitPrice(EE_Line_Item $line_item, float $pretax_total, bool $save = true)
583
+	{
584
+		$quantity = $line_item->quantity();
585
+		// don't divide by zero else you'll create a singularity and implode the interweb
586
+		// we also don't set unit prices for percentage based line items
587
+		if ($quantity === 0 || $line_item->is_percent()) {
588
+			return;
589
+		}
590
+		$new_unit_price = $pretax_total / $quantity;
591
+		$new_unit_price = $this->decimal_values->roundDecimalValue($new_unit_price);
592
+		$sign = $line_item->type() === EEM_Line_Item::type_cancellation ? -1 : 1;
593
+		$new_unit_price = $sign * $new_unit_price;
594
+		$this->debugLog(' ? ' . __FUNCTION__, 2);
595
+		$this->debugLog(' ??? ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
596
+		$this->debugLog(" ????? SIGN: $sign  &&  new_unit_price: $new_unit_price", 3);
597
+		// update and save new total only if incoming value does not match existing value
598
+		if ($line_item->unit_price() !== $new_unit_price) {
599
+			$this->debugLog(' @ ' . __FUNCTION__, 3);
600
+			$this->debugLog(' @ @ ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
601
+			$this->debugLog(" @ @ @ pretax: $pretax_total", 3);
602
+			$this->debugLog(" @ @ @ quantity: $quantity", 3);
603
+			$this->debugLog(" @ @ @ old unit price: " . $line_item->unit_price(), 3);
604
+			$this->debugLog(" @ @ @ new unit price: $new_unit_price", 3);
605
+			$line_item->set_unit_price($new_unit_price);
606
+			if ($save) {
607
+				$line_item->maybe_save();
608
+			}
609
+		}
610
+	}
611
+
612
+
613
+	/**
614
+	 * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets
615
+	 * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items
616
+	 * and tax sub-total if already in the DB
617
+	 *
618
+	 * @param EE_Line_Item $total_line_item
619
+	 * @return float
620
+	 * @throws EE_Error
621
+	 * @throws ReflectionException
622
+	 */
623
+	public function recalculateTaxesAndTaxTotal(EE_Line_Item $total_line_item): float
624
+	{
625
+		$this->debugLog(__FUNCTION__, 3);
626
+		$this->validateLineItemAndType($total_line_item, EEM_Line_Item::type_total);
627
+		// calculate the total taxable amount for globally applied taxes
628
+		$taxable_total    = $this->taxableAmountForGlobalTaxes($total_line_item);
629
+		[$total_tax, $global_taxes ]    = $this->applyGlobalTaxes($total_line_item, $taxable_total);
630
+		$non_global_taxes = $this->calculateNonGlobalTaxes($total_line_item);
631
+		$all_tax_total    = $this->applyNonGlobalTaxes($total_line_item, $total_tax, $global_taxes, $non_global_taxes);
632
+		$this->recalculateTaxSubTotal($total_line_item);
633
+		$this->debugLog(" - taxable_total : $taxable_total", 4);
634
+		$this->debugLog(" - total_tax : $total_tax", 4);
635
+		$this->debugLog(" - all_tax_total : $all_tax_total", 4);
636
+		return $all_tax_total;
637
+	}
638
+
639
+
640
+	/**
641
+	 * @param EE_Line_Item $total_line_item
642
+	 * @param float        $taxable_total
643
+	 * @return array
644
+	 * @throws EE_Error
645
+	 * @throws ReflectionException
646
+	 */
647
+	private function applyGlobalTaxes(EE_Line_Item $total_line_item, float $taxable_total): array
648
+	{
649
+		$this->debugLog(__FUNCTION__, 4);
650
+		$this->validateLineItemAndType($total_line_item, EEM_Line_Item::type_total);
651
+		$total_tax = 0;
652
+		if ($taxable_total === 0.0) {
653
+			return [0, []];
654
+		}
655
+		// loop through all global taxes all taxes
656
+		$global_taxes = $total_line_item->tax_descendants();
657
+		foreach ($global_taxes as $tax) {
658
+			$tax_total = $this->calculatePercentage($taxable_total, $tax->percent());
659
+			if ($tax_total === 0.0) {
660
+				$tax->delete();
661
+				continue;
662
+			}
663
+			$tax_total = $this->updateTotal($tax, $tax_total, true);
664
+			$total_tax += $tax_total;
665
+		}
666
+		return [$this->decimal_values->roundDecimalValue($total_tax, true), $global_taxes];
667
+	}
668
+
669
+
670
+	/**
671
+	 * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated
672
+	 *
673
+	 * @param EE_Line_Item $line_item
674
+	 * @return void
675
+	 * @throws EE_Error
676
+	 * @throws ReflectionException
677
+	 */
678
+	private function recalculateTaxSubTotal(EE_Line_Item $line_item)
679
+	{
680
+		$this->debugLog(__FUNCTION__, 4);
681
+		$this->validateLineItemAndType($line_item, EEM_Line_Item::type_total);
682
+		foreach ($line_item->children() as $maybe_tax_subtotal) {
683
+			if (
684
+				$this->validateLineItemAndType($maybe_tax_subtotal)
685
+				&& $maybe_tax_subtotal->is_tax_sub_total()
686
+			) {
687
+				$total         = 0;
688
+				$total_percent = 0;
689
+				// simply loop through all its children (which should be taxes) and sum their total
690
+				foreach ($maybe_tax_subtotal->children() as $child_tax) {
691
+					if ($this->validateLineItemAndType($child_tax) && $child_tax->isGlobalTax()) {
692
+						$total         += $child_tax->total();
693
+						$total_percent += $child_tax->percent();
694
+					}
695
+				}
696
+				$this->updateTotal($maybe_tax_subtotal, $total, true);
697
+				$this->updatePercent($maybe_tax_subtotal, $total_percent);
698
+			}
699
+		}
700
+	}
701
+
702
+
703
+	/**
704
+	 * returns an array of tax details like:
705
+	 *  [
706
+	 *      'GST_7' => [
707
+	 *          'name'  => 'GST',
708
+	 *          'rate'  => float(7),
709
+	 *          'total' => float(4.9),
710
+	 *      ]
711
+	 *  ]
712
+	 *
713
+	 * @param EE_Line_Item $total_line_item
714
+	 * @param array        $non_global_taxes
715
+	 * @param float        $line_item_total
716
+	 * @return array
717
+	 * @throws EE_Error
718
+	 * @throws ReflectionException
719
+	 */
720
+	private function calculateNonGlobalTaxes(
721
+		EE_Line_Item $total_line_item,
722
+		array $non_global_taxes = [],
723
+		float $line_item_total = 0
724
+	): array {
725
+		$this->debugLog(__FUNCTION__, 4);
726
+		foreach ($total_line_item->children() as $line_item) {
727
+			if ($this->validateLineItemAndType($line_item)) {
728
+				if ($line_item->is_sub_total()) {
729
+					$non_global_taxes = $this->calculateNonGlobalTaxes($line_item, $non_global_taxes);
730
+				} elseif ($line_item->is_line_item()) {
731
+					$non_global_taxes = $this->calculateNonGlobalTaxes(
732
+						$line_item,
733
+						$non_global_taxes,
734
+						$line_item->pretaxTotal()
735
+					);
736
+				} elseif ($line_item->isSubTax()) {
737
+					$tax_ID = $line_item->name() . '_' . $line_item->percent();
738
+					if (! isset($non_global_taxes[ $tax_ID ])) {
739
+						$non_global_taxes[ $tax_ID ] = [
740
+							'name'  => $line_item->name(),
741
+							'rate'  => $line_item->percent(),
742
+							'total' => 0,
743
+							'obj'   => $line_item->OBJ_type(),
744
+							'objID' => $line_item->OBJ_ID(),
745
+						];
746
+					}
747
+					$tax = $this->calculatePercentage($line_item_total, $line_item->percent());
748
+
749
+					$non_global_taxes[ $tax_ID ]['total'] += $tax;
750
+				}
751
+			}
752
+		}
753
+		return $non_global_taxes;
754
+	}
755
+
756
+
757
+	/**
758
+	 * @param EE_Line_Item   $total_line_item
759
+	 * @param float          $tax_total
760
+	 * @param EE_Line_Item[] $global_taxes array of tax line items returned from applyGlobalTaxes()
761
+	 * @param array          $non_global_taxes array of tax details generated by calculateNonGlobalTaxes()
762
+	 * @return float
763
+	 * @throws EE_Error
764
+	 * @throws ReflectionException
765
+	 */
766
+	private function applyNonGlobalTaxes(
767
+		EE_Line_Item $total_line_item,
768
+		float $tax_total,
769
+		array $global_taxes,
770
+		array $non_global_taxes
771
+	): float {
772
+		$this->debugLog(__FUNCTION__, 4);
773
+		$taxes_subtotal = EEH_Line_Item::get_taxes_subtotal($total_line_item);
774
+		foreach ($non_global_taxes as $non_global_tax) {
775
+			$found = false;
776
+			foreach ($global_taxes as $global_tax) {
777
+				if (
778
+					$this->validateLineItemAndType($global_tax)
779
+					&& $non_global_tax['obj'] === $global_tax->OBJ_type()
780
+					&& $non_global_tax['objID'] === $global_tax->OBJ_ID()
781
+				) {
782
+					$found     = true;
783
+					$new_total = $global_tax->total() + $non_global_tax['total'];
784
+					// add non-global tax to matching global tax AND the tax total
785
+					$global_tax->set_total($new_total);
786
+					$global_tax->maybe_save();
787
+					$tax_total += $non_global_tax['total'];
788
+				}
789
+			}
790
+			if (! $found) {
791
+				// add a new line item for this non-global tax
792
+				$taxes_subtotal->add_child_line_item(
793
+					EE_Line_Item::new_instance(
794
+						[
795
+							'LIN_name'       => $non_global_tax['name'],
796
+							'LIN_percent'    => $non_global_tax['rate'],
797
+							'LIN_is_taxable' => false,
798
+							'LIN_total'      => $non_global_tax['total'],
799
+							'LIN_type'       => EEM_Line_Item::type_tax,
800
+							'OBJ_type'       => $non_global_tax['obj'],
801
+							'OBJ_ID'         => $non_global_tax['objID'],
802
+						]
803
+					)
804
+				);
805
+				$tax_total += $non_global_tax['total'];
806
+			}
807
+		}
808
+		return $this->decimal_values->roundDecimalValue($tax_total, true);
809
+	}
810
+
811
+
812
+	/**
813
+	 * Gets the total tax on this line item. Assumes taxes have already been calculated using
814
+	 * recalculate_taxes_and_total
815
+	 *
816
+	 * @param EE_Line_Item $line_item
817
+	 * @return float
818
+	 * @throws EE_Error
819
+	 * @throws ReflectionException
820
+	 */
821
+	public function getTotalTax(EE_Line_Item $line_item): float
822
+	{
823
+		$this->validateLineItemAndType($line_item, EEM_Line_Item::type_total);
824
+		$this->recalculateTaxSubTotal($line_item);
825
+		$total = 0;
826
+		foreach ($line_item->tax_descendants() as $tax_line_item) {
827
+			if ($this->validateLineItemAndType($tax_line_item)) {
828
+				$total += $tax_line_item->total();
829
+			}
830
+		}
831
+		return $this->decimal_values->roundDecimalValue($total, true);
832
+	}
833
+
834
+
835
+	/**
836
+	 * Returns the amount taxable among this line item's children (or if it has no children,
837
+	 * how much of it is taxable). Does not recalculate totals or subtotals.
838
+	 * If the taxable total is negative, (eg, if none of the tickets were taxable,
839
+	 * but there is a "Taxable" discount), returns 0.
840
+	 *
841
+	 * @param EE_Line_Item|null $line_item
842
+	 * @return float
843
+	 * @throws EE_Error
844
+	 * @throws ReflectionException
845
+	 */
846
+	public function taxableAmountForGlobalTaxes(?EE_Line_Item $line_item): float
847
+	{
848
+		$this->debugLog(__FUNCTION__, 4);
849
+		$total            = 0;
850
+		$child_line_items = $line_item->children($this->default_query_params);
851
+		foreach ($child_line_items as $child_line_item) {
852
+			$this->validateLineItemAndType($child_line_item);
853
+			if ($child_line_item->is_sub_total()) {
854
+				$total += $this->taxableAmountForGlobalTaxes($child_line_item);
855
+			} elseif ($child_line_item->is_line_item() && $child_line_item->is_taxable()) {
856
+				// if it's a percent item, only take into account
857
+				// the percentage that's taxable (the taxable total so far)
858
+				if ($child_line_item->is_percent()) {
859
+					$total += $this->calculatePercentage($total, $child_line_item->percent(), true);
860
+				} else {
861
+					// pretax total will be equal to the total for line items with globally applied taxes
862
+					$pretax_total = $this->calculateTotalForQuantity($child_line_item);
863
+					$total        += $this->updatePreTaxTotal($child_line_item, $pretax_total);
864
+				}
865
+			}
866
+		}
867
+		return max($total, 0);
868
+	}
869
+
870
+
871
+	/**
872
+	 * @param EE_Line_Item|null $line_item
873
+	 * @param string|null       $type
874
+	 * @return bool
875
+	 * @throws EE_Error
876
+	 * @throws ReflectionException
877
+	 */
878
+	private function validateLineItemAndType(?EE_Line_Item $line_item, ?string $type = null): bool
879
+	{
880
+		if (! $line_item instanceof EE_Line_Item) {
881
+			throw new DomainException(
882
+				esc_html__('Invalid or missing Line Item supplied .', 'event_espresso')
883
+			);
884
+		}
885
+		if ($type && $line_item->type() !== $type) {
886
+			throw new DomainException(
887
+				sprintf(
888
+					esc_html__(
889
+						'Invalid Line Item type supplied. Received "%1$s" but expected "%2$s".',
890
+						'event_espresso'
891
+					),
892
+					$line_item->type(),
893
+					$type
894
+				)
895
+			);
896
+		}
897
+		return true;
898
+	}
899
+
900
+
901
+	/**
902
+	 * loops through all sub-line-items for the supplied line item and reorders them as follows:
903
+	 * 1. sub items
904
+	 * 2. other??? (not a sub-item or sub-tax)
905
+	 * 3. sub taxes
906
+	 *
907
+	 * @param EE_Line_Item $line_item
908
+	 * @return void
909
+	 * @throws EE_Error
910
+	 * @throws ReflectionException
911
+	 * @since 5.0.12.p
912
+	 */
913
+	public function reorderSubLineItems(EE_Line_Item $line_item)
914
+	{
915
+		if ($line_item->type() !== EEM_Line_Item::type_line_item) {
916
+			return;
917
+		}
918
+		$this->debugLog(' + LineItemCalculator::reorderSubLineItems', 3);
919
+		$this->debugLog(
920
+			' + + ' . $line_item->OBJ_type() . ' ' . $line_item->name()
921
+			. ' - ' . $line_item->type() . ' (' . $line_item->code() . ')',
922
+			3
923
+		);
924
+		$sub_line_items = $line_item->children();
925
+		$items          = [];
926
+		$other          = [];
927
+		$taxes          = [];
928
+		foreach ($sub_line_items as $sub_line_item) {
929
+			switch ($sub_line_item->type()) {
930
+				case EEM_Line_Item::type_sub_line_item:
931
+					$items[ $sub_line_item->ID() ] = $sub_line_item;
932
+					break;
933
+				case EEM_Line_Item::type_sub_tax:
934
+					$taxes[ $sub_line_item->ID() ] = $sub_line_item;
935
+					break;
936
+				default:
937
+					$other[ $sub_line_item->ID() ] = $sub_line_item;
938
+			}
939
+		}
940
+		$order      = 0;
941
+		$line_items = apply_filters(
942
+			'FHEE__EventEspresso_core_services_calculators_LineItemCalculator__reorderSubLineItems__line_items',
943
+			['items' => $items, 'other' => $other, 'taxes' => $taxes]
944
+		);
945
+		foreach ($line_items as $sub_items) {
946
+			foreach ($sub_items as $sub_item) {
947
+				$order++;
948
+				$sub_item->set_order($order);
949
+				$sub_item->save();
950
+				$this->debugLog(
951
+					' + + + ' . $order . '. ' . $sub_item->OBJ_type() . ' ' . $sub_item->name()
952
+					. ' - ' . $sub_item->type() . ' (' . $sub_item->code() . ')',
953
+					3
954
+				);
955
+			}
956
+		}
957
+	}
958 958
 }
Please login to merge, or discard this patch.
Spacing   +47 added lines, -47 removed lines patch added patch discarded remove patch
@@ -56,7 +56,7 @@  discard block
 block discarded – undo
56 56
         $this->debugLog('', 2);
57 57
         $this->debugLog(__METHOD__);
58 58
         $this->debugLog(str_repeat('*', strlen(__METHOD__)), 2);
59
-        $this->debugLog(">>> TXN : " . $line_item->TXN_ID(), 2);
59
+        $this->debugLog(">>> TXN : ".$line_item->TXN_ID(), 2);
60 60
         $this->validateLineItemAndType($line_item, EEM_Line_Item::type_total);
61 61
         $ticket_line_items = EEH_Line_Item::get_ticket_line_items($line_item);
62 62
         if (empty($ticket_line_items)) {
@@ -102,7 +102,7 @@  discard block
 block discarded – undo
102 102
         $OBJ = $line_item->OBJ_type();
103 103
         $OBJ .= $OBJ ? ': ' : '';
104 104
         $this->debugLog(
105
-            ' * ' . $OBJ . $line_item->name() . ' - ' . $line_item->type() . ' (' . $line_item->code() . ')',
105
+            ' * '.$OBJ.$line_item->name().' - '.$line_item->type().' ('.$line_item->code().')',
106 106
             2
107 107
         );
108 108
         $this->debugLog(" * total: $total", 3);
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
         // recursively loop through children and recalculate their totals
159 159
         $children = $line_item->children($this->default_query_params);
160 160
         if (empty($children)) {
161
-            $this->debugLog(' - ' . __FUNCTION__, 3);
161
+            $this->debugLog(' - '.__FUNCTION__, 3);
162 162
             $this->debugLog(" - - total : $total ", 3);
163 163
             $this->debugLog(" - - pretax: $pretax_total ", 3);
164 164
             return [$total, $pretax_total];
@@ -175,17 +175,17 @@  discard block
 block discarded – undo
175 175
         // update the unit price and pretax total
176 176
         $this->updateUnitPrice($line_item, $pretax_total, false);
177 177
         $pretax_total = $this->updatePreTaxTotal($line_item, $pretax_total, true, false);
178
-        $this->debugLog(' - ' . __FUNCTION__, 3);
179
-        $this->debugLog(" - - line_item->name() : " . $line_item->name(), 3);
180
-        $this->debugLog(" - - line_item->code() : " . $line_item->code(), 3);
178
+        $this->debugLog(' - '.__FUNCTION__, 3);
179
+        $this->debugLog(" - - line_item->name() : ".$line_item->name(), 3);
180
+        $this->debugLog(" - - line_item->code() : ".$line_item->code(), 3);
181 181
         // for the actual pre-tax sub-total line item, we want to save the pretax value for everything
182 182
         if ($line_item->is_sub_total() && $line_item->code() === 'pre-tax-subtotal') {
183 183
             $this->updateTotal($line_item, $pretax_total, true);
184
-        } elseif (! $line_item->is_total()) {
184
+        } elseif ( ! $line_item->is_total()) {
185 185
             // we don't update the total for the total line item, because that will need to include taxes
186 186
             $total = $this->updateTotal($line_item, $total, true);
187 187
         }
188
-        $this->debugLog(' - ' . __FUNCTION__, 3);
188
+        $this->debugLog(' - '.__FUNCTION__, 3);
189 189
         $this->debugLog(" - - total : $total ", 3);
190 190
         $this->debugLog(" - - pretax: $pretax_total ", 3);
191 191
         return [$total, $pretax_total];
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
 
217 217
         // need to also adjust unit price too if the pretax total or quantity has been updated
218 218
         $this->updateUnitPrice($line_item, $pretax_total);
219
-        $this->debugLog(' - ' . __FUNCTION__, 3);
219
+        $this->debugLog(' - '.__FUNCTION__, 3);
220 220
         $this->debugLog(" - - total : $total", 3);
221 221
         $this->debugLog(" - - pretax: $pretax_total", 3);
222 222
         return [$total, $pretax_total];
@@ -237,14 +237,14 @@  discard block
 block discarded – undo
237 237
         float $total = 0,
238 238
         float $pretax_total = 0
239 239
     ): array {
240
-        $this->debugLog(' % ' . __FUNCTION__, 2);
240
+        $this->debugLog(' % '.__FUNCTION__, 2);
241 241
         $pretax_total = $this->calculatePercentage($pretax_total, $line_item->percent());
242 242
         // if the line item is taxable, then we need to calculate the total,
243 243
         // otherwise we can just use the pretax total
244 244
         $total = $line_item->is_taxable()
245 245
             ? $this->calculatePercentage($total, $line_item->percent())
246 246
             : $pretax_total;
247
-        $this->debugLog(' % ' . __FUNCTION__, 3);
247
+        $this->debugLog(' % '.__FUNCTION__, 3);
248 248
         $this->debugLog(" % % total : $total ", 3);
249 249
         $this->debugLog(" % % pretax: $pretax_total ", 3);
250 250
         return [$total, $pretax_total];
@@ -261,10 +261,10 @@  discard block
 block discarded – undo
261 261
     private function recalculateNonPercentageLineItem(
262 262
         EE_Line_Item $line_item
263 263
     ): array {
264
-        $this->debugLog(' $ ' . __FUNCTION__, 2);
264
+        $this->debugLog(' $ '.__FUNCTION__, 2);
265 265
         // recursively loop through children and recalculate their totals
266 266
         $children = $line_item->children($this->default_query_params);
267
-        if (! empty($children)) {
267
+        if ( ! empty($children)) {
268 268
             // reset the total and pretax total to zero since we are recalculating them
269 269
             $total = $pretax_total = 0;
270 270
             foreach ($children as $child_line_item) {
@@ -274,10 +274,10 @@  discard block
 block discarded – undo
274 274
                     $pretax_total,
275 275
                     $line_item->is_taxable()
276 276
                 );
277
-                $this->debugLog(' $ $ ' . __FUNCTION__, 3);
277
+                $this->debugLog(' $ $ '.__FUNCTION__, 3);
278 278
                 $this->debugLog(
279
-                    ' $ $ $ ' . $child_line_item->name() . ' '
280
-                    . $child_line_item->type() . ' ' . $child_line_item->code(),
279
+                    ' $ $ $ '.$child_line_item->name().' '
280
+                    . $child_line_item->type().' '.$child_line_item->code(),
281 281
                     3
282 282
                 );
283 283
                 $this->debugLog(" $ $ $ $ child total: $child_total", 3);
@@ -290,8 +290,8 @@  discard block
 block discarded – undo
290 290
             // and set the pretax total to match since there are obviously no sub-taxes
291 291
             $pretax_total = $total = $this->calculateTotalForQuantity($line_item);
292 292
         }
293
-        $this->debugLog(' $ ' . __FUNCTION__, 3);
294
-        $this->debugLog(' $ $ ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
293
+        $this->debugLog(' $ '.__FUNCTION__, 3);
294
+        $this->debugLog(' $ $ '.$line_item->name().' '.$line_item->type().' '.$line_item->code(), 3);
295 295
         $this->debugLog(" $ $ $ total: $total", 3);
296 296
         $this->debugLog(" $ $ $ pretax: $pretax_total", 3);
297 297
         return [$total, $pretax_total];
@@ -425,7 +425,7 @@  discard block
 block discarded – undo
425 425
     {
426 426
         $amount = $total * $percent / 100;
427 427
         $amount = $this->decimal_values->roundDecimalValue($amount, $round);
428
-        $this->debugLog(' % ' . __FUNCTION__, 2);
428
+        $this->debugLog(' % '.__FUNCTION__, 2);
429 429
         $this->debugLog(" % % total: $total", 3);
430 430
         $this->debugLog(" % % percent: $percent", 3);
431 431
         $this->debugLog(" % % amount: $amount", 3);
@@ -441,10 +441,10 @@  discard block
 block discarded – undo
441 441
      */
442 442
     private function calculateTotalForQuantity(EE_Line_Item $line_item): float
443 443
     {
444
-        $this->debugLog(' # ' . __FUNCTION__, 2);
445
-        $this->debugLog(' # # ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
446
-        $this->debugLog(" # # # unit_price: " . $line_item->unit_price(), 3);
447
-        $this->debugLog(" # # # quantity: " . $line_item->quantity(), 3);
444
+        $this->debugLog(' # '.__FUNCTION__, 2);
445
+        $this->debugLog(' # # '.$line_item->name().' '.$line_item->type().' '.$line_item->code(), 3);
446
+        $this->debugLog(" # # # unit_price: ".$line_item->unit_price(), 3);
447
+        $this->debugLog(" # # # quantity: ".$line_item->quantity(), 3);
448 448
         $total = $line_item->unit_price() * $line_item->quantity();
449 449
         return $this->decimal_values->roundDecimalValue($total);
450 450
     }
@@ -484,8 +484,8 @@  discard block
 block discarded – undo
484 484
         $pretax_total = $this->decimal_values->roundDecimalValue($pretax_total, $round);
485 485
         $sign = $line_item->type() === EEM_Line_Item::type_cancellation ? -1 : 1;
486 486
         $pretax_total = $sign * $pretax_total;
487
-        $this->debugLog(' ? ' . __FUNCTION__, 2);
488
-        $this->debugLog(' ??? ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
487
+        $this->debugLog(' ? '.__FUNCTION__, 2);
488
+        $this->debugLog(' ??? '.$line_item->name().' '.$line_item->type().' '.$line_item->code(), 3);
489 489
         $this->debugLog(" ????? SIGN: $sign  &&  pretax_total: $pretax_total", 3);
490 490
         // update and save new total only if incoming value does not match existing value
491 491
         if ($line_item->preTaxTotal() !== $pretax_total) {
@@ -528,8 +528,8 @@  discard block
 block discarded – undo
528 528
         $total = $this->decimal_values->roundDecimalValue($total, $round);
529 529
         $sign = $line_item->type() === EEM_Line_Item::type_cancellation ? -1 : 1;
530 530
         $total = $sign * $total;
531
-        $this->debugLog(' ? ' . __FUNCTION__, 2);
532
-        $this->debugLog(' ??? ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
531
+        $this->debugLog(' ? '.__FUNCTION__, 2);
532
+        $this->debugLog(' ??? '.$line_item->name().' '.$line_item->type().' '.$line_item->code(), 3);
533 533
         $this->debugLog(" ????? SIGN: $sign  &&  total: $total", 3);
534 534
         // update and save new total only if incoming value does not match existing value
535 535
         if ($line_item->total() !== $total) {
@@ -591,16 +591,16 @@  discard block
 block discarded – undo
591 591
         $new_unit_price = $this->decimal_values->roundDecimalValue($new_unit_price);
592 592
         $sign = $line_item->type() === EEM_Line_Item::type_cancellation ? -1 : 1;
593 593
         $new_unit_price = $sign * $new_unit_price;
594
-        $this->debugLog(' ? ' . __FUNCTION__, 2);
595
-        $this->debugLog(' ??? ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
594
+        $this->debugLog(' ? '.__FUNCTION__, 2);
595
+        $this->debugLog(' ??? '.$line_item->name().' '.$line_item->type().' '.$line_item->code(), 3);
596 596
         $this->debugLog(" ????? SIGN: $sign  &&  new_unit_price: $new_unit_price", 3);
597 597
         // update and save new total only if incoming value does not match existing value
598 598
         if ($line_item->unit_price() !== $new_unit_price) {
599
-            $this->debugLog(' @ ' . __FUNCTION__, 3);
600
-            $this->debugLog(' @ @ ' . $line_item->name() . ' ' . $line_item->type() . ' ' . $line_item->code(), 3);
599
+            $this->debugLog(' @ '.__FUNCTION__, 3);
600
+            $this->debugLog(' @ @ '.$line_item->name().' '.$line_item->type().' '.$line_item->code(), 3);
601 601
             $this->debugLog(" @ @ @ pretax: $pretax_total", 3);
602 602
             $this->debugLog(" @ @ @ quantity: $quantity", 3);
603
-            $this->debugLog(" @ @ @ old unit price: " . $line_item->unit_price(), 3);
603
+            $this->debugLog(" @ @ @ old unit price: ".$line_item->unit_price(), 3);
604 604
             $this->debugLog(" @ @ @ new unit price: $new_unit_price", 3);
605 605
             $line_item->set_unit_price($new_unit_price);
606 606
             if ($save) {
@@ -626,7 +626,7 @@  discard block
 block discarded – undo
626 626
         $this->validateLineItemAndType($total_line_item, EEM_Line_Item::type_total);
627 627
         // calculate the total taxable amount for globally applied taxes
628 628
         $taxable_total    = $this->taxableAmountForGlobalTaxes($total_line_item);
629
-        [$total_tax, $global_taxes ]    = $this->applyGlobalTaxes($total_line_item, $taxable_total);
629
+        [$total_tax, $global_taxes] = $this->applyGlobalTaxes($total_line_item, $taxable_total);
630 630
         $non_global_taxes = $this->calculateNonGlobalTaxes($total_line_item);
631 631
         $all_tax_total    = $this->applyNonGlobalTaxes($total_line_item, $total_tax, $global_taxes, $non_global_taxes);
632 632
         $this->recalculateTaxSubTotal($total_line_item);
@@ -734,9 +734,9 @@  discard block
 block discarded – undo
734 734
                         $line_item->pretaxTotal()
735 735
                     );
736 736
                 } elseif ($line_item->isSubTax()) {
737
-                    $tax_ID = $line_item->name() . '_' . $line_item->percent();
738
-                    if (! isset($non_global_taxes[ $tax_ID ])) {
739
-                        $non_global_taxes[ $tax_ID ] = [
737
+                    $tax_ID = $line_item->name().'_'.$line_item->percent();
738
+                    if ( ! isset($non_global_taxes[$tax_ID])) {
739
+                        $non_global_taxes[$tax_ID] = [
740 740
                             'name'  => $line_item->name(),
741 741
                             'rate'  => $line_item->percent(),
742 742
                             'total' => 0,
@@ -746,7 +746,7 @@  discard block
 block discarded – undo
746 746
                     }
747 747
                     $tax = $this->calculatePercentage($line_item_total, $line_item->percent());
748 748
 
749
-                    $non_global_taxes[ $tax_ID ]['total'] += $tax;
749
+                    $non_global_taxes[$tax_ID]['total'] += $tax;
750 750
                 }
751 751
             }
752 752
         }
@@ -787,7 +787,7 @@  discard block
 block discarded – undo
787 787
                     $tax_total += $non_global_tax['total'];
788 788
                 }
789 789
             }
790
-            if (! $found) {
790
+            if ( ! $found) {
791 791
                 // add a new line item for this non-global tax
792 792
                 $taxes_subtotal->add_child_line_item(
793 793
                     EE_Line_Item::new_instance(
@@ -860,7 +860,7 @@  discard block
 block discarded – undo
860 860
                 } else {
861 861
                     // pretax total will be equal to the total for line items with globally applied taxes
862 862
                     $pretax_total = $this->calculateTotalForQuantity($child_line_item);
863
-                    $total        += $this->updatePreTaxTotal($child_line_item, $pretax_total);
863
+                    $total += $this->updatePreTaxTotal($child_line_item, $pretax_total);
864 864
                 }
865 865
             }
866 866
         }
@@ -877,7 +877,7 @@  discard block
 block discarded – undo
877 877
      */
878 878
     private function validateLineItemAndType(?EE_Line_Item $line_item, ?string $type = null): bool
879 879
     {
880
-        if (! $line_item instanceof EE_Line_Item) {
880
+        if ( ! $line_item instanceof EE_Line_Item) {
881 881
             throw new DomainException(
882 882
                 esc_html__('Invalid or missing Line Item supplied .', 'event_espresso')
883 883
             );
@@ -917,8 +917,8 @@  discard block
 block discarded – undo
917 917
         }
918 918
         $this->debugLog(' + LineItemCalculator::reorderSubLineItems', 3);
919 919
         $this->debugLog(
920
-            ' + + ' . $line_item->OBJ_type() . ' ' . $line_item->name()
921
-            . ' - ' . $line_item->type() . ' (' . $line_item->code() . ')',
920
+            ' + + '.$line_item->OBJ_type().' '.$line_item->name()
921
+            . ' - '.$line_item->type().' ('.$line_item->code().')',
922 922
             3
923 923
         );
924 924
         $sub_line_items = $line_item->children();
@@ -928,13 +928,13 @@  discard block
 block discarded – undo
928 928
         foreach ($sub_line_items as $sub_line_item) {
929 929
             switch ($sub_line_item->type()) {
930 930
                 case EEM_Line_Item::type_sub_line_item:
931
-                    $items[ $sub_line_item->ID() ] = $sub_line_item;
931
+                    $items[$sub_line_item->ID()] = $sub_line_item;
932 932
                     break;
933 933
                 case EEM_Line_Item::type_sub_tax:
934
-                    $taxes[ $sub_line_item->ID() ] = $sub_line_item;
934
+                    $taxes[$sub_line_item->ID()] = $sub_line_item;
935 935
                     break;
936 936
                 default:
937
-                    $other[ $sub_line_item->ID() ] = $sub_line_item;
937
+                    $other[$sub_line_item->ID()] = $sub_line_item;
938 938
             }
939 939
         }
940 940
         $order      = 0;
@@ -948,8 +948,8 @@  discard block
 block discarded – undo
948 948
                 $sub_item->set_order($order);
949 949
                 $sub_item->save();
950 950
                 $this->debugLog(
951
-                    ' + + + ' . $order . '. ' . $sub_item->OBJ_type() . ' ' . $sub_item->name()
952
-                    . ' - ' . $sub_item->type() . ' (' . $sub_item->code() . ')',
951
+                    ' + + + '.$order.'. '.$sub_item->OBJ_type().' '.$sub_item->name()
952
+                    . ' - '.$sub_item->type().' ('.$sub_item->code().')',
953 953
                     3
954 954
                 );
955 955
             }
Please login to merge, or discard this patch.
core/services/routing/Router.php 1 patch
Indentation   +219 added lines, -219 removed lines patch added patch discarded remove patch
@@ -29,243 +29,243 @@
 block discarded – undo
29 29
  */
30 30
 class Router
31 31
 {
32
-    protected EE_Dependency_Map $dependency_map;
32
+	protected EE_Dependency_Map $dependency_map;
33 33
 
34
-    protected LoaderInterface   $loader;
34
+	protected LoaderInterface   $loader;
35 35
 
36
-    protected RouteHandler      $route_handler;
36
+	protected RouteHandler      $route_handler;
37 37
 
38
-    protected string            $route_request_type;
38
+	protected string            $route_request_type;
39 39
 
40
-    protected array             $routes_loaded;
40
+	protected array             $routes_loaded;
41 41
 
42 42
 
43
-    /**
44
-     * RoutingSwitch constructor.
45
-     *
46
-     * @param EE_Dependency_Map $dependency_map
47
-     * @param LoaderInterface   $loader
48
-     * @param RouteHandler      $router
49
-     */
50
-    public function __construct(EE_Dependency_Map $dependency_map, LoaderInterface $loader, RouteHandler $router)
51
-    {
52
-        $this->dependency_map = $dependency_map;
53
-        $this->loader         = $loader;
54
-        $this->route_handler  = $router;
55
-    }
43
+	/**
44
+	 * RoutingSwitch constructor.
45
+	 *
46
+	 * @param EE_Dependency_Map $dependency_map
47
+	 * @param LoaderInterface   $loader
48
+	 * @param RouteHandler      $router
49
+	 */
50
+	public function __construct(EE_Dependency_Map $dependency_map, LoaderInterface $loader, RouteHandler $router)
51
+	{
52
+		$this->dependency_map = $dependency_map;
53
+		$this->loader         = $loader;
54
+		$this->route_handler  = $router;
55
+	}
56 56
 
57 57
 
58
-    /**
59
-     * @throws Exception
60
-     */
61
-    public function loadPrimaryRoutes()
62
-    {
63
-        if (isset($this->routes_loaded[ __FUNCTION__ ])) {
64
-            return;
65
-        }
66
-        $this->dependency_map->registerDependencies(
67
-            'EventEspresso\core\domain\entities\routing\handlers\admin\ActivationRequests',
68
-            Route::getFullDependencies()
69
-        );
70
-        $this->dependency_map->registerDependencies(
71
-            'EventEspresso\core\domain\entities\routing\handlers\shared\RegularRequests',
72
-            Route::getFullDependencies()
73
-        );
74
-        // now load and prep all primary Routes
75
-        $this->route_handler->addRoute('EventEspresso\core\domain\entities\routing\handlers\admin\ActivationRequests');
76
-        $this->route_handler->addRoute('EventEspresso\core\domain\entities\routing\handlers\shared\RegularRequests');
77
-        $this->route_request_type = $this->route_handler->getRouteRequestType();
78
-        do_action(
79
-            'AHEE__EventEspresso_core_services_routing_Router__loadPrimaryRoutes',
80
-            $this->route_handler,
81
-            $this->route_request_type,
82
-            $this->dependency_map
83
-        );
84
-        $this->routes_loaded[ __FUNCTION__ ] = true;
85
-    }
58
+	/**
59
+	 * @throws Exception
60
+	 */
61
+	public function loadPrimaryRoutes()
62
+	{
63
+		if (isset($this->routes_loaded[ __FUNCTION__ ])) {
64
+			return;
65
+		}
66
+		$this->dependency_map->registerDependencies(
67
+			'EventEspresso\core\domain\entities\routing\handlers\admin\ActivationRequests',
68
+			Route::getFullDependencies()
69
+		);
70
+		$this->dependency_map->registerDependencies(
71
+			'EventEspresso\core\domain\entities\routing\handlers\shared\RegularRequests',
72
+			Route::getFullDependencies()
73
+		);
74
+		// now load and prep all primary Routes
75
+		$this->route_handler->addRoute('EventEspresso\core\domain\entities\routing\handlers\admin\ActivationRequests');
76
+		$this->route_handler->addRoute('EventEspresso\core\domain\entities\routing\handlers\shared\RegularRequests');
77
+		$this->route_request_type = $this->route_handler->getRouteRequestType();
78
+		do_action(
79
+			'AHEE__EventEspresso_core_services_routing_Router__loadPrimaryRoutes',
80
+			$this->route_handler,
81
+			$this->route_request_type,
82
+			$this->dependency_map
83
+		);
84
+		$this->routes_loaded[ __FUNCTION__ ] = true;
85
+	}
86 86
 
87 87
 
88
-    /**
89
-     * @throws Exception
90
-     */
91
-    public function registerShortcodesModulesAndWidgets()
92
-    {
93
-        if (isset($this->routes_loaded[ __FUNCTION__ ])) {
94
-            return;
95
-        }
96
-        do_action(
97
-            'AHEE__EventEspresso_core_services_routing_Router__registerShortcodesModulesAndWidgets',
98
-            $this->route_handler,
99
-            $this->route_request_type,
100
-            $this->dependency_map
101
-        );
88
+	/**
89
+	 * @throws Exception
90
+	 */
91
+	public function registerShortcodesModulesAndWidgets()
92
+	{
93
+		if (isset($this->routes_loaded[ __FUNCTION__ ])) {
94
+			return;
95
+		}
96
+		do_action(
97
+			'AHEE__EventEspresso_core_services_routing_Router__registerShortcodesModulesAndWidgets',
98
+			$this->route_handler,
99
+			$this->route_request_type,
100
+			$this->dependency_map
101
+		);
102 102
 
103
-        /** @var LegacyModulesManager $legacy_modules_manager */
104
-        $legacy_modules_manager = $this->loader->getShared(LegacyModulesManager::class);
105
-        $legacy_modules_manager->setHooks();
103
+		/** @var LegacyModulesManager $legacy_modules_manager */
104
+		$legacy_modules_manager = $this->loader->getShared(LegacyModulesManager::class);
105
+		$legacy_modules_manager->setHooks();
106 106
 
107
-        switch ($this->route_request_type) {
108
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
109
-                break;
110
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
111
-                $this->route_handler->addRoute(
112
-                    'EventEspresso\core\domain\entities\routing\handlers\frontend\ShortcodeRequests'
113
-                );
114
-                /** @var LegacyWidgetsManager $legacy_widgets_manager */
115
-                $legacy_widgets_manager = $this->loader->getShared(LegacyWidgetsManager::class);
116
-                $legacy_widgets_manager->setHooks();
117
-                break;
118
-        }
119
-        $this->routes_loaded[ __FUNCTION__ ] = true;
120
-    }
107
+		switch ($this->route_request_type) {
108
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
109
+				break;
110
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
111
+				$this->route_handler->addRoute(
112
+					'EventEspresso\core\domain\entities\routing\handlers\frontend\ShortcodeRequests'
113
+				);
114
+				/** @var LegacyWidgetsManager $legacy_widgets_manager */
115
+				$legacy_widgets_manager = $this->loader->getShared(LegacyWidgetsManager::class);
116
+				$legacy_widgets_manager->setHooks();
117
+				break;
118
+		}
119
+		$this->routes_loaded[ __FUNCTION__ ] = true;
120
+	}
121 121
 
122 122
 
123
-    /**
124
-     * @throws Exception
125
-     */
126
-    public function brewEspresso()
127
-    {
128
-        if (isset($this->routes_loaded[ __FUNCTION__ ])) {
129
-            return;
130
-        }
131
-        do_action(
132
-            'AHEE__EventEspresso_core_services_routing_Router__brewEspresso',
133
-            $this->route_handler,
134
-            $this->route_request_type,
135
-            $this->dependency_map
136
-        );
137
-        switch ($this->route_request_type) {
138
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
139
-                break;
140
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
141
-                $this->route_handler->addRoute(
142
-                    'EventEspresso\core\domain\entities\routing\handlers\shared\GQLRequests'
143
-                );
144
-                $this->route_handler->addRoute(
145
-                    'EventEspresso\core\domain\entities\routing\handlers\shared\RestApiRequests'
146
-                );
147
-                break;
148
-        }
149
-        $this->routes_loaded[ __FUNCTION__ ] = true;
150
-    }
123
+	/**
124
+	 * @throws Exception
125
+	 */
126
+	public function brewEspresso()
127
+	{
128
+		if (isset($this->routes_loaded[ __FUNCTION__ ])) {
129
+			return;
130
+		}
131
+		do_action(
132
+			'AHEE__EventEspresso_core_services_routing_Router__brewEspresso',
133
+			$this->route_handler,
134
+			$this->route_request_type,
135
+			$this->dependency_map
136
+		);
137
+		switch ($this->route_request_type) {
138
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
139
+				break;
140
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
141
+				$this->route_handler->addRoute(
142
+					'EventEspresso\core\domain\entities\routing\handlers\shared\GQLRequests'
143
+				);
144
+				$this->route_handler->addRoute(
145
+					'EventEspresso\core\domain\entities\routing\handlers\shared\RestApiRequests'
146
+				);
147
+				break;
148
+		}
149
+		$this->routes_loaded[ __FUNCTION__ ] = true;
150
+	}
151 151
 
152 152
 
153
-    /**
154
-     * @throws Exception
155
-     */
156
-    public function loadControllers()
157
-    {
158
-        if (isset($this->routes_loaded[ __FUNCTION__ ])) {
159
-            return;
160
-        }
161
-        do_action(
162
-            'AHEE__EventEspresso_core_services_routing_Router__loadControllers',
163
-            $this->route_handler,
164
-            $this->route_request_type,
165
-            $this->dependency_map
166
-        );
167
-        $this->route_handler->addRoute(
168
-            'EventEspresso\core\domain\entities\routing\handlers\admin\AdminRoute'
169
-        );
170
-        switch ($this->route_request_type) {
171
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
172
-                $this->route_handler->addRoute(
173
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPluginsPage'
174
-                );
175
-                break;
176
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
177
-                $this->route_handler->addRoute(
178
-                    'EventEspresso\core\domain\entities\routing\handlers\frontend\FrontendRequests'
179
-                );
180
-                $this->route_handler->addRoute(
181
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoLegacyAdmin'
182
-                );
183
-                $this->route_handler->addRoute(
184
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoEventsAdmin'
185
-                );
186
-                $this->route_handler->addRoute(
187
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoEventEditor'
188
-                );
189
-                $this->route_handler->addRoute(
190
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\GutenbergEditor'
191
-                );
192
-                $this->route_handler->addRoute(
193
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\NonEspressoAdminAjax'
194
-                );
195
-                $this->route_handler->addRoute(
196
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPluginsPage'
197
-                );
198
-                $this->route_handler->addRoute(
199
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressProfilePage'
200
-                );
201
-                $this->route_handler->addRoute(
202
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPostsPage'
203
-                );
204
-                $this->route_handler->addRoute(
205
-                    'EventEspresso\core\domain\entities\routing\handlers\shared\WordPressHeartbeat'
206
-                );
207
-                $this->route_handler->addRoute(
208
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoBatchJob'
209
-                );
210
-                break;
211
-        }
212
-        $this->routes_loaded[ __FUNCTION__ ] = true;
213
-    }
153
+	/**
154
+	 * @throws Exception
155
+	 */
156
+	public function loadControllers()
157
+	{
158
+		if (isset($this->routes_loaded[ __FUNCTION__ ])) {
159
+			return;
160
+		}
161
+		do_action(
162
+			'AHEE__EventEspresso_core_services_routing_Router__loadControllers',
163
+			$this->route_handler,
164
+			$this->route_request_type,
165
+			$this->dependency_map
166
+		);
167
+		$this->route_handler->addRoute(
168
+			'EventEspresso\core\domain\entities\routing\handlers\admin\AdminRoute'
169
+		);
170
+		switch ($this->route_request_type) {
171
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
172
+				$this->route_handler->addRoute(
173
+					'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPluginsPage'
174
+				);
175
+				break;
176
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
177
+				$this->route_handler->addRoute(
178
+					'EventEspresso\core\domain\entities\routing\handlers\frontend\FrontendRequests'
179
+				);
180
+				$this->route_handler->addRoute(
181
+					'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoLegacyAdmin'
182
+				);
183
+				$this->route_handler->addRoute(
184
+					'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoEventsAdmin'
185
+				);
186
+				$this->route_handler->addRoute(
187
+					'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoEventEditor'
188
+				);
189
+				$this->route_handler->addRoute(
190
+					'EventEspresso\core\domain\entities\routing\handlers\admin\GutenbergEditor'
191
+				);
192
+				$this->route_handler->addRoute(
193
+					'EventEspresso\core\domain\entities\routing\handlers\admin\NonEspressoAdminAjax'
194
+				);
195
+				$this->route_handler->addRoute(
196
+					'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPluginsPage'
197
+				);
198
+				$this->route_handler->addRoute(
199
+					'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressProfilePage'
200
+				);
201
+				$this->route_handler->addRoute(
202
+					'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPostsPage'
203
+				);
204
+				$this->route_handler->addRoute(
205
+					'EventEspresso\core\domain\entities\routing\handlers\shared\WordPressHeartbeat'
206
+				);
207
+				$this->route_handler->addRoute(
208
+					'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoBatchJob'
209
+				);
210
+				break;
211
+		}
212
+		$this->routes_loaded[ __FUNCTION__ ] = true;
213
+	}
214 214
 
215 215
 
216
-    /**
217
-     * @throws Exception
218
-     */
219
-    public function coreLoadedAndReady()
220
-    {
221
-        if (isset($this->routes_loaded[ __FUNCTION__ ])) {
222
-            return;
223
-        }
224
-        do_action(
225
-            'AHEE__EventEspresso_core_services_routing_Router__coreLoadedAndReady',
226
-            $this->route_handler,
227
-            $this->route_request_type,
228
-            $this->dependency_map
229
-        );
230
-        switch ($this->route_request_type) {
231
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
232
-                break;
233
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
234
-                $this->route_handler->addRoute(
235
-                    'EventEspresso\core\domain\entities\routing\handlers\shared\AssetRequests'
236
-                );
237
-                $this->route_handler->addRoute(
238
-                    'EventEspresso\core\domain\entities\routing\handlers\shared\SessionRequests'
239
-                );
240
-                break;
241
-        }
242
-        $this->routes_loaded[ __FUNCTION__ ] = true;
243
-    }
216
+	/**
217
+	 * @throws Exception
218
+	 */
219
+	public function coreLoadedAndReady()
220
+	{
221
+		if (isset($this->routes_loaded[ __FUNCTION__ ])) {
222
+			return;
223
+		}
224
+		do_action(
225
+			'AHEE__EventEspresso_core_services_routing_Router__coreLoadedAndReady',
226
+			$this->route_handler,
227
+			$this->route_request_type,
228
+			$this->dependency_map
229
+		);
230
+		switch ($this->route_request_type) {
231
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
232
+				break;
233
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
234
+				$this->route_handler->addRoute(
235
+					'EventEspresso\core\domain\entities\routing\handlers\shared\AssetRequests'
236
+				);
237
+				$this->route_handler->addRoute(
238
+					'EventEspresso\core\domain\entities\routing\handlers\shared\SessionRequests'
239
+				);
240
+				break;
241
+		}
242
+		$this->routes_loaded[ __FUNCTION__ ] = true;
243
+	}
244 244
 
245 245
 
246
-    /**
247
-     * @throws Exception
248
-     */
249
-    public function initializeLast()
250
-    {
251
-        if (isset($this->routes_loaded[ __FUNCTION__ ])) {
252
-            return;
253
-        }
254
-        do_action(
255
-            'AHEE__EventEspresso_core_services_routing_Router__initializeLast',
256
-            $this->route_handler,
257
-            $this->route_request_type,
258
-            $this->dependency_map
259
-        );
260
-        switch ($this->route_request_type) {
261
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
262
-                break;
263
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
264
-                $this->route_handler->addRoute(
265
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\PersonalDataRequests'
266
-                );
267
-                break;
268
-        }
269
-        $this->routes_loaded[ __FUNCTION__ ] = true;
270
-    }
246
+	/**
247
+	 * @throws Exception
248
+	 */
249
+	public function initializeLast()
250
+	{
251
+		if (isset($this->routes_loaded[ __FUNCTION__ ])) {
252
+			return;
253
+		}
254
+		do_action(
255
+			'AHEE__EventEspresso_core_services_routing_Router__initializeLast',
256
+			$this->route_handler,
257
+			$this->route_request_type,
258
+			$this->dependency_map
259
+		);
260
+		switch ($this->route_request_type) {
261
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
262
+				break;
263
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
264
+				$this->route_handler->addRoute(
265
+					'EventEspresso\core\domain\entities\routing\handlers\admin\PersonalDataRequests'
266
+				);
267
+				break;
268
+		}
269
+		$this->routes_loaded[ __FUNCTION__ ] = true;
270
+	}
271 271
 }
Please login to merge, or discard this patch.
core/services/graphql/interfaces/GraphQLInterfaceInterface.php 1 patch
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -8,18 +8,18 @@
 block discarded – undo
8 8
 
9 9
 interface GraphQLInterfaceInterface
10 10
 {
11
-    public function getName(): string;
11
+	public function getName(): string;
12 12
 
13
-    public function getDescription(): string;
13
+	public function getDescription(): string;
14 14
 
15
-    /**
16
-     * @return GraphQLFieldInterface[]
17
-     */
18
-    public function getFields(): array;
15
+	/**
16
+	 * @return GraphQLFieldInterface[]
17
+	 */
18
+	public function getFields(): array;
19 19
 
20
-    /**
21
-     * @param mixed $source
22
-     * @return mixed
23
-     */
24
-    public function resolveField($source, array $args, AppContext $context, ResolveInfo $info);
20
+	/**
21
+	 * @param mixed $source
22
+	 * @return mixed
23
+	 */
24
+	public function resolveField($source, array $args, AppContext $context, ResolveInfo $info);
25 25
 }
Please login to merge, or discard this patch.
core/services/graphql/interfaces/GraphQLInterface.php 2 patches
Indentation   +69 added lines, -69 removed lines patch added patch discarded remove patch
@@ -10,73 +10,73 @@
 block discarded – undo
10 10
 
11 11
 abstract class GraphQLInterface implements GraphQLInterfaceInterface
12 12
 {
13
-    protected string $namespace = 'Espresso';
14
-
15
-    protected string $name;
16
-
17
-    protected FieldResolverV2 $resolver;
18
-
19
-    /**
20
-     * @var GraphQLFieldInterface[]
21
-     */
22
-    protected array $fields;
23
-
24
-    public function __construct()
25
-    {
26
-        $this->name = $this->namespace . $this->getShortName();
27
-
28
-        $this->validateFields($this->getArrayOfFields());
29
-
30
-        $this->fields = $this->getArrayOfFields();
31
-
32
-        $this->resolver = new FieldResolverV2($this->getArrayOfFields());
33
-    }
34
-
35
-    public function getName(): string
36
-    {
37
-        return $this->name;
38
-    }
39
-
40
-    public function getDescription(): string
41
-    {
42
-        return '';
43
-    }
44
-
45
-    /**
46
-     * @return GraphQLFieldInterface[]
47
-     */
48
-    public function getFields(): array
49
-    {
50
-        return $this->fields;
51
-    }
52
-
53
-    /**
54
-     * Get GraphQL interface name *without* namespace prefix
55
-     */
56
-    abstract protected function getShortName(): string;
57
-
58
-    /**
59
-     * @return GraphQLFieldInterface[]
60
-     */
61
-    abstract protected function getArrayOfFields(): array;
62
-
63
-    /**
64
-     * @param mixed[] $array
65
-     * @return GraphQLFieldInterface[]
66
-     */
67
-    protected function validateFields(array $array): array
68
-    {
69
-        foreach ($array as $field) {
70
-            if (! ($field instanceof GraphQLFieldInterface)) {
71
-                throw new RuntimeException(esc_html__(sprintf('GraphQL interface %1$s expects its fields to be instance of %2$s', $this->name, GraphQLFieldInterface::class), 'event_espresso'));
72
-            }
73
-        }
74
-
75
-        return $array;
76
-    }
77
-
78
-    public function resolveField($source, array $args, AppContext $context, ResolveInfo $info)
79
-    {
80
-        return $this->resolver->resolve($source, $args, $context, $info);
81
-    }
13
+	protected string $namespace = 'Espresso';
14
+
15
+	protected string $name;
16
+
17
+	protected FieldResolverV2 $resolver;
18
+
19
+	/**
20
+	 * @var GraphQLFieldInterface[]
21
+	 */
22
+	protected array $fields;
23
+
24
+	public function __construct()
25
+	{
26
+		$this->name = $this->namespace . $this->getShortName();
27
+
28
+		$this->validateFields($this->getArrayOfFields());
29
+
30
+		$this->fields = $this->getArrayOfFields();
31
+
32
+		$this->resolver = new FieldResolverV2($this->getArrayOfFields());
33
+	}
34
+
35
+	public function getName(): string
36
+	{
37
+		return $this->name;
38
+	}
39
+
40
+	public function getDescription(): string
41
+	{
42
+		return '';
43
+	}
44
+
45
+	/**
46
+	 * @return GraphQLFieldInterface[]
47
+	 */
48
+	public function getFields(): array
49
+	{
50
+		return $this->fields;
51
+	}
52
+
53
+	/**
54
+	 * Get GraphQL interface name *without* namespace prefix
55
+	 */
56
+	abstract protected function getShortName(): string;
57
+
58
+	/**
59
+	 * @return GraphQLFieldInterface[]
60
+	 */
61
+	abstract protected function getArrayOfFields(): array;
62
+
63
+	/**
64
+	 * @param mixed[] $array
65
+	 * @return GraphQLFieldInterface[]
66
+	 */
67
+	protected function validateFields(array $array): array
68
+	{
69
+		foreach ($array as $field) {
70
+			if (! ($field instanceof GraphQLFieldInterface)) {
71
+				throw new RuntimeException(esc_html__(sprintf('GraphQL interface %1$s expects its fields to be instance of %2$s', $this->name, GraphQLFieldInterface::class), 'event_espresso'));
72
+			}
73
+		}
74
+
75
+		return $array;
76
+	}
77
+
78
+	public function resolveField($source, array $args, AppContext $context, ResolveInfo $info)
79
+	{
80
+		return $this->resolver->resolve($source, $args, $context, $info);
81
+	}
82 82
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -23,7 +23,7 @@  discard block
 block discarded – undo
23 23
 
24 24
     public function __construct()
25 25
     {
26
-        $this->name = $this->namespace . $this->getShortName();
26
+        $this->name = $this->namespace.$this->getShortName();
27 27
 
28 28
         $this->validateFields($this->getArrayOfFields());
29 29
 
@@ -67,7 +67,7 @@  discard block
 block discarded – undo
67 67
     protected function validateFields(array $array): array
68 68
     {
69 69
         foreach ($array as $field) {
70
-            if (! ($field instanceof GraphQLFieldInterface)) {
70
+            if ( ! ($field instanceof GraphQLFieldInterface)) {
71 71
                 throw new RuntimeException(esc_html__(sprintf('GraphQL interface %1$s expects its fields to be instance of %2$s', $this->name, GraphQLFieldInterface::class), 'event_espresso'));
72 72
             }
73 73
         }
Please login to merge, or discard this patch.