PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 3.33
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v3.33
3.36 3.35 3.34 3.33 2.19 2.20 2.21 2.22 2.23 2.24 2.25 2.26 2.27 2.28 2.29 2.30 2.31 2.32 2.33 2.34 2.40 2.41 2.42 2.43 2.44 All 141 releases
photonic / Admin / Admin.php

Admin.php in Photonic Gallery & Lightbox for Flickr, SmugMug & Others 3.33, at Admin/Admin.php

417 lines 16.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Photonic_Plugin\Admin;
4
5 use Photonic_Plugin\Admin\Wizard\Wizard;
6 use Photonic_Plugin\Core\Photonic;
7 use Photonic_Plugin\Platforms\SmugMug;
8
9 class Admin {
10 public function __construct() {
11 global $photonic_disable_flow_editor_global;
12
13 // General
14 add_action('admin_head', [$this, 'admin_head']);
15 add_action('admin_enqueue_scripts', [&$this, 'add_admin_scripts']);
16
17 // Vanilla Editor
18 add_filter('media_upload_tabs', [&$this, 'media_upload_tabs']);
19 add_action('media_upload_photonic', [&$this, 'media_upload_photonic']);
20
21 add_action('print_media_templates', [&$this, 'edit_gallery']);
22
23 // Gutenberg
24 add_action('enqueue_block_editor_assets', [&$this, 'enqueue_gutenberg_assets']);
25 add_action('enqueue_block_assets', [&$this, 'enqueue_fse_assets']); // Site Editor; without this, the block doesn't work on the FSE Site Editor
26
27 if (empty($photonic_disable_flow_editor_global)) {
28 add_action('media_buttons', [&$this, 'add_photonic_button']);
29 add_action('admin_action_photonic_wizard', [&$this, 'open_wizard']);
30 add_action('wp_ajax_photonic_wizard_next_screen', [&$this, 'wizard_next_screen']);
31 add_action('wp_ajax_photonic_wizard_more', [&$this, 'flow_more']);
32 }
33 }
34
35 public function admin_head() {
36 // check user permissions
37 if (!current_user_can('edit_posts') && !current_user_can('edit_pages')) {
38 return;
39 }
40
41 global $photonic_disable_editor, $photonic_disable_editor_post_type;
42 $disabled_types = explode(',', esc_attr($photonic_disable_editor_post_type));
43 $screen = get_current_screen();
44
45 // check if WYSIWYG is enabled
46 if (user_can_richedit() && empty($photonic_disable_editor) && !in_array($_REQUEST['post_type'] ?? 'post', $disabled_types, true) && 'post' === $screen->base) { // phpcs:ignore WordPress.Security.NonceVerification
47 $this->prepare_mce_data();
48 add_filter('mce_external_plugins', [$this, 'mce_photonic'], 5);
49 add_filter('mce_buttons', [$this, 'mce_flow_button'], 5);
50 }
51 }
52
53 public function add_photonic_button() {
54 add_thickbox();
55 $url = $this->get_wizard_modal_url();
56
57 printf(
58 '<a href="%1$s" class="button photonic-button thickbox" id="photonic-add-gallery" title="Photonic Gallery"><img class="wp-media-buttons-icon" src="' . esc_url(PHOTONIC_URL) . 'include/images/Photonic-20.png" alt="%2$s" /> %2$s</a>',
59 esc_url($url),
60 esc_html__('Add / Edit Photonic Gallery', 'photonic')
61 );
62 }
63
64 public function open_wizard() {
65 define('IFRAME_REQUEST', true); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
66 $this->enqueue_wizard_scripts();
67 iframe_header(esc_html__('Add / Edit Photonic Gallery', 'photonic'));
68 require_once PHOTONIC_PATH . '/Admin/Wizard/Screen_Flow.php';
69 iframe_footer();
70 exit;
71 }
72
73 public function enqueue_wizard_scripts() {
74 if (current_user_can('edit_posts') && isset($_REQUEST['nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['nonce'])), 'photonic-wizard-' . get_current_user_id())) {
75 global $photonic_alternative_shortcode, $photonic_debug_on;
76 $safe_origin = '';
77 $url_parts = wp_parse_url(home_url());
78 $safe_origin_scheme = $url_parts['scheme'] ?? '';
79 $safe_origin_separator = empty($safe_origin_scheme) ? '' : '://';
80 $safe_origin_port = empty($url_parts['port']) ? '' : ':' . $url_parts['port'];
81 $safe_origin .= $safe_origin_scheme . $safe_origin_separator . $url_parts['host'] . $safe_origin_port;
82 $wizard_js = [
83 'ajaxurl' => admin_url('admin-ajax.php'),
84 'shortcode' => sanitize_text_field($photonic_alternative_shortcode ?: 'gallery'),
85 'insert_gallery' => esc_html__('Insert Gallery', 'photonic'),
86 'update_gallery' => esc_html__('Update Gallery', 'photonic'),
87 'error_mandatory' => esc_html__('Please fill the mandatory fields. Mandatory fields are marked with a red "*".', 'photonic'),
88 'media_library_title' => esc_html__('Select from WordPress Media Library', 'photonic'),
89 'media_library_button' => esc_html__('Select', 'photonic'),
90 'info_editor_not_shortcode' => esc_html__('The text selected in the editor is not a Photonic shortcode. Creating a new shortcode.', 'photonic'),
91 'info_editor_google_shortcode' => esc_html__('The text selected in the editor is Photonic shortcode for Google Photos. With effect from April 2025, Google Photos is no longer supported. Creating a new shortcode.', 'photonic'),
92 /* Translators: 1: Open HTML tag 2: Close HTML tag */
93 'info_editor_block_select' => sprintf(esc_html__('%1$sHint:%2$s To edit an existing Photonic block simply click on the block.', 'photonic'), '<strong>', '</strong>'),
94 'safe_origin' => $safe_origin,
95 'debug_on' => !empty($photonic_debug_on),
96 ];
97 if (!empty($_REQUEST['shortcode'])) {
98 $wizard_js['shortcode'] = sanitize_text_field($_REQUEST['shortcode']);
99 }
100 wp_enqueue_style('photonic-flow', PHOTONIC_URL . 'include/css/admin/admin-flow.css', [], Photonic::get_version(PHOTONIC_PATH . '/include/css/admin/admin-flow.css'));
101 wp_enqueue_script('photonic-flow-js', PHOTONIC_URL . 'include/js/admin/wizard.js', ['jquery'], Photonic::get_version(PHOTONIC_PATH . '/include/js/admin/wizard.js'), false);
102 wp_localize_script('photonic-flow-js', 'Photonic_Wizard_JS', $wizard_js);
103 }
104 }
105
106 public function wizard_next_screen() {
107 if (check_ajax_referer('photonic-wizard-next-' . get_current_user_id())) {
108 require_once PHOTONIC_PATH . '/Admin/Wizard/Wizard.php';
109 if (isset($_POST['provider'])) {
110 $safe_tags = array_merge_recursive(
111 [
112 'form' => [
113 'id' => true,
114 'class' => true,
115 'name' => true,
116 'data-photonic-submission' => true,
117 'data-photonic-submission-pending' => true,
118 ],
119
120 'input' => [
121 'type' => true,
122 'id' => true,
123 'name' => true,
124 'value' => true,
125 'checked' => true,
126 'class' => true,
127 'data-photonic-option-condition' => true,
128 ],
129
130 'label' => [
131 'class' => true,
132 'for' => true,
133 ],
134
135 'select' => [
136 'name' => true,
137 'id' => true,
138 'class' => true,
139 'aria-describedby' => true,
140 ],
141
142 'option' => [
143 'value' => true,
144 'selected' => true,
145 'data-photonic-option-condition' => true,
146 ],
147
148 // Custom data attributes
149 'div' => [
150 'data-current-screen' => true,
151
152 'data-photonic-flow-selector-for' => true,
153 'data-photonic-flow-selector-mode' => true,
154
155 'data-photonic-condition' => true,
156 'data-photonic-flow-sequence' => true,
157 'data-photonic-flow-sequence-group' => true,
158
159 'data-photonic-flow-selection-id' => true,
160 'data-photonic-selection-alt-id' => true,
161 'data-photonic-selection-alt-id-2' => true,
162 ],
163
164 'span' => [
165 'data-photonic-selection-id' => true,
166 ],
167
168 'ol' => [
169 'data-photonic-date-filter' => true,
170 'data-photonic-filter-count' => true,
171 'data-photonic-date-range-filter' => true,
172 ],
173
174 'a' => [
175 'data-photonic-add-date' => true,
176 'data-photonic-mark-for' => true,
177 'data-photonic-more-link' => true,
178 'data-photonic-display-type' => true,
179 'data-photonic-provider' => true,
180 'data-photonic-nonce' => true,
181 ]
182 ],
183 wp_kses_allowed_html('post')
184 );
185
186 $wizard = new Wizard();
187 // echo $wizard->get_screen(); // Cannot escape ... has form and JS markup; individual parts are escaped as appropriate.
188 echo wp_kses($wizard->get_screen(), $safe_tags); // Cannot escape ... has form and JS markup; individual parts are escaped as appropriate.
189 }
190 }
191 die();
192 }
193
194 public function flow_more() {
195 if (check_ajax_referer('photonic-wizard-more-' . get_current_user_id())) {
196 require_once PHOTONIC_PATH . '/Admin/Wizard/Wizard.php';
197 if (isset($_POST['url']) && isset($_POST['provider']) && isset($_POST['display_type'])) {
198 $url = base64_decode(sanitize_text_field($_POST['url'])); // The `url` for fetching additional results is base64-encoded in the wizard in wizard.js using `btoa`
199
200 $provider = sanitize_text_field($_POST['provider']);
201 $display_type = sanitize_text_field($_POST['display_type']);
202 $existing = [];
203 if (!empty($_POST['filter'])) {
204 $existing['selected_data'] = sanitize_text_field($_POST['filter']);
205 }
206 $args = ['sslverify' => PHOTONIC_SSL_VERIFY];
207 if ('smugmug' === $provider) {
208 require_once PHOTONIC_PATH . '/Platforms/SmugMug.php';
209 $gallery = SmugMug::get_instance();
210
211 $body = [
212 'APIKey' => $gallery->api_key,
213 '_accept' => 'application/json',
214 '_expandmethod' => 'inline',
215 '_verbosity' => '1',
216 ];
217
218 if ('album-photo' === $display_type || 'multi-album' === $display_type) {
219 $body['_expand'] = 'HighlightImage.ImageSizes';
220 }
221
222 $args['body'] = $body;
223 }
224
225 // URL has come via base64, so we will check that it is directing to a whitelist of hosts...
226 $url_parts = wp_parse_url($url);
227 if (in_array($url_parts['host'], Wizard::base_apis(), true)) {
228 $response = wp_remote_request($url, $args);
229 $wizard = new Wizard();
230 $objects = $wizard->process_response($response, $provider, $display_type, [], $existing, $url, true);
231
232 if (!empty($objects['success'])) {
233 echo wp_kses_post($objects['success']);
234 }
235 elseif (!empty($objects['error'])) {
236 if ($objects['error'] !== $wizard->error_no_data_returned) { // Typically happens if there is a "next token" without corresponding data
237 echo wp_kses_post($objects['error']);
238 }
239 }
240 }
241 }
242 }
243 die();
244 }
245
246 /**
247 * Adds all scripts and their dependencies to the <head> of the Photonic administration page. This takes care to not add scripts on other admin pages.
248 *
249 * @param $hook
250 * @return void
251 */
252 public function add_admin_scripts($hook) {
253 if ('media-upload-popup' === $hook) {
254 wp_enqueue_script('jquery');
255 wp_enqueue_style('photonic-upload', PHOTONIC_URL . 'include/css/admin/admin-form.css', [], Photonic::get_version(PHOTONIC_PATH . '/include/css/admin/admin-form.css'));
256 }
257 elseif ('post-new.php' === $hook || 'post.php' === $hook) {
258 global $photonic_disable_editor, $photonic_disable_editor_post_type, $photonic_alternative_shortcode;
259 $disabled_types = explode(',', $photonic_disable_editor_post_type);
260 wp_enqueue_style('photonic-upload', PHOTONIC_URL . 'include/css/admin/admin-form.css', [], Photonic::get_version(PHOTONIC_PATH . '/include/css/admin/admin-form.css'));
261 wp_enqueue_script('photonic-native-ui', PHOTONIC_URL . 'include/js/admin/native-ui.js', ['shortcode', 'thickbox'], Photonic::get_version(PHOTONIC_PATH . '/include/js/admin/native-ui.js'), false);
262 wp_enqueue_script('photonic-editor', PHOTONIC_URL . 'include/js/admin/editor.js', ['photonic-native-ui'], Photonic::get_version(PHOTONIC_PATH . '/include/js/admin/editor.js'), false);
263 $editor_js = [
264 'shortcode' => sanitize_text_field($photonic_alternative_shortcode ?: 'gallery'),
265 ];
266 wp_localize_script('photonic-editor', 'Photonic_Editor_JS', $editor_js);
267
268 if (empty($photonic_disable_editor) && !in_array($_REQUEST['post_type'] ?? 'post', $disabled_types, true)) { // phpcs:ignore WordPress.Security.NonceVerification
269 $this->prepare_mce_data();
270
271 add_editor_style(PHOTONIC_URL . 'include/css/admin/admin-editor.css?' . Photonic::get_version(PHOTONIC_PATH . '/include/css/admin/admin-editor.css'));
272 }
273 }
274 elseif ('widgets.php' === $hook) {
275 Photonic::enqueue_widget_scripts();
276 }
277 }
278
279 public function prepare_mce_data() {
280 $url = $this->get_wizard_modal_url();
281 $js_array = $this->get_wizard_js_parameters($url);
282
283 wp_enqueue_script('photonic-admin-js', PHOTONIC_URL . 'include/js/admin/gallery-settings.js', ['jquery', 'media-views', 'media-upload'], Photonic::get_version(PHOTONIC_PATH . '/include/js/admin/gallery-settings.js'), false);
284 wp_localize_script('photonic-admin-js', 'Photonic_Admin_JS', $js_array);
285 }
286
287 public function mce_photonic($plugin_array) {
288 $plugin_array['photonic'] = PHOTONIC_URL . 'include/js/admin/mce.js?' . Photonic::get_version(PHOTONIC_PATH . '/include/js/admin/mce.js');
289 return $plugin_array;
290 }
291
292 public function mce_flow_button($buttons) {
293 array_push($buttons, 'photonic_wizard');
294 return $buttons;
295 }
296
297 public function enqueue_gutenberg_assets() {
298 wp_enqueue_script('photonic-native-ui', PHOTONIC_URL . 'include/js/admin/native-ui.js', ['shortcode', 'thickbox'], Photonic::get_version(PHOTONIC_PATH . '/include/js/admin/native-ui.js'), false);
299 wp_enqueue_script(
300 'photonic-gutenberg',
301 PHOTONIC_URL . 'include/js/admin/block.js',
302 ['wp-blocks', 'wp-i18n', 'wp-element', 'shortcode', 'thickbox', 'photonic-native-ui'],
303 Photonic::get_version(PHOTONIC_PATH . '/include/js/admin/block.js'),
304 false
305 );
306
307 wp_set_script_translations('photonic-gutenberg', 'photonic');
308
309 $url = $this->get_wizard_modal_url();
310 $js_array = $this->get_wizard_js_parameters($url);
311 wp_localize_script('photonic-gutenberg', 'Photonic_Gutenberg_JS', $js_array);
312
313 wp_enqueue_style(
314 'photonic-gutenberg',
315 PHOTONIC_URL . 'include/css/admin/admin-block.css',
316 ['thickbox'],
317 Photonic::get_version(PHOTONIC_PATH . '/include/css/admin/admin-block.css')
318 );
319 }
320
321 public function enqueue_fse_assets() {
322 if (is_admin()) {
323 wp_enqueue_style(
324 'photonic-gutenberg',
325 PHOTONIC_URL . 'include/css/admin/admin-block.css',
326 ['thickbox'],
327 Photonic::get_version(PHOTONIC_PATH . '/include/css/admin/admin-block.css')
328 );
329 }
330 }
331
332 /**
333 * Adds a "Photonic" tab to the "Add Media" panel.
334 *
335 * @param $tabs
336 * @return array
337 */
338 public function media_upload_tabs($tabs): array {
339 $current_screen = get_current_screen();
340 if (!empty($current_screen) && $current_screen->is_block_editor()) {
341 $tabs['photonic'] = 'Photonic';
342 }
343 return $tabs;
344 }
345
346 /**
347 * Invokes the form to display the photonic insertion screen in the "Add Media" panel. The call to wp_iframe ensures that the right CSS and JS are called.
348 *
349 * @return void
350 */
351 public function media_upload_photonic() {
352 wp_iframe([&$this, 'media_upload_photonic_form']);
353 }
354
355 /**
356 * First prints the standard buttons for media upload, then shows the UI for Photonic.
357 *
358 * @return void
359 */
360 public function media_upload_photonic_form() {
361 media_upload_header();
362 require_once PHOTONIC_PATH . '/Admin/Forms/Add_Gallery.php';
363 }
364
365 public function edit_gallery() {
366 global $photonic_disable_editor, $photonic_disable_editor_post_type;
367 $disabled_types = explode(',', $photonic_disable_editor_post_type);
368 // check if WYSIWYG is enabled
369 if (user_can_richedit() && empty($photonic_disable_editor) && !in_array($_REQUEST['post_type'] ?? 'post', $disabled_types, true)) { // phpcs:ignore WordPress.Security.NonceVerification
370 require_once PHOTONIC_PATH . '/Admin/Forms/Edit_Gallery_Templates.php';
371 }
372 }
373
374 /**
375 * @return string
376 */
377 private function get_wizard_modal_url(): string {
378 $user = get_current_user_id();
379 if (0 === $user) {
380 $user = wp_rand(1);
381 }
382
383 $post = empty($_REQUEST['post']) ? '' : sanitize_text_field($_REQUEST['post']); // phpcs:ignore WordPress.Security.NonceVerification
384
385 return add_query_arg(
386 [
387 'action' => 'photonic_wizard',
388 'class' => 'photonic-flow',
389 'post_id' => $post,
390 'nonce' => wp_create_nonce('photonic-wizard-' . $user),
391 'width' => '1000',
392 'height' => '600',
393 'TB_iframe' => 'true',
394 ],
395 admin_url('admin.php')
396 );
397 }
398
399 /**
400 * @param string $url
401 * @return array
402 */
403 private function get_wizard_js_parameters($url): array {
404 global $photonic_alternative_shortcode, $photonic_disable_flow_editor, $photonic_disable_flow_editor_global;
405 return [
406 'flow_url' => $url,
407 'ajaxurl' => admin_url('admin-ajax.php'),
408 'shortcode' => sanitize_text_field($photonic_alternative_shortcode ?: 'gallery'),
409 'disable_flow' => !empty($photonic_disable_flow_editor) || !empty($photonic_disable_flow_editor_global),
410 'default_gallery_type' => 'default',
411 'plugin_dir' => plugin_dir_url(__FILE__),
412 ];
413 }
414 }
415
416 new Admin();
417