PluginProbe ʕ •ᴥ•ʔ
LiteSpeed Cache / 7.8.1
LiteSpeed Cache v7.8.1
trunk 1.0.15 1.9.1.1 2.9.9.2 3.6.4 4.6 5.7.0.1 6.5.4 7.0.0.1 7.0.1 7.1 7.2 7.3 7.3.0.1 7.4 7.5 7.5.0.1 7.6 7.6.1 7.6.2 7.7 7.8 7.8.0.1 7.8.1
litespeed-cache / src / cloud-misc.trait.php
litespeed-cache / src Last commit date
cdn 2 months ago data_structure 2 months ago activation.cls.php 2 months ago admin-display.cls.php 2 months ago admin-settings.cls.php 2 months ago admin.cls.php 2 months ago api.cls.php 2 months ago avatar.cls.php 2 months ago base.cls.php 2 months ago cdn.cls.php 2 months ago cloud-auth-callback.trait.php 2 months ago cloud-auth-ip.trait.php 2 months ago cloud-auth.trait.php 2 months ago cloud-misc.trait.php 2 months ago cloud-node.trait.php 2 months ago cloud-request.trait.php 2 months ago cloud.cls.php 2 months ago conf.cls.php 2 months ago control.cls.php 2 months ago core.cls.php 2 months ago crawler-map.cls.php 2 months ago crawler.cls.php 2 months ago css.cls.php 2 months ago data.cls.php 2 months ago data.upgrade.func.php 2 months ago db-optm.cls.php 2 months ago debug2.cls.php 2 months ago doc.cls.php 2 months ago error.cls.php 2 months ago esi.cls.php 2 months ago file.cls.php 2 months ago guest.cls.php 2 months ago gui.cls.php 2 months ago health.cls.php 2 months ago htaccess.cls.php 2 months ago img-optm-manage.trait.php 2 months ago img-optm-pull.trait.php 2 months ago img-optm-send.trait.php 2 months ago img-optm.cls.php 2 months ago import.cls.php 2 months ago import.preset.cls.php 2 months ago lang.cls.php 2 months ago localization.cls.php 2 months ago media.cls.php 2 months ago metabox.cls.php 2 months ago object-cache-wp.cls.php 2 months ago object-cache.cls.php 2 months ago object.lib.php 2 months ago optimize.cls.php 2 months ago optimizer.cls.php 2 months ago placeholder.cls.php 2 months ago purge.cls.php 2 months ago report.cls.php 2 months ago rest.cls.php 2 months ago root.cls.php 2 months ago router.cls.php 2 months ago str.cls.php 2 months ago tag.cls.php 2 months ago task.cls.php 2 months ago tool.cls.php 2 months ago ucss.cls.php 2 months ago utility.cls.php 2 months ago vary.cls.php 2 months ago vpi.cls.php 2 months ago
cloud-misc.trait.php
405 lines
1 <?php
2 /**
3 * Cloud misc trait
4 *
5 * @package LiteSpeed
6 * @since 7.8
7 */
8
9 namespace LiteSpeed;
10
11 defined( 'WPINC' ) || exit();
12
13 /**
14 * Trait Cloud_Misc
15 *
16 * Handles version check, news, usage, promo, and other misc features.
17 */
18 trait Cloud_Misc {
19
20 /**
21 * Load QC status for dash usage.
22 * Format to translate: `<a href="{#xxx#}" class="button button-primary">xxxx</a><a href="{#xxx#}">xxxx2</a>`
23 *
24 * @since 7.0
25 *
26 * @param string $type Type.
27 * @param bool $force Force refresh.
28 * @return string
29 */
30 public function load_qc_status_for_dash( $type, $force = false ) {
31 return Str::translate_qc_apis( $this->_load_qc_status_for_dash( $type, $force ) );
32 }
33
34 /**
35 * Internal: load QC status HTML for dash.
36 *
37 * @param string $type Type.
38 * @param bool $force Force refresh.
39 * @return string
40 */
41 private function _load_qc_status_for_dash( $type, $force = false ) {
42 if (
43 ! $force &&
44 ! empty( $this->_summary['mini_html'] ) &&
45 isset( $this->_summary['mini_html'][ $type ] ) &&
46 ! empty( $this->_summary['mini_html'][ 'ttl.' . $type ] ) &&
47 $this->_summary['mini_html'][ 'ttl.' . $type ] > time()
48 ) {
49 return Str::safe_html( $this->_summary['mini_html'][ $type ] );
50 }
51
52 // Try to update dash content
53 $data = self::post( self::SVC_D_DASH, [ 'action2' => ( 'cdn_dash_mini' === $type ? 'cdn_dash' : $type ) ] );
54 if ( ! empty( $data['qc_activated'] ) ) {
55 // Sync conf as changed
56 if ( empty( $this->_summary['qc_activated'] ) || $this->_summary['qc_activated'] !== $data['qc_activated'] ) {
57 $msg = sprintf( __( 'Congratulations, %s successfully set this domain up for the online services with CDN service.', 'litespeed-cache' ), 'QUIC.cloud' );
58 Admin_Display::success( '🎊 ' . $msg );
59 $this->_clear_reset_qc_reg_msg();
60 // Turn on CDN option
61 $this->cls( 'Conf' )->update_confs( [ self::O_CDN_QUIC => true ] );
62 $this->cls( 'CDN\Quic' )->try_sync_conf( true );
63 }
64
65 $this->_summary['qc_activated'] = $data['qc_activated'];
66 $this->save_summary();
67 }
68
69 // Show the info
70 if ( isset( $this->_summary['mini_html'][ $type ] ) ) {
71 return Str::safe_html( $this->_summary['mini_html'][ $type ] );
72 }
73
74 return '';
75 }
76
77 /**
78 * Show latest commit version always if is on dev
79 *
80 * @since 3.0
81 */
82 public function check_dev_version() {
83 if ( ! preg_match( '/[^\d\.]/', Core::VER ) ) {
84 return;
85 }
86
87 $last_check = empty( $this->_summary[ 'last_request.' . self::API_VER ] ) ? 0 : $this->_summary[ 'last_request.' . self::API_VER ];
88
89 if ( time() - $last_check > 86400 ) {
90 $auto_v = self::version_check( 'dev' );
91 if ( ! empty( $auto_v['dev'] ) ) {
92 self::save_summary( [ 'version.dev' => $auto_v['dev'] ] );
93 }
94 }
95
96 if ( empty( $this->_summary['version.dev'] ) ) {
97 return;
98 }
99
100 self::debug( 'Latest dev version ' . $this->_summary['version.dev'] );
101
102 if ( version_compare( $this->_summary['version.dev'], Core::VER, '<=' ) ) {
103 return;
104 }
105
106 // Show the dev banner
107 require_once LSCWP_DIR . 'tpl/banner/new_version_dev.tpl.php';
108 }
109
110 /**
111 * Check latest version
112 *
113 * @since 2.9
114 * @access public
115 *
116 * @param string|false $src Source.
117 * @return mixed
118 */
119 public static function version_check( $src = false ) {
120 $req_data = [
121 'v' => defined( 'LSCWP_CUR_V' ) ? LSCWP_CUR_V : '',
122 'src' => $src,
123 'php' => phpversion(),
124 ];
125 // If code ver is smaller than db ver, bypass
126 if ( ! empty( $req_data['v'] ) && version_compare( Core::VER, $req_data['v'], '<' ) ) {
127 return;
128 }
129 if ( defined( 'LITESPEED_ERR' ) ) {
130 $litespeed_err = constant( 'LITESPEED_ERR' );
131 $req_data['err'] = base64_encode( ! is_string( $litespeed_err ) ? wp_json_encode( $litespeed_err ) : $litespeed_err ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
132 }
133 $data = self::post( self::API_VER, $req_data );
134
135 return $data;
136 }
137
138 /**
139 * Show latest news
140 *
141 * @since 3.0
142 */
143 public function news() {
144 $this->_update_news();
145
146 if ( empty( $this->_summary['news.new'] ) ) {
147 return;
148 }
149
150 if ( ! empty( $this->_summary['news.plugin'] ) && Activation::cls()->dash_notifier_is_plugin_active( $this->_summary['news.plugin'] ) ) {
151 return;
152 }
153
154 require_once LSCWP_DIR . 'tpl/banner/cloud_news.tpl.php';
155 }
156
157 /**
158 * Update latest news
159 *
160 * @since 2.9.9.1
161 */
162 private function _update_news() {
163 if ( ! empty( $this->_summary['news.utime'] ) && time() - (int) $this->_summary['news.utime'] < 86400 * 7 ) {
164 return;
165 }
166
167 self::save_summary( [ 'news.utime' => time() ] );
168
169 $data = self::get( self::API_NEWS );
170 if ( empty( $data['id'] ) ) {
171 return;
172 }
173
174 // Save news
175 if ( ! empty( $this->_summary['news.id'] ) && (string) $this->_summary['news.id'] === (string) $data['id'] ) {
176 return;
177 }
178
179 $this->_summary['news.id'] = $data['id'];
180 $this->_summary['news.plugin'] = ! empty( $data['plugin'] ) ? $data['plugin'] : '';
181 $this->_summary['news.title'] = ! empty( $data['title'] ) ? $data['title'] : '';
182 $this->_summary['news.content'] = ! empty( $data['content'] ) ? $data['content'] : '';
183 $this->_summary['news.zip'] = ! empty( $data['zip'] ) ? $data['zip'] : '';
184 $this->_summary['news.new'] = 1;
185
186 if ( $this->_summary['news.plugin'] ) {
187 $plugin_info = Activation::cls()->dash_notifier_get_plugin_info( $this->_summary['news.plugin'] );
188 if ( $plugin_info && ! empty( $plugin_info->name ) ) {
189 $this->_summary['news.plugin_name'] = $plugin_info->name;
190 }
191 }
192
193 self::save_summary();
194 }
195
196 /**
197 * Check if contains a package in a service or not
198 *
199 * @since 4.0
200 *
201 * @param string $service Service.
202 * @param int $pkg Package flag.
203 * @return bool
204 */
205 public function has_pkg( $service, $pkg ) {
206 if ( ! empty( $this->_summary[ 'usage.' . $service ]['pkgs'] ) && ( $this->_summary[ 'usage.' . $service ]['pkgs'] & $pkg ) ) {
207 return true;
208 }
209
210 return false;
211 }
212
213 /**
214 * Get allowance of current service
215 *
216 * @since 3.0
217 * @access private
218 *
219 * @param string $service Service.
220 * @param string|bool $err Error code by ref.
221 * @return int
222 */
223 public function allowance( $service, &$err = false ) {
224 // Only auto sync usage at most one time per day
225 if ( empty( $this->_summary[ 'last_request.' . self::SVC_D_USAGE ] ) || time() - (int) $this->_summary[ 'last_request.' . self::SVC_D_USAGE ] > 86400 ) {
226 $this->sync_usage();
227 }
228
229 if ( in_array( $service, [ self::SVC_CCSS, self::SVC_UCSS, self::SVC_VPI ], true ) ) {
230 // @since 4.2
231 $service = self::SVC_PAGE_OPTM;
232 }
233
234 if ( empty( $this->_summary[ 'usage.' . $service ] ) ) {
235 return 0;
236 }
237 $usage = $this->_summary[ 'usage.' . $service ];
238
239 // Image optm is always free
240 $allowance_max = 0;
241 if ( self::SVC_IMG_OPTM === $service ) {
242 $allowance_max = self::IMG_OPTM_DEFAULT_GROUP;
243 }
244
245 $allowance = (int) $usage['quota'] - (int) $usage['used'];
246
247 $err = 'out_of_quota';
248
249 if ( $allowance > 0 ) {
250 if ( $allowance_max && $allowance_max < $allowance ) {
251 $allowance = $allowance_max;
252 }
253
254 // Daily limit @since 4.2
255 if ( isset( $usage['remaining_daily_quota'] ) && $usage['remaining_daily_quota'] >= 0 && $usage['remaining_daily_quota'] < $allowance ) {
256 $allowance = $usage['remaining_daily_quota'];
257 if ( ! $allowance ) {
258 $err = 'out_of_daily_quota';
259 }
260 }
261
262 return $allowance;
263 }
264
265 // Check Pay As You Go balance
266 if ( empty( $usage['pag_bal'] ) ) {
267 return $allowance_max;
268 }
269
270 if ( $allowance_max && $allowance_max < $usage['pag_bal'] ) {
271 return $allowance_max;
272 }
273
274 return (int) $usage['pag_bal'];
275 }
276
277 /**
278 * Sync Cloud usage summary data
279 *
280 * @since 3.0
281 * @access public
282 */
283 public function sync_usage() {
284 $usage = $this->_post( self::SVC_D_USAGE );
285 if ( ! $usage ) {
286 return;
287 }
288
289 self::debug( 'sync_usage ' . wp_json_encode( $usage ) );
290
291 foreach ( self::$services as $v ) {
292 $this->_summary[ 'usage.' . $v ] = ! empty( $usage[ $v ] ) ? $usage[ $v ] : false;
293 }
294
295 self::save_summary();
296
297 return $this->_summary;
298 }
299
300 /**
301 * REST call: check if the error domain is valid call for auto alias purpose
302 *
303 * @since 5.0
304 */
305 public function rest_err_domains() {
306 // phpcs:ignore WordPress.Security.NonceVerification.Missing
307 $alias = !empty( $_POST['alias'] ) ? sanitize_text_field( wp_unslash( $_POST['alias'] ) ) : '';
308 // phpcs:ignore WordPress.Security.NonceVerification.Missing
309 if ( empty( $_POST['main_domain'] ) || !$alias ) {
310 return self::err( 'lack_of_param' );
311 }
312
313 // phpcs:ignore WordPress.Security.NonceVerification.Missing
314 $this->extract_msg( $_POST, 'Quic.cloud', false, true );
315
316 if ( $this->_is_err_domain( $alias ) ) {
317 if ( site_url() === $alias ) {
318 $this->_remove_domain_from_err_list( $alias );
319 }
320 return self::ok();
321 }
322
323 return self::err( 'Not an alias req from here' );
324 }
325
326 /**
327 * Remove a domain from err domain
328 *
329 * @since 5.0
330 *
331 * @param string $url URL to remove.
332 */
333 private function _remove_domain_from_err_list( $url ) {
334 unset( $this->_summary['err_domains'][ $url ] );
335 self::save_summary();
336 }
337
338 /**
339 * Check if is err domain
340 *
341 * @since 5.0
342 *
343 * @param string $site_url Site URL.
344 * @return bool
345 */
346 private function _is_err_domain( $site_url ) {
347 if ( empty( $this->_summary['err_domains'] ) ) {
348 return false;
349 }
350 if ( ! array_key_exists( $site_url, $this->_summary['err_domains'] ) ) {
351 return false;
352 }
353 // Auto delete if too long ago
354 if ( time() - (int) $this->_summary['err_domains'][ $site_url ] > 86400 * 10 ) {
355 $this->_remove_domain_from_err_list( $site_url );
356
357 return false;
358 }
359 if ( time() - (int) $this->_summary['err_domains'][ $site_url ] > 86400 ) {
360 return false;
361 }
362 return true;
363 }
364
365 /**
366 * Show promo from cloud
367 *
368 * @since 3.0
369 * @access public
370 */
371 public function show_promo() {
372 if ( empty( $this->_summary['promo'] ) ) {
373 return;
374 }
375
376 require_once LSCWP_DIR . 'tpl/banner/cloud_promo.tpl.php';
377 }
378
379 /**
380 * Clear promo from cloud
381 *
382 * @since 3.0
383 * @access private
384 */
385 private function _clear_promo() {
386 if ( count( $this->_summary['promo'] ) > 1 ) {
387 array_shift( $this->_summary['promo'] );
388 } else {
389 $this->_summary['promo'] = [];
390 }
391 self::save_summary();
392 }
393
394 /**
395 * Display a banner for dev env if using preview QC node.
396 *
397 * @since 7.0
398 */
399 public function maybe_preview_banner() {
400 if ( false !== strpos( $this->_cloud_server, 'preview.' ) ) {
401 Admin_Display::note( __( 'Linked to QUIC.cloud preview environment, for testing purpose only.', 'litespeed-cache' ), true, true, 'litespeed-warning-bg' );
402 }
403 }
404 }
405