PluginProbe
Parse.ly / 3.18.1
Parse.ly v3.18.1
3.24.1 3.24.0 3.23.7 3.23.6 3.23.5 3.23.4 3.23.3 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.17.0 3.18.0 3.18.1 3.19.0 3.19.1 3.19.2 3.19.3 3.2.0 3.2.1 3.20.0 3.20.1 3.20.2 3.20.3 All 105 releases
wp-parsely / src / Utils / class-utils.php

class-utils.php in Parse.ly 3.18.1, at src/Utils/class-utils.php

462 lines 11.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Utils Class.
4 *
5 * To enforce typing on commonly used functions.
6 *
7 * @package Parsely
8 * @since 3.7.0
9 * @since 3.17.0 Refactored to a class.
10 */
11
12 declare(strict_types=1);
13
14 namespace Parsely\Utils;
15
16 use WP_Post;
17 use WP_Error;
18
19 use const Parsely\PARSELY_FILE;
20
21 /**
22 * Utils Class.
23 *
24 * @since 3.17.0
25 */
26 class Utils {
27 const DATE_UTC_FORMAT = 'Y-m-d';
28 const WP_DATE_TIME_FORMAT = 'Y-m-d H:i:s';
29
30 /**
31 * Gets UTC Date.
32 *
33 * @since 3.7.0
34 *
35 * @param int $days Number of days before or after the current date.
36 *
37 * @return string
38 */
39 public static function get_utc_date_format( int $days = 0 ): string {
40 if ( 0 === $days ) {
41 return gmdate( self::DATE_UTC_FORMAT );
42 }
43
44 return gmdate( self::DATE_UTC_FORMAT, (int) strtotime( "{$days} days" ) );
45 }
46
47 /**
48 * Gets default category.
49 *
50 * @since 3.7.0
51 *
52 * @return int
53 */
54 public static function get_default_category(): int {
55 /**
56 * Variable.
57 *
58 * @var string
59 */
60 $default_category = get_option( 'default_category' );
61 return (int) $default_category;
62 }
63
64 /**
65 * Gets option `page_for_posts`.
66 *
67 * @since 3.7.0
68 *
69 * @param bool $default_value Default Value.
70 *
71 * @return int|WP_Post
72 */
73 public static function get_page_for_posts( bool $default_value = false ) {
74 /**
75 * Variable.
76 *
77 * @var int|WP_Post
78 */
79 return get_option( 'page_for_posts', $default_value );
80 }
81
82 /**
83 * Gets option `page_on_front`.
84 *
85 * @since 3.7.0
86 *
87 * @return bool
88 */
89 public static function get_page_on_front(): bool {
90 /**
91 * Variable.
92 *
93 * @var bool
94 */
95 return (bool) get_option( 'page_on_front' );
96 }
97
98 /**
99 * Gets 'string' query variable from WP_Query class.
100 *
101 * @since 3.7.0
102 *
103 * @param string $key Variable key to retrieve.
104 *
105 * @return string
106 */
107 public static function get_string_query_var( string $key ): string {
108 /**
109 * Variable.
110 *
111 * @var string
112 */
113 return get_query_var( $key );
114 }
115
116 /**
117 * Gets site date format.
118 *
119 * @since 3.7.0
120 *
121 * @return string
122 */
123 public static function get_date_format(): string {
124 /**
125 * Variable.
126 *
127 * @var string
128 */
129 return get_option( 'date_format' );
130 }
131
132 /**
133 * Gets site time format.
134 *
135 * @since 3.7.0
136 *
137 * @return string
138 */
139 public static function get_time_format(): string {
140 /**
141 * Variable.
142 *
143 * @var string
144 */
145 return get_option( 'time_format' );
146 }
147
148 /**
149 * Returns the current time's timestamp.
150 *
151 * @since 3.12.0
152 *
153 * @return string
154 */
155 public static function get_timestamp(): string {
156 $timestamp = round( microtime( true ) * 1000 );
157 return number_format( $timestamp, 0, '', '' );
158 }
159
160 /**
161 * Gets number in formatted form i.e. express bigger numbers in form of
162 * thousands (k), millions (M), billions (B).
163 *
164 * Note: This function is not made to process float numbers, and it is a PHP
165 * port of our formatToImpreciseNumber() TypeScript function.
166 *
167 * Example:
168 * - Represent 10000 as 10K.
169 *
170 * @since 3.7.0
171 *
172 * @param string $value The number to process. It can be formatted.
173 * @param int $fraction_digits The number of desired fraction digits.
174 * @param string $glue A string to put between the number and unit.
175 *
176 * @return string The number formatted as an imprecise number.
177 */
178 public static function get_formatted_number( string $value, int $fraction_digits = 1, string $glue = '' ): string {
179 $number = (int) preg_replace( '/\D/', '', $value );
180
181 if ( $number < 1000 ) {
182 return $value;
183 } elseif ( $number < 10000 ) {
184 $fraction_digits = 1;
185 }
186
187 $unit_names = array(
188 '1000' => 'k',
189 '1000000' => 'M',
190 '1000000000' => 'B',
191 '1000000000000' => 'T',
192 '1000000000000000' => 'Q',
193 );
194 $current_number = $number;
195 $current_number_as_string = (string) $number;
196 $unit = '';
197 $previous_number = 0;
198
199 foreach ( $unit_names as $thousands => $suffix ) {
200 $thousands_int = (int) preg_replace( '/\D/', '', (string) $thousands );
201
202 if ( $number >= $thousands_int ) {
203 $current_number = $number / $thousands_int;
204 $precision = $fraction_digits;
205
206 // For over 10 units, we reduce the precision to 1 fraction digit.
207 $modulo = (int) fmod( $current_number, 1 );
208 if ( 0 !== $previous_number && $modulo > 1 / $previous_number ) {
209 $precision = $current_number > 10 ? 1 : 2;
210 }
211
212 // Precision override, where we want to show 2 fraction digits.
213 $zeroes = floatval( number_format( $current_number, 2 ) ) === floatval( number_format( $current_number, 0 ) );
214 $precision = $zeroes ? 0 : $precision;
215 $current_number_as_string = number_format( $current_number, $precision, '.', '' );
216 $unit = $suffix;
217 }
218
219 $previous_number = $current_number;
220 }
221
222 return $current_number_as_string . $glue . $unit;
223 }
224
225 /**
226 * Gets time in formatted form.
227 *
228 * Example:
229 * - Input `1000` (seconds) and Output `16:40` which represents "16 minutes, 40 seconds”
230 *
231 * @since 3.7.0
232 *
233 * @param float $seconds Time in seconds to be formatted.
234 *
235 * @return string
236 */
237 public static function get_formatted_time( $seconds ): string {
238 $seconds = round( $seconds );
239 $hours = floor( $seconds / 3600 );
240
241 if ( $hours >= 1 ) {
242 $seconds = $seconds - ( $hours * 3600 );
243 $minutes = floor( $seconds / 60 );
244 $seconds = round( $seconds % 60 );
245
246 return esc_html(
247 sprintf(
248 /* translators: 1: Number of hours 2: Number of minutes 3: Number of seconds */
249 __( '%1$d:%2$02d:%3$02d', 'wp-parsely' ),
250 $hours,
251 $minutes,
252 $seconds
253 )
254 );
255 }
256
257 $minutes = floor( $seconds / 60 );
258 $seconds = round( $seconds % 60 );
259
260 if ( $minutes >= 1 ) {
261 return esc_html(
262 sprintf(
263 /* translators: 1: Number of minutes 2: Number of seconds */
264 __( '%1$d:%2$02d', 'wp-parsely' ),
265 $minutes,
266 $seconds
267 )
268 );
269 }
270
271 return esc_html(
272 sprintf(
273 /* translators: 1: Number of seconds */
274 __( '%1$d sec.', 'wp-parsely' ),
275 round( $seconds )
276 )
277 );
278 }
279
280 /**
281 * Returns the passed float as a time duration in m:ss format.
282 *
283 * Examples:
284 * - $time of 1.005 yields '1:00'.
285 * - $time of 1.5 yields '1:30'.
286 * - $time of 1.999 yields '2:00'.
287 *
288 * @since 3.6.0
289 *
290 * @param float $time The time as a float number.
291 *
292 * @return string The resulting formatted time duration.
293 */
294 public static function get_formatted_duration( float $time ): string {
295 $minutes = absint( $time );
296 $seconds = absint( round( fmod( $time, 1 ) * 60 ) );
297
298 if ( 60 === $seconds ) {
299 ++$minutes;
300 $seconds = 0;
301 }
302
303 return sprintf( '%d:%02d', $minutes, $seconds );
304 }
305
306 /**
307 * Converts to associate array.
308 *
309 * @since 3.7.0
310 *
311 * @param mixed $obj Input object.
312 *
313 * @return array<string, mixed>|WP_Error
314 */
315 public static function convert_to_associative_array( $obj ) {
316 $encoded = wp_json_encode( $obj );
317 if ( false === $encoded ) {
318 return new WP_Error( 'parsely_encoding_failed', __( 'Unable to encode API response for associative array', 'wp-parsely' ) );
319 }
320
321 /**
322 * Variable.
323 *
324 * @var array<string, mixed>
325 */
326 return json_decode( $encoded, true );
327 }
328
329 /**
330 * Converts a string to a positive integer, removing any non-numeric
331 * characters.
332 *
333 * @param string $value The string to be converted to an integer.
334 * @return int The integer resulting from the conversion.
335 */
336 public static function convert_to_positive_integer( string $value ): int {
337 return (int) preg_replace( '/\D/', '', $value );
338 }
339
340 /**
341 * Converts endpoint to filter key by replacing `/` with `_`.
342 *
343 * @param string $endpoint Route of the endpoint.
344 *
345 * @since 3.7.0
346 *
347 * @return string
348 */
349 public static function convert_endpoint_to_filter_key( string $endpoint ): string {
350 return trim( str_replace( array( '-', '/' ), '_', $endpoint ), '_' );
351 }
352
353 /**
354 * Gets content of asset file.
355 *
356 * @param string $path Path of the asset file.
357 *
358 * @since 3.8.0
359 *
360 * @return Asset_Info
361 */
362 public static function get_asset_info( string $path ) {
363 return require plugin_dir_path( PARSELY_FILE ) . $path;
364 }
365
366 /**
367 * Checks if a string starts with a specific substring.
368 *
369 * This function uses the built-in PHP function `str_starts_with` if it's available (PHP 8.0 and later).
370 * If the function is not available (PHP versions prior to 8.0), it uses the `strpos` function as a fallback.
371 *
372 * @since 3.13.0
373 *
374 * @param string $haystack The string to search in.
375 * @param string $needle The substring to search for at the start of $haystack.
376 * @return bool Returns true if $haystack starts with $needle, false otherwise.
377 */
378 public static function str_starts_with( string $haystack, string $needle ): bool {
379 if ( function_exists( '\str_starts_with' ) ) {
380 return \str_starts_with( $haystack, $needle );
381 }
382 return 0 === strpos( $haystack, $needle );
383 }
384
385 /**
386 * Checks if HTTPS is supported for the site.
387 *
388 * This function checks if the WordPress function 'wp_is_using_https' exists and uses it to determine if
389 * HTTPS is supported.
390 * If the function does not exist, it checks if the home URL scheme is HTTPS.
391 * If neither of the above conditions are met, it checks if the site URL option scheme is HTTPS.
392 *
393 * @since 3.14.1
394 *
395 * @return bool Returns true if HTTPS is supported, false otherwise.
396 */
397 public static function parsely_is_https_supported(): bool {
398 if ( function_exists( 'wp_is_using_https' ) ) {
399 return wp_is_using_https();
400 }
401
402 if ( 'https' === wp_parse_url( home_url(), PHP_URL_SCHEME ) ) {
403 return true;
404 }
405
406 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
407 $site_url = apply_filters( 'site_url', get_option( 'siteurl' ), '', null, null );
408 return 'https' === wp_parse_url( $site_url, PHP_URL_SCHEME );
409 }
410
411 /**
412 * Returns the post ID for the passed URL.
413 *
414 * @since 3.16.0
415 * @since 3.18.0 Moved from `Models/class-smart-link.php`.
416 *
417 * @param string $url The URL to get the post ID for.
418 * @return int The post ID of the URL, 0 if not found.
419 */
420 public static function get_post_id_by_url( string $url ): int {
421 $cache = wp_cache_get( $url, 'wp_parsely_smart_link_url_to_postid' );
422 if ( is_integer( $cache ) ) {
423 return $cache;
424 }
425
426 if ( function_exists( 'wpcom_vip_url_to_postid' ) ) {
427 $post_id = wpcom_vip_url_to_postid( $url );
428 } else {
429 // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.url_to_postid_url_to_postid
430 $post_id = url_to_postid( $url );
431 wp_cache_set( $url, $post_id, 'wp_parsely_smart_link_url_to_postid' );
432 }
433
434 // A post ID was found, return it.
435 if ( 0 !== $post_id ) {
436 return $post_id;
437 }
438
439 // No post ID was found, try to find it from the slug.
440 $clean_url = preg_replace( '/\?.*$/', '', $url ); // Remove the query string from the URL.
441 if ( null === $clean_url ) {
442 $clean_url = $url;
443 }
444 $post_slug = basename( $clean_url );
445
446 $public_post_types = get_post_types(
447 array(
448 'public' => true,
449 'show_in_rest' => true,
450 )
451 );
452 $post = get_page_by_path( $post_slug, OBJECT, array_keys( $public_post_types ) );
453
454 if ( null !== $post ) {
455 wp_cache_set( $url, $post->ID, 'wp_parsely_smart_link_url_to_postid' );
456 return $post->ID;
457 }
458
459 return 0;
460 }
461 }
462