Completed
Branch CASC/delete-transactions3 (0728c4)
by
unknown
10:54 queued 55s
created
core/libraries/batch/JobHandlers/PreviewEventDeletion.php 3 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -199,7 +199,7 @@
 block discarded – undo
199 199
             if ($units_processed >= $batch_size) {
200 200
                 break;
201 201
             }
202
-            if (!$root_node instanceof ModelObjNode) {
202
+            if ( ! $root_node instanceof ModelObjNode) {
203 203
                 throw new InvalidClassException('ModelObjNode');
204 204
             }
205 205
             if ($root_node->isComplete()) {
Please login to merge, or discard this patch.
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -12,7 +12,6 @@
 block discarded – undo
12 12
 use EventEspresso\core\exceptions\InvalidClassException;
13 13
 use EventEspresso\core\exceptions\InvalidDataTypeException;
14 14
 use EventEspresso\core\exceptions\InvalidInterfaceException;
15
-use EventEspresso\core\services\loaders\LoaderFactory;
16 15
 use EventEspresso\core\services\orm\tree_traversal\ModelObjNode;
17 16
 use EventEspresso\core\services\orm\tree_traversal\NodeGroupDao;
18 17
 use EventEspressoBatchRequest\Helpers\BatchRequestException;
Please login to merge, or discard this patch.
Indentation   +214 added lines, -214 removed lines patch added patch discarded remove patch
@@ -36,149 +36,149 @@  discard block
 block discarded – undo
36 36
 class PreviewEventDeletion extends JobHandler
37 37
 {
38 38
 
39
-    /**
40
-     * @var NodeGroupDao
41
-     */
42
-    protected $model_obj_node_group_persister;
39
+	/**
40
+	 * @var NodeGroupDao
41
+	 */
42
+	protected $model_obj_node_group_persister;
43 43
 
44
-    public function __construct(NodeGroupDao $model_obj_node_group_persister)
45
-    {
46
-        $this->model_obj_node_group_persister = $model_obj_node_group_persister;
47
-    }
44
+	public function __construct(NodeGroupDao $model_obj_node_group_persister)
45
+	{
46
+		$this->model_obj_node_group_persister = $model_obj_node_group_persister;
47
+	}
48 48
 
49
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
49
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
50 50
 
51
-    /**
52
-     *
53
-     * @param JobParameters $job_parameters
54
-     * @return JobStepResponse
55
-     * @throws EE_Error
56
-     * @throws InvalidDataTypeException
57
-     * @throws InvalidInterfaceException
58
-     * @throws InvalidArgumentException
59
-     * @throws ReflectionException
60
-     */
61
-    public function create_job(JobParameters $job_parameters)
62
-    {
63
-        // Set the "root" model objects we will want to delete (record their ID and model)
64
-        $event_ids = $job_parameters->request_datum('EVT_IDs', array());
65
-        // Find all the root nodes to delete (this isn't just events, because there's other data, like related tickets,
66
-        // prices, message templates, etc, whose model definition doesn't make them dependent on events. But,
67
-        // we have no UI to access them independent of events, so they may as well get deleted too.)
68
-        $roots = [];
69
-        foreach ($event_ids as $event_id) {
70
-            $roots[] = new ModelObjNode(
71
-                $event_id,
72
-                EEM_Event::instance()
73
-            );
74
-            // Also, we want to delete their related, non-global, tickets, prices and message templates
75
-            $related_non_global_tickets = EEM_Ticket::instance()->get_all_deleted_and_undeleted(
76
-                [
77
-                    [
78
-                        'TKT_is_default' => false,
79
-                        'Datetime.EVT_ID' => $event_id
80
-                    ]
81
-                ]
82
-            );
83
-            foreach ($related_non_global_tickets as $ticket) {
84
-                $roots[] = new ModelObjNode(
85
-                    $ticket->ID(),
86
-                    $ticket->get_model(),
87
-                    ['Registration']
88
-                );
89
-            }
90
-            $related_non_global_prices = EEM_Price::instance()->get_all_deleted_and_undeleted(
91
-                [
92
-                    [
93
-                        'PRC_is_default' => false,
94
-                        'Ticket.Datetime.EVT_ID' => $event_id
95
-                    ]
96
-                ]
97
-            );
98
-            foreach ($related_non_global_prices as $price) {
99
-                $roots[] = new ModelObjNode(
100
-                    $price->ID(),
101
-                    $price->get_model()
102
-                );
103
-            }
104
-        }
105
-        $transactions_ids = $this->getTransactionsToDelete($event_ids);
106
-        foreach ($transactions_ids as $transaction_id) {
107
-            $roots[] = new ModelObjNode(
108
-                $transaction_id,
109
-                EEM_Transaction::instance(),
110
-                ['Registration']
111
-            );
112
-        }
113
-        $job_parameters->add_extra_data('roots', $roots);
114
-        // Set an estimate of how long this will take (we're discovering as we go, so it seems impossible to give
115
-        // an accurate count.)
116
-        $estimated_work_per_model_obj = 10;
117
-        $count_regs = EEM_Registration::instance()->count(
118
-            [
119
-                [
120
-                    'EVT_ID' => ['IN', $event_ids]
121
-                ]
122
-            ]
123
-        );
124
-        $job_parameters->set_job_size((count($roots) + $count_regs) * $estimated_work_per_model_obj);
125
-        return new JobStepResponse(
126
-            $job_parameters,
127
-            esc_html__('Generating preview of data to be deleted...', 'event_espresso')
128
-        );
129
-    }
51
+	/**
52
+	 *
53
+	 * @param JobParameters $job_parameters
54
+	 * @return JobStepResponse
55
+	 * @throws EE_Error
56
+	 * @throws InvalidDataTypeException
57
+	 * @throws InvalidInterfaceException
58
+	 * @throws InvalidArgumentException
59
+	 * @throws ReflectionException
60
+	 */
61
+	public function create_job(JobParameters $job_parameters)
62
+	{
63
+		// Set the "root" model objects we will want to delete (record their ID and model)
64
+		$event_ids = $job_parameters->request_datum('EVT_IDs', array());
65
+		// Find all the root nodes to delete (this isn't just events, because there's other data, like related tickets,
66
+		// prices, message templates, etc, whose model definition doesn't make them dependent on events. But,
67
+		// we have no UI to access them independent of events, so they may as well get deleted too.)
68
+		$roots = [];
69
+		foreach ($event_ids as $event_id) {
70
+			$roots[] = new ModelObjNode(
71
+				$event_id,
72
+				EEM_Event::instance()
73
+			);
74
+			// Also, we want to delete their related, non-global, tickets, prices and message templates
75
+			$related_non_global_tickets = EEM_Ticket::instance()->get_all_deleted_and_undeleted(
76
+				[
77
+					[
78
+						'TKT_is_default' => false,
79
+						'Datetime.EVT_ID' => $event_id
80
+					]
81
+				]
82
+			);
83
+			foreach ($related_non_global_tickets as $ticket) {
84
+				$roots[] = new ModelObjNode(
85
+					$ticket->ID(),
86
+					$ticket->get_model(),
87
+					['Registration']
88
+				);
89
+			}
90
+			$related_non_global_prices = EEM_Price::instance()->get_all_deleted_and_undeleted(
91
+				[
92
+					[
93
+						'PRC_is_default' => false,
94
+						'Ticket.Datetime.EVT_ID' => $event_id
95
+					]
96
+				]
97
+			);
98
+			foreach ($related_non_global_prices as $price) {
99
+				$roots[] = new ModelObjNode(
100
+					$price->ID(),
101
+					$price->get_model()
102
+				);
103
+			}
104
+		}
105
+		$transactions_ids = $this->getTransactionsToDelete($event_ids);
106
+		foreach ($transactions_ids as $transaction_id) {
107
+			$roots[] = new ModelObjNode(
108
+				$transaction_id,
109
+				EEM_Transaction::instance(),
110
+				['Registration']
111
+			);
112
+		}
113
+		$job_parameters->add_extra_data('roots', $roots);
114
+		// Set an estimate of how long this will take (we're discovering as we go, so it seems impossible to give
115
+		// an accurate count.)
116
+		$estimated_work_per_model_obj = 10;
117
+		$count_regs = EEM_Registration::instance()->count(
118
+			[
119
+				[
120
+					'EVT_ID' => ['IN', $event_ids]
121
+				]
122
+			]
123
+		);
124
+		$job_parameters->set_job_size((count($roots) + $count_regs) * $estimated_work_per_model_obj);
125
+		return new JobStepResponse(
126
+			$job_parameters,
127
+			esc_html__('Generating preview of data to be deleted...', 'event_espresso')
128
+		);
129
+	}
130 130
 
131
-    /**
132
-     * @since $VID:$
133
-     * @param EE_Base_Class[] $model_objs
134
-     * @param array $dont_traverse_models
135
-     * @return array
136
-     * @throws EE_Error
137
-     * @throws InvalidArgumentException
138
-     * @throws InvalidDataTypeException
139
-     * @throws InvalidInterfaceException
140
-     * @throws ReflectionException
141
-     */
142
-    protected function createModelObjNodes($model_objs, array $dont_traverse_models = [])
143
-    {
144
-        $nodes = [];
145
-        foreach ($model_objs as $model_obj) {
146
-            $nodes[] = new ModelObjNode(
147
-                $model_obj->ID(),
148
-                $model_obj->get_model(),
149
-                $dont_traverse_models
150
-            );
151
-        }
152
-        return $nodes;
153
-    }
131
+	/**
132
+	 * @since $VID:$
133
+	 * @param EE_Base_Class[] $model_objs
134
+	 * @param array $dont_traverse_models
135
+	 * @return array
136
+	 * @throws EE_Error
137
+	 * @throws InvalidArgumentException
138
+	 * @throws InvalidDataTypeException
139
+	 * @throws InvalidInterfaceException
140
+	 * @throws ReflectionException
141
+	 */
142
+	protected function createModelObjNodes($model_objs, array $dont_traverse_models = [])
143
+	{
144
+		$nodes = [];
145
+		foreach ($model_objs as $model_obj) {
146
+			$nodes[] = new ModelObjNode(
147
+				$model_obj->ID(),
148
+				$model_obj->get_model(),
149
+				$dont_traverse_models
150
+			);
151
+		}
152
+		return $nodes;
153
+	}
154 154
 
155
-    /**
156
-     * Gets all the transactions related to these events that aren't related to other events. They'll be deleted too.
157
-     * (Ones that are related to other events can stay around until those other events are deleted too.)
158
-     * @since $VID:$
159
-     * @param $event_ids
160
-     * @return array of transaction IDs
161
-     */
162
-    protected function getTransactionsToDelete($event_ids)
163
-    {
164
-        if (empty($event_ids)) {
165
-            return [];
166
-        }
167
-        global $wpdb;
168
-        $event_ids = array_map(
169
-            'intval',
170
-            $event_ids
171
-        );
172
-        $imploded_sanitized_event_ids = implode(',', $event_ids);
173
-        // Select transactions with registrations for the events $event_ids which also don't have registrations
174
-        // for any events NOT in $event_ids.
175
-        // Notice the outer query searched for transactions whose registrations ARE in $event_ids,
176
-        // whereas the inner query checks if the outer query's transaction has any registrations that are
177
-        // NOT IN $event_ids (ie, don't have registrations for events we're not just about to delete.)
178
-        return array_map(
179
-            'intval',
180
-            $wpdb->get_col(
181
-                "SELECT 
155
+	/**
156
+	 * Gets all the transactions related to these events that aren't related to other events. They'll be deleted too.
157
+	 * (Ones that are related to other events can stay around until those other events are deleted too.)
158
+	 * @since $VID:$
159
+	 * @param $event_ids
160
+	 * @return array of transaction IDs
161
+	 */
162
+	protected function getTransactionsToDelete($event_ids)
163
+	{
164
+		if (empty($event_ids)) {
165
+			return [];
166
+		}
167
+		global $wpdb;
168
+		$event_ids = array_map(
169
+			'intval',
170
+			$event_ids
171
+		);
172
+		$imploded_sanitized_event_ids = implode(',', $event_ids);
173
+		// Select transactions with registrations for the events $event_ids which also don't have registrations
174
+		// for any events NOT in $event_ids.
175
+		// Notice the outer query searched for transactions whose registrations ARE in $event_ids,
176
+		// whereas the inner query checks if the outer query's transaction has any registrations that are
177
+		// NOT IN $event_ids (ie, don't have registrations for events we're not just about to delete.)
178
+		return array_map(
179
+			'intval',
180
+			$wpdb->get_col(
181
+				"SELECT 
182 182
                       DISTINCT t.TXN_ID
183 183
                     FROM 
184 184
                       {$wpdb->prefix}esp_transaction t INNER JOIN 
@@ -196,84 +196,84 @@  discard block
 block discarded – undo
196 196
                            tsub.TXN_ID=t.TXN_ID AND
197 197
                            rsub.EVT_ID NOT IN ({$imploded_sanitized_event_ids})
198 198
                        )"
199
-            )
200
-        );
201
-    }
199
+			)
200
+		);
201
+	}
202 202
 
203
-    /**
204
-     * Performs another step of the job
205
-     * @param JobParameters $job_parameters
206
-     * @param int $batch_size
207
-     * @return JobStepResponse
208
-     * @throws BatchRequestException
209
-     */
210
-    public function continue_job(JobParameters $job_parameters, $batch_size = 50)
211
-    {
212
-        // Serializing and unserializing is what really makes this drag on (eg on localhost, the ajax requests took
213
-        // about 4 seconds when the batch size was 250, but 3 seconds when the batch size was 50. So like
214
-        // 50% of the request is just serializing and unserializing.) So, make the batches much bigger.
215
-        $batch_size *= 3;
216
-        $units_processed = 0;
217
-        foreach ($job_parameters->extra_datum('roots', array()) as $root_node) {
218
-            if ($units_processed >= $batch_size) {
219
-                break;
220
-            }
221
-            if (!$root_node instanceof ModelObjNode) {
222
-                throw new InvalidClassException('ModelObjNode');
223
-            }
224
-            if ($root_node->isComplete()) {
225
-                continue;
226
-            }
227
-            $units_processed += $root_node->visit($batch_size - $units_processed);
228
-        }
229
-        $job_parameters->mark_processed($units_processed);
230
-        // If the most-recently processed root node is complete, we must be all done because we're doing them
231
-        // sequentially.
232
-        if (isset($root_node) && $root_node instanceof ModelObjNode && $root_node->isComplete()) {
233
-            $job_parameters->set_status(JobParameters::status_complete);
234
-            // Show a full progress bar.
235
-            $job_parameters->set_units_processed($job_parameters->job_size());
236
-            $deletion_job_code = $job_parameters->request_datum('deletion_job_code');
237
-            $this->model_obj_node_group_persister->persistModelObjNodesGroup(
238
-                $job_parameters->extra_datum('roots'),
239
-                $deletion_job_code
240
-            );
241
-            return new JobStepResponse(
242
-                $job_parameters,
243
-                esc_html__('Finished identifying items for deletion.', 'event_espresso'),
244
-                [
245
-                    'deletion_job_code' => $deletion_job_code
246
-                ]
247
-            );
248
-        } else {
249
-            // Because the job size was a guess, it may have likely been provden wrong. We don't want to show more work
250
-            // done than we originally said there would be. So adjust the estimate.
251
-            if (($job_parameters->units_processed() / $job_parameters->job_size()) > .8) {
252
-                $job_parameters->set_job_size($job_parameters->job_size() * 2);
253
-            }
254
-            return new JobStepResponse(
255
-                $job_parameters,
256
-                sprintf(
257
-                    esc_html__('Identified %d items for deletion.', 'event_espresso'),
258
-                    $units_processed
259
-                )
260
-            );
261
-        }
262
-    }
203
+	/**
204
+	 * Performs another step of the job
205
+	 * @param JobParameters $job_parameters
206
+	 * @param int $batch_size
207
+	 * @return JobStepResponse
208
+	 * @throws BatchRequestException
209
+	 */
210
+	public function continue_job(JobParameters $job_parameters, $batch_size = 50)
211
+	{
212
+		// Serializing and unserializing is what really makes this drag on (eg on localhost, the ajax requests took
213
+		// about 4 seconds when the batch size was 250, but 3 seconds when the batch size was 50. So like
214
+		// 50% of the request is just serializing and unserializing.) So, make the batches much bigger.
215
+		$batch_size *= 3;
216
+		$units_processed = 0;
217
+		foreach ($job_parameters->extra_datum('roots', array()) as $root_node) {
218
+			if ($units_processed >= $batch_size) {
219
+				break;
220
+			}
221
+			if (!$root_node instanceof ModelObjNode) {
222
+				throw new InvalidClassException('ModelObjNode');
223
+			}
224
+			if ($root_node->isComplete()) {
225
+				continue;
226
+			}
227
+			$units_processed += $root_node->visit($batch_size - $units_processed);
228
+		}
229
+		$job_parameters->mark_processed($units_processed);
230
+		// If the most-recently processed root node is complete, we must be all done because we're doing them
231
+		// sequentially.
232
+		if (isset($root_node) && $root_node instanceof ModelObjNode && $root_node->isComplete()) {
233
+			$job_parameters->set_status(JobParameters::status_complete);
234
+			// Show a full progress bar.
235
+			$job_parameters->set_units_processed($job_parameters->job_size());
236
+			$deletion_job_code = $job_parameters->request_datum('deletion_job_code');
237
+			$this->model_obj_node_group_persister->persistModelObjNodesGroup(
238
+				$job_parameters->extra_datum('roots'),
239
+				$deletion_job_code
240
+			);
241
+			return new JobStepResponse(
242
+				$job_parameters,
243
+				esc_html__('Finished identifying items for deletion.', 'event_espresso'),
244
+				[
245
+					'deletion_job_code' => $deletion_job_code
246
+				]
247
+			);
248
+		} else {
249
+			// Because the job size was a guess, it may have likely been provden wrong. We don't want to show more work
250
+			// done than we originally said there would be. So adjust the estimate.
251
+			if (($job_parameters->units_processed() / $job_parameters->job_size()) > .8) {
252
+				$job_parameters->set_job_size($job_parameters->job_size() * 2);
253
+			}
254
+			return new JobStepResponse(
255
+				$job_parameters,
256
+				sprintf(
257
+					esc_html__('Identified %d items for deletion.', 'event_espresso'),
258
+					$units_processed
259
+				)
260
+			);
261
+		}
262
+	}
263 263
 
264
-    /**
265
-     * Performs any clean-up logic when we know the job is completed
266
-     * @param JobParameters $job_parameters
267
-     * @return JobStepResponse
268
-     */
269
-    public function cleanup_job(JobParameters $job_parameters)
270
-    {
271
-        // Nothing much to do. We can't delete the option with the built tree because we may need it in a moment for the deletion
272
-        return new JobStepResponse(
273
-            $job_parameters,
274
-            esc_html__('All done', 'event_espresso')
275
-        );
276
-    }
264
+	/**
265
+	 * Performs any clean-up logic when we know the job is completed
266
+	 * @param JobParameters $job_parameters
267
+	 * @return JobStepResponse
268
+	 */
269
+	public function cleanup_job(JobParameters $job_parameters)
270
+	{
271
+		// Nothing much to do. We can't delete the option with the built tree because we may need it in a moment for the deletion
272
+		return new JobStepResponse(
273
+			$job_parameters,
274
+			esc_html__('All done', 'event_espresso')
275
+		);
276
+	}
277 277
 }
278 278
 // End of file EventDeletion.php
279 279
 // Location: EventEspressoBatchRequest\JobHandlers/EventDeletion.php
Please login to merge, or discard this patch.
core/services/orm/tree_traversal/ModelObjNode.php 1 patch
Indentation   +186 added lines, -186 removed lines patch added patch discarded remove patch
@@ -22,204 +22,204 @@
 block discarded – undo
22 22
  */
23 23
 class ModelObjNode extends BaseNode
24 24
 {
25
-    /**
26
-     * @var int|string
27
-     */
28
-    protected $id;
25
+	/**
26
+	 * @var int|string
27
+	 */
28
+	protected $id;
29 29
 
30
-    /**
31
-     * @var EEM_Base
32
-     */
33
-    protected $model;
30
+	/**
31
+	 * @var EEM_Base
32
+	 */
33
+	protected $model;
34 34
 
35
-    /**
36
-     * @var RelationNode[]
37
-     */
38
-    protected $nodes;
35
+	/**
36
+	 * @var RelationNode[]
37
+	 */
38
+	protected $nodes;
39 39
 
40
-    /**
41
-     * We don't pass the model objects because this needs to serialize to something tiny for effiency.
42
-     * @param $model_obj_id
43
-     * @param EEM_Base $model
44
-     * @param array $dont_traverse_models array of model names we DON'T want to traverse.
45
-     */
46
-    public function __construct($model_obj_id, EEM_Base $model, array $dont_traverse_models = [])
47
-    {
48
-        $this->id = $model_obj_id;
49
-        $this->model = $model;
50
-        $this->dont_traverse_models = $dont_traverse_models;
51
-    }
40
+	/**
41
+	 * We don't pass the model objects because this needs to serialize to something tiny for effiency.
42
+	 * @param $model_obj_id
43
+	 * @param EEM_Base $model
44
+	 * @param array $dont_traverse_models array of model names we DON'T want to traverse.
45
+	 */
46
+	public function __construct($model_obj_id, EEM_Base $model, array $dont_traverse_models = [])
47
+	{
48
+		$this->id = $model_obj_id;
49
+		$this->model = $model;
50
+		$this->dont_traverse_models = $dont_traverse_models;
51
+	}
52 52
 
53
-    /**
54
-     * Creates a relation node for each relation of this model's relations.
55
-     * Does NOT call `discover` on them yet though.
56
-     * @since $VID:$
57
-     * @throws \EE_Error
58
-     * @throws InvalidDataTypeException
59
-     * @throws InvalidInterfaceException
60
-     * @throws InvalidArgumentException
61
-     * @throws ReflectionException
62
-     */
63
-    protected function discover()
64
-    {
65
-        $this->nodes = [];
66
-        foreach ($this->model->relation_settings() as $relationName => $relation) {
67
-            // Make sure this isn't one of the models we were told to not traverse into.
68
-            if (in_array($relationName, $this->dont_traverse_models)) {
69
-                continue;
70
-            }
71
-            if ($relation instanceof EE_Has_Many_Relation) {
72
-                $this->nodes[ $relationName ] = new RelationNode(
73
-                    $this->id,
74
-                    $this->model,
75
-                    $relation->get_other_model(),
76
-                    $this->dont_traverse_models
77
-                );
78
-            } elseif ($relation instanceof EE_HABTM_Relation &&
79
-                ! in_array(
80
-                    $relation->get_join_model()->get_this_model_name(),
81
-                    $this->dont_traverse_models
82
-                )) {
83
-                $this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode(
84
-                    $this->id,
85
-                    $this->model,
86
-                    $relation->get_join_model(),
87
-                    $this->dont_traverse_models
88
-                );
89
-            }
90
-        }
91
-        ksort($this->nodes);
92
-    }
53
+	/**
54
+	 * Creates a relation node for each relation of this model's relations.
55
+	 * Does NOT call `discover` on them yet though.
56
+	 * @since $VID:$
57
+	 * @throws \EE_Error
58
+	 * @throws InvalidDataTypeException
59
+	 * @throws InvalidInterfaceException
60
+	 * @throws InvalidArgumentException
61
+	 * @throws ReflectionException
62
+	 */
63
+	protected function discover()
64
+	{
65
+		$this->nodes = [];
66
+		foreach ($this->model->relation_settings() as $relationName => $relation) {
67
+			// Make sure this isn't one of the models we were told to not traverse into.
68
+			if (in_array($relationName, $this->dont_traverse_models)) {
69
+				continue;
70
+			}
71
+			if ($relation instanceof EE_Has_Many_Relation) {
72
+				$this->nodes[ $relationName ] = new RelationNode(
73
+					$this->id,
74
+					$this->model,
75
+					$relation->get_other_model(),
76
+					$this->dont_traverse_models
77
+				);
78
+			} elseif ($relation instanceof EE_HABTM_Relation &&
79
+				! in_array(
80
+					$relation->get_join_model()->get_this_model_name(),
81
+					$this->dont_traverse_models
82
+				)) {
83
+				$this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode(
84
+					$this->id,
85
+					$this->model,
86
+					$relation->get_join_model(),
87
+					$this->dont_traverse_models
88
+				);
89
+			}
90
+		}
91
+		ksort($this->nodes);
92
+	}
93 93
 
94 94
 
95
-    /**
96
-     * Whether this item has already been initialized
97
-     */
98
-    protected function isDiscovered()
99
-    {
100
-        return $this->nodes !== null && is_array($this->nodes);
101
-    }
95
+	/**
96
+	 * Whether this item has already been initialized
97
+	 */
98
+	protected function isDiscovered()
99
+	{
100
+		return $this->nodes !== null && is_array($this->nodes);
101
+	}
102 102
 
103
-    /**
104
-     * @since $VID:$
105
-     * @return boolean
106
-     */
107
-    public function isComplete()
108
-    {
109
-        if ($this->complete === null) {
110
-            $this->complete = false;
111
-        }
112
-        return $this->complete;
113
-    }
103
+	/**
104
+	 * @since $VID:$
105
+	 * @return boolean
106
+	 */
107
+	public function isComplete()
108
+	{
109
+		if ($this->complete === null) {
110
+			$this->complete = false;
111
+		}
112
+		return $this->complete;
113
+	}
114 114
 
115
-    /**
116
-     * Triggers working on each child relation node that has work to do.
117
-     * @since $VID:$
118
-     * @param $model_objects_to_identify
119
-     * @return int units of work done
120
-     */
121
-    protected function work($model_objects_to_identify)
122
-    {
123
-        $num_identified = 0;
124
-        // Begin assuming we'll finish all the work on this node and its children...
125
-        $this->complete = true;
126
-        foreach ($this->nodes as $model_name => $relation_node) {
127
-            $num_identified += $relation_node->visit($model_objects_to_identify - $num_identified);
128
-            // To save on space when serializing, only bother keeping a record of relation nodes that actually found
129
-            // related model objects.
130
-            if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) {
131
-                unset($this->nodes[ $model_name ]);
132
-            }
133
-            if ($num_identified >= $model_objects_to_identify) {
134
-                // ...but admit we're wrong if the work exceeded the budget.
135
-                $this->complete = false;
136
-                break;
137
-            }
138
-        }
139
-        return $num_identified;
140
-    }
115
+	/**
116
+	 * Triggers working on each child relation node that has work to do.
117
+	 * @since $VID:$
118
+	 * @param $model_objects_to_identify
119
+	 * @return int units of work done
120
+	 */
121
+	protected function work($model_objects_to_identify)
122
+	{
123
+		$num_identified = 0;
124
+		// Begin assuming we'll finish all the work on this node and its children...
125
+		$this->complete = true;
126
+		foreach ($this->nodes as $model_name => $relation_node) {
127
+			$num_identified += $relation_node->visit($model_objects_to_identify - $num_identified);
128
+			// To save on space when serializing, only bother keeping a record of relation nodes that actually found
129
+			// related model objects.
130
+			if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) {
131
+				unset($this->nodes[ $model_name ]);
132
+			}
133
+			if ($num_identified >= $model_objects_to_identify) {
134
+				// ...but admit we're wrong if the work exceeded the budget.
135
+				$this->complete = false;
136
+				break;
137
+			}
138
+		}
139
+		return $num_identified;
140
+	}
141 141
 
