PluginProbe ʕ •ᴥ•ʔ
Presto Player / 4.2.1
Presto Player v4.2.1
4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.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.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / inc / Support / Utility.php
presto-player / inc / Support Last commit date
Block.php 1 month ago BlockFinder.php 1 year ago DynamicData.php 1 year ago HasOneRelationship.php 1 year ago Integration.php 1 year ago Utility.php 1 month ago
Utility.php
334 lines
1 <?php
2 /**
3 * Utility class for Presto Player.
4 *
5 * @package PrestoPlayer
6 * @subpackage Support
7 */
8
9 namespace PrestoPlayer\Support;
10
11 /**
12 * Utility class containing helper functions.
13 */
14 class Utility {
15
16 /**
17 * Presto Player admin page screen IDs.
18 *
19 * @var array
20 */
21 const PRESTO_PLAYER_SCREENS = array(
22 'toplevel_page_presto-dashboard', // Main dashboard (React SPA).
23 'edit-pp_video_block', // Media-hub page.
24 'edit-pp_email_submission', // Email Submissions list/edit page.
25 );
26
27 /**
28 * Detect whether a string contains an HTML tag (`<word` or `</word`).
29 *
30 * Centralized so the save-time and render-time CSS sanitizers stay in lock-step.
31 *
32 * @param string $value String to inspect.
33 * @return bool
34 */
35 public static function hasHtmlMarkup( $value ) {
36 if ( ! is_string( $value ) || '' === $value ) {
37 return false;
38 }
39 return (bool) preg_match( '#</?\w+#', $value );
40 }
41
42 /**
43 * Sanitize CSS input.
44 *
45 * Strips HTML tags rather than wiping the value, so a single stray `<`
46 * in a legitimate selector doesn't blank the user's entire stylesheet.
47 * The remaining CSS still runs through `wp_kses_post()` + `esc_attr()` at
48 * render time (see `Support\Block::getCSS()`), so this is defense in depth.
49 *
50 * @param string $css CSS to sanitize.
51 * @return string Sanitized CSS.
52 */
53 public static function sanitizeCSS( $css ) {
54 $css = $css ?? '';
55 if ( ! self::hasHtmlMarkup( $css ) ) {
56 return $css;
57 }
58 if ( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) {
59 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
60 error_log( 'Presto Player: HTML markup stripped from custom player CSS.' );
61 }
62 return wp_strip_all_tags( $css );
63 }
64
65 /**
66 * Insert a string after another string.
67 *
68 * @param string $str The original string.
69 * @param string $search The string to search for.
70 * @param string $insert The string to insert.
71 * @return string Modified string.
72 */
73 public static function insertAfterString( $str, $search, $insert ) {
74 $index = strpos( $str, $search );
75 if ( false === $index ) {
76 return $str;
77 }
78 return substr_replace( $str, $search . $insert, $index, strlen( $search ) );
79 }
80
81 /**
82 * Convert snake_case to camelCase.
83 *
84 * @param string $input The input string in snake_case.
85 * @return string The output string in camelCase.
86 */
87 public static function snakeToCamel( $input ) {
88 return lcfirst( str_replace( ' ', '', ucwords( str_replace( '_', ' ', $input ) ) ) );
89 }
90
91 /**
92 * Convert a duration to human readable format.
93 *
94 * @since 5.1.0.
95 *
96 * @param string $duration Duration will be in string format (HH:ii:ss) OR (ii:ss),
97 * with a possible prepended negative sign (-).
98 * @return string|false A human readable duration string, false on failure.
99 */
100 public static function human_readable_duration( $duration = '' ) {
101 if ( ( empty( $duration ) || ! is_string( $duration ) ) ) {
102 return __( '0 seconds', 'presto-player' );
103 }
104
105 $duration = trim( $duration );
106
107 // Remove prepended negative sign.
108 if ( '-' === substr( $duration, 0, 1 ) ) {
109 $duration = substr( $duration, 1 );
110 }
111
112 // Extract duration parts.
113 $duration_parts = array_reverse( explode( ':', $duration ) );
114 $duration_count = count( $duration_parts );
115
116 $hour = null;
117 $minute = null;
118 $second = null;
119
120 if ( 3 === $duration_count ) {
121 // Validate HH:ii:ss duration format.
122 if ( ! ( (bool) preg_match( '/^([0-9]+):([0-5]?[0-9]):([0-5]?[0-9])$/', $duration ) ) ) {
123 return false;
124 }
125 // Three parts: hours, minutes & seconds.
126 list($second, $minute, $hour) = $duration_parts;
127 } elseif ( 2 === $duration_count ) {
128 // Validate ii:ss duration format.
129 if ( ! ( (bool) preg_match( '/^([0-5]?[0-9]):([0-5]?[0-9])$/', $duration ) ) ) {
130 return false;
131 }
132 // Two parts: minutes & seconds.
133 list($second, $minute) = $duration_parts;
134 } else {
135 return false;
136 }
137
138 $human_readable_duration = array();
139
140 // Add the hour part to the string.
141 if ( is_numeric( $hour ) && $hour > 0 ) {
142 /* translators: %s: Time duration in hour or hours. */
143 $human_readable_duration[] = sprintf( _n( '%s hour', '%s hours', $hour ), (int) $hour );
144 }
145
146 // Add the minute part to the string.
147 if ( is_numeric( $minute ) && $minute > 0 ) {
148 /* translators: %s: Time duration in minute or minutes. */
149 $human_readable_duration[] = sprintf( _n( '%s minute', '%s minutes', $minute ), (int) $minute );
150 }
151
152 // Add the second part to the string.
153 if ( is_numeric( $second ) && $second > 0 ) {
154 /* translators: %s: Time duration in second or seconds. */
155 $human_readable_duration[] = sprintf( _n( '%s second', '%s seconds', $second ), (int) $second );
156 }
157
158 return implode( ', ', $human_readable_duration );
159 }
160
161 /**
162 * Get the IP address.
163 *
164 * @param string $ip_address Optional. IP address to validate.
165 * @return string Valid IP address or empty string.
166 */
167 public static function getIPAddress( $ip_address = '' ) {
168 $ip = $ip_address ? $ip_address : ( isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '' );
169
170 if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
171 return $ip;
172 } else {
173 return '';
174 }
175 }
176
177 /**
178 * Insert an array into another array before/after a certain key.
179 *
180 * @param array $array The initial array.
181 * @param array $pairs The array to insert.
182 * @param string $key The certain key.
183 * @param string $position Wether to insert the array before or after the key.
184 * @return array
185 */
186 public static function arrayInsert( $array, $pairs, $key, $position = 'after' ) {
187 $key_pos = array_search( $key, array_keys( $array ), true );
188
189 if ( 'after' === $position ) {
190 ++$key_pos;
191 }
192
193 if ( false !== $key_pos ) {
194 $result = array_slice( $array, 0, $key_pos );
195 $result = array_merge( $result, $pairs );
196 $result = array_merge( $result, array_slice( $array, $key_pos ) );
197 } else {
198 $result = array_merge( $array, $pairs );
199 }
200
201 return $result;
202 }
203
204 /**
205 * Inserts a new key/value before the specified key in the array.
206 *
207 * @param string $key The key to insert before.
208 * @param array $array An array to insert into.
209 * @param string $new_key The key to insert.
210 * @param mixed $new_value The value to insert.
211 *
212 * @return array|false The new array if the key exists, FALSE otherwise.
213 */
214 public static function arrayInsertBefore( $key, array &$array, $new_key, $new_value ) {
215 if ( array_key_exists( $key, $array ) ) {
216 $new = array();
217 foreach ( $array as $k => $value ) {
218 if ( $k === $key ) {
219 $new[ $new_key ] = $new_value;
220 }
221 $new[ $k ] = $value;
222 }
223 return $new;
224 }
225 return false;
226 }
227
228 /**
229 * Inserts a new key/value pair after a specific key in an array.
230 *
231 * @param string $key The key to insert after.
232 * @param array $array The array to insert into.
233 * @param string $new_key The new key to insert.
234 * @param mixed $new_value The new value to insert.
235 *
236 * @return array|false The new array if the key exists, FALSE otherwise.
237 */
238 public static function arrayInsertAfter( $key, array &$array, $new_key, $new_value ) {
239 if ( array_key_exists( $key, $array ) ) {
240 $new = array();
241 foreach ( $array as $k => $value ) {
242 $new[ $k ] = $value;
243 if ( $k === $key ) {
244 $new[ $new_key ] = $new_value;
245 }
246 }
247 return $new;
248 }
249 return false;
250 }
251
252 /**
253 * Convert hexadecimal color to RGBA.
254 *
255 * This function takes a hexadecimal color code and an optional opacity value
256 * and converts it to an RGBA color string.
257 *
258 * @param string $color The hexadecimal color code.
259 * @param float $opacity Optional. The opacity value between 0 and 1. Default false.
260 *
261 * @return string The RGBA color string.
262 */
263 public static function hex2rgba( $color, $opacity = false ) {
264
265 $default_color = 'rgb(0,0,0)';
266
267 // Return default color if no color provided.
268 if ( empty( $color ) ) {
269 return $default_color;
270 }
271
272 // Ignore "#" if provided.
273 if ( '#' === $color[0] ) {
274 $color = substr( $color, 1 );
275 }
276
277 // Check if color has 6 or 3 characters, get values.
278 if ( 6 === strlen( $color ) ) {
279 $hex = array( $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] );
280 } elseif ( 3 === strlen( $color ) ) {
281 $hex = array( $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] );
282 } else {
283 return $default_color;
284 }
285
286 // Convert hex values to rgb values.
287 $rgb = array_map( 'hexdec', $hex );
288
289 // Check if opacity is set(rgba or rgb).
290 if ( $opacity ) {
291 if ( abs( $opacity ) > 1 ) {
292 $opacity = 1.0;
293 }
294 $output = 'rgba(' . implode( ',', $rgb ) . ',' . $opacity . ')';
295 } else {
296 $output = 'rgb(' . implode( ',', $rgb ) . ')';
297 }
298
299 // Return rgb(a) color string.
300 return $output;
301 }
302
303 /**
304 * Flatten an array.
305 *
306 * @param array $array Array.
307 *
308 * @return array
309 */
310 public static function flatten( array $array ) {
311 $return = array();
312 array_walk_recursive(
313 $array,
314 function ( $a ) use ( &$return ) {
315 $return[] = $a;
316 }
317 );
318 return $return;
319 }
320
321 /**
322 * Check if the current admin page is a Presto Player page.
323 *
324 * @return bool True if on a Presto Player page, false otherwise.
325 */
326 public static function isPrestoPlayerPage() {
327 $current_screen = get_current_screen();
328 if ( ! $current_screen ) {
329 return false;
330 }
331 return in_array( $current_screen->id, self::PRESTO_PLAYER_SCREENS, true );
332 }
333 }
334