PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.3.2
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.3.2
1.3.2 1.3.1 1.3.0 1.2.4 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.2.0 All 28 releases
xspeed / includes / class-deep-link.php

class-deep-link.php in xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN 1.3.2, at includes/class-deep-link.php

113 lines 3.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Deep_Link — build the dashboard hash a notice or recommendation CTA
4 * points at (issue #49).
5 *
6 * The contract, shared with the React shell (src/components/deepLink.ts):
7 *
8 * #cache panel
9 * #health/pagespeed panel + tab
10 * #cache?focus=cache:cache_expiry panel + scroll/blink control
11 * #cache?focus=cache:cache_expiry&suggest=24 …and offer that value
12 *
13 * It exists so no caller hand-assembles the string. A CTA that links to a
14 * panel and leaves the user hunting for the setting it just described is
15 * the exact failure this replaces, and a typo'd hash fails silently —
16 * the panel opens, nothing focuses, and nobody notices for a release.
17 *
18 * Pure: no WordPress calls, so the format is unit-testable on its own.
19 *
20 * @package XSpeed
21 */
22
23 declare(strict_types=1);
24
25 namespace XSpeed;
26
27 defined( 'ABSPATH' ) || exit;
28
29 final class Deep_Link {
30
31 /**
32 * Build a dashboard hash.
33 *
34 * @param string $module Module slug — which panel opens.
35 * @param string|null $field Field key to focus, within $focus_module.
36 * @param mixed $suggest Recommended value, or null for none.
37 * @param string $subtab Tab within a host page.
38 * @param string|null $focus_module Module owning $field, when it isn't
39 * $module (a host page can render
40 * fields from several modules).
41 */
42 public static function hash( string $module, ?string $field = null, $suggest = null, string $subtab = '', ?string $focus_module = null ): string {
43 $module = trim( $module );
44 if ( '' === $module ) {
45 return '#';
46 }
47
48 $hash = '#' . $module;
49 if ( '' !== $subtab ) {
50 $hash .= '/' . $subtab;
51 }
52
53 $params = array();
54 if ( null !== $field && '' !== $field ) {
55 $params[] = 'focus=' . rawurlencode( ( $focus_module ?? $module ) . ':' . $field );
56 }
57 if ( null !== $suggest && '' !== $suggest ) {
58 $params[] = 'suggest=' . rawurlencode( self::stringify( $suggest ) );
59 }
60 if ( ! empty( $params ) ) {
61 $hash .= '?' . implode( '&', $params );
62 }
63
64 return $hash;
65 }
66
67 /**
68 * The action array a notice or recommendation carries to the UI.
69 *
70 * Structured rather than a pre-built hash so the React side owns the
71 * final string — one format, one builder per language, and no chance
72 * of a half-encoded hash arriving from PHP.
73 *
74 * @param mixed $suggest Recommended value, or null.
75 * @return array<string,string>
76 */
77 public static function action( string $label, string $module, ?string $field = null, $suggest = null, string $subtab = '', ?string $focus_module = null ): array {
78 $action = array(
79 'label' => $label,
80 'module' => $module,
81 );
82 if ( '' !== $subtab ) {
83 $action['subtab'] = $subtab;
84 }
85 if ( null !== $field && '' !== $field ) {
86 $action['focus'] = ( $focus_module ?? $module ) . ':' . $field;
87 }
88 if ( null !== $suggest && '' !== $suggest ) {
89 $action['suggest'] = self::stringify( $suggest );
90 }
91 return $action;
92 }
93
94 /**
95 * Render a value the way the link carries it.
96 *
97 * Booleans become 1/0 rather than PHP's "" for false — an empty string
98 * would be dropped as "no suggestion", turning "we recommend turning
99 * this off" into no recommendation at all.
100 *
101 * @param mixed $value Any scalar or list.
102 */
103 private static function stringify( $value ): string {
104 if ( is_bool( $value ) ) {
105 return $value ? '1' : '0';
106 }
107 if ( is_array( $value ) ) {
108 return implode( ',', array_map( 'strval', $value ) );
109 }
110 return (string) $value;
111 }
112 }
113