142
-    /**
143
-     * @since $VID:$
144
-     * @return array
145
-     * @throws \EE_Error
146
-     * @throws InvalidDataTypeException
147
-     * @throws InvalidInterfaceException
148
-     * @throws InvalidArgumentException
149
-     * @throws ReflectionException
150
-     */
151
-    public function toArray()
152
-    {
153
-        $tree = [
154
-            'id' => $this->id,
155
-            'complete' => $this->isComplete(),
156
-            'rels' => []
157
-        ];
158
-        if ($this->nodes === null) {
159
-            $tree['rels'] = null;
160
-        } else {
161
-            foreach ($this->nodes as $relation_name => $relation_node) {
162
-                $tree['rels'][ $relation_name ] = $relation_node->toArray();
163
-            }
164
-        }
165
-        return $tree;
166
-    }
142
+	/**
143
+	 * @since $VID:$
144
+	 * @return array
145
+	 * @throws \EE_Error
146
+	 * @throws InvalidDataTypeException
147
+	 * @throws InvalidInterfaceException
148
+	 * @throws InvalidArgumentException
149
+	 * @throws ReflectionException
150
+	 */
151
+	public function toArray()
152
+	{
153
+		$tree = [
154
+			'id' => $this->id,
155
+			'complete' => $this->isComplete(),
156
+			'rels' => []
157
+		];
158
+		if ($this->nodes === null) {
159
+			$tree['rels'] = null;
160
+		} else {
161
+			foreach ($this->nodes as $relation_name => $relation_node) {
162
+				$tree['rels'][ $relation_name ] = $relation_node->toArray();
163
+			}
164
+		}
165
+		return $tree;
166
+	}
167 167
 
