PluginProbe
Extendify / trunk
Extendify vtrunk
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
← All changes | app/Agent/Admin.php +103 -6 3.1.3 → trunk View file →
@@ -15,12 +15,14 @@
15 15 use Extendify\Shared\Services\Escaper;
16 16 use Extendify\Shared\Services\HttpClient;
17 17 use Extendify\Agent\TagBlocks;
18 18 use Extendify\Agent\TagTemplateParts;
19 +use Extendify\Agent\WooProductImages;
19 20 use Extendify\Agent\AbilitiesDiscovery;
20 21 use Extendify\Agent\Controllers\SiteNavigationController;
21 22 use Extendify\PartnerData;
22 23 use Extendify\Shared\DataProvider\ProductsData;
24 +use Extendify\SiteVisibility;
23 25
24 26 /**
25 27 * This class handles any file loading for the admin area.
26 28 */
@@ -43,12 +45,30 @@
43 45
44 46 // Add the site navigation ids to the navigation blocks
45 47 SiteNavigationController::init();
46 48
49 + Skeleton::init();
50 +
51 + WooProductImages::init();
52 +
47 53 \add_action('extendify_agent_suggestions_refresh', [$this, 'refreshSuggestions']);
48 54 }
49 55
50 56 /**
57 + * Where the agent panel mounts — docked-left only on the onboarding front end.
58 + *
59 + * @return string
60 + */
61 + public static function agentPosition()
62 + {
63 + $agentOnboarding = PartnerData::setting('useAgentOnboarding') ||
64 + Config::preview('agent-onboarding') ||
65 + constant('EXTENDIFY_DEVMODE');
66 +
67 + return $agentOnboarding && !is_admin() ? 'docked-left' : 'floating';
68 + }
69 +
70 + /**
51 71 * Adds various JS scripts and styles
52 72 *
53 73 * @return void
54 74 */
@@ -99,14 +119,13 @@
99 119 (bool) use_block_editor_for_post($this->getCurrentPostId()) :
100 120 false,
101 121 'isOnEditorOrFSE' => $this->isGutenbergOrFse(),
102 122 'activePlugins' => array_values(\get_option('active_plugins', [])),
103 - // Whether the user is using the vibes experience or not.
104 - 'isUsingVibes' => (bool) file_exists(EXTENDIFY_PATH . 'src/Launch/_data/block-style-variations.json') &&
105 - version_compare(wp_get_theme("extendable")->get('Version'), '2.0.32', '>='),
123 + 'isUsingVibes' => version_compare((string) wp_get_theme('extendable')->get('Version'), '2.0.32', '>='),
106 124 'siteTitle' => \esc_attr(\get_bloginfo('name')),
107 125 'siteDescription' => \esc_attr(\get_bloginfo('description')),
108 126 'themePresets' => $this->getThemePresets(),
127 + 'presetSlugs' => $this->getPresetSlugs(),
109 128 ];
110 129 $recommendations = ProductsData::get() ?? [];
111 130 $pluginRecommendations = array_filter($recommendations, function ($item) {
112 131 return in_array('ai-agent', $item['slots'] ?? [], true) && $item['ctaType'] === 'plugin';
@@ -121,8 +140,10 @@
121 140 }, $pluginRecommendations));
122 141 $agentContext = [
123 142 'availableAdminPages' => get_option('_transient_extendify_admin_pages_menu', []),
124 143 'pluginRecommendations' => $mappedPluginRecommendations,
144 + 'sitePublished' => SiteVisibility::isPublished(),
145 + 'comingSoonEnabled' => (bool) PartnerData::setting('useComingSoon'),
125 146 ];
126 147 $abilities = [
127 148 'canEditPost' => (bool) \current_user_can('edit_post', \get_queried_object_id()),
128 149 // TODO: this may be true for a user, while they still can't edit every post
@@ -145,13 +166,12 @@
145 166 Config::$slug . '-agent-scripts',
146 167 'window.extAgentData = ' . \wp_json_encode([
147 168 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
148 169 'startOnboarding' => isset($_GET['extendify-launch-success']) && $agentOnboarding,
149 - 'agentPosition' => $agentOnboarding && !is_admin() ? 'docked-left' : 'floating',
170 + 'agentPosition' => self::agentPosition(),
150 171 // Add context about where they are
151 172 'context' => $context,
152 - // Context that the Agent might need when returning a response,
153 - // but not for handling the workflow.
173 + // Material a workflow may want; each declares the keys it reads.
154 174 'agentContext' => $agentContext,
155 175 // List of abilities the AI can perform for this user.
156 176 // For example, we could check whether their theme has variations.
157 177 'abilities' => $abilities,
@@ -275,8 +295,85 @@
275 295 'fontSizes' => $fontSizes,
276 296 'fontFamilies' => $fontFamilies,
277 297 'colorPairs' => $colorPairs,
278 298 ];
299 + }
300 +
301 + /**
302 + * Preset slugs per design-token family across every origin. Feeds the Agent's
303 + * block-attribute schema so the model picks named tokens, not raw CSS.
304 + *
305 + * @return array<string,string[]>
306 + */
307 + private function getPresetSlugs()
308 + {
309 + if (!function_exists('wp_get_global_settings')) {
310 + return [];
311 + }
312 +
313 + $color = \wp_get_global_settings(['color']);
314 + $typography = \wp_get_global_settings(['typography']);
315 +
316 + return [
317 + 'color' => $this->originSlugs($color, 'palette', 'defaultPalette'),
318 + 'colorValues' => $this->originValues($color, 'palette', 'defaultPalette', 'color'),
319 + 'gradient' => $this->originSlugs($color, 'gradients', 'defaultGradients'),
320 + 'fontSize' => $this->originSlugs($typography, 'fontSizes', 'defaultFontSizes'),
321 + 'fontFamily' => $this->originSlugs($typography, 'fontFamilies', 'defaultFontFamilies'),
322 + ];
323 + }
324 +
325 + /**
326 + * Slug => value, so a colour written as its own hex finds the token naming it.
327 + *
328 + * @return array<string, string>
329 + */
330 + private function originValues($node, $listKey, $defaultKey, $valueKey)
331 + {
332 + $list = $node[$listKey] ?? [];
333 +
334 + $origins = ['custom', 'theme'];
335 + if (($node[$defaultKey] ?? true) !== false) {
336 + $origins[] = 'default';
337 + }
338 +
339 + $values = [];
340 + foreach ($origins as $origin) {
341 + foreach ($list[$origin] ?? [] as $item) {
342 + if (isset($item['slug'], $item[$valueKey])) {
343 + $values[(string) $item['slug']] = (string) $item[$valueKey];
344 + }
345 + }
346 + }
347 +
348 + return $values;
349 + }
350 +
351 + /**
352 + * Preset slugs from a settings node's origin buckets; drops the `default`
353 + * origin when the theme opted the family out.
354 + *
355 + * @return string[]
356 + */
357 + private function originSlugs($node, $listKey, $defaultKey)
358 + {
359 + $list = $node[$listKey] ?? [];
360 +
361 + $origins = ['custom', 'theme'];
362 + if (($node[$defaultKey] ?? true) !== false) {
363 + $origins[] = 'default';
364 + }
365 +
366 + $slugs = [];
367 + foreach ($origins as $origin) {
368 + foreach ($list[$origin] ?? [] as $item) {
369 + if (isset($item['slug'])) {
370 + $slugs[] = (string) $item['slug'];
371 + }
372 + }
373 + }
374 +
375 + return array_values(array_unique($slugs));
279 376 }
280 377
281 378 private static function extractColorSlug(string $value)
282 379 {