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/Shared/Admin.php +102 -3 3.0.4 → trunk View file →
@@ -9,14 +9,21 @@
9 9 defined('ABSPATH') || die('No direct access.');
10 10
11 11 use Extendify\Config;
12 12 use Extendify\PartnerData;
13 +use Extendify\Notifications\Availability;
13 14 use Extendify\Shared\Controllers\UserSelectionController;
15 +use Extendify\Shared\DataProvider\NotificationData;
14 16 use Extendify\Shared\DataProvider\ResourceData;
15 17 use Extendify\Shared\Services\AdminMenuList;
16 18 use Extendify\Shared\Services\ApexDomain\ApexDomain;
17 19 use Extendify\Shared\Services\Escaper;
18 20 use Extendify\Shared\Services\PluginDependencies\SimplyBook;
21 +use Extendify\Shared\Services\PluginsActivation\Imagify as ImagifyActivation;
22 +use Extendify\Shared\Services\PluginsActivation\Metricool as MetricoolActivation;
23 +use Extendify\Shared\Services\PluginsActivation\SimplyBook as SimplyBookActivation;
24 +use Extendify\Shared\Services\PluginsActivation\TranslatePress as TranslatePressActivation;
25 +use Extendify\Shared\Services\SiteImages;
19 26 use Extendify\SiteSettings;
20 27 use Extendify\Shared\Controllers\ImageGenerationController;
21 28 use Extendify\Shared\DataProvider\ProductsData;
22 29
@@ -140,8 +147,67 @@
140 147 if (!function_exists('get_plugins')) {
141 148 require_once ABSPATH . 'wp-admin/includes/plugin.php';
142 149 }
143 150
151 + $activePlugins = array_values(\get_option('active_plugins', []));
152 + $activePluginSlugs = array_map(function ($plugin) {
153 + return dirname($plugin);
154 + }, $activePlugins);
155 + $productActivationPlugins = PartnerData::setting('showProductActivation') ?? [];
156 +
157 + $productActivationPlugins = array_filter(
158 + $productActivationPlugins,
159 + function ($plugin) use ($activePluginSlugs) {
160 + return in_array($plugin['slug'], $activePluginSlugs);
161 + }
162 + );
163 +
164 + $activations = [
165 + ImagifyActivation::class,
166 + MetricoolActivation::class,
167 + SimplyBookActivation::class,
168 + TranslatePressActivation::class,
169 + ];
170 +
171 + $productActivationPlugins = array_map(function ($plugin) use ($activations) {
172 + foreach ($activations as $activation) {
173 + if ($plugin['slug'] === $activation::slug()) {
174 + return array_merge($plugin, [
175 + 'scriptData' => $activation::scriptData(),
176 + 'eligible' => $activation::isEligible(),
177 + 'endpoint' => Config::$slug . '/' . Config::$apiVersion
178 + . $activation::createAccountRoute(),
179 + ]);
180 + }
181 + }
182 +
183 + return $plugin;
184 + }, $productActivationPlugins);
185 +
186 + // Visitors read the stamp and the alt text, so both resolve in the site's locale.
187 + $switchedLocale = \switch_to_locale(\get_locale());
188 + // translators: Short label stamped onto an image marking it as AI-generated.
189 + // Give the all-caps form your language uses.
190 + $aiImageLabel = \_x('AI GENERATED', 'uppercase', 'extendify-local');
191 + // translators: %s is the image description. Alt text prefix marking an image as AI-generated.
192 + $aiImageAltPattern = \__('AI Generated: %s', 'extendify-local');
193 + if ($switchedLocale) {
194 + \restore_previous_locale();
195 + }
196 +
197 + $extendifyCodeData = (array) PartnerData::setting('extendifyCodeData');
198 +
199 + // esc_url() strips the {DESCRIPTION} braces; shield the placeholder across it.
200 + $extendifyCodeLink = str_replace(
201 + '__EXTENDIFY_DESCRIPTION__',
202 + '{DESCRIPTION}',
203 + \esc_url_raw(str_replace(
204 + '{DESCRIPTION}',
205 + '__EXTENDIFY_DESCRIPTION__',
206 + (string) ($extendifyCodeData['link'] ?? '')
207 + ))
208 + );
209 +
144 210 \wp_add_inline_script(
145 211 Config::$slug . '-shared-scripts',
146 212 'window.extSharedData = ' . \wp_json_encode([
147 213 'root' => \esc_url_raw(rest_url(Config::$slug . '/' . Config::$apiVersion)),
@@ -155,17 +221,33 @@
155 221 'themeSlug' => \esc_attr(\get_option('stylesheet')),
156 222 'version' => \esc_attr(Config::$version),
157 223 'siteTitle' => \esc_attr(\get_bloginfo('name')),
158 224 'siteProfile' => \get_option('extendify_site_profile', []),
225 + // Empty when the launch-time image fetch failed.
226 + 'siteImages' => SiteImages::normalize(\get_option('extendify_site_images', [])),
159 227 'wpLanguage' => \esc_attr(\get_locale()),
228 + 'aiImageLabel' => $aiImageLabel,
229 + 'aiImageAltPattern' => $aiImageAltPattern,
160 230 'wpVersion' => \esc_attr(\get_bloginfo('version')),
161 231 'isBlockTheme' => function_exists('wp_is_block_theme') ? (bool) wp_is_block_theme() : false,
162 232 'userId' => \esc_attr(\get_current_user_id()),
233 + // phpcs:ignore WordPress.Security.NonceVerification
234 + 'userEmail' => isset($_GET['extendify-launch-success'])
235 + ? \esc_attr(\wp_get_current_user()->user_email)
236 + : null,
163 237 'partnerLogo' => \esc_attr(PartnerData::$logo),
164 238 'partnerId' => \esc_attr(PartnerData::$id),
165 239 'partnerName' => \esc_attr(PartnerData::$name),
166 240 'launchDataLegacy' => \wp_json_encode((UserSelectionController::get()->get_data() ?? [])),
167 241 'resourceData' => \wp_json_encode((new ResourceData())->getData()),
242 + 'notifications' => \wp_json_encode(
243 + Availability::available(NotificationData::get())
244 + ),
245 + 'notificationState' => \get_user_meta(
246 + \get_current_user_id(),
247 + 'extendify_notification_state',
248 + true
249 + ) ?: ['cards' => []],
168 250 'showAIConsent' => isset($partnerData['showAIConsent']) ? (bool) $partnerData['showAIConsent'] : false,
169 251 'showChat' => (bool) (PartnerData::setting('showChat') || constant('EXTENDIFY_DEVMODE')),
170 252 'useAgentOnboarding' => (bool) (
171 253 PartnerData::setting('useAgentOnboarding') ||
@@ -176,16 +258,19 @@
176 258 PartnerData::setting('showAIPageCreation') || constant('EXTENDIFY_DEVMODE')
177 259 ),
178 260 'showAILogo' => (bool) PartnerData::setting('showAILogo'),
179 261 'showImprint' => array_map('esc_attr', (array) PartnerData::setting('showImprint')),
180 - 'consentTermsCustom' => \wp_kses((html_entity_decode(($partnerData['consentTermsCustom'] ?? ''))
181 - ?? ''), $htmlAllowlist),
262 + 'showProductActivation' => array_values($productActivationPlugins),
263 + 'consentTermsCustom' => \wp_kses((html_entity_decode(
264 + ($partnerData['consentTermsCustom'] ?? ''),
265 + ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401
266 + ) ?? ''), $htmlAllowlist),
182 267 'userGaveConsent' => $userConsent ? (bool) $userConsent : false,
183 268 'installedPlugins' => array_map('esc_attr', array_keys(\get_plugins())),
269 + 'activePlugins' => $activePlugins,
184 270 'installedPluginsSlugs' => array_values(array_filter(array_map(function ($p) {
185 271 return $p['TextDomain'] ?? '';
186 272 }, \get_plugins()))),
187 - 'activePlugins' => array_map('esc_attr', array_values(\get_option('active_plugins', []))),
188 273 'frontPage' => \esc_attr(\get_option('page_on_front', 0)),
189 274 'globalStylesPostID' => \esc_attr(\WP_Theme_JSON_Resolver::get_user_global_styles_post_id()),
190 275 'showLocalizedCopy' => (bool) array_key_exists('showLocalizedCopy', $partnerData),
191 276 'activity' => \wp_json_encode(\get_option('extendify_shared_activity', null)),
@@ -200,8 +285,15 @@
200 285 PartnerData::setting('showLaunchQuestions') || Config::preview('launch-questions')
201 286 ),
202 287 'products' => ProductsData::get(),
203 288 'showAIAgents' => (bool) (PartnerData::setting('showAIAgents') || Config::preview('ai-agent')),
289 + 'showExtendifyCode' => (bool) PartnerData::setting('showExtendifyCode'),
290 + 'extendifyCodeData' => [
291 + 'link' => $extendifyCodeLink,
292 + 'title' => $extendifyCodeData['title'] ?? '',
293 + 'message' => $extendifyCodeData['message'] ?? '',
294 + 'ctaPrimary' => $extendifyCodeData['cta-primary'] ?? '',
295 + ],
204 296 'pluginGroupId' => Escaper::recursiveEscAttr(PartnerData::setting('pluginGroupId')),
205 297 'adminPagesMenuList' => get_option('_transient_extendify_admin_pages_menu', []),
206 298 'globalState' => ImageGenerationController::get()->get_data(),
207 299 ]),
@@ -245,8 +337,15 @@
245 337 'type' => 'boolean',
246 338 'show_in_rest' => true,
247 339 ]);
248 340 register_post_meta('post', 'made_with_extendify_launch', [
341 + 'single' => true,
342 + 'type' => 'boolean',
343 + 'show_in_rest' => true,
344 + ]);
345 +
346 + // Marks AI-generated images for EU AI Act disclosure.
347 + register_post_meta('attachment', 'extendify_ai_generated', [
249 348 'single' => true,
250 349 'type' => 'boolean',
251 350 'show_in_rest' => true,
252 351 ]);