PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 3.36
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v3.36
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
← All changes | Admin/Wizard/Wizard.php +601 -543 2.413.36 View file →
@@ -1,5 +1,6 @@
1 1 <?php
2 +
2 3 namespace Photonic_Plugin\Admin\Wizard;
3 4
4 5 use Photonic_Plugin\Core\Photonic;
5 6
@@ -11,14 +12,27 @@
11 12 *
12 13 * @since 2.00
13 14 */
14 15 class Wizard {
15 - var $flow_fields, $display_types, $shortcode_attributes, $aka_attributes, $date_parts, $date_part_hints, $check_for_blanks,
16 - $error_mandatory, $error_no_response, $error_not_found, $error_no_data_returned, $error_not_permitted, $error_authentication, $error_missing_api,
17 - $force_next_screen, $force_previous_screen, $is_gutenberg;
16 + private Screen_Fields $flow_fields;
17 + private array $display_types;
18 + private array $shortcode_attributes;
19 + private array $aka_attributes;
20 + private array $date_parts;
21 + private array $date_part_hints;
22 + private string $error_mandatory;
23 + private string $error_no_response;
24 + private string $error_not_found;
25 + public string $error_no_data_returned;
26 + private string $error_not_permitted;
27 + private string $error_authentication;
28 + private string $error_missing_api;
29 + private int $force_next_screen;
30 + private int $force_previous_screen;
31 + private bool $is_gutenberg = false;
18 32
19 - function __construct() {
20 - require_once("Screen_Fields.php");
33 + public function __construct() {
34 + require_once "Screen_Fields.php";
21 35 $this->flow_fields = new Screen_Fields();
22 36
23 37 $this->force_next_screen = -1;
24 38 $this->force_previous_screen = -1;
@@ -34,45 +48,46 @@
34 48 $this->date_parts = [0 => esc_html__('Year', 'photonic'), 1 => esc_html__('Month', 'photonic'), 2 => esc_html__('Date', 'photonic')];
35 49 $this->date_part_hints = [0 => esc_html__('Year (0 - 9999)', 'photonic'), 1 => esc_html__('Month (0 - 12)', 'photonic'), 2 => esc_html__('Date (0 - 31)', 'photonic')];
36 50
37 51 $this->display_types = [
38 - 'single-photo' => 0,
39 - 'multi-photo' => 1,
40 - 'album-photo' => 1,
41 - 'folder-photo' => 1,
42 - 'user-photo' => 1,
43 - 'gallery-photo' => 1,
44 - 'collection-photo' => 1,
45 - 'current-post' => 1,
46 - 'another-post' => 1,
47 - 'multi-album' => 2,
48 - 'multi-gallery' => 2,
49 - 'multi-collection' => 2,
52 + 'single-photo' => 0,
53 + 'multi-photo' => 1,
54 + 'album-photo' => 1,
55 + 'folder-photo' => 1,
56 + 'user-photo' => 1,
57 + 'gallery-photo' => 1,
58 + 'collection-photo' => 1,
59 + 'current-post' => 1,
60 + 'another-post' => 1,
61 + 'shared-album-photo' => 1,
62 + 'multi-album' => 2,
63 + 'multi-gallery' => 2,
64 + 'multi-collection' => 2,
50 65 'multi-gallery-collection' => 2,
51 - 'collection' => 3,
52 - 'collections' => 3,
53 - 'folder' => 3,
54 - 'tree' => 3,
55 - 'group' => 3,
56 - 'group-hierarchy' => 3,
66 + 'collection' => 3,
67 + 'collections' => 3,
68 + 'folder' => 3,
69 + 'tree' => 3,
70 + 'group' => 3,
71 + 'group-hierarchy' => 3,
57 72 ];
58 73
59 74 $this->shortcode_attributes = [
60 - 'common' => [
61 - 'columns', 'count', 'more', 'photo_count', 'photo_more', 'photo_layout', 'title_position', 'caption', 'media', 'main_size', 'thumb_size', 'tile_size', 'video_size', 'popup', 'thumbnail_effect', 'show_gallery', // All lightbox
75 + 'common' => [
76 + 'columns', 'count', 'more', 'photo_count', 'photo_more', 'photo_layout', 'title_position', 'caption', 'media', 'main_size', 'thumb_size', 'tile_size', 'video_size', 'popup', 'thumbnail_effect', 'show_gallery', 'load_mode', 'layout_engine', 'headers', // All lightbox
62 77 'speed', 'timeout', 'fx', 'pause', 'strip-style', 'controls', // Slideshow
63 78 ],
64 - 'flickr' => ['user_id', 'group_id', 'collections_display', 'tags', 'tag_mode', 'text', 'sort', 'privacy_filter',],
65 - 'smugmug' => ['nick_name', 'password', 'text', 'keywords', 'sort_order', 'sort_method', 'album_sort_order',],
66 - 'google' => ['user_id', 'access', 'protection', 'crop_thumb', 'content_filters',],
67 - 'zenfolio' => ['login_name', 'text', 'category_code', 'sort_order', 'structure', 'password'],
68 - 'instagram' => ['embed_type', 'carousel_handling'],
69 - 'wp' => [],
79 + 'flickr' => ['user_id', 'group_id', 'collections_display', 'tags', 'tag_mode', 'text', 'sort', 'privacy_filter'],
80 + 'smugmug' => ['nick_name', 'password', 'text', 'keywords', 'sort_order', 'sort_method', 'album_sort_order'],
81 + 'google' => ['user_id', 'access', 'protection', 'crop_thumb', 'content_filters'],
82 + 'zenfolio' => ['login_name', 'text', 'category_code', 'sort_order', 'structure', 'password'],
83 + 'instagram' => ['embed_type', 'carousel_handling', 'carousel_position'],
84 + 'wp' => ['order', 'orderby', 'link'],
70 85 ];
71 86 $this->aka_attributes = [
72 - 'flickr' => ['per_page' => 'count'],
87 + 'flickr' => ['per_page' => 'count'],
73 88 'zenfolio' => ['limit' => 'count'],
74 - 'wp' => ['slide_size' => 'main_size'],
89 + 'wp' => ['slide_size' => 'main_size'],
75 90 ];
76 91 }
77 92
78 93 /**
@@ -81,77 +96,81 @@
81 96 * an error is returned.
82 97 *
83 98 * @return string
84 99 */
85 - function get_screen() {
86 - $screen = isset($_POST['screen']) ? sanitize_text_field($_POST['screen']) : 0;
87 - $provider = isset($_POST['provider']) ? sanitize_text_field($_POST['provider']) : '';
88 - $display_type = isset($_POST['display_type']) ? sanitize_text_field($_POST['display_type']) : '';
100 + public function get_screen(): string {
101 + $ret = '';
89 102
90 - $raw_shortcode = !empty($_POST['photonic-editor-shortcode-raw']) ? sanitize_text_field($_POST['photonic-editor-shortcode-raw']) : '';
91 - if (!empty($raw_shortcode)) {
92 - $input = base64_decode($raw_shortcode);
93 - $input = json_decode($input);
94 - if (!empty($input->shortcode) && !empty($input->shortcode->attrs) && !empty($input->shortcode->attrs->named)) {
95 - $input = $input->shortcode->attrs->named;
103 + if (check_ajax_referer('photonic-wizard-next-' . get_current_user_id())) {
104 + $screen = sanitize_text_field(wp_unslash($_POST['screen'] ?? 0));
105 + $provider = sanitize_text_field(wp_unslash($_POST['provider'] ?? ''));
106 + $display_type = sanitize_text_field(wp_unslash($_POST['display_type'] ?? ''));
107 +
108 + $raw_shortcode = !empty($_POST['photonic-editor-shortcode-raw']) ? sanitize_text_field($_POST['photonic-editor-shortcode-raw']) : '';
109 + if (!empty($raw_shortcode)) {
110 + $input = base64_decode($raw_shortcode); // The in-flight shortcode is passed from screen to screen using the JS function `btoa`, in wizard.js, which encodes it
111 + $input = json_decode($input);
112 + if (!empty($input->shortcode) && !empty($input->shortcode->attrs) && !empty($input->shortcode->attrs->named)) {
113 + $input = $input->shortcode->attrs->named;
114 + }
96 115 }
97 - }
98 - else {
99 - $raw_shortcode = !empty($_POST['photonic-editor-json']) ? stripslashes_deep($_POST['photonic-editor-json']) : '';
100 - $input = json_decode($raw_shortcode);
101 - if (!empty($_POST['photonic-gutenberg-active'])) {
102 - $this->is_gutenberg = true;
116 + else {
117 + $raw_shortcode = !empty($_POST['photonic-editor-json']) ? stripslashes_deep(sanitize_text_field($_POST['photonic-editor-json'])) : '';
118 + $input = json_decode($raw_shortcode);
119 + if (!empty($_POST['photonic-gutenberg-active'])) {
120 + $this->is_gutenberg = true;
121 + }
103 122 }
104 - }
105 123
106 - $deconstructed = $this->deconstruct_shortcode($input);
124 + $deconstructed = $this->deconstruct_shortcode($input);
107 125
108 - $output = $this->validate($screen, $provider, $deconstructed);
109 - if (!empty($output['error'])) {
110 - return '<div class="photonic-flow-error">' . $output['error'] . "</div>\n";
111 - }
126 + $output = $this->validate($screen, $provider, $deconstructed);
127 + if (!empty($output['error'])) {
128 + return '<div class="photonic-flow-error">' . wp_kses_post($output['error']) . "</div>\n";
129 + }
112 130
113 - $screen = ((int)$screen) + 1;
114 - if ($this->force_next_screen > -1) {
115 - $screen = $this->force_next_screen;
116 - }
131 + $screen = ((int) $screen) + 1;
132 + if ($this->force_next_screen > -1) {
133 + $screen = $this->force_next_screen;
134 + }
117 135
118 - $ret = '';
136 + if (2 === $screen || '2' === $screen) {
137 + /*
138 + * The display_type screen. This gathers inputs about what the user wants to show: photos from an album, a collection of
139 + * albums, user trees, single photos etc., along with who the photos are from - the default user, a different user, any user etc.
140 + */
141 + $screen_fields = $this->flow_fields->get_screen_2_fields($provider);
142 + $fields = $screen_fields['display'];// $screen_fields[$provider]['display'];
143 + $ret .= $this->render_all_fields($fields, $deconstructed);
144 + $ret = (empty($screen_fields['header']) ? '' : "<h1>" . wp_kses_post($screen_fields['header']) . "</h1>\n") .
145 + (empty($screen_fields['notice']) ? '' : "<section class='photonic-flow-notice'>" . wp_kses_post($screen_fields['notice']) . "</section>\n") .
146 + (empty($screen_fields['desc']) ? '' : "<p>" . wp_kses_post($screen_fields['desc']) . "</p>\n") .
147 + $ret;
148 + }
149 + elseif (3 === $screen) {
150 + /*
151 + * The Gallery Builder screen, where all the photos / albums / folders are displayed
152 + */
153 + $screen_fields = $this->flow_fields->get_screen_3_fields($provider);
154 + $fields = $screen_fields[$display_type]['display'];
155 + $ret .= $this->render_all_fields($fields, $deconstructed);
119 156
120 - if ($screen == 2 || $screen == '2') {
121 - /*
122 - * The display_type screen. This gathers inputs about what the user wants to show: photos from an album, a collection of
123 - * albums, user trees, single photos etc., along with who the photos are from - the default user, a different user, any user etc.
124 - */
125 - $screen_fields = $this->flow_fields->get_screen_2_fields($provider);
126 - $fields = $screen_fields['display'];// $screen_fields[$provider]['display'];
127 - $ret .= $this->render_all_fields($fields, $deconstructed);
128 - $ret = (empty($screen_fields['header']) ? '' : "<h1>" . $screen_fields['header'] . "</h1>\n") .
129 - (empty($screen_fields['desc']) ? '' : "<p>" . $screen_fields['desc'] . "</p>\n") .
130 - $ret;
157 + $ret = (empty($screen_fields[$display_type]['header']) ? '' : "<h1>" . wp_kses_post($screen_fields[$display_type]['header']) . "</h1>\n") .
158 + (empty($screen_fields[$display_type]['notice']) ? '' : "<section class='photonic-flow-notice'>" . wp_kses_post($screen_fields[$display_type]['notice']) . "</section>\n") .
159 + (empty($screen_fields[$display_type]['desc']) ? '' : "<p>" . wp_kses_post($screen_fields[$display_type]['desc']) . "</p>\n") .
160 + str_replace('{{placeholder_value}}', $output['success'], $ret);
161 + }
162 + elseif (4 === $screen) {
163 + /*
164 + * The layout selection screen
165 + */
166 + $ret .= $output['success'];
167 + }
168 + else {
169 + $ret .= $output['success'];
170 + }
131 171 }
132 - else if ($screen == 3) {
133 - /*
134 - * The Gallery Builder screen, where all the photos / albums / folders are displayed
135 - */
136 - $screen_fields = $this->flow_fields->get_screen_3_fields($provider);
137 - $fields = $screen_fields[$display_type]['display'];
138 - $ret .= $this->render_all_fields($fields, $deconstructed);
139 172
140 - $ret = (empty($screen_fields[$display_type]['header']) ? '' : "<h1>" . $screen_fields[$display_type]['header'] . "</h1>\n") .
141 - (empty($screen_fields[$display_type]['desc']) ? '' : "<p>" . $screen_fields[$display_type]['desc'] . "</p>\n") .
142 - str_replace('{{placeholder_value}}', $output['success'], $ret);
143 - }
144 - else if ($screen == 4) {
145 - /*
146 - * The layout selection screen
147 - */
148 - $ret .= $output['success'];
149 - }
150 - else {
151 - $ret .= $output['success'];
152 - }
153 -
154 173 return $ret;
155 174 }
156 175
157 176 /**
@@ -162,152 +181,152 @@
162 181 * @param $provider
163 182 * @param array $existing
164 183 * @return array|string
165 184 */
166 - function validate($screen, $provider, $existing = []) {
167 - if (empty($screen) || !is_numeric($screen) || (is_numeric($screen) && (intval($screen) <= 0 || intval($screen) > 5))) {
168 - return ['error' => sprintf(esc_html__('Invalid screen value: %s', 'photonic'), $screen)];
169 - }
170 - if (!in_array($provider, ['wp', 'flickr', 'picasa', 'google', 'smugmug', 'zenfolio', 'instagram'])) {
171 - return ['error' => sprintf(esc_html__('Invalid photo provider: %s', 'photonic'), $provider)];
172 - }
185 + public function validate($screen, $provider, $existing = []) {
186 + if (check_ajax_referer('photonic-wizard-next-' . get_current_user_id())) {
187 + if (empty($screen) || !is_numeric($screen) || (is_numeric($screen) && (intval($screen) <= 0 || intval($screen) > 5))) {
188 + return ['error' => sprintf(esc_html__('Invalid screen value: %s', 'photonic'), $screen)];
189 + }
190 + if (!in_array($provider, ['wp', 'flickr', 'picasa', 'google', 'smugmug', 'zenfolio', 'instagram'], true)) {
191 + return ['error' => sprintf(esc_html__('Invalid photo provider: %s', 'photonic'), $provider)];
192 + }
173 193
174 - $screen = intval($screen);
175 - $display_type = isset($_POST['display_type']) ? sanitize_text_field($_POST['display_type']) : '';
194 + $screen = intval($screen);
195 + $display_type = sanitize_text_field($_POST['display_type'] ?? '');
176 196
177 - if ($screen == 1) {
178 - switch ($provider) {
179 - case 'flickr':
180 - global $photonic_flickr_api_key, $photonic_flickr_api_secret;
181 - if (empty($photonic_flickr_api_key) || empty($photonic_flickr_api_secret)) {
182 - return ['error' => sprintf($this->error_missing_api, 'Flickr API key', '<em>Photonic &rarr; Settings &rarr; Flickr &rarr; Flickr Settings</em>')];
183 - }
184 - break;
197 + if (1 === $screen) {
198 + switch ($provider) {
199 + case 'flickr':
200 + global $photonic_flickr_api_key, $photonic_flickr_api_secret;
201 + if (empty($photonic_flickr_api_key) || empty($photonic_flickr_api_secret)) {
202 + return ['error' => sprintf($this->error_missing_api, 'Flickr API key', '<em>Photonic &rarr; Settings &rarr; Flickr &rarr; Flickr Settings</em>')];
203 + }
204 + break;
185 205
186 - case 'picasa':
187 - return ['error' => esc_html__('Google has deprecated the Picasa API with effect from January 2019. Please consider using the Google Photos module.', 'photonic')];
206 + case 'google':
207 + global $photonic_google_client_id, $photonic_google_client_secret, $photonic_google_refresh_token;
208 + // if (!empty($photonic_google_use_own_keys) && (empty($photonic_google_client_id) || empty($photonic_google_client_secret))) {
209 + if (empty($photonic_google_client_id) || empty($photonic_google_client_secret)) {
210 + return ['error' => sprintf($this->error_missing_api, 'Google Client ID', '<em>Photonic &rarr; Settings &rarr; Google Photos &rarr; Google Photos Settings</em>')];
211 + }
212 + elseif (empty($photonic_google_refresh_token)) {
213 + return ['error' => sprintf($this->error_authentication, 'Google Photos', '<em>Photonic &rarr; Authentication</em>')];
214 + }
215 + break;
188 216
189 - case 'google':
190 - global $photonic_google_client_id, $photonic_google_client_secret, $photonic_google_refresh_token;
191 -// if (!empty($photonic_google_use_own_keys) && (empty($photonic_google_client_id) || empty($photonic_google_client_secret))) {
192 - if (empty($photonic_google_client_id) || empty($photonic_google_client_secret)) {
193 - return ['error' => sprintf($this->error_missing_api, 'Google Client ID', '<em>Photonic &rarr; Settings &rarr; Google Photos &rarr; Google Photos Settings</em>')];
194 - }
195 - else if (empty($photonic_google_refresh_token)) {
196 - return ['error' => sprintf($this->error_authentication, 'Google Photos', '<em>Photonic &rarr; Authentication</em>')];
197 - }
198 - break;
217 + case 'smugmug':
218 + case 'zenfolio':
219 + return '';
199 220
200 - case 'smugmug':
201 - case 'zenfolio':
202 - return '';
221 + case 'instagram':
222 + return ['error' => esc_html__('In September 2022, Meta changed the terms of the Instagram API, blocking its use by individual developers. Please consider using a business-backed plugin for Instagram, instead of an individual-backed plugin such as Photonic.', 'photonic')];
223 + // global $photonic_instagram_access_token;
224 + // if (empty($photonic_instagram_access_token)) {
225 + // return ['error' => sprintf($this->error_authentication, 'Instagram', '<em>Photonic &rarr; Authentication</em>')];
226 + // }
227 + // break;
203 228
204 - case 'instagram':
205 - global $photonic_instagram_access_token;
206 - if (empty($photonic_instagram_access_token)) {
207 - return ['error' => sprintf($this->error_authentication, 'Instagram', '<em>Photonic &rarr; Authentication</em>')];
229 + default: // wp
230 + return '';
231 + }
232 + }
233 + elseif (2 === $screen) {
234 + $screen_fields = $this->flow_fields->get_screen_2_fields($provider);
235 +
236 + $fields = $screen_fields['display'];
237 + $flattened_fields = [];
238 + foreach ($fields as $id => $field) {
239 + if (!empty($field['type']) && 'field_list' !== $field['type']) {
240 + $flattened_fields[$id] = $field;
208 241 }
209 - break;
242 + elseif (!empty($field['type']) && 'field_list' === $field['type']) {
243 + $flattened_fields = array_merge($field['list'], $flattened_fields);
244 + }
245 + }
210 246
211 - default: // wp
212 - return '';
213 - }
214 - }
215 - else if ($screen == 2) {
216 - $screen_fields = $this->flow_fields->get_screen_2_fields($provider);
247 + $for = !empty($_POST['for']) ? sanitize_text_field($_POST['for']) : null;
217 248
218 - $fields = $screen_fields['display'];
219 - $flattened_fields = [];
220 - foreach ($fields as $id => $field) {
221 - if (!empty($field['type']) && $field['type'] != 'field_list') {
222 - $flattened_fields[$id] = $field;
249 + if (empty($display_type) || (empty($for) && in_array($provider, ['flickr', 'smugmug', 'zenfolio'], true) && empty($existing))) {
250 + return ['error' => $this->error_mandatory];
223 251 }
224 - else if (!empty($field['type']) && $field['type'] == 'field_list') {
225 - $flattened_fields = array_merge($field['list'], $flattened_fields);
252 +
253 + if (empty($for) && in_array($provider, ['flickr', 'smugmug', 'zenfolio'], true) && !empty($existing)) {
254 + return ['error' => esc_html__('While the "For whom?" setting may not be required for the shortcode to function in the front-end, it is required to edit this shortcode in this editor. Please specify a value.', 'photonic')];
226 255 }
227 - }
228 256
229 - if (empty($display_type) || (empty($_POST['for']) && in_array($provider, ['flickr', 'smugmug', 'zenfolio']) && empty($existing))) {
230 - return ['error' => $this->error_mandatory];
231 - }
257 + if (!in_array($display_type, array_keys($flattened_fields['display_type']['options']), true)) {
258 + return ['error' => sprintf(esc_html__('Invalid display type: %s', 'photonic'), $display_type)];
259 + }
232 260
233 - if (empty($_POST['for']) && in_array($provider, ['flickr', 'smugmug', 'zenfolio']) && !empty($existing)) {
234 - return ['error' => esc_html__('While the "For whom?" setting may not be required for the shortcode to function in the front-end, it is required to edit this shortcode in this editor. Please specify a value.', 'photonic')];
261 + $gallery = $this->flow_fields->get_source($provider);
262 + $response = $gallery->make_request($display_type, $for, $flattened_fields);
263 + if (empty($response)) { // WP
264 + $this->force_next_screen = 4;
265 + $this->force_previous_screen = 2;
266 + return ['success' => $this->get_layout_selector($display_type, $existing)];
267 + }
268 + elseif (!empty($response['error'])) { // Error occurred
269 + return $response;
270 + }
271 + else {
272 + list($https, $form_parameters, $url) = $response;
273 + return $this->process_response($https, $provider, $display_type, $form_parameters, $existing, $url);
274 + }
235 275 }
276 + elseif (3 === $screen) {
277 + // Check for display_type
278 + $screen_fields = $this->flow_fields->get_screen_3_fields($provider); // $this->field_list['screen-' . $screen];
279 + $provider_fields = $screen_fields; // $screen_fields[$provider];
280 + $fields = $provider_fields[$display_type]['display'];
281 + foreach ($fields as $id => $field) {
282 + $checks = $this->do_basic_option_check($id, $field, true);
283 + if (!empty($checks)) {
284 + return $checks;
285 + }
236 286
237 - if (!in_array($display_type, array_keys($flattened_fields['display_type']['options']))) {
238 - return ['error' => sprintf(esc_html__('Invalid display type: %s', 'photonic'), $display_type)];
239 - }
287 + if ('selection' === $id && 'selected' === sanitize_text_field($_POST['selection']) && empty($_POST['selected_data'])) {
288 + return ['error' => esc_html__('Please select what you want to show.', 'photonic')];
289 + }
240 290
241 - $for = !empty($_POST['for']) ? sanitize_text_field($_POST['for']) : null;
242 -
243 - $gallery = $this->flow_fields->get_source($provider);
244 - $response = $gallery->make_request($display_type, $for, $flattened_fields);
245 - if (empty($response)) { // WP
246 - $this->force_next_screen = 4;
247 - $this->force_previous_screen = 2;
248 - return ['success' => $this->get_layout_selector($display_type, $existing)];
249 - }
250 - else if (!empty($response['error'])) { // Error occurred
251 - return $response;
252 - }
253 - else {
254 - list($https, $form_parameters, $url) = $response;
255 - return $this->process_response($https, $provider, $display_type, $form_parameters, $existing, $url);
256 - }
257 - }
258 - else if ($screen == 3) {
259 - //Check for display_type
260 - $screen_fields = $this->flow_fields->get_screen_3_fields($provider); // $this->field_list['screen-' . $screen];
261 - $provider_fields = $screen_fields; //$screen_fields[$provider];
262 - $fields = $provider_fields[$display_type]['display'];
263 - foreach ($fields as $id => $field) {
264 - $checks = $this->do_basic_option_check($id, $field, true);
265 - if (!empty($checks)) {
266 - return $checks;
291 + if (in_array($display_type, ['single-photo', 'album-photo', 'gallery-photo', 'folder-photo', 'collection-photo'], true) && empty($_POST['selected_data'])) {
292 + return ['error' => esc_html__('Please select what you want to show.', 'photonic')];
293 + }
267 294 }
268 295
269 - if ($id == 'selection' && sanitize_text_field($_POST['selection']) == 'selected' && empty($_POST['selected_data'])) {
270 - return ['error' => esc_html__('Please select what you want to show.', 'photonic')];
296 + // All OK? Get next screen
297 + if ('single-photo' !== $display_type) {
298 + $output = $this->get_layout_selector($display_type, $existing, $provider);
271 299 }
272 -
273 - if (in_array($display_type, ['single-photo', 'album-photo', 'gallery-photo', 'folder-photo', 'collection-photo']) && empty($_POST['selected_data'])) {
274 - return ['error' => esc_html__('Please select what you want to show.', 'photonic')];
300 + else {
301 + $this->force_next_screen = 6;
302 + $this->force_previous_screen = 3;
303 + $output = $this->construct_shortcode();
275 304 }
305 + return ['success' => $output];
276 306 }
307 + elseif (4 === $screen) {
308 + $layout = sanitize_text_field($_POST['layout'] ?? '');
309 + if (empty($layout)) {
310 + return ['error' => $this->error_mandatory];
311 + }
312 + $layout_options = $this->flow_fields->get_layout_options();
313 + if (!array_key_exists($layout, $layout_options)) {
314 + return ['error' => sprintf(esc_html__('Invalid layout: %s', 'photonic'), $layout)];
315 + }
277 316
278 - // All OK? Get next screen
279 - if ($display_type != 'single-photo') {
280 - $output = $this->get_layout_selector($display_type, $existing, $provider);
317 + // All good. Next screen:
318 + return ['success' => $this->get_layout_options($provider, $display_type, $layout, $existing)];
281 319 }
282 320 else {
283 - $this->force_next_screen = 6;
284 - $this->force_previous_screen = 3;
285 - $output = $this->construct_shortcode();
321 + $passworded = sanitize_text_field($_POST['selection_passworded'] ?? '');
322 + $password = sanitize_text_field($_POST['password'] ?? '');
323 + if (!empty($passworded) && empty($password)) {
324 + return ['error' => $this->error_mandatory];
325 + }
326 + return ['success' => $this->construct_shortcode()];
286 327 }
287 - return ['success' => $output];
288 328 }
289 - else if ($screen == 4) {
290 - $layout = isset($_POST['layout']) ? sanitize_text_field($_POST['layout']) : '';
291 - if (empty($layout)) {
292 - return ['error' => $this->error_mandatory];
293 - }
294 - $layout_options = $this->flow_fields->get_layout_options();
295 - if (!array_key_exists($layout, $layout_options)) {
296 - return ['error' => sprintf(esc_html__('Invalid layout: %s', 'photonic'), $layout)];
297 - }
298 -
299 - // All good. Next screen:
300 - return ['success' => $this->get_layout_options($provider, $display_type, $layout, $existing)];
301 - }
302 - else {
303 - $passworded = isset($_POST['selection_passworded']) ? sanitize_text_field($_POST['selection_passworded']) : '';
304 - $password = isset($_POST['password']) ? sanitize_text_field($_POST['password']) : '';
305 - if (!empty($passworded) && empty($password)) {
306 - return ['error' => $this->error_mandatory];
307 - }
308 - return ['success' => $this->construct_shortcode()];
309 - }
310 329 return '';
311 330 }
312 331
313 332 /**
@@ -317,15 +336,15 @@
317 336 * @param array $fields
318 337 * @param array $existing
319 338 * @return String
320 339 */
321 - private function render_all_fields($fields, $existing = []) {
340 + private function render_all_fields($fields, $existing = []): string {
322 341 $output = '';
323 342 foreach ($fields as $id => $field) {
324 - if (!empty($field['type']) && $field['type'] == 'field_list') {
343 + if (!empty($field['type']) && 'field_list' === $field['type']) {
325 344 $output .= $this->process_field_list($id, $field, $existing);
326 345 }
327 - else if (!empty($field['type'])) {
346 + elseif (!empty($field['type'])) {
328 347 $output .= $this->process_field($id, $field, 0, null, $existing);
329 348 }
330 349 }
331 350 return $output;
@@ -342,10 +361,10 @@
342 361 * @param array $field_list
343 362 * @param array $existing
344 363 * @return string
345 364 */
346 - function process_field_list($field_list_name, $field_list, $existing = []) {
347 - if (!is_array($field_list) || empty($field_list['type']) || $field_list['type'] != 'field_list' || empty($field_list['list'])) {
365 + private function process_field_list($field_list_name, $field_list, $existing = []): string {
366 + if (!is_array($field_list) || empty($field_list['type']) || 'field_list' !== $field_list['type'] || empty($field_list['list'])) {
348 367 return '';
349 368 }
350 369 else {
351 370 $ret = '';
@@ -351,9 +370,9 @@
351 370 $ret = '';
352 371 $counter = 0;
353 372 $sequence_group = null;
354 373 foreach ($field_list['list'] as $id => $field) {
355 - if ($field_list['list_type'] == 'sequence') {
374 + if ('sequence' === $field_list['list_type']) {
356 375 $counter++;
357 376 $sequence_group = $field_list_name;
358 377 }
359 378 $ret .= $this->process_field($id, $field, $counter, $sequence_group, $existing);
@@ -371,209 +390,214 @@
371 390 * @param null $sequence_group
372 391 * @param array $existing
373 392 * @return string
374 393 */
375 - function process_field($id, $field, $sequence, $sequence_group = null, $existing = []) {
394 + private function process_field($id, $field, $sequence, $sequence_group = null, $existing = []): string {
376 395 if (!is_array($field) || empty($field['type'])) {
377 396 return '';
378 397 }
379 398
380 - if (!empty($field['post_condition']) && is_array($field['post_condition'])) {
381 - foreach ($field['post_condition'] as $var => $permitted_values) {
382 - $pass = false;
383 - foreach ($permitted_values as $permitted) {
384 - if (isset($_POST[$var]) && $_POST[$var] === $permitted) {
385 - $pass = true;
386 - break;
399 + $ret = '';
400 +
401 + if (check_ajax_referer('photonic-wizard-next-' . get_current_user_id())) {
402 + if (!empty($field['post_condition']) && is_array($field['post_condition'])) {
403 + foreach ($field['post_condition'] as $var => $permitted_values) {
404 + $pass = false;
405 + foreach ($permitted_values as $permitted) {
406 + if (isset($_POST[$var]) && $_POST[$var] === $permitted) {
407 + $pass = true;
408 + break;
409 + }
387 410 }
411 + if (!$pass) {
412 + // Variable has not been set in a different screen. Hide this field.
413 + return '';
414 + }
388 415 }
389 - if (!$pass) {
390 - // Variable has not been set in a different screen. Hide this field.
391 - return '';
392 - }
393 416 }
394 - }
395 417
396 - $req = empty($field['req']) ? '' : '<span class="photonic-required"><abbr title="'.esc_html__('Required', 'photonic').'">*</abbr></span>';
397 - $default = !empty($existing[$id]) ? $existing[$id] : (isset($field['std']) ? $field['std'] : '');
398 - $hint = '';
399 - $hint_in = '';
400 - if (!empty($field['hint'])) {
401 - $hint = "<div class='photonic-flow-hint' role='tooltip' id='{$id}-hint'>{$field['hint']}</div>\n";
402 - $hint_in = "aria-describedby='{$id}-hint'";
403 - }
418 + $id = esc_attr($id);
419 + $req = empty($field['req']) ? '' : '<span class="photonic-required"><abbr title="' . esc_html__('Required', 'photonic') . '">*</abbr></span>';
420 + $default = esc_attr(!empty($existing[$id]) ? $existing[$id] : ($field['std'] ?? ''));
421 + $hint = '';
422 + $hint_in = '';
423 + if (!empty($field['hint'])) {
424 + $hint = "<div class='photonic-flow-hint' role='tooltip' id='{$id}-hint'>{$field['hint']}</div>\n";
425 + $hint_in = "aria-describedby='" . esc_attr($id) . "-hint'";
426 + }
404 427
405 - switch ($field['type']) {
406 - case 'text':
407 - $ret = "<label class='photonic-flow-option-name'>{$field['desc']}$req<input type='text' name='{$id}' value='" . $default . "' $hint_in/>$hint</label>";
408 - break;
428 + switch ($field['type']) {
429 + case 'text':
430 + $ret = "<label class='photonic-wizard-option-name'>" . wp_kses_post($field['desc']) . $req . "<input type='text' name='$id' value='" . $default . "' $hint_in/>" . wp_kses_post($hint) . "</label>";
431 + break;
409 432
410 - case 'radio':
411 - $ret = !empty($field['desc']) ? '<div class="photonic-flow-option-name">' . $field['desc'] . $req . '</div>' : '';
412 - foreach ($field['options'] as $option_value => $option_description) {
413 - $option_condition = (empty($field['option-conditions']) || empty($field['option-conditions'][$option_value])) ? '' :
414 - "data-photonic-option-condition='" . json_encode($field['option-conditions'][$option_value]) . "'";
415 - $checked = checked($default, $option_value, false);
416 - $ret .= "\t<div class='photonic-flow-field-radio'><label><input type='radio' name='{$id}' value='$option_value' $checked $option_condition/>" . $option_description . "</label></div>\n";
417 - }
418 - break;
433 + case 'radio':
434 + $ret = !empty($field['desc']) ? '<div class="photonic-wizard-option-name">' . wp_kses_post($field['desc']) . $req . '</div>' : '';
435 + $ret .= "<div class='photonic-flow-field-radio-group'>\n";
436 + foreach ($field['options'] as $option_value => $option_description) {
437 + $option_condition = (empty($field['option-conditions']) || empty($field['option-conditions'][$option_value])) ? '' :
438 + "data-photonic-option-condition='" . wp_json_encode($field['option-conditions'][$option_value]) . "'";
439 + $checked = checked($default, $option_value, false);
440 + $ret .= "\t<div class='photonic-flow-field-radio'><label><input type='radio' name='$id' value='" . esc_attr($option_value) . "' $checked $option_condition />" . wp_kses_post($option_description) . "</label></div>\n";
441 + }
442 + $ret .= "</div>\n";
443 + break;
419 444
420 - case 'select':
421 - $ret = "<label class='photonic-flow-option-name'>{$field['desc']}$req\n\t<select name='{$id}' $hint_in>\n";
422 - foreach ($field['options'] as $option_value => $option_description) {
423 - $option_condition = (empty($field['option-conditions']) || empty($field['option-conditions'][$option_value])) ? '' :
424 - "data-photonic-option-condition='" . json_encode($field['option-conditions'][$option_value]) . "'";
425 - $selected = selected($default, $option_value, false);
426 - $ret .= "\t\t<option value='$option_value' $selected $option_condition>" . esc_attr($option_description) . "</option>\n";
427 - }
428 - $ret .= "\t</select>\n$hint</label>\n";
429 - break;
445 + case 'select':
446 + $ret = "<label class='photonic-wizard-option-name'>" . wp_kses_post($field['desc']) . $req . "\n\t<select name='$id' $hint_in>\n";
447 + foreach ($field['options'] as $option_value => $option_description) {
448 + $option_condition = (empty($field['option-conditions']) || empty($field['option-conditions'][$option_value])) ? '' :
449 + "data-photonic-option-condition='" . wp_json_encode($field['option-conditions'][$option_value]) . "'";
450 + $selected = selected($default, $option_value, false);
451 + $ret .= "\t\t<option value='" . esc_attr($option_value) . "' $selected $option_condition>" . esc_attr($option_description) . "</option>\n";
452 + }
453 + $ret .= "\t</select>\n" . wp_kses_post($hint) . "</label>\n";
454 + break;
430 455
431 - case 'image-select':
432 - $ret = '';
433 - $ret .= '<div class="photonic-flow-option-name">' . $field['desc'] . '</div>';
434 - if (!empty($default)) {
435 - $selection = !in_array($default, $field['options']) ? array_keys($field['options'])[0] : $default;
436 - }
437 - else {
438 - $selection = array_keys($field['options'])[0];
439 - }
440 - foreach ($field['options'] as $option_name => $desc) {
441 - $esc_desc = esc_attr($desc);
442 - $selected = ($option_name == $selection) ? 'selected' : '';
443 - $ret .= "<div class=\"photonic-flow-selector photonic-flow-$id-$option_name $selected\" title=\"$esc_desc\">\n\t<span class=\"photonic-flow-selector-inner photonic-$id\" data-photonic-selection-id=\"$option_name\">&nbsp;</span>\n\t<div class='photonic-flow-selector-info'>$desc</div>\n</div>\n";
444 - }
445 - if (!empty($ret)) {
446 - $ret = "<div class='photonic-flow-selector-container photonic-flow-$id' data-photonic-flow-selector-mode='single-no-plus' data-photonic-flow-selector-for=\"$id\">\n<input type=\"hidden\" id=\"$id\" name=\"$id\" value='$selection'/>\n$ret</div>\n";
447 - }
448 - break;
449 -
450 - case 'multi-select':
451 - $ret = '';
452 - $ret .= '<div class="photonic-flow-option-name">' . $field['desc'] . '</div>';
453 - $selection = explode(',', $default);
454 - foreach ($field['options'] as $option_value => $desc) {
455 - $checked = in_array($option_value, $selection) ? 'checked' : '';
456 - $ret .= "\t<label class='photonic-multi-select-item'><input type='checkbox' name='{$id}[]' value=\"$option_value\" $checked />$desc</label>\n";
457 - }
458 - if (!empty($ret)) {
459 - $ret = "<div class='photonic-flow-multi-select-container'>\n$ret</div>\n";
460 - }
461 - break;
462 -
463 - case 'date-filter':
464 - $ret = '';
465 - $ret .= '<div class="photonic-flow-option-name">' . $field['desc'] . '</div>';
466 - $dates = !empty($default) ? explode(',', $default) : [];
467 - $count = isset($field['count']) && is_numeric($field['count']) ? intval($field['count']) : 1;
468 - $ret .= "<ol data-photonic-date-filter='$id' data-photonic-filter-count='$count'>\n";
469 - $ctr = 0;
470 - foreach ($dates as $didx => $date) {
471 - $y_m_d = explode('/', $date);
472 - $ret .= "\t<li>\n";
473 - $ret .= "\t\t<div class='photonic-single-date'>\n";
474 - for ($pidx = 0; $pidx < 3; $pidx++) {
475 - $lower = strtolower($this->date_parts[$pidx]);
476 - $ret .= "\t\t\t<label class='photonic-date-filter'>\n" .
477 - "\t\t\t\t".substr($this->date_parts[$pidx], 0, 1)."<input type='text' class='photonic-date-$lower' name='{$id}_{$lower}[]' value=\"" . (isset($y_m_d[$pidx]) ? $y_m_d[$pidx] : '') . "\" aria-describedby='{$id}-{$didx}_{$lower}-hint'/>\n" .
478 - "\t\t\t\t<div class='photonic-flow-hint' role='tooltip' id='{$id}-{$didx}_{$lower}-hint'>" . $this->date_part_hints[$pidx] . "</div>\n" .
479 - "\t\t\t</label> \n";
456 + case 'image-select':
457 + if (!empty($default)) {
458 + $selection = !in_array($default, array_keys($field['options']), true) ? array_keys($field['options'])[0] : $default;
480 459 }
481 - $ret .= "\t\t</div>\n";
482 - $ret .= "\t\t<a href='#' class='photonic-remove-date-filter' title='Remove filter'><span class=\"dashicons dashicons-no\"> </span></a>\n";
483 - $ret .= "\t</li>\n";
484 - $ctr++;
485 - if ($ctr >= $count) {
486 - break;
460 + else {
461 + $selection = array_keys($field['options'])[0];
487 462 }
488 - }
489 - $ret .= "</ol>\n";
490 - $ret .= "<input type='hidden' name='$id' value='$default'/>\n";
491 - if ($ctr < $count) {
492 - $ret .= "<a href='#' class='photonic-add-date-filter' data-photonic-add-date='$id'><span class=\"dashicons dashicons-plus-alt\"> </span> Add filter</a>\n";
493 - }
494 463
495 - break;
464 + $ret = "<div class='photonic-flow-selector-container photonic-flow-$id' data-photonic-flow-selector-mode='single-no-plus' data-photonic-flow-selector-for=\"$id\">\n<input type=\"hidden\" id=\"$id\" name=\"$id\" value='$selection'/>\n";
465 + $ret .= '<div class="photonic-wizard-option-name">' . wp_kses_post($field['desc']) . '</div>';
466 + foreach ($field['options'] as $option_name => $desc) {
467 + $option_name = esc_attr($option_name);
468 + $esc_desc = esc_attr($desc);
469 + $selected = ($option_name === $selection) ? 'selected' : '';
470 + $ret .= "<div class=\"photonic-flow-selector photonic-flow-$id-$option_name $selected\" title=\"$esc_desc\">\n\t<span class=\"photonic-flow-selector-inner photonic-$id\" data-photonic-selection-id=\"$option_name\">&nbsp;</span>\n\t<div class='photonic-flow-selector-info'>" . wp_kses_post($desc) . "</div>\n</div>\n";
471 + }
472 + $ret .= "</div>\n";
473 + break;
496 474
497 - case 'date-range-filter':
498 - $ret = '';
499 - $ret .= '<div class="photonic-flow-option-name">' . $field['desc'] . '</div>';
500 - $date_ranges = !empty($default) ? explode(',', $default) : [];
501 - $count = isset($field['count']) && is_numeric($field['count']) ? intval($field['count']) : 1;
502 - $ret .= "<ol data-photonic-date-range-filter='$id' data-photonic-filter-count='$count'>\n";
503 - $ctr = 0;
504 - foreach ($date_ranges as $date_range) {
505 - $from_to = explode('-', $date_range);
506 - if (count($from_to) != 2) {
507 - continue;
475 + case 'multi-select':
476 + $ret = "<div class='photonic-flow-multi-select-container'>\n";
477 + $ret .= '<div class="photonic-wizard-option-name">' . wp_kses_post($field['desc']) . '</div>';
478 + $selection = explode(',', $default);
479 + foreach ($field['options'] as $option_value => $desc) {
480 + $checked = in_array($option_value, $selection, true) ? 'checked' : '';
481 + $ret .= "\t<label class='photonic-multi-select-item'><input type='checkbox' name='{$id}[]' value=\"" . esc_attr($option_value) . "\" $checked />" . wp_kses_post($desc) . "</label>\n";
508 482 }
509 - $ret .= "\t<li>\n";
510 - foreach ($from_to as $didx => $date) {
483 + $ret .= "</div>\n";
484 + break;
485 +
486 + case 'date-filter':
487 + $ret = '';
488 + $ret .= '<div class="photonic-wizard-option-name">' . wp_kses_post($field['desc']) . '</div>';
489 + $dates = !empty($default) ? explode(',', $default) : [];
490 + $count = isset($field['count']) && is_numeric($field['count']) ? intval($field['count']) : 1;
491 + $ret .= "<ol data-photonic-date-filter='$id' data-photonic-filter-count='$count'>\n";
492 + $ctr = 0;
493 + foreach ($dates as $didx => $date) {
494 + $y_m_d = explode('/', $date);
495 + $ret .= "\t<li>\n";
511 496 $ret .= "\t\t<div class='photonic-single-date'>\n";
512 - $y_m_d = explode('/', $date);
513 - $from_or_to = $didx === 0 ? 'start' : 'end';
514 497 for ($pidx = 0; $pidx < 3; $pidx++) {
515 - $lower = strtolower($this->date_parts[$pidx]);
498 + $lower = esc_attr(strtolower($this->date_parts[$pidx]));
516 499 $ret .= "\t\t\t<label class='photonic-date-filter'>\n" .
517 - "\t\t\t\t".substr($this->date_parts[$pidx], 0, 1)."<input type='text' class='photonic-date-$lower' name='{$id}_{$from_or_to}_{$lower}[]' value=\"" . (isset($y_m_d[$pidx]) ? $y_m_d[$pidx] : '') . "\" aria-describedby='{$id}-{$didx}_{$from_or_to}_{$lower}-hint'/>\n" .
518 - "\t\t\t\t<div class='photonic-flow-hint' role='tooltip' id='{$id}-{$didx}_{$from_or_to}_{$lower}-hint'>" . $this->date_part_hints[$pidx] . "</div>\n" .
500 + "\t\t\t\t" . wp_kses_post(substr($this->date_parts[$pidx], 0, 1)) . "<input type='text' class='photonic-date-$lower' name='{$id}_{$lower}[]' value='" . esc_attr($y_m_d[$pidx] ?? '') . "' aria-describedby='{$id}-{$didx}_{$lower}-hint'/>\n" .
501 + "\t\t\t\t<div class='photonic-flow-hint' role='tooltip' id='{$id}-{$didx}_{$lower}-hint'>" . wp_kses_post($this->date_part_hints[$pidx]) . "</div>\n" .
519 502 "\t\t\t</label> \n";
520 503 }
521 504 $ret .= "\t\t</div>\n";
505 + $ret .= "\t\t<a href='#' class='photonic-remove-date-filter' title='Remove filter'><span class=\"dashicons dashicons-no\"> </span></a>\n";
506 + $ret .= "\t</li>\n";
507 + $ctr++;
508 + if ($ctr >= $count) {
509 + break;
510 + }
522 511 }
523 - $ret .= "\t\t<a href='#' class='photonic-remove-date-range-filter' title='Remove filter'><span class=\"dashicons dashicons-no\"> </span></a>\n";
524 - $ret .= "\t</li>\n";
525 - $ctr++;
526 - if ($ctr >= $count) {
527 - break;
512 + $ret .= "</ol>\n";
513 + $ret .= "<input type='hidden' name='$id' value='" . esc_attr($default) . "'/>\n";
514 + if ($ctr < $count) {
515 + $ret .= "<a href='#' class='photonic-add-date-filter' data-photonic-add-date='$id'><span class=\"dashicons dashicons-plus-alt\"> </span> Add filter</a>\n";
528 516 }
529 - }
530 - $ret .= "</ol>\n";
531 - $ret .= "<input type='hidden' name='$id' value='$default'/>\n";
532 - if ($ctr < $count) {
533 - $ret .= "<a href='#' class='photonic-add-date-range-filter' data-photonic-add-date-range='$id'><span class=\"dashicons dashicons-plus-alt\"> </span> Add filter</a>\n";
534 - }
535 517
536 - break;
518 + break;
537 519
538 - case 'thumbnail-selector':
539 - $ret = "<div class=\"photonic-flow-selector-container\" data-photonic-flow-selector-mode=\"{$field['mode']}\" data-photonic-flow-selector-for=\"{$field['for']}\">\n{{placeholder_value}}</div>\n";
520 + case 'date-range-filter':
521 + $ret = '';
522 + $ret .= '<div class="photonic-wizard-option-name">' . wp_kses_post($field['desc']) . '</div>';
523 + $date_ranges = !empty($default) ? explode(',', $default) : [];
524 + $count = esc_attr(isset($field['count']) && is_numeric($field['count']) ? intval($field['count']) : 1);
525 + $ret .= "<ol data-photonic-date-range-filter='$id' data-photonic-filter-count='$count'>\n";
526 + $ctr = 0;
527 + foreach ($date_ranges as $date_range) {
528 + $from_to = explode('-', $date_range);
529 + if (count($from_to) !== 2) {
530 + continue;
531 + }
532 + $ret .= "\t<li>\n";
533 + foreach ($from_to as $didx => $date) {
534 + $ret .= "\t\t<div class='photonic-single-date'>\n";
535 + $y_m_d = explode('/', $date);
536 + $from_or_to = 0 === $didx ? 'start' : 'end';
537 + for ($pidx = 0; $pidx < 3; $pidx++) {
538 + $lower = strtolower($this->date_parts[$pidx]);
539 + $ret .= "\t\t\t<label class='photonic-date-filter'>\n" .
540 + "\t\t\t\t" . substr($this->date_parts[$pidx], 0, 1) . "<input type='text' class='photonic-date-$lower' name='{$id}_{$from_or_to}_{$lower}[]' value=\"" . ($y_m_d[$pidx] ?? '') . "\" aria-describedby='{$id}-{$didx}_{$from_or_to}_{$lower}-hint'/>\n" .
541 + "\t\t\t\t<div class='photonic-flow-hint' role='tooltip' id='{$id}-{$didx}_{$from_or_to}_{$lower}-hint'>" . wp_kses_post($this->date_part_hints[$pidx]) . "</div>\n" .
542 + "\t\t\t</label> \n";
543 + }
544 + $ret .= "\t\t</div>\n";
545 + }
546 + $ret .= "\t\t<a href='#' class='photonic-remove-date-range-filter' title='Remove filter'><span class=\"dashicons dashicons-no\"> </span></a>\n";
547 + $ret .= "\t</li>\n";
548 + $ctr++;
549 + if ($ctr >= $count) {
550 + break;
551 + }
552 + }
553 + $ret .= "</ol>\n";
554 + $ret .= "<input type='hidden' name='$id' value='$default'/>\n";
555 + if ($ctr < $count) {
556 + $ret .= "<a href='#' class='photonic-add-date-range-filter' data-photonic-add-date-range='$id'><span class=\"dashicons dashicons-plus-alt\"> </span> Add filter</a>\n";
557 + }
540 558
541 - $controls = "<div class='thumb-controls'>\n";
542 - if ($field['mode'] != 'none') {
543 - $controls .= "<input type='text' class='search-thumbs' name='thumb-search' id='thumb-search'/>\n";
544 - }
559 + break;
545 560
546 - if ($field['mode'] == 'multi') {
547 - $controls .= esc_html__('Mark:', 'photonic').
548 - sprintf(esc_html__('%1$sAll%2$s', 'photonic'), "<a href='#' class='photonic-mark photonic-mark-all' data-photonic-mark-for='{$field['for']}'>", '</a>').'|'.
549 - sprintf(esc_html__('%1$sNone%2$s', 'photonic'), "<a href='#' class='photonic-mark photonic-mark-none' data-photonic-mark-for='{$field['for']}'>", '</a>');
550 - }
551 - $controls .= "</div>\n";
552 - $ret = $controls.$ret;
553 - break;
561 + case 'thumbnail-selector':
562 + $ret = "<div class=\"photonic-flow-selector-container\" data-photonic-flow-selector-mode=\"{$field['mode']}\" data-photonic-flow-selector-for=\"{$field['for']}\">\n{{placeholder_value}}</div>\n";
554 563
555 - default:
556 - return '';
557 - }
564 + $controls = "<div class='thumb-controls'>\n";
565 + if ('none' !== $field['mode']) {
566 + $controls .= "<input type='text' class='search-thumbs' name='thumb-search' id='thumb-search'/>\n";
567 + }
558 568
559 - if (!empty($ret)) {
560 - $sequence_str = '';
561 - if ($sequence !== 0) {
562 - $sequence_str = 'data-photonic-flow-sequence="' . $sequence . '"';
569 + if ('multi' === $field['mode']) {
570 + $controls .= esc_html__('Mark:', 'photonic') .
571 + sprintf(esc_html__('%1$sAll%2$s', 'photonic'), "<a href='#' class='photonic-mark photonic-mark-all' data-photonic-mark-for='{$field['for']}'>", '</a>') . '|' .
572 + sprintf(esc_html__('%1$sNone%2$s', 'photonic'), "<a href='#' class='photonic-mark photonic-mark-none' data-photonic-mark-for='{$field['for']}'>", '</a>');
573 + }
574 + $controls .= "</div>\n";
575 + $ret = $controls . $ret;
576 + break;
577 +
578 + default:
579 + return '';
563 580 }
564 581
565 - $sequence_group_str = '';
566 - if (!is_null($sequence_group)) {
567 - $sequence_group_str = 'data-photonic-flow-sequence-group="' . $sequence_group . '"';
568 - }
582 + if (!empty($ret)) {
583 + $sequence_str = '';
584 + if (0 !== $sequence) {
585 + $sequence_str = 'data-photonic-flow-sequence="' . esc_attr($sequence) . '"';
586 + }
569 587
570 - $condition = '';
571 - if (!empty($field['conditions'])) {
572 - $condition = "data-photonic-condition='" . json_encode($field['conditions']) . "'";
588 + $sequence_group_str = '';
589 + if (!is_null($sequence_group)) {
590 + $sequence_group_str = 'data-photonic-flow-sequence-group="' . esc_attr($sequence_group) . '"';
591 + }
592 +
593 + $condition = '';
594 + if (!empty($field['conditions'])) {
595 + $condition = "data-photonic-condition='" . wp_json_encode($field['conditions']) . "'";
596 + }
597 +
598 + $ret = "<div class='photonic-flow-field' $sequence_str $condition $sequence_group_str>\n" . $ret . "</div>\n";
573 599 }
574 -
575 - $ret = "<div class='photonic-flow-field' $sequence_str $condition $sequence_group_str>\n" . $ret . "</div>\n";
576 600 }
577 601 return $ret;
578 602 }
579 603
@@ -585,18 +609,20 @@
585 609 * @param bool $check_required
586 610 * @return array|bool
587 611 */
588 612 private function do_basic_option_check($id, $field, $check_required = false) {
589 - if (empty($field['type']) || ($field['type'] != 'select' && $field['type'] != 'radio')) {
590 - return false;
591 - }
613 + if (check_ajax_referer('photonic-wizard-next-' . get_current_user_id())) {
614 + if (empty($field['type']) || ('select' !== $field['type'] && 'radio' !== $field['type'])) {
615 + return false;
616 + }
592 617
593 - if ($check_required && !empty($field['req']) && (!isset($_POST[$id]) || trim($_POST[$id]) === '')) {
594 - return ['error' => $this->error_mandatory];
595 - }
618 + if ($check_required && !empty($field['req']) && (!isset($_POST[$id]) || '' === trim($_POST[$id]))) {
619 + return ['error' => $this->error_mandatory];
620 + }
596 621
597 - if (isset($_POST[$id]) && !in_array(sanitize_text_field($_POST[$id]), array_keys($field['options']))) {
598 - return ['error' => sprintf($this->error_not_permitted, $field['name'], $_POST[$id])];
622 + if (isset($_POST[$id]) && !in_array(sanitize_text_field($_POST[$id]), array_keys($field['options']), false)) { // Need strict = false, otherwise if $field['options'] returns integers, string comparison fails. E.g. Zenfolio categories
623 + return ['error' => sprintf($this->error_not_permitted, $id, sanitize_text_field($_POST[$id]))];
624 + }
599 625 }
600 626 return false;
601 627 }
602 628
@@ -608,43 +634,45 @@
608 634 * @param array $existing
609 635 * @param null $provider
610 636 * @return string
611 637 */
612 - private function get_layout_selector($display_type, $existing = [], $provider = null) {
638 + private function get_layout_selector($display_type, $existing = [], $provider = null): string {
613 639 global $photonic_thumbnail_style;
614 640 $output = '';
615 641 $level = empty($this->display_types[$display_type]) ? -1 : $this->display_types[$display_type];
616 -// $layout_from_option = empty($existing['layout']) ? (in_array($photonic_thumbnail_style, ['strip-below', 'strip-above', 'strip-right', 'no-strip']) ? 'slideshow' : $photonic_thumbnail_style) : $existing['layout'];
617 642 if (empty($existing['layout'])) {
618 - if (in_array($photonic_thumbnail_style, ['strip-below', 'strip-above', 'strip-right', 'no-strip'])) {
643 + if (in_array($photonic_thumbnail_style, ['strip-below', 'strip-above', 'strip-right', 'no-strip'], true)) {
619 644 $layout_from_option = 'slideshow';
620 645 }
621 - else if ($photonic_thumbnail_style == 'square' && !empty($provider) && $provider == 'instagram') {
646 + elseif ('square' === $photonic_thumbnail_style && !empty($provider) && 'instagram' === $provider) {
622 647 $layout_from_option = 'random';
623 648 }
624 649 else {
625 - $layout_from_option = $photonic_thumbnail_style;
650 + $layout_from_option = sanitize_text_field($photonic_thumbnail_style);
626 651 }
627 652 }
628 653 else {
629 - $layout_from_option = $existing['layout'];
654 + $layout_from_option = sanitize_text_field($existing['layout']);
630 655 }
631 656
632 657 if ($level > 0) {
633 658 $layout_options = $this->flow_fields->get_layout_options();
634 659 foreach ($layout_options as $layout => $desc) {
635 - $selected = $layout == $layout_from_option ? 'selected' : '';
636 - if (($layout == 'slideshow' && $level == 1) || $layout != 'slideshow') {
660 + $selected = $layout === $layout_from_option ? 'selected' : '';
661 + if (('slideshow' === $layout && 1 === $level) || 'slideshow' !== $layout) {
637 662 $esc_desc = esc_attr($desc);
638 - $output .= "<div class=\"photonic-flow-selector photonic-flow-layout-$layout $selected\" title=\"$esc_desc\">\n\t<span class=\"photonic-flow-selector-inner photonic-layout\" data-photonic-selection-id=\"$layout\">&nbsp;</span>\n\t<div class='photonic-flow-selector-info'>$desc</div>\n</div>\n";
663 + $output .= "<div class=\"photonic-flow-selector photonic-flow-layout-$layout $selected\" title=\"$esc_desc\">\n
664 + \t<span class=\"photonic-flow-selector-inner photonic-layout\" data-photonic-selection-id=\"$layout\">&nbsp;</span>\n
665 + \t<div class='photonic-flow-selector-info'>$desc</div>\n
666 + </div>\n";
639 667 }
640 668 }
641 669 if (!empty($output)) {
642 - $output = "<div class='photonic-flow-selector-container photonic-flow-layout' data-photonic-flow-selector-mode='single-no-plus' data-photonic-flow-selector-for=\"layout\">\n<input type=\"hidden\" id=\"layout\" name=\"layout\" value='$layout_from_option'/>\n$output</div>\n";
670 + $output = "<div class='photonic-flow-selector-container photonic-flow-layout' data-photonic-flow-selector-mode='single-no-plus' data-photonic-flow-selector-for=\"layout\">\n<input type=\"hidden\" id=\"layout\" name=\"layout\" value='" . esc_attr($layout_from_option) . "'/>\n$output</div>\n";
643 671 }
644 672 }
645 673 $output = '<h1>' . esc_html__('Pick Your Layout', 'photonic') . '</h1>' .
646 - "<p>" . sprintf(esc_html__('You can configure the default settings from %s.', 'photonic'), '<strong>Photonic &rarr; Settings &rarr; Generic Options &rarr; Generic Settings &rarr; Layouts</strong>') . "</p>\n".
674 + "<p>" . sprintf(esc_html__('You can configure the default settings from %s.', 'photonic'), '<strong>Photonic &rarr; Settings &rarr; Generic Options &rarr; Generic Settings &rarr; Layouts</strong>') . "</p>\n" .
647 675 $output;
648 676
649 677 if ($this->force_next_screen > -1) {
650 678 $output .= "\n<input type='hidden' name='force_next_screen' value='{$this->force_next_screen}'/>\n";
@@ -666,9 +694,9 @@
666 694 * @param $layout
667 695 * @param array $existing
668 696 * @return string
669 697 */
670 - private function get_layout_options($provider, $display_type, $layout, $existing = []) {
698 + private function get_layout_options($provider, $display_type, $layout, $existing = []): string {
671 699 // All levels, all layouts - media
672 700 // L1, L2 All layouts - title position
673 701 // L1 All layouts - count, more
674 702 // L1, L2, L3 basic lightbox layouts - # of columns, constrain by etc., thumbnail size, full size
@@ -698,8 +726,13 @@
698 726 if (!empty($screen_fields[$layout])) {
699 727 $extract = array_merge($screen_fields[$layout], $extract);
700 728 }
701 729
730 +/* if ('wp' === $provider) {
731 + unset($extract['count']);
732 + unset($extract['more']);
733 + }*/
734 +
702 735 $output .= $this->render_all_fields($extract, $existing);
703 736 return $output;
704 737 }
705 738
@@ -708,159 +741,171 @@
708 741 * Others are used to determine other attributes, e.g. <code>display_type</code>
709 742 *
710 743 * @return string
711 744 */
712 - private function construct_shortcode() {
713 - global $photonic_alternative_shortcode;
745 + private function construct_shortcode(): string {
746 + $output = '';
714 747
715 - $provider = sanitize_text_field($_POST['provider']);
716 - $display_type = sanitize_text_field($_POST['display_type']);
748 + if (check_ajax_referer('photonic-wizard-next-' . get_current_user_id())) {
749 + global $photonic_alternative_shortcode;
717 750
718 - $short_code = [];
719 - if ($provider !== 'wp') {
720 - $short_code['type'] = $provider;
721 - }
751 + $provider = sanitize_text_field(wp_unslash($_POST['provider']));
752 + $display_type = sanitize_text_field($_POST['display_type']);
722 753
723 - // Get specific attributes for a provider
724 - $gallery = $this->flow_fields->get_source($provider);
725 - $gallery_attr = $gallery->construct_shortcode_from_screen_selections($display_type);
726 - $short_code = array_merge($short_code, $gallery_attr);
754 + $short_code = [];
755 + if ('wp' !== $provider) {
756 + $short_code['type'] = $provider;
757 + }
727 758
728 - if (!empty($_POST['selection'])) {
729 - if ($_POST['selection'] != 'all') {
730 - $short_code['filter'] = sanitize_text_field($_POST['selected_data']);
759 + // Get specific attributes for a provider
760 + $gallery = $this->flow_fields->get_source($provider);
761 + $gallery_attr = $gallery->construct_shortcode_from_screen_selections($display_type);
762 + $short_code = array_merge($short_code, $gallery_attr);
763 +
764 + if (!empty($_POST['selection'])) {
765 + if ('all' !== $_POST['selection']) {
766 + $short_code['filter'] = sanitize_text_field($_POST['selected_data']);
767 + }
768 + if ('not-selected' === $_POST['selection']) {
769 + $short_code['filter_type'] = 'exclude';
770 + }
731 771 }
732 - if ($_POST['selection'] == 'not-selected') {
733 - $short_code['filter_type'] = 'exclude';
772 +
773 + if (isset($_POST['headers']) && '' !== $_POST['headers']) {
774 + if ('none' === trim($_POST['headers'])) {
775 + $short_code['headers'] = '';
776 + }
777 + else {
778 + $short_code['headers'] = sanitize_text_field($_POST['headers']);
779 + }
734 780 }
735 - }
736 781
737 - if (isset($_POST['headers']) && trim($_POST['headers'] !== '')) {
738 - if (trim($_POST['headers']) == 'none') {
739 - $short_code['headers'] = '';
782 + $additional_attrs = array_merge(
783 + $this->shortcode_attributes[$provider],
784 + $this->shortcode_attributes['common']
785 + );
786 + foreach ($additional_attrs as $attr) {
787 + if (!empty($_POST[$attr]) && is_array($_POST[$attr])) {
788 + $short_code[$attr] = sanitize_text_field(implode(',', $_POST[$attr]));
789 + }
790 + elseif (!empty($_POST[$attr])) {
791 + $short_code[$attr] = sanitize_text_field($_POST[$attr]);
792 + }
740 793 }
741 - else {
742 - $short_code['headers'] = sanitize_text_field($_POST['headers']);
743 - }
744 - }
745 794
746 - $additional_attrs = array_merge(
747 - $this->shortcode_attributes[$provider],
748 - $this->shortcode_attributes['common']
749 - );
750 - foreach ($additional_attrs as $attr) {
751 - if (!empty($_POST[$attr]) && is_array($_POST[$attr])) {
752 - $short_code[$attr] = implode(',', $_POST[$attr]);
795 + if (!empty($_POST['layout'])) {
796 + $key = 'wp' === $provider ? 'style' : 'layout';
797 + if ('slideshow' !== $_POST['layout']) {
798 + $short_code[$key] = sanitize_text_field($_POST['layout']);
799 + }
800 + else {
801 + $short_code[$key] = sanitize_text_field($_POST['slideshow-style']);
802 + }
753 803 }
754 - else if (!empty($_POST[$attr])) {
755 - $short_code[$attr] = $_POST[$attr];
756 - }
757 - }
804 + // layout
758 805
759 - if (!empty($_POST['layout'])) {
760 - $key = $provider == 'wp' ? 'style' : 'layout';
761 - if ($_POST['layout'] != 'slideshow') {
762 - $short_code[$key] = sanitize_text_field($_POST['layout']);
806 + $raw_shortcode = !empty($_POST['photonic-editor-shortcode-raw']) ? sanitize_text_field($_POST['photonic-editor-shortcode-raw']) : '';
807 + if (!empty($raw_shortcode)) {
808 + $input = base64_decode($raw_shortcode); // The in-flight shortcode is passed from screen to screen using the JS function `btoa`, in wizard.js, which encodes it
809 + $input = json_decode($input);
810 + if (!empty($input->shortcode) && !empty($input->shortcode->attrs) && !empty($input->shortcode->attrs->named)) {
811 + $input = $input->shortcode->attrs->named;
812 + }
763 813 }
764 814 else {
765 - $short_code[$key] = sanitize_text_field($_POST['slideshow-style']);
815 + $raw_shortcode = !empty($_POST['photonic-editor-json']) ? stripslashes_deep(sanitize_text_field($_POST['photonic-editor-json'])) : '';
816 + $input = json_decode($raw_shortcode);
766 817 }
767 - }
768 - // layout
769 818
770 - $raw_shortcode = !empty($_POST['photonic-editor-shortcode-raw']) ? sanitize_text_field($_POST['photonic-editor-shortcode-raw']) : '';
771 - if (!empty($raw_shortcode)) {
772 - $input = base64_decode($raw_shortcode);
773 - $input = json_decode($input);
774 - if (!empty($input->shortcode) && !empty($input->shortcode->attrs) && !empty($input->shortcode->attrs->named)) {
775 - $input = $input->shortcode->attrs->named;
776 - }
777 - }
778 - else {
779 - $raw_shortcode = !empty($_POST['photonic-editor-json']) ? stripslashes_deep($_POST['photonic-editor-json']) : '';
780 - $input = json_decode($raw_shortcode);
781 - }
819 + if (!empty($input)) {
820 + $attr_array = (array) $input;
782 821
783 - if (!empty($input)) {
784 - $attr_array = (array)$input;
822 + // If the type changes, regardless of everything else blank out the attributes
823 + if (!(empty($short_code['type']) && (empty($attr_array['type']) || in_array($attr_array['type'], ['wp', 'default'], true))) &&
824 + ($attr_array['type'] !== $short_code['type'])) {
825 + $attr_array = [];
826 + }
827 + else {
828 + foreach ($short_code as $key => $value) {
829 + unset($attr_array[$key]);
830 + }
831 + }
785 832
786 - // If the type changes, regardless of everything else blank out the attributes
787 - if (!(empty($short_code['type']) && (empty($attr_array['type']) || in_array($attr_array['type'], ['wp', 'default']))) &&
788 - ($attr_array['type'] != $short_code['type'])) {
789 - $attr_array = [];
790 - }
791 - else {
792 - foreach ($short_code as $key => $value) {
793 - unset($attr_array[$key]);
833 + if (!empty($this->aka_attributes[$provider])) {
834 + $aka = $this->aka_attributes[$provider];
835 + foreach ($aka as $key => $value) {
836 + if (isset($short_code[$key]) || isset($short_code[$value])) {
837 + unset($attr_array[$key]);
838 + }
839 + }
794 840 }
795 - }
796 841
797 - if (!empty($this->aka_attributes[$provider])) {
798 - $aka = $this->aka_attributes[$provider];
799 - foreach ($aka as $key => $value) {
800 - if (isset($short_code[$key]) || isset($short_code[$value])) unset($attr_array[$key]);
842 + // Others ...
843 + if (!empty($short_code['type']) && 'instagram' === $short_code['type']) {
844 + if (!empty($short_code['media_id'])) {
845 + unset($attr_array['view']);
846 + unset($attr_array['media']);
847 + }
848 + elseif (!empty($short_code['media'])) {
849 + unset($attr_array['media_id']);
850 + }
801 851 }
802 - }
803 852
804 - // Others ...
805 - if (!empty($short_code['type']) && $short_code['type'] == 'instagram') {
806 - if (!empty($short_code['media_id'])) {
807 - unset($attr_array['view']);
808 - unset($attr_array['media']);
853 + if (!empty($short_code['type']) && 'flickr' === $short_code['type'] && in_array($display_type, ['multi-album', 'multi-gallery', 'collections'], true)) {
854 + unset($attr_array['photoset_id']);
855 + unset($attr_array['gallery_id']);
856 + unset($attr_array['collection_id']);
809 857 }
810 - else if (!empty($short_code['media'])) {
811 - unset($attr_array['media_id']);
858 +
859 + foreach ($attr_array as $key => $value) {
860 + if (in_array($key, ['more', 'photo_more', 'count', 'photo_count', 'photo_layout', 'show_gallery', 'order', 'orderby', 'link'], true) && empty($short_code[$key])) {
861 + unset($attr_array[$key]);
862 + }
812 863 }
864 + $short_code = array_merge($short_code, $attr_array);
813 865 }
814 866
815 - foreach ($attr_array as $key => $value) {
816 - if (in_array($key, ['more', 'photo_more', 'count', 'photo_count', 'photo_layout', 'show_gallery']) && empty($short_code[$key])) {
817 - unset($attr_array[$key]);
867 + if (!$this->is_gutenberg) {
868 + $output = '<h1>' . esc_html__('Your shortcode', 'photonic') . '</h1>';
869 + $output .= "<code id='photonic_shortcode'>[" . esc_html($photonic_alternative_shortcode ?: 'gallery') . ' ';
870 + $shortcode_attrs = [];
871 + foreach ($short_code as $attr => $value) {
872 + $shortcode_attrs[] = $attr . "='" . esc_attr($value) . "'";
818 873 }
874 +
875 + $output .= implode(' ', $shortcode_attrs);
876 + $output .= ']</code>';
877 + $output .= '<p>' . esc_html__('The above shortcode was generated based on your selections. You can either copy the above and paste it manually into your post, or click on the buttons below to insert it into or update your post', 'photonic') . '</p>';
819 878 }
820 - $short_code = array_merge($short_code, $attr_array);
821 - }
879 + else {
880 + $output = '<h1>' . esc_html__('Your Gallery', 'photonic') . '</h1>';
881 + $output .= '<p>' . esc_html__('Based on your selections a gallery with the following attributes will be generated. Please click on the buttons below to insert it into or update your post:', 'photonic') . '</p>';
882 + $shortcode_attrs = [];
883 + foreach ($short_code as $attr => $value) {
884 + $shortcode_attrs[] = '<code>' . $attr . ": " . esc_attr($value) . '</code>';
885 + }
886 + $output .= implode("<br/>\n", $shortcode_attrs);
822 887
823 - if (!$this->is_gutenberg) {
824 - $output = '<h1>' . esc_html__('Your shortcode', 'photonic') . '</h1>';
825 - $output .= "<code id='photonic_shortcode'>[" . (empty($photonic_alternative_shortcode) ? 'gallery' : $photonic_alternative_shortcode).' ';
826 - $shortcode_attrs = [];
827 - foreach ($short_code as $attr => $value) {
828 - $shortcode_attrs[] = $attr . "='" . esc_attr($value) . "'";
888 + $output .= '<p>' . esc_html__('The following is the corresponding shortcode for this block. If for some reason you are unable to create a Photonic block you can paste this into a Shortcode block:', 'photonic') . '</p>';
889 + $output .= "<code>[" . (empty($photonic_alternative_shortcode) ? 'gallery' : $photonic_alternative_shortcode) . ' ';
890 + $shortcode_attrs = [];
891 + foreach ($short_code as $attr => $value) {
892 + $shortcode_attrs[] = $attr . "='" . esc_attr($value) . "'";
893 + }
894 +
895 + $output .= implode(' ', $shortcode_attrs);
896 + $output .= ']</code>';
897 +
898 + $output .= "<input id='photonic_shortcode' name='photonic_shortcode' type='hidden' value='" . esc_attr(wp_json_encode($short_code)) . "' />\n";
829 899 }
830 900
831 - $output .= implode(' ', $shortcode_attrs);
832 - $output .= ']</code>';
833 - $output .= '<p>'.esc_html__('The above shortcode was generated based on your selections. You can either copy the above and paste it manually into your post, or click on the buttons below to insert it into or update your post', 'photonic').'</p>';
834 - }
835 - else {
836 - $output = '<h1>' . esc_html__('Your Gallery', 'photonic') . '</h1>';
837 - $output .= '<p>'.esc_html__('Based on your selections a gallery with the following attributes will be generated. Please click on the buttons below to insert it into or update your post:', 'photonic').'</p>';
838 - $shortcode_attrs = [];
839 - foreach ($short_code as $attr => $value) {
840 - $shortcode_attrs[] = '<code>'.$attr . ": " . esc_attr($value).'</code>';
901 + if ($this->force_next_screen > -1) {
902 + $output .= "\n<input type='hidden' name='force_next_screen' value='{$this->force_next_screen}'/>\n";
841 903 }
842 - $output .= implode("<br/>\n", $shortcode_attrs);
843 -
844 - $output .= '<p>'.esc_html__('The following is the corresponding shortcode for this block. If for some reason you are unable to create a Photonic block you can paste this into a Shortcode block:', 'photonic').'</p>';
845 - $output .= "<code>[" . (empty($photonic_alternative_shortcode) ? 'gallery' : $photonic_alternative_shortcode).' ';
846 - $shortcode_attrs = [];
847 - foreach ($short_code as $attr => $value) {
848 - $shortcode_attrs[] = $attr . "='" . esc_attr($value) . "'";
904 + if ($this->force_previous_screen > -1) {
905 + $output .= "\n<input type='hidden' name='force_previous_screen' value='{$this->force_previous_screen}'/>\n";
849 906 }
850 -
851 - $output .= implode(' ', $shortcode_attrs);
852 - $output .= ']</code>';
853 -
854 - $output .= "<input id='photonic_shortcode' name='photonic_shortcode' type='hidden' value='".esc_attr(json_encode($short_code))."' />\n";
855 907 }
856 -
857 - if ($this->force_next_screen > -1) {
858 - $output .= "\n<input type='hidden' name='force_next_screen' value='{$this->force_next_screen}'/>\n";
859 - }
860 - if ($this->force_previous_screen > -1) {
861 - $output .= "\n<input type='hidden' name='force_previous_screen' value='{$this->force_previous_screen}'/>\n";
862 - }
863 908 return $output;
864 909 }
865 910
866 911 /**
@@ -869,13 +914,17 @@
869 914 *
870 915 * @param $input
871 916 * @return array
872 917 */
873 - private function deconstruct_shortcode($input) {
918 + private function deconstruct_shortcode($input): array {
874 919 $deconstructed = [];
875 920 if (!empty($input)) {
876 - if ((!empty($input->type) && in_array($input->type, ['wp', 'default', 'flickr', 'smugmug', 'picasa', 'google', 'zenfolio', 'instagram'])) ||
877 - ((empty($input->type) && !empty($input->style)) && in_array($input->style, ['square', 'circle', 'random', 'masonry', 'mosaic', 'strip-above', 'strip-below', 'strip-right', 'no-strip']))
921 + global $photonic_alternative_shortcode;
922 + $shortcode_tag = $photonic_alternative_shortcode ?: 'gallery';
923 +
924 + if ((!empty($input->type) && in_array($input->type, ['wp', 'default', 'flickr', 'smugmug', 'zenfolio'], true)) ||
925 + ((empty($input->type) && !empty($input->style)) && in_array($input->style, ['square', 'circle', 'random', 'masonry', 'masonry-horizontal', 'mosaic', 'strip-above', 'strip-below', 'strip-right', 'no-strip'], true)) ||
926 + (empty($input->type) && empty($input->style) && 'gallery' !== $shortcode_tag)
878 927 ) {
879 928 $deconstructed['provider'] = !empty($input->type) ? $input->type : 'wp';
880 929
881 930 $gallery = $this->flow_fields->get_source($deconstructed['provider']);
@@ -883,9 +932,9 @@
883 932 $deconstructed = array_merge($deconstructed, $deconstructed_selections);
884 933
885 934 if (!empty($input->filter)) {
886 935 $deconstructed['selected_data'] = $input->filter;
887 - if (empty($input->filter_type) && in_array($input->filter_type, ['include', 'exclude'])) {
936 + if (!empty($input->filter_type) && in_array($input->filter_type, ['include', 'exclude'], true)) {
888 937 $deconstructed['selection'] = $input->filter_type;
889 938 }
890 939 else {
891 940 $deconstructed['selection'] = 'selected';
@@ -905,12 +954,12 @@
905 954 }
906 955
907 956 $layout = empty($input->layout) ? (empty($input->style) ? '' : $input->style) : $input->layout;
908 957 if (!empty($layout)) {
909 - if (in_array($layout, ['square', 'circle', 'random', 'masonry', 'mosaic',])) {
958 + if (in_array($layout, ['square', 'circle', 'random', 'masonry', 'masonry-horizontal', 'mosaic'], true)) {
910 959 $deconstructed['layout'] = $layout;
911 960 }
912 - else if (in_array($layout, ['strip-above', 'strip-below', 'strip-right', 'no-strip'])) {
961 + elseif (in_array($layout, ['strip-above', 'strip-below', 'strip-right', 'no-strip'], true)) {
913 962 $deconstructed['layout'] = 'slideshow';
914 963 $deconstructed['slideshow-style'] = $layout;
915 964 }
916 965 }
@@ -936,14 +985,14 @@
936 985 * @param array $present
937 986 * @param bool $more
938 987 * @return string
939 988 */
940 - function get_thumbnail_display($objects, $provider = false, $existing = [], &$present = [], $more = false) {
989 + private function get_thumbnail_display($objects, $provider = false, $existing = [], &$present = [], $more = false): string {
941 990 $output = '';
942 991 $selected_data = empty($existing['selected_data']) ? [] : explode(',', $existing['selected_data']);
943 992 foreach ($objects as $object) {
944 993 if (!is_array($object)) {
945 - $output .= '<h4>'.$object."</h4>\n";
994 + $output .= '<h4>' . $object . "</h4>\n";
946 995 continue;
947 996 }
948 997 if (!isset($object['id'])) {
949 998 continue;
@@ -948,10 +997,10 @@
948 997 if (!isset($object['id'])) {
949 998 continue;
950 999 }
951 1000 $selected = '';
952 - if (in_array($object['id'], $selected_data) || (!empty($object['alt_id']) && in_array($object['alt_id'], $selected_data))
953 - || (!empty($object['alt_id2']) && in_array($object['alt_id2'], $selected_data))) {
1001 + if (in_array($object['id'], $selected_data, true) || (!empty($object['alt_id']) && in_array($object['alt_id'], $selected_data, true))
1002 + || (!empty($object['alt_id2']) && in_array($object['alt_id2'], $selected_data, true))) {
954 1003 $selected = 'selected';
955 1004 $present[] = $object['id'];
956 1005 }
957 1006 $passworded = !empty($object['passworded']) ? 'passworded' : '';
@@ -988,12 +1037,12 @@
988 1037 * @param null $url
989 1038 * @param bool $more
990 1039 * @return array
991 1040 */
992 - function process_response($response, $provider, $display_type = null, $form_parameters = [], $existing = [], $url = null, $more = false) {
1041 + public function process_response($response, $provider, $display_type = null, $form_parameters = [], $existing = [], $url = null, $more = false): array {
993 1042 if (!is_wp_error($response)) {
994 - if (isset($response['response']) && isset($response['response']['code'])) {
995 - if ($response['response']['code'] == 200) {
1043 + if (isset($response['response']['code'])) {
1044 + if (200 === $response['response']['code']) {
996 1045 $pagination = [];
997 1046 $source = $this->flow_fields->get_source($provider);
998 1047 $objects = $source->process_response($response, $display_type, $url, $pagination);
999 1048
@@ -999,9 +1048,9 @@
999 1048
1000 1049 if (empty($objects)) {
1001 1050 return ['error' => $this->error_no_data_returned];
1002 1051 }
1003 - else if (!empty($objects['error']) || !empty($objects['success'])) {
1052 + elseif (!empty($objects['error']) || !empty($objects['success'])) {
1004 1053 // Happens for "Find user" kind of calls
1005 1054 return $objects;
1006 1055 }
1007 1056
@@ -1007,19 +1056,18 @@
1007 1056
1008 1057 $present = [];
1009 1058 $output = $this->get_thumbnail_display($objects, $provider, $existing, $present, $more);
1010 1059
1011 - $selected_data = empty($existing['selected_data']) ? [] : explode(',', $existing['selected_data']);
1012 - $missing = array_diff($selected_data, $present);
1013 - if (!empty($missing)) {
1014 - //
1015 - }
1060 + if (!empty($pagination['url'])) {
1061 + $user = get_current_user_id();
1062 + if (0 === $user) {
1063 + $user = wp_rand(1);
1064 + }
1016 1065
1017 - if (!empty($pagination['url'])) {
1018 1066 $data_display_type = empty($display_type) ? '' : $display_type;
1019 - $output .= "<div class='photonic-more-wrapper'>\n".
1020 - "\t<a href='#' class='photonic-flow-more' data-photonic-more-link='{$pagination['url']}' data-photonic-display-type='$data_display_type' data-photonic-provider='$provider'>".esc_html__('Load More', 'photonic')."</a>\n".
1021 - "</div>";
1067 + $output .= "<div class='photonic-more-wrapper'>\n" .
1068 + "\t<a href='#' class='photonic-flow-more' data-photonic-more-link='{$pagination['url']}' data-photonic-display-type='$data_display_type' data-photonic-provider='$provider' data-photonic-nonce='" . wp_create_nonce('photonic-wizard-more-' . $user) . "'>" . esc_html__('Load More', 'photonic') . "</a>\n" .
1069 + "</div>";
1022 1070 }
1023 1071
1024 1072 if (!$more) {
1025 1073 foreach ($form_parameters as $id => $value) {
@@ -1040,6 +1088,16 @@
1040 1088 }
1041 1089 else {
1042 1090 return ['error' => $response->get_error_message()];
1043 1091 }
1092 + }
1093 +
1094 + public static function base_apis(): array {
1095 + return [
1096 + 'flickr' => 'api.flickr.com',
1097 + // 'google' => 'photoslibrary.googleapis.com',
1098 + 'smugmug' => 'api.smugmug.com',
1099 + // 'instagram' => 'graph.instagram.com',
1100 + 'zenfolio' => 'api.zenfolio.com',
1101 + ];
1044 1102 }
1045 1103 }