PluginProbe
CryptX / trunk
CryptX vtrunk
4.2.0 4.1.1 trunk 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.9 2.0 2.1 2.2 2.3 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 All 92 releases
cryptx / classes / Admin / SettingsPage.php

SettingsPage.php in CryptX trunk, at classes/Admin/SettingsPage.php

219 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace CryptX\Admin;
4
5 /**
6 * Registers the settings screen and loads the application that renders it.
7 *
8 * The PHP side is deliberately thin: a menu entry, one empty container and the
9 * built assets. Everything the screen knows about the options comes from
10 * SettingsSchema over the REST routes, so there is no second description of
11 * the settings hiding in a template.
12 *
13 * @package CryptX
14 * @since 4.1.0
15 */
16 final class SettingsPage
17 {
18 /**
19 * The slug the settings page is registered under.
20 *
21 * Public because the link in the plugin list has to point at the same
22 * place. That link used to be built from CRYPTX_BASEFOLDER, the directory
23 * name -- identical on wordpress.org, and wrong the moment someone renames
24 * the folder.
25 */
26 public const MENU_SLUG = 'cryptx';
27 private const SCRIPT_HANDLE = 'cryptx-settings';
28
29 private RestController $rest;
30
31 public function __construct()
32 {
33 $this->rest = new RestController();
34 }
35
36 /**
37 * Hooks the screen in.
38 *
39 * @return void
40 */
41 public function register(): void
42 {
43 $this->rest->register();
44
45 if (is_admin()) {
46 add_action('admin_menu', [$this, 'registerMenu']);
47 add_action('network_admin_menu', [$this, 'registerNetworkMenu']);
48 }
49 }
50
51 /**
52 * Adds the entry under Settings.
53 *
54 * @return void
55 */
56 public function registerMenu(): void
57 {
58 $hook = add_submenu_page(
59 'options-general.php',
60 _x('CryptX', 'CryptX settings page', 'cryptx'),
61 _x('CryptX', 'CryptX settings menu', 'cryptx'),
62 'manage_options',
63 self::MENU_SLUG,
64 [$this, 'render']
65 );
66
67 if ($hook) {
68 add_action('load-' . $hook, [$this, 'onLoad']);
69 }
70 }
71
72 /**
73 * Adds the network entry, for the defaults a new site starts with.
74 *
75 * Under the network's own Settings and behind manage_network_options: a
76 * site administrator configures their own site, a super administrator
77 * decides what the next site begins with. Two different questions, two
78 * different capabilities.
79 *
80 * @return void
81 */
82 public function registerNetworkMenu(): void
83 {
84 $hook = add_submenu_page(
85 'settings.php',
86 _x('CryptX', 'CryptX network defaults page', 'cryptx'),
87 _x('CryptX', 'CryptX network defaults menu', 'cryptx'),
88 'manage_network_options',
89 self::MENU_SLUG,
90 [$this, 'renderNetwork']
91 );
92
93 if ($hook) {
94 add_action('load-' . $hook, [$this, 'onLoad']);
95 }
96 }
97
98 /**
99 * Runs only when our own screen is being loaded.
100 *
101 * @return void
102 */
103 public function onLoad(): void
104 {
105 add_action('admin_enqueue_scripts', [$this, 'enqueueAssets']);
106 }
107
108 /**
109 * Loads the built application.
110 *
111 * @return void
112 */
113 public function enqueueAssets(): void
114 {
115 $assetFile = CRYPTX_DIR_PATH . 'build/index.asset.php';
116
117 if (!is_readable($assetFile)) {
118 add_action('admin_notices', [$this, 'renderMissingBuildNotice']);
119
120 return;
121 }
122
123 $asset = require $assetFile;
124
125 wp_enqueue_script(
126 self::SCRIPT_HANDLE,
127 CRYPTX_DIR_URL . 'build/index.js',
128 $asset['dependencies'] ?? [],
129 $asset['version'] ?? CRYPTX_VERSION,
130 true
131 );
132
133 wp_set_script_translations(self::SCRIPT_HANDLE, 'cryptx');
134
135 $style = CRYPTX_DIR_PATH . 'build/index.css';
136 if (is_readable($style)) {
137 wp_enqueue_style(
138 self::SCRIPT_HANDLE,
139 CRYPTX_DIR_URL . 'build/index.css',
140 ['wp-components'],
141 $asset['version'] ?? CRYPTX_VERSION
142 );
143 }
144
145 // The media library picker for the "image from the media library"
146 // option needs the classic media modal to be present.
147 //
148 // Not in the network backend: the one field that needs it is left out
149 // of the network defaults on purpose -- an attachment id means nothing
150 // on another site -- and there is no media library there to pick from
151 // either.
152 if (!is_network_admin()) {
153 wp_enqueue_media();
154 }
155 }
156
157 /**
158 * Shown when the plugin was installed without its built assets.
159 *
160 * @return void
161 */
162 public function renderMissingBuildNotice(): void
163 {
164 echo '<div class="notice notice-error"><p>';
165 echo esc_html__('CryptX: the settings screen could not be loaded because its built assets are missing. If you installed CryptX from a source checkout, run "npm install && npm run build" in the plugin directory.', 'cryptx');
166 echo '</p></div>';
167 }
168
169 /**
170 * The container the application mounts into.
171 *
172 * @return void
173 */
174 public function render(): void
175 {
176 if (!current_user_can('manage_options')) {
177 wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'cryptx'));
178 }
179
180 $this->renderRoot('site', __('Loading the settings…', 'cryptx'));
181 }
182
183 /**
184 * The same application, told that it is editing the network defaults.
185 *
186 * @return void
187 */
188 public function renderNetwork(): void
189 {
190 if (!current_user_can('manage_network_options')) {
191 wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'cryptx'));
192 }
193
194 $this->renderRoot('network', __('Loading the network defaults…', 'cryptx'));
195 }
196
197 /**
198 * The container the application mounts into.
199 *
200 * @param string $scope Either 'site' or 'network'.
201 * @param string $loading What to show until the application takes over.
202 *
203 * @return void
204 */
205 private function renderRoot(string $scope, string $loading): void
206 {
207 printf(
208 '<div class="wrap cryptx-settings-root" id="cryptx-settings-root" data-cryptx-scope="%s">',
209 esc_attr($scope)
210 );
211
212 // Shown until the application takes over, and the only thing left if
213 // JavaScript is unavailable.
214 echo '<h1>' . esc_html__('CryptX', 'cryptx') . '</h1>';
215 echo '<p>' . esc_html($loading) . '</p>';
216 echo '</div>';
217 }
218 }
219