PluginProbe
Extendify / 3.0.4
Extendify v3.0.4
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 / AdminPageRouter.php

AdminPageRouter.php in Extendify 3.0.4, at app/AdminPageRouter.php

305 lines 12.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Simple router to handle admin page loading
5 */
6
7 namespace Extendify;
8
9 defined('ABSPATH') || die('No direct access.');
10
11 use Extendify\Assist\AdminPage as AssistAdminPage;
12 use Extendify\Launch\AdminPage as LaunchAdminPage;
13 use Extendify\AutoLaunch\AdminPage as AutoLaunchAdminPage;
14
15 /**
16 * This class handles routing when the main admin button is pressed.
17 * This used to be more robust but now just routes to Assist. And
18 * possibly loads Launch depending on the state.
19 */
20
21 class AdminPageRouter
22 {
23 /**
24 * Adds various actions to set up the page
25 *
26 * @return void
27 */
28 public function __construct()
29 {
30 // This does the initial redirect to Launch.
31 \add_action('admin_init', [$this, 'redirectOnce'], 10);
32 \add_action('admin_init', [$this, 'maybeForceFlush'], 5);
33
34 // Add a dropdown above Dashboard in the admin toolbar.
35 \add_action('admin_bar_menu', function ($wpAdminBar) {
36 if (!PartnerData::$id || is_admin()) {
37 return;
38 }
39
40 $wpAdminBar->add_node([
41 'id' => 'extendify-site-assistant',
42 'title' => \__('Site Assistant', 'extendify-local'),
43 'href' => \admin_url() . $this->getRoute(),
44 'parent' => 'site-name',
45 'meta' => ['position' => 1],
46 ]);
47 }, 11);
48
49 // When Launch is finished, fire this to set the correct permalinks.
50 // phpcs:ignore WordPress.Security.NonceVerification
51 if (isset($_GET['extendify-launch-success'])) {
52 \add_action('admin_init', function () {
53 \flush_rewrite_rules();
54 });
55 }
56
57 \add_action('admin_menu', function () {
58 // If no partner, we don't show any menu.
59 if (!PartnerData::$id) {
60 return;
61 }
62
63 $assist = new AssistAdminPage();
64 // Adds the top Assist menu.
65 $this->addAdminMenu(
66 __('Site Assistant', 'extendify-local'),
67 $assist->slug,
68 [$assist, 'pageContent']
69 );
70
71 if (!Config::$showLaunch) {
72 return;
73 }
74
75 $launch = new LaunchAdminPage();
76 $this->addSubMenu(
77 // translators: Launch is a noun.
78 __('Launch', 'extendify-local'),
79 $launch->slug,
80 [$launch, 'pageContent']
81 );
82 $autoLaunch = new AutoLaunchAdminPage();
83 $this->addSubMenu(
84 // translators: Launch is a noun.
85 __('Auto Launch', 'extendify-local'),
86 $autoLaunch->slug,
87 [$autoLaunch, 'pageContent']
88 );
89 });
90
91 // If the user is redirected to this while visiting our url, intercept it.
92 \add_filter('wp_redirect', function ($url) {
93 if (!PartnerData::$id) {
94 return $url;
95 }
96
97 // Check for extendify-launch-success as other plugins will not override
98 // this as they intercept the request.
99 // phpcs:ignore WordPress.Security.NonceVerification
100 if (isset($_GET['extendify-launch-success'])) {
101 return \admin_url() . $this->getRoute();
102 }
103
104 // Special treatment for Yoast to disable their redirect when installing.
105 if ($url === \admin_url() . 'admin.php?page=wpseo_installation_successful_free') {
106 return \admin_url() . $this->getRoute();
107 }
108
109 // Special treatment for Germanized for WooCommerce to disable their redirect when installing.
110 if ($url === \admin_url() . 'admin.php?page=wc-gzd-setup') {
111 return \admin_url() . $this->getRoute();
112 }
113
114 return $url;
115 }, 9999);
116 }
117
118 /**
119 * A helper for handling sub menus
120 *
121 * @param string $name - The menu name.
122 * @param string $slug - The menu slug.
123 * @param callable $callback - The callback to render the page.
124 *
125 * @return void
126 */
127 public function addSubMenu($name, $slug, $callback = '')
128 {
129 \add_submenu_page(
130 // Uses a "dummy" page for adding pages without a menu.
131 (constant('EXTENDIFY_DEVMODE') ? 'extendify-assist' : 'extendify-page'),
132 $name,
133 $name,
134 Config::$requiredCapability,
135 $slug,
136 $callback
137 );
138 }
139
140 /**
141 * Adds Extendify top menu
142 *
143 * @param string $label - The menu label.
144 * @param string $slug - The menu slug.
145 * @param string|callable $callback - The callback to render the page.
146 * @return void
147 */
148 public function addAdminMenu($label, $slug, $callback)
149 {
150 $menuLabel = sprintf(
151 '%1$s <span class="extendify-assist-badge-count" data-test="assist-badge-count"></span>',
152 $label
153 );
154
155 \add_menu_page(
156 'Extendify',
157 $menuLabel,
158 Config::$requiredCapability,
159 $slug,
160 $callback,
161 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode, Generic.Files.LineLength.TooLong
162 'data:image/svg+xml;base64,' . base64_encode('<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M17.773,9.373L16.679,10.467L10,3.788L3.321,10.467L2.227,9.373L10,1.6L14.129,5.729L14.129,3.665L16.194,3.665L16.194,7.794L17.773,9.373ZM16.194,11.437L16.194,17.6L3.806,17.6L3.806,11.437L10,5.254L16.194,11.437ZM13.297,11.525C13.394,11.437 13.432,11.301 13.387,11.178L13.388,11.176C13.326,11.008 13.251,10.847 13.165,10.692L13.099,10.578C13.006,10.423 12.901,10.276 12.787,10.138C12.704,10.037 12.566,10.002 12.441,10.042L11.881,10.219C11.74,10.263 11.586,10.235 11.462,10.155C11.393,10.111 11.322,10.07 11.249,10.032C11.116,9.964 11.015,9.845 10.984,9.702L10.858,9.127C10.83,8.999 10.731,8.897 10.601,8.876C10.406,8.843 10.206,8.827 10.001,8.827C9.797,8.827 9.596,8.843 9.402,8.877C9.272,8.899 9.173,9 9.145,9.129L9.019,9.703C8.987,9.847 8.885,9.966 8.754,10.033C8.68,10.07 8.61,10.112 8.541,10.156C8.415,10.236 8.263,10.266 8.121,10.221L7.561,10.043C7.437,10.004 7.299,10.037 7.215,10.139C7.101,10.277 6.997,10.424 6.904,10.579L6.837,10.694C6.751,10.849 6.676,11.01 6.614,11.178C6.569,11.301 6.607,11.437 6.705,11.525L7.141,11.923C7.251,12.022 7.302,12.168 7.294,12.317C7.293,12.358 7.292,12.399 7.292,12.441C7.292,12.483 7.293,12.524 7.294,12.565C7.302,12.712 7.249,12.859 7.141,12.959L6.705,13.355C6.607,13.443 6.569,13.58 6.614,13.703C6.676,13.871 6.751,14.031 6.837,14.187L6.904,14.301C6.997,14.456 7.101,14.603 7.215,14.741C7.299,14.841 7.437,14.877 7.561,14.837L8.12,14.658C8.261,14.613 8.415,14.642 8.539,14.723C8.608,14.767 8.679,14.808 8.752,14.846C8.884,14.913 8.987,15.032 9.018,15.176L9.143,15.75C9.171,15.879 9.27,15.98 9.4,16.002C9.595,16.034 9.795,16.051 10,16.051C10.205,16.051 10.405,16.034 10.6,16.002C10.729,15.98 10.828,15.879 10.857,15.75L10.982,15.176C11.015,15.032 11.116,14.913 11.247,14.846C11.321,14.809 11.391,14.767 11.461,14.723C11.586,14.642 11.739,14.613 11.88,14.658L12.44,14.836C12.564,14.875 12.703,14.841 12.786,14.74C12.9,14.602 13.005,14.455 13.098,14.3L13.164,14.185C13.25,14.03 13.325,13.869 13.387,13.701C13.432,13.578 13.394,13.441 13.297,13.354L12.861,12.957C12.751,12.859 12.7,12.712 12.707,12.564C12.708,12.523 12.71,12.482 12.71,12.439C12.71,12.397 12.708,12.356 12.707,12.315C12.7,12.168 12.752,12.022 12.861,11.922L13.297,11.525ZM10.8,13.238C10.588,13.449 10.301,13.569 10.001,13.569C9.702,13.569 9.415,13.449 9.203,13.238C8.991,13.026 8.872,12.739 8.872,12.439C8.872,12.14 8.991,11.853 9.203,11.641C9.415,11.429 9.702,11.31 10.001,11.31C10.301,11.31 10.588,11.429 10.8,11.641C11.011,11.853 11.13,12.14 11.13,12.439C11.13,12.739 11.011,13.026 10.8,13.238Z" style="fill:#a7aaad;" fill="currentColor" /></svg>'),
163 PartnerData::$id ? 0 : null
164 );
165 }
166
167 /**
168 * Routes pages accordingly
169 *
170 * @return string
171 */
172 public function getRoute()
173 {
174 // This router use to handle more cases but now everyone goes to Assist.
175 return 'admin.php?page=extendify-assist';
176 }
177
178 /**
179 * Redirect once to Launch, only once (at least once) when
180 * the email matches the entry in WP Admin > Settings > General.
181 *
182 * @return void
183 */
184 public function redirectOnce()
185 {
186 if (wp_doing_ajax()) {
187 return;
188 }
189
190 if (defined('EXTENDIFY_IS_THEME_EXTENDABLE') && !EXTENDIFY_IS_THEME_EXTENDABLE) {
191 return;
192 }
193
194 if (\get_option('extendify_launch_loaded', false) || !Config::$showLaunch) {
195 return;
196 }
197
198 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
199 if (isset($_GET['page']) && $_GET['page'] === 'extendify-auto-launch') {
200 return;
201 }
202
203 // Only redirect if we aren't already on the page.
204 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
205 if (isset($_GET['page']) && $_GET['page'] === 'extendify-launch') {
206 $agentOnboarding = PartnerData::setting('useAgentOnboarding') ||
207 Config::preview('agent-onboarding') ||
208 constant('EXTENDIFY_DEVMODE');
209 if ($agentOnboarding) {
210 // If they landed on launch but have the Agent onboarding enabled, redirect to auto-launch.
211 $redirect_url = \add_query_arg(
212 ['page' => 'extendify-auto-launch'],
213 \admin_url('admin.php')
214 );
215 \wp_safe_redirect($redirect_url);
216 exit;
217 }
218 return;
219 }
220
221 $user = \wp_get_current_user();
222 if (
223 $user
224 // Check the main admin email, and they have an admin role.
225 && \get_option('admin_email') === $user->user_email
226 && in_array('administrator', $user->roles, true)
227 ) {
228 // Only redirect 3 times.
229 $currentCount = \get_option('extendify_attempted_redirect_count', 0);
230 if ($currentCount >= 3) {
231 return;
232 }
233
234 \update_option('extendify_attempted_redirect_count', ($currentCount + 1));
235 \update_option('extendify_attempted_redirect', gmdate('Y-m-d H:i:s'));
236
237 // Update permalink structure to postname when auto-redirecting to Launch
238 \update_option('permalink_structure', '/%postname%/');
239 \update_option('extendify_needs_rewrite_flush', true);
240
241 $allowed_launch_params = [
242 'objective',
243 'title',
244 'description',
245 'structure',
246 'tone',
247 'skip',
248 // new for autolaunch (some duplicated)
249 'type',
250 'title',
251 'description',
252 'objective',
253 'category',
254 'structure',
255 'tone',
256 'products',
257 'appointments',
258 'events',
259 'donations',
260 'multilingual',
261 'contact',
262 'address',
263 'blog',
264 'landing-page',
265 'cta-link',
266 'build-id',
267 'go',
268 ];
269 // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash
270 $autoLaunch = isset($_GET['auto-launch']) && filter_var($_GET['auto-launch'], FILTER_VALIDATE_BOOLEAN);
271 $query_params = ['page' => $autoLaunch ? 'extendify-auto-launch' : 'extendify-launch'];
272
273 foreach ($allowed_launch_params as $param) {
274 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
275 $value = sanitize_text_field(wp_unslash($_GET[$param] ?? ''));
276 if (!empty($value)) {
277 $query_params[$param] = $value;
278 }
279 }
280
281 $redirect_url = \add_query_arg($query_params, \admin_url('admin.php'));
282 \wp_safe_redirect($redirect_url);
283 exit;
284 }
285 }
286
287 /**
288 * Flushes WordPress rewrite rules if previously scheduled by `redirectOnce()`.
289 *
290 * This is triggered based on a flag (`extendify_needs_rewrite_flush`) that is set
291 * when the permalink structure is modified. Flushing rewrite rules in the same
292 * request where the permalink structure is updated can be ineffective due to
293 * internal WordPress caching, so the flush is deferred to a subsequent request.
294 *
295 * @return void
296 */
297 public function maybeForceFlush()
298 {
299 if (\get_option('extendify_needs_rewrite_flush', false)) {
300 \flush_rewrite_rules(true);
301 \delete_option('extendify_needs_rewrite_flush');
302 }
303 }
304 }
305