168
-    /**
169
-     * @since $VID:$
170
-     * @return array|mixed
171
-     * @throws InvalidArgumentException
172
-     * @throws InvalidDataTypeException
173
-     * @throws InvalidInterfaceException
174
-     * @throws ReflectionException
175
-     * @throws \EE_Error
176
-     */
177
-    public function getIds()
178
-    {
179
-        $ids = [
180
-            $this->model->get_this_model_name() => [
181
-                $this->id => $this->id
182
-            ]
183
-        ];
184
-        if ($this->nodes && is_array($this->nodes)) {
185
-            foreach ($this->nodes as $relation_node) {
186
-                $ids = array_replace_recursive($ids, $relation_node->getIds());
187
-            }
188
-        }
189
-        return $ids;
190
-    }
168
+	/**
169
+	 * @since $VID:$
170
+	 * @return array|mixed
171
+	 * @throws InvalidArgumentException
172
+	 * @throws InvalidDataTypeException
173
+	 * @throws InvalidInterfaceException
174
+	 * @throws ReflectionException
175
+	 * @throws \EE_Error
176
+	 */
177
+	public function getIds()
178
+	{
179
+		$ids = [
180
+			$this->model->get_this_model_name() => [
181
+				$this->id => $this->id
182
+			]
183
+		];
184
+		if ($this->nodes && is_array($this->nodes)) {
185
+			foreach ($this->nodes as $relation_node) {
186
+				$ids = array_replace_recursive($ids, $relation_node->getIds());
187
+			}
188
+		}
189
+		return $ids;
190
+	}
191 191
 
