PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / 1.10.29
ووسلام – همگام سازی ووکامرس و باسلام v1.10.29
1.10.29 1.10.28 1.1.26 1.10.27 1.10.24 1.10.25 1.10.23 1.10.22 1.10.21 1.10.19 1.10.20 1.10.18 1.10.17 1.10.15 1.10.14 1.10.13 1.10.12 1.10.10 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 All 62 releases
sync-basalam / tests / integration / webservers / fixture.php

fixture.php in ووسلام – همگام سازی ووکامرس و باسلام 1.10.29, at tests/integration/webservers/fixture.php

135 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /** Local-only HTTP fixture; mounted exclusively by the webserver test stack. */
3 defined('ABSPATH') || exit;
4 if (wp_get_environment_type() !== 'local' || !getenv('MATRIX_TOKEN')) return;
5
6 // Keep loopbacks real; refuse remote APIs, email and update checks.
7 add_filter('pre_http_request', static function ($preempt, $args, $url) {
8 if (wp_parse_url($url, PHP_URL_HOST) === wp_parse_url(home_url(), PHP_URL_HOST)) return $preempt;
9 return new WP_Error('matrix_external_http_blocked', 'Only local matrix loopbacks are allowed.');
10 }, PHP_INT_MAX, 3);
11 add_filter('pre_wp_mail', '__return_false');
12 add_filter('sync_basalam_jobs_runner_async_time_limit', static function () { return 1.0; });
13
14 add_action('plugins_loaded', static function () {
15 if (!function_exists('syncBasalamContainer')) return;
16
17 $fixture = new class implements \SyncBasalam\Jobs\JobType {
18 public function getType(): string { return 'sync_basalam_matrix'; }
19 public function getPriority(): int { return -100; }
20 public function canRun(): bool { return true; }
21 public function execute(array $payload) {
22 $key = $payload['key'];
23 $events = get_option('sync_basalam_matrix_events', []);
24 $event = $events[$key] ?? ['starts' => 0, 'returns' => 0];
25 $event['starts']++;
26 $event['pid'] = getmypid();
27 $event['sapi'] = PHP_SAPI;
28 $event['noabort'] = $_SERVER['noabort'] ?? $_SERVER['REDIRECT_noabort'] ?? getenv('noabort') ?: null;
29 $event['started_at'] = microtime(true);
30 $job = syncBasalamContainer()->get(\SyncBasalam\JobManager::class)->getJob(['job_type' => 'sync_basalam_matrix', 'status' => 'processing']);
31 $event['history'][] = ['pid' => getmypid(), 'time' => $event['started_at'], 'job_id' => (int) $job->id, 'attempts' => (int) $job->attempts];
32 $events[$key] = $event;
33 update_option('sync_basalam_matrix_events', $events, false);
34 usleep((int) ($payload['seconds'] * 1000000));
35 if ($payload['mode'] === 'fatal') trigger_error('Intentional matrix worker fatal', E_USER_ERROR);
36 $events = get_option('sync_basalam_matrix_events', []);
37 $events[$key]['returns']++;
38 $events[$key]['returned_at'] = microtime(true);
39 update_option('sync_basalam_matrix_events', $events, false);
40 if ($payload['mode'] === 'reject') {
41 return \SyncBasalam\Jobs\JobResult::failed(new \SyncBasalam\Jobs\Exceptions\NonRetryableException('matrix API rejection (422)', 422));
42 }
43 return \SyncBasalam\Jobs\JobResult::success();
44 }
45 };
46 syncBasalamContainer()->get(\SyncBasalam\Jobs\JobRegistry::class)->register($fixture);
47
48 // Control requests inspect/prepare evidence without accidentally restarting a worker.
49 if (($_REQUEST['action'] ?? '') === 'sync_basalam_matrix_control' || defined('WP_INSTALLING')) {
50 $runner = syncBasalamContainer()->get(\SyncBasalam\JobsRunner::class);
51 remove_action('shutdown', [$runner, 'maybeDispatchAsyncRequest'], 2);
52 remove_action('sync_basalam_job_created', [$runner, 'maybeDispatchAsyncRequest'], 10);
53 }
54 });
55
56 $control = static function () {
57 if (!hash_equals(getenv('MATRIX_TOKEN'), $_SERVER['HTTP_X_MATRIX_TOKEN'] ?? '')) {
58 wp_send_json_error(['message' => 'Invalid matrix token'], 403);
59 }
60 global $wpdb;
61 $queue = syncBasalamContainer()->get(\SyncBasalam\JobManager::class);
62 $runner = syncBasalamContainer()->get(\SyncBasalam\JobsRunner::class);
63 $lock = syncBasalamContainer()->get(\SyncBasalam\Jobs\LockManager::class);
64 $table = $wpdb->prefix . 'sync_basalam_job_manager';
65 $op = $_POST['op'] ?? 'state';
66 if ($op === 'reset') {
67 if (!$lock->acquireGlobalJobsLock()) wp_send_json_error(['message' => 'Worker still active'], 409);
68 $wpdb->delete($table, ['job_type' => 'sync_basalam_matrix']);
69 foreach (['sync_basalam_async_worker_health', 'sync_basalam_matrix_events', 'sync_basalam_jobs_runner_last_run', 'sync_basalam_circuit_breaker'] as $name) delete_option($name);
70 foreach (['sync_basalam_jobs_runner_async_dispatch_lock', 'sync_basalam_jobs_runner_idle_probe_lock'] as $name) delete_transient($name);
71 $lock->releaseGlobalJobsLock();
72 } elseif ($op === 'enqueue') {
73 $key = sanitize_key($_POST['key'] ?? 'job');
74 $mode = $_POST['mode'] ?? 'success';
75 if (!in_array($mode, ['success', 'reject', 'fatal'], true)) wp_send_json_error([], 400);
76 $seconds = max(0.0, min(60.0, (float) ($_POST['seconds'] ?? 0)));
77 $queue->createJob('sync_basalam_matrix', 'pending', wp_json_encode(compact('key', 'mode', 'seconds')));
78 $id = (int) $wpdb->insert_id;
79 update_option('sync_basalam_jobs_runner_last_run', 0, false);
80 if (!empty($_POST['dispatch'])) $runner->maybeDispatchAsyncRequest();
81 wp_send_json_success(['id' => $id]);
82 } elseif (in_array($op, ['age', 'retry'], true)) {
83 $id = (int) ($_POST['id'] ?? 0);
84 $job = $queue->getJob(['id' => $id, 'job_type' => 'sync_basalam_matrix']);
85 if (!$job) wp_send_json_error([], 404);
86 $values = ['started_at' => time() - 121];
87 if ($op === 'retry') {
88 $payload = json_decode($job->payload, true);
89 $payload['mode'] = 'success';
90 $payload['seconds'] = 0;
91 $values['payload'] = wp_json_encode($payload);
92 $values['retry_after'] = 0;
93 update_option('sync_basalam_jobs_runner_last_run', 0, false);
94 }
95 $queue->updateJob($values, ['id' => $id]);
96 } elseif ($op === 'lease') {
97 $name = 'sync_basalam_jobs_runner_async_dispatch_lock';
98 delete_transient($name);
99 add_option('_transient_' . $name, 1, '', false);
100 delete_option('_transient_timeout_' . $name);
101 } elseif ($op === 'dispatch') {
102 $runner->maybeDispatchAsyncRequest();
103 } elseif ($op === 'notice') {
104 $_GET['page'] = 'sync_basalam';
105 if (($_POST['role'] ?? 'administrator') === 'anonymous') wp_set_current_user(0);
106 else {
107 $users = get_users(['role' => sanitize_key($_POST['role'] ?? 'administrator'), 'number' => 1]);
108 if (!$users) wp_send_json_error([], 404);
109 wp_set_current_user($users[0]->ID);
110 }
111 ob_start();
112 $runner->renderWorkerHealthNotice();
113 wp_send_json_success(['html' => ob_get_clean()]);
114 } elseif ($op !== 'state') {
115 wp_send_json_error([], 400);
116 }
117 $free = $lock->acquireGlobalJobsLock();
118 if ($free) $lock->releaseGlobalJobsLock();
119 $health = new \SyncBasalam\Services\AsyncWorkerHealth();
120 wp_send_json_success([
121 'nonce' => wp_create_nonce('sync_basalam_run_jobs_async'),
122 'sapi' => PHP_SAPI,
123 'php' => PHP_VERSION,
124 'server' => $_SERVER['SERVER_SOFTWARE'] ?? '',
125 'jobs' => $wpdb->get_results($wpdb->prepare("SELECT * FROM {$table} WHERE job_type = %s ORDER BY id", 'sync_basalam_matrix')),
126 'events' => (object) get_option('sync_basalam_matrix_events', []),
127 'health' => get_option(\SyncBasalam\Services\AsyncWorkerHealth::OPTION_KEY, []),
128 'notice' => $health->getNotice(),
129 'lock_free' => $free,
130 'autoload' => $wpdb->get_var($wpdb->prepare("SELECT autoload FROM {$wpdb->options} WHERE option_name = %s", \SyncBasalam\Services\AsyncWorkerHealth::OPTION_KEY)),
131 ]);
132 };
133 add_action('wp_ajax_sync_basalam_matrix_control', $control);
134 add_action('wp_ajax_nopriv_sync_basalam_matrix_control', $control);
135