PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.7.0
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.7.0
3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.10 All 111 releases
templately / includes / Core / Importer / Runners / Loop.php

Loop.php in Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! 3.7.0, at includes/Core/Importer/Runners/Loop.php

299 lines 9.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Templately\Core\Importer\Runners;
4
5 use Exception;
6 use Templately\Core\Importer\Exception\SkippableErrorException;
7 use Templately\Core\Importer\FullSiteImport;
8 use Templately\Core\Importer\LogHelper;
9 use Templately\Core\Importer\Utils\SessionData;
10 use Templately\Core\Importer\Utils\Utils;
11 use Templately\Utils\Helper;
12
13 /**
14 * @method string get_name()
15 * @method void sse_message(array $data)
16 */
17 trait Loop {
18
19 public static $max_error_attempts = 2;
20 public static $max_consecutive_skips = 5;
21
22 /**
23 * Undocumented function
24 *
25 * @param [type] $items
26 * @param [type] $callback($key, $item, $results)
27 * @param [type] $unique_id
28 * @param boolean $split_to_chunks
29 * @return array
30 */
31 public function loop($items, $callback, $unique_id = null, $split_to_chunks = false) {
32 // throw error if the callback is not callable
33 if (!is_callable($callback)) {
34 throw new \Exception('The callback is not callable');
35 }
36 if (!is_array($items)) {
37 throw new \Exception('The items should be an array');
38 }
39
40 $results = $this->_get_loop_result([], $unique_id);
41
42 if(!empty($this->backup_attributes)){
43 $this->_retrieve_attributes($this->backup_attributes, $unique_id);
44 }
45
46 foreach ($items as $key => $item) {
47 // If the template has been processed, skip it
48 if ($this->_is_key_processed($key, $unique_id)) {
49 continue;
50 }
51
52 // Skip-on-error: Check if feature is enabled and item should be skipped
53 if ($this->_is_skip_feature_enabled()) {
54 $calling_class = SessionData::get_calling_identifier($unique_id, true, false);
55 $error_attempts = SessionData::get_error_attempts($this->session_id, $calling_class, $key);
56
57 // Skip if error attempts >= MAX_ERROR_ATTEMPTS
58 if ($error_attempts >= self::$max_error_attempts) {
59 $this->_mark_key_skipped($key, $unique_id, 'Max error attempts reached');
60 $this->_increment_consecutive_skips();
61 continue;
62 }
63 }
64
65 // Wrap callback in try-catch for skip-on-error handling
66 try {
67 $result = $callback($key, $item, $results);
68 if($result === 'continue'){
69 // If the callback returns 'continue', skip to the next iteration
70 continue;
71 }
72 $results = $result;
73
74 // Success - reset consecutive skip counter
75 if ($this->_is_skip_feature_enabled()) {
76 $this->_reset_consecutive_skips();
77 }
78 } catch (SkippableErrorException $e) {
79 // Catchable skip error - increment attempts and mark as skipped
80 if ($this->_is_skip_feature_enabled()) {
81 $this->_increment_error_attempts($key, $unique_id);
82 $this->_mark_key_skipped($key, $unique_id, $e->getMessage());
83 continue;
84 } else {
85 // Feature disabled - throw as normal exception
86 throw new Exception($e->getMessage(), $e->getCode(), $e);
87 }
88 } catch (Exception $e) {
89 // Other exceptions - increment error attempts then re-throw
90 if ($this->_is_skip_feature_enabled()) {
91 $this->_increment_error_attempts($key, $unique_id);
92 }
93 throw $e;
94 }
95
96 // Mark as processed and save result
97 $this->_mark_key_processed($key, $unique_id);
98 $this->_set_loop_result($results, $unique_id);
99
100 // If it's not the last item, send the SSE message and exit
101
102 $is_last_runner = key( array_slice( $items, -1, 1, true ) ) === $key;
103
104 if( (Helper::fsi_should_exit() || $split_to_chunks) && !$is_last_runner && method_exists($this, 'sse_message') ) {
105 if(!empty($this->backup_attributes)){
106 $this->_backup_attributes($this->backup_attributes, $unique_id);
107 }
108 $this->sse_message( [
109 'type' => 'continue',
110 'action' => 'continue',
111 'name' => method_exists($this, 'get_name') ? $this->get_name() : '',
112 'index' => $key,
113 'results' => SessionData::get_calling_identifier($unique_id, true, false, 3),
114 ] );
115 exit;
116 }
117 }
118 return $results;
119 }
120
121 /**
122 * Check if a key has been processed (internal)
123 *
124 * @param mixed $key The item key
125 * @param string|null $unique_id Optional unique identifier
126 * @return bool True if processed
127 */
128 private function _is_key_processed($key, $unique_id = null): bool {
129 $calling_class = SessionData::get_calling_identifier($unique_id, true, false);
130 return SessionData::is_key_processed($this->session_id, $calling_class, $key);
131 }
132
133 /**
134 * Check if a key has been processed (public wrapper)
135 */
136 public function is_key_processed($key, $unique_id = null): bool {
137 return $this->_is_key_processed($key, $unique_id);
138 }
139
140 /**
141 * Mark a key as processed (internal)
142 *
143 * @param mixed $key The item key
144 * @param string|null $unique_id Optional unique identifier
145 * @return bool Success status
146 */
147 private function _mark_key_processed($key, $unique_id = null): bool {
148 $calling_class = SessionData::get_calling_identifier($unique_id, true, false);
149 return SessionData::mark_key_processed($this->session_id, $calling_class, $key);
150 }
151
152 /**
153 * Mark a key as processed (public wrapper)
154 */
155 public function mark_key_processed($key, $unique_id = null): bool {
156 return $this->_mark_key_processed($key, $unique_id);
157 }
158
159 /**
160 * Set loop result (internal)
161 *
162 * @param array $result The result data
163 * @param string|null $unique_id Optional unique identifier
164 * @return bool Success status
165 */
166 private function _set_loop_result($result, $unique_id = null): bool {
167 $calling_class = SessionData::get_calling_identifier($unique_id, true, false);
168 return SessionData::set_loop_result($this->session_id, $calling_class, $result);
169 }
170
171 /**
172 * Set loop result (public wrapper)
173 */
174 public function set_loop_result($result, $unique_id = null): bool {
175 return $this->_set_loop_result($result, $unique_id);
176 }
177
178 private function _get_loop_result($defaults = [], $unique_id = null, $function = true) {
179 $calling_class = SessionData::get_calling_identifier($unique_id, $function, false);
180 return SessionData::get_loop_result($this->session_id, $calling_class, $defaults);
181 }
182
183 public function get_loop_result($defaults = [], $unique_id = null, $function = true) {
184 return $this->_get_loop_result($defaults, $unique_id, $function);
185 }
186
187 // Modified get_session_data to use SessionData
188 protected function get_session_data(): array {
189 return SessionData::get_data($this->session_id);
190 }
191
192 // Modified update_session_data to use SessionData (deprecated - use specific methods)
193 protected function update_session_data($data): bool {
194 $existing = SessionData::get_data($this->session_id);
195 return SessionData::save($this->session_id, array_merge($existing, $data));
196 }
197
198 private function _retrieve_attributes($attributes, $unique_id){
199 $calling_class = SessionData::get_calling_identifier($unique_id, false, false, 4);
200 $attr_values = SessionData::get($this->session_id, "loop.backup_attributes.{$calling_class}", []);
201
202 foreach ($attributes as $attribute) {
203 if(isset($attr_values[$attribute])){
204 $this->$attribute = $attr_values[$attribute];
205 }
206 }
207 }
208
209 private function _backup_attributes($attributes, $unique_id){
210 $calling_class = SessionData::get_calling_identifier($unique_id, false, false, 4);
211 $attr_values = [];
212
213 foreach ($attributes as $attribute) {
214 if(isset($this->$attribute)){
215 $attr_values[$attribute] = $this->$attribute;
216 }
217 }
218
219 return SessionData::set($this->session_id, "loop.backup_attributes.{$calling_class}", $attr_values);
220 }
221
222 // ============================================================================
223 // Skip-on-Error Helper Methods
224 // ============================================================================
225
226 /**
227 * Check if skip-on-error feature is enabled
228 *
229 * @return bool True if enabled
230 */
231 protected function _is_skip_feature_enabled(): bool {
232 return (bool) get_option('templately_enable_fsi_skip_on_error', false);
233 }
234
235 /**
236 * Increment error attempts for a loop item
237 *
238 * @param mixed $key The item key
239 * @param string|null $unique_id Optional unique identifier
240 * @return int New error attempt count
241 */
242 private function _increment_error_attempts($key, $unique_id = null): int {
243 $calling_class = SessionData::get_calling_identifier($unique_id, true, false);
244 return SessionData::increment_error_attempts($this->session_id, $calling_class, $key);
245 }
246
247 /**
248 * Get error attempts for a loop item
249 *
250 * @param mixed $key The item key
251 * @param string|null $unique_id Optional unique identifier
252 * @return int Error attempt count
253 */
254 private function _get_error_attempts($key, $unique_id = null): int {
255 $calling_class = SessionData::get_calling_identifier($unique_id, true, false);
256 return SessionData::get_error_attempts($this->session_id, $calling_class, $key);
257 }
258
259 /**
260 * Mark a loop item as skipped
261 *
262 * @param mixed $key The item key
263 * @param string|null $unique_id Optional unique identifier
264 * @param string $reason The reason for skipping
265 * @return bool Success status
266 */
267 private function _mark_key_skipped($key, $unique_id = null, $reason = ''): bool {
268 $calling_class = SessionData::get_calling_identifier($unique_id, true, false);
269 return SessionData::mark_key_skipped($this->session_id, $calling_class, $key, $reason);
270 }
271
272 /**
273 * Increment consecutive skip counter
274 *
275 * @return int New consecutive skip count
276 */
277 private function _increment_consecutive_skips(): int {
278 return SessionData::increment_consecutive_skips($this->session_id);
279 }
280
281 /**
282 * Reset consecutive skip counter
283 *
284 * @return bool Success status
285 */
286 private function _reset_consecutive_skips(): bool {
287 return SessionData::reset_consecutive_skips($this->session_id);
288 }
289
290 /**
291 * Get consecutive skip count
292 *
293 * @return int Consecutive skip count
294 */
295 private function _get_consecutive_skips(): int {
296 return SessionData::get_consecutive_skips($this->session_id);
297 }
298
299 }