PluginProbe
Media Cloud Sync / trunk
Media Cloud Sync vtrunk
1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 All 34 releases
media-cloud-sync / includes / bulk / sync.php

sync.php in Media Cloud Sync trunk, at includes/bulk/sync.php

236 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Dudlewebs\WPMCS;
3 defined('ABSPATH') || exit;
4
5 class Sync {
6 protected static $instance = null;
7
8 private $syncClasses = [
9 'SyncToCloud'
10 ];
11
12 /**
13 * Constructor method.
14 */
15 public function __construct() {
16 // Initialize sync classes
17 foreach ($this->syncClasses as $class) {
18 $class_with_namespace = __NAMESPACE__.'\\'. trim($class);
19 if(class_exists($class_with_namespace)) {
20 $class_with_namespace::instance();
21 }
22 }
23 }
24
25
26 /**
27 * Add new sync classes to the list of sync classes.
28 *
29 * @param array $classes List of new sync classes to add.
30 *
31 * @return void
32 */
33 public function add_sync_classes($classes = []) {
34 // Only add classes that are not already in syncClasses
35 $new_classes = array_diff($classes, $this->syncClasses);
36
37 // Merge new classes
38 $this->syncClasses = array_merge($this->syncClasses, $new_classes);
39
40 // Initialize new classes
41 foreach ($new_classes as $class) {
42 $class_with_namespace = __NAMESPACE__ . '\\' . trim($class);
43 if (class_exists($class_with_namespace)) {
44 $class_with_namespace::instance();
45 }
46 }
47 }
48
49
50 /**
51 * Gets the status of the sync.
52 *
53 * @return array An associative array with the action as key and the status
54 * as value.
55 */
56 public function get_status() {
57 $status = [];
58 foreach ($this->syncClasses as $class) {
59 $class_with_namespace = __NAMESPACE__.'\\'. trim($class);
60 if(!class_exists($class_with_namespace)) continue;
61 $instance = $class_with_namespace::instance();
62 $action = $instance->get_action();
63 $status[$action] = $instance->get_status();
64 }
65 return $status;
66 }
67
68
69 /**
70 * Starts the sync process.
71 *
72 */
73 public function start( $action ) {
74 $action_class = $this->get_class_by_action($action);
75
76 if($action_class) {
77 // BGRunner's lock is per-type — nothing else stops two different actions from running at once.
78 $blocking_action = $this->find_running_action($action);
79 if ($blocking_action) {
80 return [
81 'success' => false,
82 /* translators: %s: the action that is currently running */
83 'message' => sprintf(__('Another sync (%s) is currently running. Stop or finish it before starting a new one.', 'media-cloud-sync'), $blocking_action),
84 ];
85 }
86
87 $start_result = $action_class->start();
88 // A job's start() can signal a precondition failure (e.g. no destination
89 // configured) by returning ['success' => false, ...] instead of the usual
90 // void/true — short-circuit and pass that straight through instead of masking
91 // it with a status object that always reads as started.
92 if (is_array($start_result) && isset($start_result['success']) && $start_result['success'] === false) {
93 return $start_result;
94 }
95 return $action_class->get_status();
96 } else {
97 /* translators: %s: action name */
98 throw new \Exception(sprintf(__('Invalid action: %s', 'media-cloud-sync'), $action));
99 }
100 }
101
102 // Action string of another registered action currently running/paused, or null.
103 private function find_running_action( $except_action ) {
104 $runner = BGRunner::instance();
105 foreach ($this->syncClasses as $class) {
106 $class_with_namespace = __NAMESPACE__.'\\'. trim($class);
107 if(!class_exists($class_with_namespace)) continue;
108
109 $instance = $class_with_namespace::instance();
110 $other_action = $instance->get_action();
111 if ($other_action === $except_action) continue;
112
113 $status = $runner->status($other_action);
114 if (in_array($status['status'] ?? 'stopped', ['running', 'paused'], true)) {
115 return $other_action;
116 }
117 }
118 return null;
119 }
120
121 /**
122 * Pauses the sync process.
123 *
124 */
125 public function pause( $action ) {
126 $action_class = $this->get_class_by_action($action);
127
128 if($action_class) {
129 $action_class->pause();
130 return $action_class->get_status();
131 } else {
132 throw new \Exception(sprintf(__('Invalid action: %s', 'media-cloud-sync'), $action));
133 }
134 }
135
136
137 /**
138 * Resumes the sync process.
139 *
140 */
141 public function resume( $action ) {
142 $action_class = $this->get_class_by_action($action);
143
144 if($action_class) {
145 $action_class->resume();
146 return $action_class->get_status();
147 } else {
148 throw new \Exception(sprintf(__('Invalid action: %s', 'media-cloud-sync'), $action));
149 }
150 }
151
152
153 /**
154 * Stops the sync process.
155 *
156 */
157 public function stop( $action ) {
158 $action_class = $this->get_class_by_action($action);
159
160 if($action_class) {
161 $action_class->stop();
162 return $action_class->get_status();
163 } else {
164 throw new \Exception(sprintf(__('Invalid action: %s', 'media-cloud-sync'), $action));
165 }
166 }
167
168
169 /**
170 * Sets the sync method ('ajax'|'cron'|'mixed') preference for the given action's type.
171 */
172 public function set_sync_method( $action, $method ) {
173 $action_class = $this->get_class_by_action($action);
174
175 if($action_class) {
176 return $action_class->set_sync_method($method);
177 } else {
178 throw new \Exception(sprintf(__('Invalid action: %s', 'media-cloud-sync'), $action));
179 }
180 }
181
182
183 /**
184 * Ticks the sync process — processes a small batch synchronously (ajax/mixed sync mode).
185 * Gracefully no-ops (returns current status unchanged) for an action whose class hasn't
186 * been updated with a tick() method yet — it's still safely progressing via cron, this
187 * just means ajax ticking isn't wired up for it yet, not a failure.
188 * @since 1.3.13
189 */
190 public function tick( $action, $batch = 5 ) {
191 $action_class = $this->get_class_by_action($action);
192
193 if(!$action_class) {
194 throw new \Exception(sprintf(__('Invalid action: %s', 'media-cloud-sync'), $action));
195 }
196
197 if(method_exists($action_class, 'tick')) {
198 return $action_class->tick($batch);
199 }
200
201 return $action_class->get_status();
202 }
203
204
205 /**
206 * Returns the class associated with the given action.
207 *
208 * @param string $action The action to search for.
209 *
210 * @return string|null The class associated with the action, or null if not found.
211 */
212 public function get_class_by_action( $action ) {
213 foreach ($this->syncClasses as $class) {
214 $class_with_namespace = __NAMESPACE__.'\\'. trim($class);
215 if(!class_exists($class_with_namespace)) continue;
216
217 if($class_with_namespace::instance()->get_action() === $action) {
218 return $class_with_namespace::instance();
219 }
220 }
221
222 return false;
223 }
224
225
226 /**
227 * Retrieves the singleton instance of the class.
228 *
229 * @return self
230 */
231 public static function instance() {
232 if (!self::$instance) self::$instance = new self();
233 return self::$instance;
234 }
235 }
236