192
-    /**
193
-     * Don't serialize the models. Just record their names on some dynamic properties.
194
-     * @since $VID:$
195
-     */
196
-    public function __sleep()
197
-    {
198
-        $this->m = $this->model->get_this_model_name();
199
-        return array_merge(
200
-            [
201
-                'm',
202
-                'id',
203
-                'nodes',
204
-            ],
205
-            parent::__sleep()
206
-        );
207
-    }
192
+	/**
193
+	 * Don't serialize the models. Just record their names on some dynamic properties.
194
+	 * @since $VID:$
195
+	 */
196
+	public function __sleep()
197
+	{
198
+		$this->m = $this->model->get_this_model_name();
199
+		return array_merge(
200
+			[
201
+				'm',
202
+				'id',
203
+				'nodes',
204
+			],
205
+			parent::__sleep()
206
+		);
207
+	}
208 208
 
209
-    /**
210
-     * Use the dynamic properties to instantiate the models we use.
211
-     * @since $VID:$
212
-     * @throws EE_Error
213
-     * @throws InvalidArgumentException
214
-     * @throws InvalidDataTypeException
215
-     * @throws InvalidInterfaceException
216
-     * @throws ReflectionException
217
-     */
218
-    public function __wakeup()
219
-    {
220
-        $this->model = EE_Registry::instance()->load_model($this->m);
221
-        parent::__wakeup();
222
-    }
209
+	/**
210
+	 * Use the dynamic properties to instantiate the models we use.
211
+	 * @since $VID:$
212
+	 * @throws EE_Error
213
+	 * @throws InvalidArgumentException
214
+	 * @throws InvalidDataTypeException
215
+	 * @throws InvalidInterfaceException
216
+	 * @throws ReflectionException
217
+	 */
218
+	public function __wakeup()
219
+	{
220
+		$this->model = EE_Registry::instance()->load_model($this->m);
221
+		parent::__wakeup();
222
+	}
223 223
 }
