PluginProbe
Extendify / 3.2.1
Extendify v3.2.1
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.63.2.1 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 ]);