22/**
33 * Device detection for Jetpack.
44 *
5- * Since WPSC doesn't use an autoloader or composer, this is a simple copy/paste of the package
5+ * Since WPSC doesn't use an autoloader or composer, this is a simplified version of the package
66 * as of November 11, 2025.
77 *
88 * @package automattic/jetpack-device-detection
2626 */
2727class Device_Detection {
2828
29- /**
30- * Memoization cache for get_info() results.
31- *
32- * @var array
33- */
34- private static $ get_info_memo = array ();
35-
36- /**
37- * Maximum size of the memoization cache.
38- *
39- * @var int
40- */
41- private static $ max_memo_size = 100 ;
42-
43- /**
44- * Returns information about the current device accessing the page.
45- *
46- * @param string $ua (Optional) User-Agent string.
47- *
48- * @return array Device information.
49- *
50- * array(
51- * 'is_phone' => (bool) Whether the current device is a mobile phone.
52- * 'is_smartphone' => (bool) Whether the current device is a smartphone.
53- * 'is_tablet' => (bool) Whether the current device is a tablet device.
54- * 'is_handheld' => (bool) Whether the current device is a handheld device.
55- * 'is_desktop' => (bool) Whether the current device is a laptop / desktop device.
56- * 'platform' => (string) Detected platform.
57- * 'is_phone_matched_ua' => (string) Matched UA.
58- * );
59- */
60- public static function get_info ( $ ua = '' ) {
61- // Return memoized result if available.
62- // phpcs:disable WordPress.Security.ValidatedSanitizedInput
63- $ memo_key = ! empty ( $ ua ) ? $ ua : ( $ _SERVER ['HTTP_USER_AGENT ' ] ?? '' );
64- // Note: UA string used raw for compatibility reasons.
65- // No sanitization is needed as the value is never output or persisted, and is only used for memoization.
66- // phpcs:enable WordPress.Security.ValidatedSanitizedInput
67- if ( isset ( self ::$ get_info_memo [ $ memo_key ] ) ) {
68- return self ::$ get_info_memo [ $ memo_key ];
69- }
70-
71- $ ua_info = new User_Agent_Info ( $ ua );
72-
73- $ info = array (
74- 'is_phone ' => self ::is_mobile ( 'any ' , false , $ ua_info ),
75- 'is_phone_matched_ua ' => self ::is_mobile ( 'any ' , true , $ ua_info ),
76- 'is_smartphone ' => self ::is_mobile ( 'smart ' , false , $ ua_info ),
77- 'is_tablet ' => $ ua_info ->is_tablet (),
78- 'platform ' => $ ua_info ->get_platform (),
79- 'desktop_platform ' => $ ua_info ->get_desktop_platform (),
80- 'browser ' => $ ua_info ->get_browser (),
81- );
82-
83- $ info ['is_handheld ' ] = $ info ['is_phone ' ] || $ info ['is_tablet ' ];
84- $ info ['is_desktop ' ] = ! $ info ['is_handheld ' ];
85-
86- if ( function_exists ( 'apply_filters ' ) ) {
87- /**
88- * Filter the value of Automattic\WPSC\Device_Detection::get_info.
89- *
90- * @since 1.0.0
91- *
92- * @param array $info Array of device information.
93- * @param string $ua User agent string passed to Automattic\WPSC\Device_Detection::get_info.
94- * @param User_Agent_Info $ua_info Instance of Automattic\WPSC\Device_Detection\User_Agent_Info.
95- */
96- $ info = apply_filters ( 'jetpack_device_detection_get_info ' , $ info , $ ua , $ ua_info );
97- }
98-
99- // Memoize the result.
100- self ::$ get_info_memo [ $ memo_key ] = $ info ;
101- if ( count ( self ::$ get_info_memo ) > self ::$ max_memo_size ) {
102- array_shift ( self ::$ get_info_memo );
103- }
104-
105- return $ info ;
106- }
107-
10829 /**
10930 * Detects phone devices.
11031 *
111- * @param string $ua User-Agent string.
112- *
113- * @return bool
114- */
115- public static function is_phone ( $ ua = '' ) {
116- $ device_info = self ::get_info ( $ ua );
117- return true === $ device_info ['is_phone ' ];
118- }
119-
120- /**
121- * Detects smartphone devices.
122- *
123- * @param string $ua User-Agent string.
124- *
125- * @return bool
126- */
127- public static function is_smartphone ( $ ua = '' ) {
128- $ device_info = self ::get_info ( $ ua );
129- return true === $ device_info ['is_smartphone ' ];
130- }
131-
132- /**
133- * Detects tablet devices.
134- *
135- * @param string $ua User-Agent string.
136- *
137- * @return bool
138- */
139- public static function is_tablet ( $ ua = '' ) {
140- $ device_info = self ::get_info ( $ ua );
141- return true === $ device_info ['is_tablet ' ];
142- }
143-
144- /**
145- * Detects desktop devices.
146- *
147- * @param string $ua User-Agent string.
148- *
149- * @return bool
150- */
151- public static function is_desktop ( $ ua = '' ) {
152- $ device_info = self ::get_info ( $ ua );
153- return true === $ device_info ['is_desktop ' ];
154- }
155-
156- /**
157- * Detects handheld (i.e. phone + tablet) devices.
158- *
159- * @param string $ua User-Agent string.
160- *
16132 * @return bool
16233 */
163- public static function is_handheld ( $ ua = '' ) {
164- $ device_info = self ::get_info ( $ ua );
165- return true === $ device_info ['is_handheld ' ];
166- }
167-
168- /**
169- * Determine if the current User Agent matches the passed $kind.
170- *
171- * @param string $kind Category of mobile device to check for. Either: any, dumb, smart.
172- * @param bool $return_matched_agent Boolean indicating if the UA should be returned.
173- * @param User_Agent_Info $ua_info Boolean indicating if the UA should be returned.
174- *
175- * @return bool|string Boolean indicating if current UA matches $kind. If `$return_matched_agent` is true, returns the UA string.
176- */
177- private static function is_mobile ( $ kind , $ return_matched_agent , $ ua_info ) {
178- $ kinds = array (
179- 'smart ' => false ,
180- 'dumb ' => false ,
181- 'any ' => false ,
182- );
183- $ matched_agent = '' ;
184-
185- // If an invalid kind is passed in, reset it to default.
186- if ( ! isset ( $ kinds [ $ kind ] ) ) {
187- $ kind = 'any ' ;
188- }
189-
34+ public static function is_phone () {
19035 if ( empty ( $ _SERVER ['HTTP_USER_AGENT ' ] ) ) {
19136 return false ;
19237 }
19338
39+ $ ua_info = new User_Agent_Info ( $ _SERVER ['HTTP_USER_AGENT ' ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Handled in User_Agent_Info
40+
19441 $ agent = strtolower ( filter_var ( wp_unslash ( $ _SERVER ['HTTP_USER_AGENT ' ] ) ) );
19542 if ( strpos ( $ agent , 'ipad ' ) ) {
19643 return false ;
@@ -211,43 +58,23 @@ private static function is_mobile( $kind, $return_matched_agent, $ua_info ) {
21158
21259 // checks for iPhoneTier devices & RichCSS devices.
21360 if ( $ ua_info ->isTierIphone () || $ ua_info ->isTierRichCSS () ) {
214- $ kinds ['smart ' ] = true ;
215- $ matched_agent = $ ua_info ->matched_agent ;
61+ return true ;
21662 }
21763
218- if ( ! $ kinds ['smart ' ] ) {
219- // if smart, we are not dumb so no need to check.
220- $ dumb_agents = $ ua_info ->dumb_agents ;
221-
222- foreach ( $ dumb_agents as $ dumb_agent ) {
223- if ( false !== strpos ( $ agent , $ dumb_agent ) ) {
224- $ kinds ['dumb ' ] = true ;
225- $ matched_agent = $ dumb_agent ;
64+ $ dumb_agents = $ ua_info ->dumb_agents ;
22665
227- break ;
228- }
229- }
230-
231- if ( ! $ kinds ['dumb ' ] ) {
232- if ( isset ( $ _SERVER ['HTTP_X_WAP_PROFILE ' ] ) ) {
233- $ kinds ['dumb ' ] = true ;
234- $ matched_agent = 'http_x_wap_profile ' ;
235- } elseif ( isset ( $ _SERVER ['HTTP_ACCEPT ' ] ) && ( preg_match ( '/wap\.|\.wap/i ' , $ _SERVER ['HTTP_ACCEPT ' ] ) || false !== strpos ( strtolower ( $ _SERVER ['HTTP_ACCEPT ' ] ), 'application/vnd.wap.xhtml+xml ' ) ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- This is doing the validating.
236- $ kinds ['dumb ' ] = true ;
237- $ matched_agent = 'vnd.wap.xhtml+xml ' ;
238- }
66+ foreach ( $ dumb_agents as $ dumb_agent ) {
67+ if ( false !== strpos ( $ agent , $ dumb_agent ) ) {
68+ return true ;
23969 }
24070 }
24171
242- if ( $ kinds ['dumb ' ] || $ kinds ['smart ' ] ) {
243- $ kinds ['any ' ] = true ;
72+ if ( isset ( $ _SERVER ['HTTP_X_WAP_PROFILE ' ] ) ) {
73+ return true ;
74+ } elseif ( isset ( $ _SERVER ['HTTP_ACCEPT ' ] ) && ( preg_match ( '/wap\.|\.wap/i ' , $ _SERVER ['HTTP_ACCEPT ' ] ) || false !== strpos ( strtolower ( $ _SERVER ['HTTP_ACCEPT ' ] ), 'application/vnd.wap.xhtml+xml ' ) ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- This is doing the validating.
75+ return true ;
24476 }
24577
246- $ value = $ kinds [ $ kind ];
247-
248- if ( $ return_matched_agent ) {
249- $ value = $ matched_agent ;
250- }
251- return $ value ;
78+ return false ;
25279 }
25380}
0 commit comments