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
extendify / app / AutoLaunch / Admin.php

Admin.php in Extendify 3.2.1, at app/AutoLaunch/Admin.php

276 lines 8.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Admin.
5 */
6
7 namespace Extendify\AutoLaunch;
8
9 defined('ABSPATH') || die('No direct access.');
10
11 use Extendify\Config;
12 use Extendify\Insights;
13 use Extendify\PartnerData;
14 use Extendify\Shared\Services\LaunchUpdate\LaunchUpdater;
15
16 /**
17 * This class handles any file loading for the admin area.
18 */
19
20 class Admin
21 {
22 /**
23 * Adds various actions to set up the page
24 *
25 * @return void
26 */
27 public function __construct()
28 {
29 \add_action('admin_enqueue_scripts', [$this, 'addScopedScriptsAndStyles']);
30 }
31
32 /**
33 * Adds various JS scripts
34 *
35 * @return void
36 */
37 public function addScopedScriptsAndStyles()
38 {
39 $version = constant('EXTENDIFY_DEVMODE') ? uniqid() : Config::$version;
40 $scriptAssetPath = EXTENDIFY_PATH . 'public/build/' . Config::$assetManifest['extendify-launch.php'];
41 $fallback = [
42 'dependencies' => [],
43 'version' => $version,
44 ];
45 $scriptAsset = file_exists($scriptAssetPath) ? require $scriptAssetPath : $fallback;
46 foreach ($scriptAsset['dependencies'] as $style) {
47 wp_enqueue_style($style);
48 }
49
50 \wp_enqueue_script(
51 Config::$slug . '-launch-scripts',
52 EXTENDIFY_BASE_URL . 'public/build/' . Config::$assetManifest['extendify-auto-launch.js'],
53 array_merge([Config::$slug . '-shared-scripts'], $scriptAsset['dependencies']),
54 $scriptAsset['version'],
55 true
56 );
57
58 if (constant('EXTENDIFY_DEVMODE')) {
59 // In dev, reset the variaton to the default.
60 wp_update_post([
61 'ID' => \WP_Theme_JSON_Resolver::get_user_global_styles_post_id(),
62 'post_content' => \wp_json_encode([
63 'styles' => [],
64 'settings' => [],
65 'isGlobalStylesUserThemeJSON' => true,
66 'version' => 2,
67 ]),
68 ]);
69 }
70
71 $showLaunchUpdate = PartnerData::setting('showLaunchUpdate');
72 $launchUpdate = $showLaunchUpdate ? LaunchUpdater::claimPendingUpdates() : [];
73 \wp_add_inline_script(
74 Config::$slug . '-launch-scripts',
75 'window.extLaunchData = ' . \wp_json_encode([
76 'editorStyles' => \get_block_editor_settings([], new \WP_Block_Editor_Context()),
77 'wpRoot' => \rest_url(),
78 'activeTests' => \get_option(Insights::ACTIVE_TESTS_OPTION, []),
79 'showLaunchTitle' => (bool) PartnerData::setting('showLaunchTitle'),
80 'customDesign' => PartnerData::setting('customDesign'),
81 'partnerStrings' => PartnerData::setting('strings'),
82 'resetSiteInformation' => [
83 'pagesIds' => array_map('esc_attr', $this->getLaunchCreatedPages()),
84 'navigationsIds' => array_map('esc_attr', $this->getLaunchCreatedNavigations()),
85 'templatePartsIds' => array_map('esc_attr', $this->getTemplatePartIds()),
86 'pageWithTitleTemplateId' => esc_attr($this->getPageWithTitleTemplateId()),
87 ],
88 'urlParams' => (object) $this->getURLParams(),
89 'helloWorldPostSlug' =>
90 // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
91 \_x(
92 'hello-world',
93 'Default post slug'
94 ),
95 'hideAutoLaunchExitLink' => (bool) PartnerData::setting('hideLaunchExitLink'),
96 'themeUpdateNeeded' => !empty($launchUpdate['theme']),
97 'pluginUpdateNeeded' => !empty($launchUpdate['plugin']),
98 'launchUpdateAttempt' => $launchUpdate['attempt'] ?? 0,
99 'launchUpdateStale' => (object) ($launchUpdate['stale'] ?? []),
100 'pluginUpdateViaRest' => LaunchUpdater::isWpOrgBuild(),
101 'pluginSlug' => Config::$slug,
102 ]),
103 'before'
104 );
105
106 \wp_set_script_translations(
107 Config::$slug . '-launch-scripts',
108 'extendify-local',
109 EXTENDIFY_PATH . 'languages/js'
110 );
111
112 \wp_enqueue_style(
113 Config::$slug . '-launch-styles',
114 EXTENDIFY_BASE_URL . 'public/build/' . Config::$assetManifest['extendify-auto-launch.css'],
115 [Config::$slug . '-shared-common-styles'],
116 Config::$version
117 );
118 }
119
120 /**
121 * Returns all the pages created by Extendify.
122 *
123 * @return array
124 */
125 public static function getLaunchCreatedPages()
126 {
127 $posts = get_posts([
128 'numberposts' => -1,
129 'post_status' => 'publish',
130 'post_type' => ['page', 'post'],
131 // only return the ID field.
132 'fields' => 'ids',
133 ]);
134
135 return array_values(array_filter(array_map(function ($post) {
136 return get_post_meta($post, 'made_with_extendify_launch') ? $post : false;
137 }, $posts)));
138 }
139
140 /**
141 * Returns all the navigations created by Extendify.
142 *
143 * @return array
144 */
145 public static function getLaunchCreatedNavigations()
146 {
147 $posts = get_posts([
148 'numberposts' => -1,
149 'post_status' => 'publish',
150 'post_type' => 'wp_navigation',
151 // only return the ID field.
152 'fields' => 'ids',
153 ]);
154
155 return array_values(array_filter(array_map(function ($post) {
156 return get_post_meta($post, 'made_with_extendify_launch') ? $post : false;
157 }, $posts)));
158 }
159
160 /**
161 * Returns the idz of the header and footer template part created by extendify.
162 *
163 * @return array
164 */
165 public static function getTemplatePartIds()
166 {
167 return [
168 (get_block_template(get_stylesheet() . '//header', 'wp_template_part')->id ?? ''),
169 (get_block_template(get_stylesheet() . '//footer', 'wp_template_part')->id ?? ''),
170 ];
171 }
172
173
174 /**
175 * Returns the id of the page-with-title template for the current theme.
176 *
177 * @return string
178 */
179 public static function getPageWithTitleTemplateId()
180 {
181 $template = get_block_template(get_stylesheet() . '//page-with-title', 'wp_template');
182 return $template && !empty($template->id) ? $template->id : '';
183 }
184
185 /**
186 * Parses and sanitizes URL parameters against an allowlist.
187 *
188 * @return array
189 */
190 private function getURLParams()
191 {
192 $allowed = [
193 'type' => 'string',
194 'title' => 'string',
195 'description' => 'string',
196 'objective' => 'string',
197 'category' => 'string',
198 'structure' => 'string',
199 'tone' => 'string[]',
200 'products' => 'string|boolean',
201 'appointments' => 'boolean',
202 'events' => 'boolean',
203 'donations' => 'boolean',
204 'multilingual' => 'boolean',
205 'contact' => 'boolean',
206 'address' => 'string|boolean',
207 'blog' => 'boolean',
208 'landing-page' => 'string',
209 'cta-link' => 'string|boolean',
210 'build-id' => 'string',
211 'go' => 'boolean',
212 ];
213
214 $params = [];
215 foreach ($allowed as $param => $type) {
216 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
217 if (!isset($_GET[$param])) {
218 continue;
219 }
220
221 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
222 $raw = sanitize_text_field(wp_unslash($_GET[$param]));
223 if ($raw === '') {
224 continue;
225 }
226
227 if ($type === 'string[]') {
228 $parts = is_array($raw) ? $raw : explode(',', (string) $raw);
229
230 $items = array_values(array_filter(
231 array_map(
232 static function ($v) {
233 return sanitize_text_field((string) $v);
234 },
235 $parts
236 ),
237 static function ($v) {
238 return $v !== '';
239 }
240 ));
241
242 if (empty($items)) {
243 continue;
244 }
245
246 $params[$param] = $items;
247 continue;
248 }
249
250 if (strtolower($raw) === 'none') {
251 $params[$param] = false;
252 continue;
253 }
254
255 $asBool = filter_var($raw, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
256
257 if ($type === 'boolean') {
258 if ($asBool === null) {
259 continue;
260 }
261 $params[$param] = $asBool;
262 continue;
263 }
264
265 if ($type === 'string|boolean' && $asBool !== null) {
266 $params[$param] = $asBool;
267 continue;
268 }
269
270 $params[$param] = $raw;
271 }
272
273 return $params;
274 }
275 }
276