PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.5.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.5.0
2.5.0 2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 All 34 releases
← All changes | app/Hooks/Handlers/BlockEditorHandler.php +173 -143 1.5.1 → 2.5.0 View file →
@@ -2,11 +2,14 @@
2 2
3 3 namespace FluentBooking\App\Hooks\Handlers;
4 4
5 5 use FluentBooking\App\App;
6 +use FluentBooking\App\Vite;
6 7 use FluentBooking\App\Models\Calendar;
7 8 use FluentBooking\App\Models\CalendarSlot;
9 +use FluentBooking\App\Services\CalendarEventService;
8 10 use FluentBooking\App\Services\Helper;
11 +use FluentBooking\App\Services\LocationService;
9 12 use FluentBooking\Framework\Support\Arr;
10 13
11 14 class BlockEditorHandler
12 15 {
@@ -12,48 +15,25 @@
12 15 {
13 16 public function init()
14 17 {
15 18 add_action('enqueue_block_editor_assets', function () {
16 - $app = App::getInstance();
17 - $assets = $app['url.assets'];
19 + $blockDeps = array('wp-blocks', 'wp-components', 'wp-block-editor', 'wp-element');
18 20
19 - wp_enqueue_script(
20 - 'fluent-booking/calendar',
21 - $assets . 'admin/fluent-booking-index.js',
22 - array('wp-blocks', 'wp-components', 'wp-block-editor', 'wp-element'),
23 - FLUENT_BOOKING_ASSETS_VERSION,
24 - true
25 - );
21 + $assetsVersion = Vite::isDev() ? time() : FLUENT_BOOKING_ASSETS_VERSION;
26 22
23 + Vite::enqueueScript('fluent-booking/calendar', 'fb_index', $blockDeps, $assetsVersion);
24 +
27 25 wp_localize_script('fluent-booking/calendar', 'fluentCalendarGutenbergVars', [
28 - 'ajaxurl' => admin_url('admin-ajax.php'),
26 + 'ajaxurl' => admin_url('admin-ajax.php'),
29 27 ]);
30 28
31 - wp_enqueue_script(
32 - 'fluent-booking/team-management',
33 - $assets . 'admin/fluent-booking-team-management-index.js',
34 - array('wp-blocks', 'wp-components', 'wp-block-editor', 'wp-element'),
35 - FLUENT_BOOKING_ASSETS_VERSION,
36 - true
37 - );
29 + Vite::enqueueScript('fluent-booking/team-management', 'fb_team', $blockDeps, $assetsVersion);
38 30
39 - wp_enqueue_script(
40 - 'fluent-booking/calendar-management',
41 - $assets . 'admin/fluent-booking-calendar-management-index.js',
42 - array('wp-blocks', 'wp-components', 'wp-block-editor', 'wp-element'),
43 - FLUENT_BOOKING_ASSETS_VERSION,
44 - true
45 - );
31 + Vite::enqueueScript('fluent-booking/calendar-management', 'fb_calendar', $blockDeps, $assetsVersion);
46 32
47 - wp_enqueue_script(
48 - 'fluent-booking/booking-management',
49 - $assets . 'admin/fluent-booking-booking-management-index.js',
50 - array('wp-blocks', 'wp-components', 'wp-block-editor', 'wp-element'),
51 - FLUENT_BOOKING_ASSETS_VERSION,
52 - true
53 - );
33 + Vite::enqueueScript('fluent-booking/booking-management', 'fb_booking', $blockDeps, $assetsVersion);
54 34
55 - $calendars = Calendar::with(['events' => function ($query) {
35 + $calendars = Calendar::with(['metas', 'events' => function ($query) {
56 36 $query->where('status', 'active');
57 37 }])->where('status', 'active')->get();
58 38
59 39 $formattedCalendars = [];
@@ -58,23 +38,23 @@
58 38
59 39 $formattedCalendars = [];
60 40
61 41 foreach ($calendars as $calendar) {
62 - $events = $calendar->events;
63 - if ($events->isEmpty()) {
42 + if ($calendar->events->isEmpty()) {
64 43 continue;
65 44 }
66 45
67 46 $formattedEvents = [];
68 -
69 47 foreach ($calendar->events as $event) {
70 48 $formattedEvents[] = [
71 - 'id' => (string)$event->id,
72 - 'title' => $event->title,
73 - 'duration' => (array)$event->duration,
74 - 'desctiption' => $event->description,
49 + 'id' => (string)$event->id,
50 + 'title' => $event->title,
75 51 'color_schema' => $event->color_schema,
76 - 'locations' => $event->defaultLocationHtml()
52 + 'durations' => $event->getAvailableDurations(),
53 + 'locations' => $event->defaultLocationHtml(),
54 + 'payment_html' => $event->getPaymentHtml(),
55 + 'loc_settings' => LocationService::sanitizePublicLocationSettings($event->location_settings),
56 + 'description' => $event->short_description
77 57 ];
78 58 }
79 59
80 60 $formattedCalendars[$calendar->id] = [
@@ -80,19 +60,33 @@
80 60 $formattedCalendars[$calendar->id] = [
81 61 'id' => (string)$calendar->id,
82 62 'title' => $calendar->title,
83 63 'description' => wpautop(Helper::excerpt($calendar->description, 200)),
84 - 'author' => $calendar->getAuthorProfile(),
64 + 'author' => Arr::only($calendar->getAuthorProfile(), ['name', 'avatar']),
65 + 'event_order' => $calendar->getMeta('event_order'),
85 66 'events' => $formattedEvents
86 67 ];
87 68 }
88 69
89 70 wp_localize_script('fluent-booking/calendar', 'fluent_booking_block', [
90 - 'assets_url' => $assets,
71 + 'assets_url' => App::getInstance()['url.assets'] ?? '',
91 72 'hosts' => $formattedCalendars
92 73 ]);
93 74 });
94 75
76 + add_action('enqueue_block_assets', function () {
77 + if (!is_admin()) {
78 + return;
79 + }
80 +
81 + $assetsVersion = Vite::isDev() ? time() : FLUENT_BOOKING_ASSETS_VERSION;
82 +
83 + Vite::enqueueStyle('fluent-booking/calendar-style', 'fb_index_css', [], $assetsVersion);
84 + Vite::enqueueStyle('fluent-booking/team-management-style', 'fb_team_css', [], $assetsVersion);
85 + Vite::enqueueStyle('fluent-booking/calendar-management-style', 'fb_calendar_css', [], $assetsVersion);
86 + Vite::enqueueStyle('fluent-booking/booking-management-style', 'fb_booking_css', [], $assetsVersion);
87 + });
88 +
95 89 register_block_type('fluent-booking/calendar', array(
96 90 'editor_script' => 'fluent-booking/calendar',
97 91 'render_callback' => array($this, 'fcalRenderBlock'),
98 92 'attributes' => [
@@ -103,8 +97,12 @@
103 97 'calendarId' => [
104 98 'type' => 'string',
105 99 'default' => '',
106 100 ],
101 + 'eventHash' => [
102 + 'type' => 'string',
103 + 'default' => '',
104 + ],
107 105 'avatar_rounded' => [
108 106 'type' => 'boolean',
109 107 'default' => false
110 108 ],
@@ -134,24 +132,24 @@
134 132 register_block_type('fluent-booking/team-management', array(
135 133 'editor_script' => 'fluent-booking/team-management',
136 134 'render_callback' => array($this, 'fcalRenderTeamManagementBlock'),
137 135 'attributes' => [
138 - 'title' => [
139 - 'type' => 'string',
140 - 'default' => ''
141 - ],
142 - 'description' => [
143 - 'type' => 'string',
144 - 'default' => ''
145 - ],
146 - 'headerImage' => [
147 - 'type' => 'object',
148 - 'default' => ''
149 - ],
150 - 'hosts' => [
151 - 'type' => 'object',
152 - 'default' => ''
153 - ]
136 + 'title' => [
137 + 'type' => 'string',
138 + 'default' => ''
139 + ],
140 + 'description' => [
141 + 'type' => 'string',
142 + 'default' => ''
143 + ],
144 + 'headerImage' => [
145 + 'type' => 'object',
146 + 'default' => ''
147 + ],
148 + 'hosts' => [
149 + 'type' => 'object',
150 + 'default' => ''
151 + ]
154 152 ]
155 153 ));
156 154
157 155 register_block_type('fluent-booking/calendar-management', array(
@@ -173,13 +171,13 @@
173 171 'calendarId' => array(
174 172 'type' => 'string',
175 173 'default' => ''
176 174 ),
177 - 'eventIds' => array(
175 + 'eventIds' => array(
178 176 'type' => 'array',
179 177 'default' => []
180 178 ),
181 - 'hideInfo' => array(
179 + 'hideInfo' => array(
182 180 'type' => 'boolean',
183 181 'default' => false
184 182 )
185 183 )
@@ -188,36 +186,36 @@
188 186 register_block_type('fluent-booking/booking-management', array(
189 187 'editor_script' => 'fluent-booking/booking-management',
190 188 'render_callback' => array($this, 'fcalRenderBookingManagementBlock'),
191 189 'attributes' => [
192 - 'title' => [
193 - 'type' => 'string',
194 - 'default' => __('My Bookings', 'fluent-booking')
195 - ],
196 - 'showFilter' => [
197 - 'type' => 'boolean',
198 - 'default' => true
199 - ],
200 - 'showPagination' => [
201 - 'type' => 'boolean',
202 - 'default' => true
203 - ],
204 - 'period' => [
205 - 'type' => 'string',
206 - 'default' => 'all'
207 - ],
208 - 'perPage' => [
209 - 'type' => 'number',
210 - 'default' => 5
211 - ],
212 - 'noBookingsMessage' => [
213 - 'type' => 'string',
214 - 'default' => __('No bookings found', 'fluent-booking')
215 - ],
216 - 'calendarIds' => [
217 - 'type' => 'array',
218 - 'default' => ['all']
219 - ]
190 + 'title' => [
191 + 'type' => 'string',
192 + 'default' => __('My Bookings', 'fluent-booking')
193 + ],
194 + 'showFilter' => [
195 + 'type' => 'boolean',
196 + 'default' => true
197 + ],
198 + 'showPagination' => [
199 + 'type' => 'boolean',
200 + 'default' => true
201 + ],
202 + 'period' => [
203 + 'type' => 'string',
204 + 'default' => 'all'
205 + ],
206 + 'perPage' => [
207 + 'type' => 'number',
208 + 'default' => 5
209 + ],
210 + 'noBookingsMessage' => [
211 + 'type' => 'string',
212 + 'default' => __('No bookings found', 'fluent-booking')
213 + ],
214 + 'calendarIds' => [
215 + 'type' => 'array',
216 + 'default' => ['all']
217 + ]
220 218 ]
221 219 ));
222 220 }
223 221
@@ -233,41 +231,32 @@
233 231
234 232 $hostItems = [];
235 233
236 234 foreach ($hosts as $config) {
237 - $calendar = Calendar::find($config['id']);
235 + $calendar = Calendar::with('metas')->find($config['id']);
238 236 if (!$calendar) {
239 237 continue;
240 238 }
239 +
241 240 $eventIds = Arr::get($config, 'events', []);
242 241 if (!$eventIds) {
243 242 continue;
244 243 }
245 244
246 - $isAll = in_array('all', $eventIds);
245 + $eventsQuery = CalendarSlot::where('calendar_id', $calendar->id)
246 + ->where('status', 'active');
247 247
248 - if ($isAll) {
249 - $events = CalendarSlot::where('calendar_id', $calendar->id)
250 - ->where('status', 'active')
251 - ->get();
252 - } else {
253 - $events = CalendarSlot::where('calendar_id', $calendar->id)
254 - ->whereIn('id', $eventIds)
255 - ->where('status', 'active')
256 - ->get();
248 + if (!in_array('all', $eventIds)) {
249 + $eventsQuery->whereIn('id', $eventIds);
257 250 }
258 251
252 + $events = $eventsQuery->get();
253 +
259 254 if ($events->isEmpty()) {
260 255 continue;
261 256 }
262 257
263 - foreach ($events as $event) {
264 - $event->public_url = $event->getPublicUrl();
265 - $event->durations = $event->getAvailableDurations();
266 - $event->description = $event->getDescription();
267 - $event->short_description = Helper::excerpt($event->description);
268 - $event->locations = $event->defaultLocationHtml();
269 - }
258 + $events = CalendarEventService::processEvents($calendar, $events);
270 259
271 260 $calendar->activeEvents = $events;
272 261
273 262 $hostItems[$calendar->id] = $calendar;
@@ -273,11 +262,11 @@
273 262 $hostItems[$calendar->id] = $calendar;
274 263 }
275 264
276 265 return (new FrontEndHandler())->renderTeamHosts($hostItems, [
277 - 'title' => Arr::get($attributes, 'title'),
278 - 'description' => Arr::get($attributes, 'description'),
279 - 'logo' => Arr::get($attributes, 'headerImage.url'),
266 + 'title' => Arr::get($attributes, 'title'),
267 + 'description' => Arr::get($attributes, 'description'),
268 + 'logo' => Arr::get($attributes, 'headerImage.url'),
280 269 'wrapper_class' => $wrapperClassName
281 270 ]);
282 271 }
283 272
@@ -295,33 +284,23 @@
295 284 if (!$calendar) {
296 285 return '';
297 286 }
298 287
299 - $isAll = in_array('all', $eventIds);
288 + $eventsQuery = CalendarSlot::where('calendar_id', $calendar->id)
289 + ->where('status', 'active');
300 290
301 - if ($isAll) {
302 - $events = CalendarSlot::where('calendar_id', $calendar->id)
303 - ->where('status', 'active')
304 - ->get();
305 - } else {
306 - $events = CalendarSlot::where('calendar_id', $calendar->id)
307 - ->whereIn('id', $eventIds)
308 - ->where('status', 'active')
309 - ->get();
291 + if (!in_array('all', $eventIds)) {
292 + $eventsQuery->whereIn('id', $eventIds);
310 293 }
311 294
295 + $events = $eventsQuery->get();
296 +
312 297 if ($events->isEmpty()) {
313 298 return '';
314 299 }
315 300
316 - foreach ($events as $event) {
317 - $event->public_url = $event->getPublicUrl();
318 - $event->durations = $event->getAvailableDurations();
319 - $event->description = $event->getDescription();
320 - $event->short_description = Helper::excerpt($event->description);
321 - $event->locations = $event->defaultLocationHtml();
322 - }
323 -
301 + $events = CalendarEventService::processEvents($calendar, $events);
302 +
324 303 $calendar->activeEvents = $events;
325 304
326 305 return (new FrontEndHandler())->renderCalendarBlock($calendar, [
327 306 'title' => Arr::get($attributes, 'title'),
@@ -333,13 +312,19 @@
333 312 }
334 313
335 314 public function fcalRenderBookingManagementBlock($attributes)
336 315 {
337 - $calendarIds = Arr::get($attributes, 'calendarIds', []);
338 -
316 + $calendarIds = (array) Arr::get($attributes, 'calendarIds', []);
317 +
318 + if (!$calendarIds || in_array('all', $calendarIds, true)) {
319 + $calendarIds = 'all';
320 + } else {
321 + $calendarIds = implode(',', array_map('intval', $calendarIds));
322 + }
323 +
339 324 $title = sanitize_text_field(Arr::get($attributes, 'title'));
340 325
341 - $period = sanitize_text_field(Arr::get($attributes, 'period', 'all'));
326 + $period = sanitize_key(Arr::get($attributes, 'period', 'all'));
342 327
343 328 $perPage = intval(Arr::get($attributes, 'perPage', 10));
344 329
345 330 $showFilter = Arr::isTrue($attributes, 'showFilter', true) ? 'show' : 'hide';
@@ -347,29 +332,74 @@
347 332 $showPagination = Arr::isTrue($attributes, 'showPagination', true) ? 'show' : 'hide';
348 333
349 334 $noBookingsMessage = sanitize_text_field(Arr::get($attributes, 'noBookingsMessage'));
350 335
351 - return do_shortcode("[fluent_booking_lists title=\"$title\" period=$period per_page=$perPage filter=$showFilter pagination=$showPagination no_bookings=\"$noBookingsMessage\" calendar_ids=" . implode(',', $calendarIds) . "]");
336 + $shortcode = sprintf(
337 + '[fluent_booking_lists title="%s" period=%s per_page=%d filter=%s pagination=%s no_bookings="%s" calendar_ids=%s]',
338 + esc_attr($title),
339 + $period,
340 + $perPage,
341 + $showFilter,
342 + $showPagination,
343 + esc_attr($noBookingsMessage),
344 + $calendarIds
345 + );
346 +
347 + return do_shortcode($shortcode);
352 348 }
353 349
354 350 public function fcalRenderBlock($attributes)
355 351 {
356 - $output = '<style>
357 - :root {
358 - --fcal_primary_color: ' . esc_attr($attributes['primary_color']) . ' !important;
359 - --fcal_date_radius: ' . esc_attr($attributes['date_round']) . ' !important;
360 - --fcal_avatar_radius: ' . esc_attr($attributes['avatarStyle']) . ' !important;
352 + $primaryColor = sanitize_hex_color(Arr::get($attributes, 'primary_color', ''));
353 + $dateRadius = self::sanitizeCssLength(Arr::get($attributes, 'date_round', ''));
354 + $avatarRadius = self::sanitizeCssLength(Arr::get($attributes, 'avatarStyle', ''));
355 +
356 + $output = '<style>:root {';
357 + if ($primaryColor) {
358 + $output .= '--fcal_primary_color: ' . $primaryColor . ' !important;';
359 + }
360 + if ($dateRadius) {
361 + $output .= '--fcal_date_radius: ' . $dateRadius . ' !important;';
362 + }
363 + if ($avatarRadius) {
364 + $output .= '--fcal_avatar_radius: ' . $avatarRadius . ' !important;';
365 + }
366 + $output .= '}</style>';
367 +
368 + $slotId = (int) Arr::get($attributes, 'slotId');
369 + $disableHost = Arr::isTrue($attributes, 'hideHostInfo') ? 'yes' : 'no';
370 + $theme = sanitize_key(Arr::get($attributes, 'theme', 'light'));
371 + $eventHash = sanitize_text_field(Arr::get($attributes, 'eventHash', ''));
372 + $align = sanitize_html_class(Arr::get($attributes, 'align', ''));
373 +
374 + $slot = CalendarSlot::find($slotId);
375 +
376 + if (!$slot) {
377 + $slot = CalendarSlot::where('hash', $eventHash)->first();
378 + if (!$slot) {
379 + return '';
361 380 }
362 - </style>';
381 + $slotId = (int) $slot->id;
382 + $eventHash = (string) $slot->hash;
383 + }
363 384
364 - $slotId = $attributes['slotId'];
365 - $disableHost = $attributes['hideHostInfo'];
366 - $theme = Arr::get($attributes, 'theme', 'light');
385 + $output .= '<div class="fluent-booking-calendar-block align' . esc_attr($align) . '">';
367 386
368 - $output .= '<div class="fluent-booking-calendar-block align'.Arr::get($attributes,'align').'">';
387 + $output .= do_shortcode(sprintf(
388 + '[fluent_booking id=%d disable_author=%s theme=%s hash=%s]',
389 + $slotId,
390 + $disableHost,
391 + $theme,
392 + esc_attr($eventHash)
393 + ));
369 394
370 - $output .= do_shortcode("[fluent_booking id=$slotId disable_author=$disableHost theme=$theme]");
371 -
372 395 $output .= '</div>';
373 396 return $output;
397 + }
398 +
399 + private static function sanitizeCssLength($value)
400 + {
401 + $value = trim((string) $value);
402 +
403 + return preg_match('/^\d{1,3}(\.\d+)?(px|%|em|rem)$/', $value) ? $value : '';
374 404 }
375 405 }