PluginProbe ʕ •ᴥ•ʔ
Atarim – AI Agency for WordPress: Edit Pages, Fix Code, Update Plugins, SEO & Client Feedback / 5.1.3
Atarim – AI Agency for WordPress: Edit Pages, Fix Code, Update Plugins, SEO & Client Feedback v5.1.3
5.1.3 5.1.2 5.1.1 5.1 5.0 trunk 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 3.2.0 3.2.1 3.22 3.22.1 3.22.2 3.22.3 3.22.4 3.22.5 3.22.6 3.3.0 3.3.1 3.3.2 3.3.2.1 3.3.2.2 3.3.3 3.30 3.31 3.32 3.4 3.4.1 3.4.3 3.4.4 3.5 3.5.1 3.6 3.6.1 3.7 3.8 3.9 3.9.1 3.9.2 3.9.3 3.9.4 3.9.6 3.9.6.1 4.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.2 4.1.3 4.2 4.2.1 4.2.2 4.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.4
atarim-visual-collaboration / includes / inject-script.php
atarim-visual-collaboration / includes Last commit date
class-ajax-functions.php 3 days ago class-define-constant.php 3 days ago class-functions.php 3 days ago do-it.php 3 days ago inject-script.php 3 days ago
inject-script.php
330 lines
1 <?php
2 if (! defined('ABSPATH')) {
3 exit; // Exit if accessed directly
4 }
5
6 class AVCF_Inject_Script {
7 private $function;
8 private $license;
9 private $is_collab_active;
10 private $inisetup;
11
12 public function __construct() {
13 $this->function = new AVCF_Functions();
14 $this->license = $this->function->avcf_get_setting_data('avc_license');
15 $this->is_collab_active = $this->function->avcf_get_setting_data('avc_collab_active');
16 $this->inisetup = $this->function->avcf_get_setting_data('avc_initial_setup_complete');
17
18 // Initialize hooks
19 $this->init_hooks();
20 }
21
22 private function init_hooks() {
23 // Load collaboration script
24 add_action('wp_head', [$this, 'load_collaboration_script'], 11);
25 add_action('admin_head', [$this, 'load_collaboration_script'], 11);
26
27
28 // Load global styles and scripts
29 add_action('wp_enqueue_scripts', [$this, 'enqueue_global_assets']);
30 add_action('admin_enqueue_scripts', [$this, 'enqueue_global_assets']);
31
32 // Load footer scripts
33 add_action('wp_footer', [$this, 'load_footer_script']);
34 add_action('admin_footer', [$this, 'load_footer_script']);
35
36 // Auto login
37 add_action('init', array($this, 'avcf_autologin'));
38 //add_action('init', array($this, 'avcf_accept_invitation'));
39 }
40
41 public function load_collaboration_script() {
42 $decision = $this->collab_script_decision();
43
44 if (! $decision['load']) {
45 return;
46 }
47
48 echo $this->function->get_collab_js($decision['site_id'], $this->function->avcf_setting_screen());
49 }
50
51 /**
52 * Whether the collaboration script will be emitted for this request, and under
53 * which site id.
54 *
55 * Split out of load_collaboration_script so other features can ask the question
56 * BEFORE wp_head runs. The block-identity markers exist purely for this script
57 * to read, so when it is not loading there is no consumer and the work of
58 * stamping attributes onto every rendered block is pure waste.
59 *
60 * Memoised: the answer cannot change within a request, and avcf_is_site_public
61 * may hit a transient (or, on a miss, the API).
62 *
63 * @return array{load:bool, site_id:string}
64 */
65 public function collab_script_decision() {
66 static $decision = null;
67
68 if ($decision !== null) {
69 return $decision;
70 }
71
72 $decision = ['load' => false, 'site_id' => ''];
73
74 if (isset($_GET['site_id']) && ! empty($_GET['site_id'])) {
75 return $decision;
76 }
77
78 $site_id = $this->function->avcf_get_setting_data('avc_site_id');
79 if (isset($_GET['activation_callback']) && ! empty($_GET['activation_callback'])) {
80 $site_id = '';
81 }
82
83 $user_id = $this->function->avcf_get_user_detail('id');
84 if (is_wp_error($user_id)) {
85 $user_id = 0;
86 }
87
88 $is_webmaster = $user_id ? (get_user_meta($user_id, 'avc_user_type', true) === 'webmaster') : false;
89 $has_consented = $user_id ? (bool) get_user_meta($user_id, 'avc_consent_status', true) : false;
90
91 $allow_collab = false;
92 if (! is_user_logged_in()) {
93 $allow_collab = $this->function->avcf_is_site_public($site_id);
94 }
95
96 if (isset($_GET['collab'])) {
97 $allow_collab = filter_var($_GET['collab'], FILTER_VALIDATE_BOOLEAN);
98 }
99
100 if (
101 ! $allow_collab && (
102 $this->license !== 'valid' ||
103 $this->is_collab_active !== 'yes' ||
104 $this->inisetup !== 'yes' ||
105 ! is_user_logged_in() ||
106 ! $this->function->avcf_allowed_user_role() ||
107 (! $is_webmaster && ! $has_consented) ||
108 $site_id == ''
109 )
110 ) {
111 return $decision;
112 }
113
114 $decision = ['load' => true, 'site_id' => $site_id];
115
116 return $decision;
117 }
118
119 public function enqueue_global_assets() {
120 wp_register_style(
121 'avc-global-style',
122 AVCF_PLUGIN_URL . 'assets/css/global.css',
123 [],
124 filemtime(AVCF_PLUGIN_DIR . 'assets/css/global.css')
125 );
126 wp_enqueue_style('avc-global-style');
127
128 wp_enqueue_script('jquery');
129
130 wp_register_script(
131 'avc-global-script',
132 AVCF_PLUGIN_URL . 'assets/js/global.js',
133 ['jquery'],
134 AVCF_VERSION,
135 true
136 );
137 wp_enqueue_script('avc-global-script');
138
139 wp_localize_script('avc-global-script', 'avcajax', [
140 'ajaxurl' => admin_url('admin-ajax.php')
141 ]);
142
143 $avc_nonce = wp_create_nonce('avc-script-nonce');
144 wp_localize_script('avc-global-script', 'avc_site_data', [
145 'site_url' => AVCF_HOME_URL,
146 'avc_nonce' => $avc_nonce
147 ]);
148 }
149
150 public function load_footer_script() {
151 $user_id = $this->function->avcf_get_user_detail('id');
152 if ( is_wp_error( $user_id ) ) {
153 $user_id = 0;
154 }
155
156 $is_webmaster = $user_id ? ( get_user_meta( $user_id, 'avc_user_type', true ) === 'webmaster' ) : false;
157 $has_consented = $user_id ? (bool) get_user_meta( $user_id, 'avc_consent_status', true ) : false;
158 $site_id = $this->function->avcf_get_setting_data('avc_site_id');
159
160 if (
161 $this->function->avcf_setting_screen() ||
162 $this->license !== 'valid' ||
163 $this->is_collab_active !== 'yes' ||
164 $this->inisetup !== 'yes' ||
165 ! is_user_logged_in() ||
166 ! $this->function->avcf_allowed_user_role() ||
167 $is_webmaster ||
168 $has_consented ||
169 $site_id == ''
170 ) {
171 return;
172 }
173
174 echo $this->function->avcf_user_consent_modal_trigger();
175 echo $this->function->avcf_user_consent_form();
176 }
177
178 public function avcf_autologin() {
179 if (! isset($_GET['wpf_token'])) {
180 return;
181 }
182
183 if (isset($_GET['wpf_token']) && is_user_logged_in()) {
184 return;
185 }
186
187 $webmaster = $this->function->avcf_get_setting_data('avc_website_developer');
188 if ($webmaster == '') {
189 return;
190 }
191
192 $payload = [
193 'site_id' => $this->function->avcf_get_setting_data('avc_site_id'),
194 ];
195
196 $wpf_token = sanitize_text_field(wp_unslash($_GET['wpf_token']));
197
198 $response = $this->function->avcf_make_api_call(
199 AVCF_CRM_API . 'wp-api/user/verify-access',
200 wp_json_encode($payload),
201 '',
202 $wpf_token
203 );
204
205 if (
206 $response['status_code'] === 200 &&
207 isset($response['data']['status']) &&
208 $response['data']['status'] == 1
209 ) {
210 $user = get_user_by('email', $webmaster);
211 if (! is_wp_error($user)) {
212 wp_clear_auth_cookie();
213 wp_set_current_user($user->ID);
214 wp_set_auth_cookie($user->ID);
215 $this->avcf_make_auth_cookies_embeddable();
216 }
217 }
218
219 $removeparam = array('wpf_token', 'wpf_username', 'wpf_login');
220 // Remove the params from the current request URL.
221 $newurl = remove_query_arg($removeparam);
222 // Redirect safely (same-host only).
223 wp_safe_redirect(esc_url_raw($newurl), 302);
224 exit;
225 }
226
227 /**
228 * Re-send the auth cookies WordPress just emitted with attributes that
229 * survive inside a cross-site iframe: the Atarim stage embeds the site
230 * on the app's origin, and WordPress emits its cookies without SameSite,
231 * which browsers treat as Lax and drop on embedded requests. Partitioned
232 * keeps them accepted once third-party cookies are fully phased out.
233 */
234 private function avcf_make_auth_cookies_embeddable() {
235 if (headers_sent()) {
236 return;
237 }
238
239 $cookies = array();
240 foreach (headers_list() as $header) {
241 if (stripos($header, 'Set-Cookie:') !== 0) {
242 continue;
243 }
244 $cookies[] = trim(substr($header, strlen('Set-Cookie:')));
245 }
246 if (empty($cookies)) {
247 return;
248 }
249
250 header_remove('Set-Cookie');
251 foreach ($cookies as $cookie) {
252 if (preg_match('/^wordpress_/i', $cookie)) {
253 $cookie = preg_replace('/;\s*samesite=[^;]*/i', '', $cookie);
254 if (! preg_match('/;\s*secure(;|$)/i', $cookie)) {
255 $cookie .= '; Secure';
256 }
257 $cookie .= '; SameSite=None; Partitioned';
258 }
259 header('Set-Cookie: ' . $cookie, false);
260 }
261 }
262
263 public function avcf_accept_invitation() {
264 if (
265 is_user_logged_in() ||
266 ! isset($_GET['token']) ||
267 empty($_GET['token'])
268 ) {
269 return;
270 }
271
272 $data = [
273 'token' => sanitize_text_field(wp_unslash($_GET['token']))
274 ];
275
276 $response = $this->function->avcf_make_api_call(
277 AVCF_CRM_API . 'collaborate/site/accept-invitation',
278 $data,
279 '',
280 '',
281 'GET'
282 );
283
284 if ($response['status_code'] === 200) {
285 if (
286 isset($response['data']['status']) &&
287 $response['data']['status'] == 1 &&
288 isset($response['data']['result']['access_token'])
289 ) {
290 $token = $response['data']['result']['access_token'];
291 setcookie('avc_token', $token, time() + (86400 * 30), '/');
292 } else if (
293 isset($response['data']['status']) &&
294 $response['data']['status'] == '' &&
295 isset($response['data']['data']['error'])
296 ) {
297 echo $response['data']['data']['message'];
298 die;
299 }
300 }
301
302 $removeparam = array('token', 'role');
303 // Remove the params from the current request URL.
304 $newurl = remove_query_arg($removeparam);
305 // Redirect safely (same-host only).
306 wp_safe_redirect(esc_url_raw($newurl), 302);
307 exit;
308 }
309 }
310
311 $GLOBALS['avcf_inject_script'] = new AVCF_Inject_Script();
312
313 /**
314 * Will the Atarim collaboration script be emitted for this request?
315 *
316 * The Do It block-identity markers are only ever read by that script, so this is
317 * the correct consumer test for whether emitting them is worth anything.
318 */
319 function atarim_collab_script_will_load() {
320 $injector = $GLOBALS['avcf_inject_script'] ?? null;
321
322 if (! $injector instanceof AVCF_Inject_Script) {
323 return false;
324 }
325
326 $decision = $injector->collab_script_decision();
327
328 return ! empty($decision['load']);
329 }
330