224 224
 // End of file Visitor.php
225 225
 // Location: EventEspresso\core\services\orm\tree_traversal/Visitor.php
Please login to merge, or discard this patch.
core/services/orm/tree_traversal/RelationNode.php 1 patch
Indentation   +264 added lines, -264 removed lines patch added patch discarded remove patch
@@ -28,289 +28,289 @@
 block discarded – undo
28 28
 class RelationNode extends BaseNode
29 29
 {
30 30
 
31
-    /**
32
-     * @var string|int
33
-     */
34
-    protected $id;
31
+	/**
32
+	 * @var string|int
33
+	 */
34
+	protected $id;
35 35
 
36
-    /**
37
-     * @var EEM_Base
38
-     */
39
-    protected $main_model;
36
+	/**
37
+	 * @var EEM_Base
38
+	 */
39
+	protected $main_model;
40 40
 
41
-    /**
42
-     * @var int
43
-     */
44
-    protected $count;
41
+	/**
42
+	 * @var int
43
+	 */
44
+	protected $count;
45 45
 
46
-    /**
47
-     * @var EEM_Base
48
-     */
49
-    protected $related_model;
46
+	/**
47
+	 * @var EEM_Base
48
+	 */
49
+	protected $related_model;
50 50
 
51
-    /**
52
-     * @var ModelObjNode[]
53
-     */
54
-    protected $nodes;
51
+	/**
52
+	 * @var ModelObjNode[]
53
+	 */
54
+	protected $nodes;
55 55
 
56
-    /**
57
-     * RelationNode constructor.
58
-     * @param $main_model_obj_id
59
-     * @param EEM_Base $main_model
60
-     * @param EEM_Base $related_model
61
-     * @param array $dont_traverse_models array of model names we DON'T want to traverse
62
-     */
63
-    public function __construct(
64
-        $main_model_obj_id,
65
-        EEM_Base $main_model,
66
-        EEM_Base $related_model,
67
-        array $dont_traverse_models = []
68
-    ) {
69
-        $this->id = $main_model_obj_id;
70
-        $this->main_model = $main_model;
71
-        $this->related_model = $related_model;
72
-        $this->nodes = [];
73
-        $this->dont_traverse_models = $dont_traverse_models;
74
-    }
56
+	/**
57
+	 * RelationNode constructor.
58
+	 * @param $main_model_obj_id
59
+	 * @param EEM_Base $main_model
60
+	 * @param EEM_Base $related_model
61
+	 * @param array $dont_traverse_models array of model names we DON'T want to traverse
62
+	 */
63
+	public function __construct(
64
+		$main_model_obj_id,
65
+		EEM_Base $main_model,
66
+		EEM_Base $related_model,
67
+		array $dont_traverse_models = []
68
+	) {
69
+		$this->id = $main_model_obj_id;
70
+		$this->main_model = $main_model;
71
+		$this->related_model = $related_model;
72
+		$this->nodes = [];
73
+		$this->dont_traverse_models = $dont_traverse_models;
74
+	}
75 75
 
76 76
 
77
-    /**
78
-     * Here is where most of the work happens. We've counted how many related model objects exist, here we identify
79
-     * them (ie, learn their IDs). But its recursive, so we'll also find their related dependent model objects etc.
80
-     * @since $VID:$
81
-     * @param int $model_objects_to_identify
82
-     * @return int
83
-     * @throws EE_Error
84
-     * @throws InvalidArgumentException
85
-     * @throws InvalidDataTypeException
86
-     * @throws InvalidInterfaceException
87
-     * @throws ReflectionException
88
-     */
89
-    protected function work($model_objects_to_identify)
90
-    {
91
-        $num_identified = $this->visitAlreadyDiscoveredNodes($this->nodes, $model_objects_to_identify);
92
-        if ($num_identified < $model_objects_to_identify) {
93
-            $related_model_objs = $this->related_model->get_all(
94
-                [
95
-                    $this->whereQueryParams(),
96
-                    'limit' => [
97
-                        count($this->nodes),
98
-                        $model_objects_to_identify - $num_identified
99
-                    ]
100
-                ]
101
-            );
102
-            $new_item_nodes = [];
77
+	/**
78
+	 * Here is where most of the work happens. We've counted how many related model objects exist, here we identify
79
+	 * them (ie, learn their IDs). But its recursive, so we'll also find their related dependent model objects etc.
80
+	 * @since $VID:$
81
+	 * @param int $model_objects_to_identify
82
+	 * @return int
83
+	 * @throws EE_Error
84
+	 * @throws InvalidArgumentException
85
+	 * @throws InvalidDataTypeException
86
+	 * @throws InvalidInterfaceException
87
+	 * @throws ReflectionException
88
+	 */
89
+	protected function work($model_objects_to_identify)
90
+	{
91
+		$num_identified = $this->visitAlreadyDiscoveredNodes($this->nodes, $model_objects_to_identify);
92
+		if ($num_identified < $model_objects_to_identify) {
93
+			$related_model_objs = $this->related_model->get_all(
94
+				[
95
+					$this->whereQueryParams(),
96
+					'limit' => [
97
+						count($this->nodes),
98
+						$model_objects_to_identify - $num_identified
99
+					]
100
+				]
101
+			);
102
+			$new_item_nodes = [];
103 103
 
104
-            // Add entity nodes for each of the model objects we fetched.
105
-            foreach ($related_model_objs as $related_model_obj) {
106
-                $entity_node = new ModelObjNode($related_model_obj->ID(), $related_model_obj->get_model(), $this->dont_traverse_models);
107
-                $this->nodes[ $related_model_obj->ID() ] = $entity_node;
108
-                $new_item_nodes[ $related_model_obj->ID() ] = $entity_node;
109
-            }
110
-            $num_identified += count($new_item_nodes);
111
-            if ($num_identified < $model_objects_to_identify) {
112
-                // And lastly do the work.
113
-                $num_identified += $this->visitAlreadyDiscoveredNodes(
114
-                    $new_item_nodes,
115
-                    $model_objects_to_identify - $num_identified
116
-                );
117
-            }
118
-        }
104
+			// Add entity nodes for each of the model objects we fetched.
105
+			foreach ($related_model_objs as $related_model_obj) {
106
+				$entity_node = new ModelObjNode($related_model_obj->ID(), $related_model_obj->get_model(), $this->dont_traverse_models);
107
+				$this->nodes[ $related_model_obj->ID() ] = $entity_node;
108
+				$new_item_nodes[ $related_model_obj->ID() ] = $entity_node;
109
+			}
110
+			$num_identified += count($new_item_nodes);
111
+			if ($num_identified < $model_objects_to_identify) {
112
+				// And lastly do the work.
113
+				$num_identified += $this->visitAlreadyDiscoveredNodes(
114
+					$new_item_nodes,
115
+					$model_objects_to_identify - $num_identified
116
+				);
117
+			}
118
+		}
119 119
 
120
-        if (count($this->nodes) >= $this->count && $this->allChildrenComplete()) {
121
-            $this->complete = true;
122
-        }
123
-        return $num_identified;
124
-    }
120
+		if (count($this->nodes) >= $this->count && $this->allChildrenComplete()) {
121
+			$this->complete = true;
122
+		}
123
+		return $num_identified;
124
+	}
125 125
 
126
-    /**
127
-     * Checks if all the identified child nodes are complete or not.
128
-     * @since $VID:$
129
-     * @return bool
130
-     */
131
-    protected function allChildrenComplete()
132
-    {
133
-        foreach ($this->nodes as $model_obj_node) {
134
-            if (! $model_obj_node->isComplete()) {
135
-                return false;
136
-            }
137
-        }
138
-        return true;
139
-    }
126
+	/**
127
+	 * Checks if all the identified child nodes are complete or not.
128
+	 * @since $VID:$
129
+	 * @return bool
130
+	 */
131
+	protected function allChildrenComplete()
132
+	{
133
+		foreach ($this->nodes as $model_obj_node) {
134
+			if (! $model_obj_node->isComplete()) {
135
+				return false;
136
+			}
137
+		}
138
+		return true;
139
+	}
140 140
 
141
-    /**
142
-     * Visits the provided nodes and keeps track of how much work was done, making sure to not go over budget.
143
-     * @since $VID:$
144
-     * @param ModelObjNode[] $model_obj_nodes
145
-     * @param $work_budget
146
-     * @return int
147
-     */
148
-    protected function visitAlreadyDiscoveredNodes($model_obj_nodes, $work_budget)
149
-    {
150
-        $work_done = 0;
151
-        if (! $model_obj_nodes) {
152
-            return 0;
153
-        }
154
-        foreach ($model_obj_nodes as $model_obj_node) {
155
-            if ($work_done >= $work_budget) {
156
-                break;
157
-            }
158
-            $work_done += $model_obj_node->visit($work_budget - $work_done);
159
-        }
160
-        return $work_done;
161
-    }
141
+	/**
142
+	 * Visits the provided nodes and keeps track of how much work was done, making sure to not go over budget.
143
+	 * @since $VID:$
144
+	 * @param ModelObjNode[] $model_obj_nodes
145
+	 * @param $work_budget
146
+	 * @return int
147
+	 */
148
+	protected function visitAlreadyDiscoveredNodes($model_obj_nodes, $work_budget)
149
+	{
150
+		$work_done = 0;
151
+		if (! $model_obj_nodes) {
152
+			return 0;
153
+		}
154
+		foreach ($model_obj_nodes as $model_obj_node) {
155
+			if ($work_done >= $work_budget) {
156
+				break;
157
+			}
158
+			$work_done += $model_obj_node->visit($work_budget - $work_done);
159
+		}
160
+		return $work_done;
161
+	}
162 162
 
163
-    /**
164
-     * Whether this item has already been initialized
165
-     */
166
-    protected function isDiscovered()
167
-    {
168
-        return $this->count !== null;
169
-    }
163
+	/**
164
+	 * Whether this item has already been initialized
165
+	 */
166
+	protected function isDiscovered()
167
+	{
168
+		return $this->count !== null;
169
+	}
170 170
 
171
-    /**
172
-     * @since $VID:$
173
-     * @return boolean
174
-     */
175
-    public function isComplete()
176
-    {
177
-        if ($this->complete === null) {
178
-            if (count($this->nodes) === $this->count) {
179
-                $this->complete = true;
180
-            } else {
181
-                $this->complete = false;
182
-            }
183
-        }
184
-        return $this->complete;
185
-    }
171
+	/**
172
+	 * @since $VID:$
173
+	 * @return boolean
174
+	 */
175
+	public function isComplete()
176
+	{
177
+		if ($this->complete === null) {
178
+			if (count($this->nodes) === $this->count) {
179
+				$this->complete = true;
180
+			} else {
181
+				$this->complete = false;
182
+			}
183
+		}
184
+		return $this->complete;
185
+	}
186 186
 
187
-    /**
188
-     * Discovers how many related model objects exist.
189
-     * @since $VID:$
190
-     * @return mixed|void
191
-     * @throws EE_Error
192
-     * @throws InvalidArgumentException
193
-     * @throws InvalidDataTypeException
194
-     * @throws InvalidInterfaceException
195
-     * @throws ReflectionException
196
-     */
197
-    protected function discover()
198
-    {
199
-        $this->count = $this->related_model->count([$this->whereQueryParams()]);
200
-    }
187
+	/**
188
+	 * Discovers how many related model objects exist.
189
+	 * @since $VID:$
190
+	 * @return mixed|void
191
+	 * @throws EE_Error
192
+	 * @throws InvalidArgumentException
193
+	 * @throws InvalidDataTypeException
194
+	 * @throws InvalidInterfaceException
195
+	 * @throws ReflectionException
196
+	 */
197
+	protected function discover()
198
+	{
199
+		$this->count = $this->related_model->count([$this->whereQueryParams()]);
200
+	}
201 201
 
202
-    /**
203
-     * @since $VID:$
204
-     * @return array
205
-     * @throws EE_Error
206
-     * @throws InvalidDataTypeException
207
-     * @throws InvalidInterfaceException
208
-     * @throws InvalidArgumentException
209
-     * @throws ReflectionException
210
-     */
211
-    protected function whereQueryParams()
212
-    {
213
-        $where_params =  [
214
-            $this->related_model->get_foreign_key_to(
215
-                $this->main_model->get_this_model_name()
216
-            )->get_name() => $this->id
217
-        ];
218
-        try {
219
-            $relation_settings = $this->main_model->related_settings_for($this->related_model->get_this_model_name());
220
-        } catch (EE_Error $e) {
221
-            // This will happen for has-and-belongs-to-many relations, when this node's related model is that join table
222
-            // which hasn't been explicitly declared in the main model object's model's relations.
223
-            $relation_settings = null;
224
-        }
225
-        if ($relation_settings instanceof EE_Has_Many_Any_Relation) {
226
-            $where_params[ $this->related_model->get_field_containing_related_model_name()->get_name() ] = $this->main_model->get_this_model_name();
227
-        }
228
-        return $where_params;
229
-    }
230
-    /**
231
-     * @since $VID:$
232
-     * @return array
233
-     */
234
-    public function toArray()
235
-    {
236
-        $tree = [
237
-            'count' => $this->count,
238
-            'complete' => $this->isComplete(),
239
-            'objs' => []
240
-        ];
241
-        foreach ($this->nodes as $id => $model_obj_node) {
242
-            $tree['objs'][ $id ] = $model_obj_node->toArray();
243
-        }
244
-        return $tree;
245
-    }
202
+	/**
203
+	 * @since $VID:$
204
+	 * @return array
205
+	 * @throws EE_Error
206
+	 * @throws InvalidDataTypeException
207
+	 * @throws InvalidInterfaceException
208
+	 * @throws InvalidArgumentException
209
+	 * @throws ReflectionException
210
+	 */
211
+	protected function whereQueryParams()
212
+	{
213
+		$where_params =  [
214
+			$this->related_model->get_foreign_key_to(
215
+				$this->main_model->get_this_model_name()
216
+			)->get_name() => $this->id
217
+		];
218
+		try {
219
+			$relation_settings = $this->main_model->related_settings_for($this->related_model->get_this_model_name());
220
+		} catch (EE_Error $e) {
221
+			// This will happen for has-and-belongs-to-many relations, when this node's related model is that join table
222
+			// which hasn't been explicitly declared in the main model object's model's relations.
223
+			$relation_settings = null;
224
+		}
225
+		if ($relation_settings instanceof EE_Has_Many_Any_Relation) {
226
+			$where_params[ $this->related_model->get_field_containing_related_model_name()->get_name() ] = $this->main_model->get_this_model_name();
227
+		}
228
+		return $where_params;
229
+	}
230
+	/**
231
+	 * @since $VID:$
232
+	 * @return array
233
+	 */
234
+	public function toArray()
235
+	{
236
+		$tree = [
237
+			'count' => $this->count,
238
+			'complete' => $this->isComplete(),
239
+			'objs' => []
240
+		];
241
+		foreach ($this->nodes as $id => $model_obj_node) {
242
+			$tree['objs'][ $id ] = $model_obj_node->toArray();
243
+		}
244
+		return $tree;
245
+	}
246 246
 
247
-    /**
248
-     * Gets the IDs of all the model objects to delete; indexed first by model object name.
249
-     * @since $VID:$
250
-     * @return array
251
-     */
252
-    public function getIds()
253
-    {
254
-        if (empty($this->nodes)) {
255
-            return [];
256
-        }
257
-        $ids = [
258
-            $this->related_model->get_this_model_name() => array_combine(
259
-                array_keys($this->nodes),
260
-                array_keys($this->nodes)
261
-            )
262
-        ];
263
-        foreach ($this->nodes as $model_obj_node) {
264
-            $ids = array_replace_recursive($ids, $model_obj_node->getIds());
265
-        }
266
-        return $ids;
267
-    }
247
+	/**
248
+	 * Gets the IDs of all the model objects to delete; indexed first by model object name.
249
+	 * @since $VID:$
250
+	 * @return array
251
+	 */
252
+	public function getIds()
253
+	{
254
+		if (empty($this->nodes)) {
255
+			return [];
256
+		}
257
+		$ids = [
258
+			$this->related_model->get_this_model_name() => array_combine(
259
+				array_keys($this->nodes),
260
+				array_keys($this->nodes)
261
+			)
262
+		];
263
+		foreach ($this->nodes as $model_obj_node) {
264
+			$ids = array_replace_recursive($ids, $model_obj_node->getIds());
265
+		}
266
+		return $ids;
267
+	}
268 268
 
269
-    /**
270
-     * Returns the number of sub-nodes found (ie, related model objects across this relation.)
271
-     * @since $VID:$
272
-     * @return int
273
-     */
274
-    public function countSubNodes()
275
-    {
276
-        return count($this->nodes);
277
-    }
269
+	/**
270
+	 * Returns the number of sub-nodes found (ie, related model objects across this relation.)
271
+	 * @since $VID:$
272
+	 * @return int
273
+	 */
274
+	public function countSubNodes()
275
+	{
276
+		return count($this->nodes);
277
+	}
278 278
 
279
-    /**
280
-     * Don't serialize the models. Just record their names on some dynamic properties.
281
-     * @since $VID:$
282
-     */
283
-    public function __sleep()
284
-    {
285
-        $this->m = $this->main_model->get_this_model_name();
286
-        $this->rm = $this->related_model->get_this_model_name();
287
-        return array_merge(
288
-            [
289
-                'm',
290
-                'rm',
291
-                'id',
292
-                'count',
293
-                'nodes',
294
-            ],
295
-            parent::__sleep()
296
-        );
297
-    }
279
+	/**
280
+	 * Don't serialize the models. Just record their names on some dynamic properties.
281
+	 * @since $VID:$
282
+	 */
283
+	public function __sleep()
284
+	{
285
+		$this->m = $this->main_model->get_this_model_name();
286
+		$this->rm = $this->related_model->get_this_model_name();
287
+		return array_merge(
288
+			[
289
+				'm',
290
+				'rm',
291
+				'id',
292
+				'count',
293
+				'nodes',
294
+			],
295
+			parent::__sleep()
296
+		);
297
+	}
298 298
 
299
-    /**
300
-     * Use the dynamic properties to instantiate the models we use.
301
-     * @since $VID:$
302
-     * @throws EE_Error
303
-     * @throws InvalidArgumentException
304
-     * @throws InvalidDataTypeException
305
-     * @throws InvalidInterfaceException
306
-     * @throws ReflectionException
307
-     */
308
-    public function __wakeup()
309
-    {
310
-        $this->main_model = EE_Registry::instance()->load_model($this->m);
311
-        $this->related_model = EE_Registry::instance()->load_model($this->rm);
312
-        parent::__wakeup();
313
-    }
299
+	/**
300
+	 * Use the dynamic properties to instantiate the models we use.
301
+	 * @since $VID:$
302
+	 * @throws EE_Error
303
+	 * @throws InvalidArgumentException
304
+	 * @throws InvalidDataTypeException
305
+	 * @throws InvalidInterfaceException
306
+	 * @throws ReflectionException
307
+	 */
308
+	public function __wakeup()
309
+	{
310
+		$this->main_model = EE_Registry::instance()->load_model($this->m);
311
+		$this->related_model = EE_Registry::instance()->load_model($this->rm);
312
+		parent::__wakeup();
313
+	}
314 314
 }
315 315
 // End of file RelationNode.php
316 316
 // Location: EventEspresso\core\services\orm\tree_traversal/RelationNode.php
Please login to merge, or discard this patch.